From 42c47d9b4481366f03ec16612bacd874f3f67aaa Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 25 Sep 2023 14:56:56 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E7=A7=92=E5=9B=9E=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=EF=BC=9A=E8=AE=A2=E5=8D=95=E9=87=91=E9=A2=9D=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/seckill/SeckillActivityApi.java | 14 ++++ .../dto/SeckillActivityProductRespDTO.java | 65 +++++++++++++++++++ .../api/seckill/SeckillActivityApiImpl.java | 9 +++ .../SeckillActivityConvert.java | 3 + .../seckill/SeckillActivityService.java | 15 ++++- .../seckill/SeckillActivityServiceImpl.java | 15 +++++ .../convert/order/TradeOrderConvert.java | 6 +- .../price/bo/TradePriceCalculateReqBO.java | 18 +++++ .../price/bo/TradePriceCalculateRespBO.java | 19 +++++- .../TradePriceCalculatorHelper.java | 3 + .../TradeSeckillActivityPriceCalculator.java | 47 ++++++++++++++ 11 files changed, 207 insertions(+), 7 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java index 11cc22864..6f01d57ba 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java @@ -1,5 +1,10 @@ package cn.iocoder.yudao.module.promotion.api.seckill; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; + +import java.util.Collection; +import java.util.List; + /** * 秒杀活动 API 接口 * @@ -16,4 +21,13 @@ public interface SeckillActivityApi { */ void updateSeckillStock(Long id, Long skuId, Integer count); + /** + * 获取秒杀活动商品信息 + * + * @param id 活动编号 + * @param skuIds sku 编号 + * @return 秒杀活动商品信息列表 + */ + List getSeckillActivityProductList(Long id, Collection skuIds); + } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java new file mode 100644 index 000000000..5fb0554d3 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.promotion.api.seckill.dto; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 秒杀活动商品 Response DTO + * + * @author HUIHUI + */ +@Data +public class SeckillActivityProductRespDTO { + + /** + * 秒杀参与商品编号 + */ + private Long id; + /** + * 秒杀活动 id + * + * 关联 SeckillActivityDO#getId() + */ + private Long activityId; + /** + * 秒杀时段 id + * + * 关联 SeckillConfigDO#getId() + */ + private List configIds; + /** + * 商品 SPU 编号 + */ + private Long spuId; + /** + * 商品 SKU 编号 + */ + private Long skuId; + /** + * 秒杀金额,单位:分 + */ + private Integer seckillPrice; + /** + * 秒杀库存 + */ + private Integer stock; + + /** + * 秒杀商品状态 + * + * 枚举 {@link CommonStatusEnum 对应的类} + */ + private Integer activityStatus; + /** + * 活动开始时间点 + */ + private LocalDateTime activityStartTime; + /** + * 活动结束时间点 + */ + private LocalDateTime activityEndTime; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java index 9a15a0ca9..b837dac7e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java @@ -1,9 +1,13 @@ package cn.iocoder.yudao.module.promotion.api.seckill; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; +import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; /** * 秒杀活动接口 Api 接口实现类 @@ -21,4 +25,9 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { activityService.updateSeckillStock(id, skuId, count); } + @Override + public List getSeckillActivityProductList(Long id, Collection skuIds) { + return SeckillActivityConvert.INSTANCE.convertList4(activityService.getSeckillActivityProductList(id, skuIds)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java index f0da88cbc..6219d9032 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.enums.DictTypeConstants; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO; @@ -137,4 +138,6 @@ public interface SeckillActivityConvert { "yyyy-MM-dd HH:mm:ss")); // 活动结束日期和时段结合 } + List convertList4(List seckillActivityProductList); + } 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 3cbee8126..b517bb237 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 @@ -37,9 +37,9 @@ public interface SeckillActivityService { /** * 更新秒杀库存 * - * @param id 活动编号 - * @param skuId sku 编号 - * @param count 数量 + * @param id 活动编号 + * @param skuId sku 编号 + * @param count 数量 */ void updateSeckillStock(Long id, Long skuId, Integer count); @@ -114,4 +114,13 @@ public interface SeckillActivityService { */ PageResult getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO); + /** + * 获取秒杀活动商品信息 + * + * @param id 活动编号 + * @param skuIds sku 编号 + * @return 秒杀活动商品信息列表 + */ + List getSeckillActivityProductList(Long id, Collection skuIds); + } 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 0092cf1b8..687fa3127 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 @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.promotion.service.seckill; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -284,4 +285,18 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus()); } + @Override + public List getSeckillActivityProductList(Long id, Collection skuIds) { + // 1、校验秒杀活动是否存在 + validateSeckillActivityExists(id); + // 2、校验活动商品是否存在 + List productList = filterList(seckillProductMapper.selectListByActivityId(id), + item -> skuIds.contains(item.getSkuId())); + if (CollectionUtil.isEmpty(productList)) { + throw exception(SKU_NOT_EXISTS); + } + + return productList; + } + } 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 d5b9546d0..9fc0cdb64 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 @@ -216,11 +216,11 @@ public interface TradeOrderConvert { }) ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO); + TradePriceCalculateReqBO convert(AppTradeOrderSettlementReqVO settlementReqVO); + default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO, List cartList) { - TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO(); - reqBO.setUserId(userId).setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId()) - .setItems(new ArrayList<>(settlementReqVO.getItems().size())); + TradePriceCalculateReqBO reqBO = convert(settlementReqVO).setUserId(userId).setItems(new ArrayList<>(settlementReqVO.getItems().size())); // 商品项的构建 Map cartMap = convertMap(cartList, CartDO::getId); for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java index ff5faea26..c52f80073 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.service.price.bo; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import javax.validation.Valid; @@ -52,6 +53,23 @@ public class TradePriceCalculateReqBO { */ private Integer deliveryType; + // ========== 秒杀活动相关字段 ========== + @Schema(description = "秒杀活动编号", example = "1024") + private Long seckillActivityId; + + // ========== 拼团活动相关字段 ========== + // TODO @puhui999:是不是拼团记录的编号哈? + @Schema(description = "拼团活动编号", example = "1024") + private Long combinationActivityId; + + @Schema(description = "拼团团长编号", example = "2048") + private Long combinationHeadId; + + // ========== 砍价活动相关字段 ========== + // TODO @puhui999:是不是砍价记录的编号哈? + @Schema(description = "砍价活动编号", example = "123") + private Long bargainActivityId; + /** * 商品 SKU 数组 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java index 76fb68c1f..2aee9c65a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java @@ -84,9 +84,19 @@ public class TradePriceCalculateRespBO { * 对应 taobao 的 trade.point_fee 字段 */ private Integer pointPrice; + /** + * 秒杀、拼团、砍价活动商品的总金额,单位:分 + * + * 基于 {@link OrderItem#getActivityPrice()} ()} * {@link OrderItem#getCount()} 求和 + */ + private Integer activityPrice; /** * 最终购买金额(总),单位:分 * + * ==========活动情况=========== + * = {@link #activityPrice} + * + {@link #deliveryPrice} + * ==========正常情况=========== * = {@link #totalPrice} * - {@link #couponPrice} * - {@link #pointPrice} @@ -153,9 +163,16 @@ public class TradePriceCalculateRespBO { * 对应 taobao 的 trade.point_fee 字段 */ private Integer pointPrice; + /** + * 秒杀、拼团、砍价活动商品的金额,单位:分 + */ + private Integer activityPrice; /** * 应付金额(总),单位:分 - * + * ==========活动情况=========== + * = {@link #activityPrice} * {@link #count} + * + {@link #deliveryPrice} + * ==========正常情况=========== * = {@link #price} * {@link #count} * - {@link #couponPrice} * - {@link #pointPrice} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java index bd3d3b5be..9e85bc390 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java @@ -84,6 +84,9 @@ public class TradePriceCalculatorHelper { if (!item.getSelected()) { return; } + // TODO puhui: 需要在这里计算活动的价格 + // ========== 一、活动情况 ========== + // ========== 二、正常情况 ========== price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount()); price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice()); price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java new file mode 100644 index 000000000..5d33bc286 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * 秒杀活动的 {@link TradePriceCalculator} 实现类 + * + * @author HUIHUI + */ +@Component +@Order(TradePriceCalculator.ORDER_DISCOUNT_ACTIVITY) +public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator { + + @Resource + private SeckillActivityApi activityApi; + + @Override + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { + // 1、判断订单类型和是否具有秒杀活动编号 + if (ObjectUtil.notEqual(param.getType(), TradeOrderTypeEnum.SECKILL.getType()) && param.getSeckillActivityId() == null) { + return; + } + // 2、获取秒杀活动商品信息 + List productList = activityApi.getSeckillActivityProductList(param.getSeckillActivityId(), convertSet(param.getItems(), + TradePriceCalculateReqBO.Item::getSkuId)); + Map productMap = convertMap(productList, SeckillActivityProductRespDTO::getSkuId); + result.getItems().forEach(item -> { + SeckillActivityProductRespDTO product = productMap.get(item.getSkuId()); + item.setActivityPrice(product.getSeckillPrice()); // 设置活动金额 + }); + } + +} From 5ecd0d94eb47aa7a81575a1b9405210bdda25497 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 30 Sep 2023 11:24:52 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E8=AE=A2=E5=8D=95=EF=BC=9A=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=20order=20handler=20=E9=BB=98=E8=AE=A4=E6=8A=BD?= =?UTF-8?q?=E8=B1=A1=E5=AE=9E=E7=8E=B0=E7=B1=BB=EF=BC=8C=E5=AD=90=E7=B1=BB?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E9=80=89=E6=8B=A9=E6=80=A7=E5=9C=B0=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E6=8A=BD=E8=B1=A1=E6=96=B9=E6=B3=95=EF=BC=8C=E8=80=8C?= =?UTF-8?q?=E4=B8=8D=E5=BF=85=E5=AE=9E=E7=8E=B0=E6=89=80=E6=9C=89=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/handler/TradeBargainHandler.java | 13 +------ .../handler/TradeCombinationHandler.java | 21 +++++++----- .../handler/TradeOrderDefaultHandler.java | 34 +++++++++++++++++++ .../order/handler/TradeOrderHandler.java | 14 +++++--- .../order/handler/TradeSeckillHandler.java | 13 +------ 5 files changed, 58 insertions(+), 37 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderDefaultHandler.java diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java index 18a276fde..aafd826b9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; -import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import org.springframework.stereotype.Component; @@ -15,7 +14,7 @@ import javax.annotation.Resource; * @author HUIHUI */ @Component -public class TradeBargainHandler implements TradeOrderHandler { +public class TradeBargainHandler extends TradeOrderDefaultHandler { @Resource private BargainActivityApi bargainActivityApi; @@ -34,14 +33,4 @@ public class TradeBargainHandler implements TradeOrderHandler { bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount()); } - @Override - public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { - - } - - @Override - public void rollback() { - - } - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java index 42a2f8139..91c99d2e8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.trade.service.order.handler; import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.module.promotion.api.combination.CombinationActivityApi; import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import org.springframework.stereotype.Component; @@ -17,28 +17,25 @@ import javax.annotation.Resource; * @author HUIHUI */ @Component -public class TradeCombinationHandler implements TradeOrderHandler { +public class TradeCombinationHandler extends TradeOrderDefaultHandler { - @Resource - private CombinationActivityApi combinationActivityApi; @Resource private CombinationRecordApi combinationRecordApi; @Override public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { - // 如果是拼团订单; + // 如果不是拼团订单则结束 if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) { return; } // 校验是否满足拼团活动相关限制 - combinationActivityApi.validateCombination(reqBO.getCombinationActivityId(), reqBO.getUserId(), reqBO.getSkuId(), reqBO.getCount()); + combinationRecordApi.validateCombinationRecord(reqBO.getCombinationActivityId(), reqBO.getUserId(), reqBO.getSkuId(), reqBO.getCount()); } @Override public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { - // TODO @puhui999:需要判断下; - if (true) { + if (reqBO.getCombinationActivityId() == null) { return; } @@ -47,8 +44,14 @@ public class TradeCombinationHandler implements TradeOrderHandler { } @Override - public void rollback() { + public void afterPayOrder(TradeAfterPayOrderReqBO reqBO) { + // 如果不是拼团订单则结束 + if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) { + return; + } + // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 + combinationRecordApi.updateRecordStatusToInProgress(reqBO.getUserId(), reqBO.getOrderId(), reqBO.getPayTime()); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderDefaultHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderDefaultHandler.java new file mode 100644 index 000000000..824ad803c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderDefaultHandler.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; + +/** + * 订单活动特殊逻辑处理器 handler 默认抽象实现类 + * + * @author HUIHUI + */ +public abstract class TradeOrderDefaultHandler implements TradeOrderHandler { + + @Override + public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { + + } + + @Override + public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { + + } + + @Override + public void afterPayOrder(TradeAfterPayOrderReqBO reqBO) { + + } + + @Override + public void cancelOrder() { + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java index 47426dd9b..5429b1add 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.trade.service.order.handler; import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; /** * 订单活动特殊逻辑处理器 handler 接口 + * 提供订单生命周期钩子接口;订单创建前、订单创建后、订单支付后、订单取消 * * @author HUIHUI */ @@ -24,12 +26,16 @@ public interface TradeOrderHandler { */ void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO); - // TODO @puhui999:这个搞成订单取消 /** - * 回滚 + * 支付订单后 + * + * @param reqBO 请求 */ - void rollback(); + void afterPayOrder(TradeAfterPayOrderReqBO reqBO); - // TODO @puhui999:再搞个订单项取消哈 + /** + * 订单取消 + */ + void cancelOrder(); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java index 652717b77..cef790cf8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; -import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import org.springframework.stereotype.Component; @@ -15,7 +14,7 @@ import javax.annotation.Resource; * @author HUIHUI */ @Component -public class TradeSeckillHandler implements TradeOrderHandler { +public class TradeSeckillHandler extends TradeOrderDefaultHandler { @Resource private SeckillActivityApi seckillActivityApi; @@ -34,14 +33,4 @@ public class TradeSeckillHandler implements TradeOrderHandler { seckillActivityApi.updateSeckillStock(reqBO.getSeckillActivityId(), reqBO.getSkuId(), reqBO.getCount()); } - @Override - public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { - - } - - @Override - public void rollback() { - - } - } From 0b35d4a7e3c55b29b2153f00285a31c6b5ecad8c Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 30 Sep 2023 11:27:24 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E8=AE=A2=E5=8D=95=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E6=8B=BC=E5=9B=A2=E6=B4=BB=E5=8A=A8=E9=83=A8=E5=88=86?= =?UTF-8?q?=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/date/LocalDateTimeUtils.java | 40 +++++++++++++++ .../ProductCommentServiceImplTest.java | 3 -- .../combination/CombinationActivityApi.java | 10 ---- .../api/combination/CombinationRecordApi.java | 10 ++++ .../promotion/enums/ErrorCodeConstants.java | 7 +-- .../CombinationActivityApiImpl.java | 11 ---- .../combination/CombinationRecordApiImpl.java | 5 ++ .../SeckillActivityConvert.java | 15 +++--- .../combination/CombinationRecordMapper.java | 4 ++ .../CombinationActivityService.java | 11 ---- .../CombinationActivityServiceImpl.java | 43 +--------------- .../combination/CombinationRecordService.java | 11 ++++ .../CombinationRecordServiceImpl.java | 51 ++++++++++++++++--- .../order/TradeOrderUpdateServiceImpl.java | 13 ++--- .../order/bo/TradeAfterPayOrderReqBO.java | 43 ++++++++++++++++ .../TradeSeckillActivityPriceCalculator.java | 4 +- 16 files changed, 179 insertions(+), 102 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 414c0af7d..92604e94c 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -93,4 +93,44 @@ public class LocalDateTimeUtils { LocalDateTime.of(nowDate, startTime2), LocalDateTime.of(nowDate, endTime2)); } + /** + * 构建日期时间 TODO 后面有需要的话再继续扩展 + * + * @author HUIHUI + */ + public static class BuilderDateTime { + + /** + * 日期;2023-10-01 + */ + private String localDate; + /** + * 时间;10:01:00 + */ + private String localTime; + + public BuilderDateTime() { + } + + public BuilderDateTime withDate(String date) { + this.localDate = date; + return this; + } + + public BuilderDateTime withDate(LocalDateTime date) { + this.localDate = LocalDateTimeUtil.format(date, "yyyy-MM-dd"); + return this; + } + + public BuilderDateTime withTime(String time) { + this.localTime = time; + return this; + } + + public LocalDateTime build() { + return LocalDateTimeUtil.parse(this.localDate + " " + this.localTime, "yyyy-MM-dd HH:mm:ss"); + } + + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java index 2f55af837..fb6bc3649 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -48,8 +47,6 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { @Lazy private ProductCommentServiceImpl productCommentService; - @MockBean - private TradeOrderApi tradeOrderApi; @MockBean private ProductSpuService productSpuService; @MockBean diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java index ad78aaa0d..a5163cdf1 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java @@ -7,14 +7,4 @@ package cn.iocoder.yudao.module.promotion.api.combination; */ public interface CombinationActivityApi { - /** - * 校验是否满足拼团条件 - * - * @param activityId 活动编号 - * @param userId 用户编号 - * @param skuId sku 编号 - * @param count 数量 - */ - void validateCombination(Long activityId, Long userId, Long skuId, Integer count); - } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java index bf70bb29c..5a144a75a 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java @@ -14,6 +14,16 @@ import java.time.LocalDateTime; */ public interface CombinationRecordApi { + /** + * 校验是否满足拼团条件 + * + * @param activityId 活动编号 + * @param userId 用户编号 + * @param skuId sku 编号 + * @param count 数量 + */ + void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count); + /** * 创建开团记录 * 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 4fc58004a..c63928fbd 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 @@ -75,9 +75,10 @@ public interface ErrorCodeConstants { ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在"); ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011003, "拼团失败,拼团人数已满"); ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011004, "拼团失败,已参与其它拼团"); - ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011005, "拼团失败,活动已经结束"); - ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出"); - ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数"); + ErrorCode COMBINATION_RECORD_FAILED_TIME_NOT_START = new ErrorCode(1013011005, "拼团失败,活动未开始"); + ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011006, "拼团失败,活动已经结束"); + ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:单次限购超出"); + ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011008, "拼团失败,原因:超出总购买次数"); // ========== 砍价活动 1013012000 ========== ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java index 14eb9dd41..967ce6101 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java @@ -1,10 +1,7 @@ package cn.iocoder.yudao.module.promotion.api.combination; -import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; import org.springframework.stereotype.Service; -import javax.annotation.Resource; - /** * 拼团活动 Api 接口实现类 * @@ -13,12 +10,4 @@ import javax.annotation.Resource; @Service public class CombinationActivityApiImpl implements CombinationActivityApi { - @Resource - private CombinationActivityService activityService; - - @Override - public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) { - activityService.validateCombination(activityId, userId, skuId, count); - } - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java index 24d42482a..8f7ce2e24 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java @@ -19,6 +19,11 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @Resource private CombinationRecordService recordService; + @Override + public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) { + recordService.validateCombinationRecord(activityId, userId, skuId, count); + } + @Override public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { recordService.createCombinationRecord(reqDTO); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java index f2e5ff50a..7c7457155 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; -import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.enums.DictTypeConstants; @@ -129,11 +129,14 @@ public interface SeckillActivityConvert { default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List products, SeckillConfigDO filteredConfig) { return convert2(seckillActivity) .setProducts(convertList1(products)) - // TODO @puhui999:要不要在里面 default 一个方法,处理这个事件;简洁一点; - .setStartTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getStartTime(), "yyyy-MM-dd") + " " + filteredConfig.getStartTime(), - "yyyy-MM-dd HH:mm:ss")) // 活动开始日期和时段结合 - .setEndTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getEndTime(), "yyyy-MM-dd") + " " + filteredConfig.getEndTime(), - "yyyy-MM-dd HH:mm:ss")); // 活动结束日期和时段结合 + .setStartTime(new LocalDateTimeUtils.BuilderDateTime() + .withDate(seckillActivity.getStartTime()) + .withTime(filteredConfig.getStartTime()) + .build())// 活动开始日期和时段结合 + .setEndTime(new LocalDateTimeUtils.BuilderDateTime() + .withDate(seckillActivity.getEndTime()) + .withTime(filteredConfig.getEndTime()) + .build()); // 活动结束日期和时段结合 } List convertList4(List seckillActivityProductList); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java index 218a24897..b1ccfc858 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java @@ -20,6 +20,10 @@ public interface CombinationRecordMapper extends BaseMapperX selectListByUserId(Long userId) { + return selectList(CombinationRecordDO::getUserId, userId); + } + default List selectListByUserIdAndStatus(Long userId, Integer status) { return selectList(new LambdaQueryWrapperX() .eq(CombinationRecordDO::getUserId, userId) 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 c5f72e6a6..e3efbfaa5 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 @@ -84,17 +84,6 @@ public interface CombinationActivityService { */ List getCombinationProductsByActivityIds(Collection activityIds); - /** - * 校验是否满足拼团条件 - * 如果不满足,会抛出异常 - * - * @param activityId 活动编号 - * @param userId 用户编号 - * @param skuId sku 编号 - * @param count 数量 - */ - void validateCombination(Long activityId, Long userId, Long skuId, Integer count); - /** * 获取正在进行的活动分页数据 * 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 index 2dc715039..41b72233a 100644 --- 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 @@ -17,12 +17,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product 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.dataobject.combination.CombinationRecordDO; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper; -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; -import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -33,7 +29,8 @@ 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.*; +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.*; @@ -53,16 +50,10 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @Resource private CombinationProductMapper combinationProductMapper; - @Resource - @Lazy // TODO @puhui999:我感觉 validateCombination 可以挪到 CombinationRecordServiceImpl 中,因为它更偏向能不能创建拼团记录; - private CombinationRecordService combinationRecordService; - @Resource private ProductSpuApi productSpuApi; @Resource private ProductSkuApi productSkuApi; - @Resource - private TradeOrderApi tradeOrderApi; @Override @Transactional(rollbackFor = Exception.class) @@ -215,36 +206,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic return combinationProductMapper.selectListByActivityIds(activityIds); } - @Override - public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) { - // 1.1 校验拼团活动是否存在 - CombinationActivityDO activity = validateCombinationActivityExists(activityId); - // 1.2 校验活动是否开启 - if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { - throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); - } - // 1.3 校验是否超出单次限购数量 - if (count > activity.getSingleLimitCount()) { - throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); - } - - // 2. 校验是否超出总限购数量 - List recordList = combinationRecordService.getRecordListByUserIdAndActivityId(userId, activityId); - if (CollUtil.isEmpty(recordList)) { - return; - } - // 过滤出拼团成功的 - // TODO @puhui999:count 要不存一个在 record 里? - List skuIds = convertList(recordList, CombinationRecordDO::getSkuId, - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); - Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList, - CombinationRecordDO::getOrderId, - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); - if (activity.getTotalLimitCount() < countSum) { - throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); - } - } - @Override public List getCombinationActivityListByCount(Integer count) { return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count); 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 e75440edd..e2e26124b 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 @@ -22,6 +22,17 @@ public interface CombinationRecordService { */ void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId); + /** + * 校验是否满足拼团条件 + * 如果不满足,会抛出异常 + * + * @param activityId 活动编号 + * @param userId 用户编号 + * @param skuId sku 编号 + * @param count 数量 + */ + void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count); + /** * 创建拼团记录 * 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 index 047e060a9..caf5d86b8 100644 --- 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 @@ -2,6 +2,7 @@ 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.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; @@ -14,6 +15,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationA 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 cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,6 +26,7 @@ import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; // TODO 芋艿:等拼团记录做完,完整 review 下 @@ -51,6 +54,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @Resource @Lazy private ProductSkuApi productSkuApi; + @Resource + private TradeOrderApi tradeOrderApi; @Override @Transactional(rollbackFor = Exception.class) @@ -97,6 +102,35 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { } // TODO @puhui999:有一个应该在创建那要做下;就是当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先; + @Override + public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) { + // 1.1 校验拼团活动是否存在 + CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(activityId); + // 1.2 校验活动是否开启 + if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); + } + // 1.3 校验是否超出单次限购数量 + if (count > activity.getSingleLimitCount()) { + throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); + } + + // 2. 校验是否超出总限购数量 + List recordList = getRecordListByUserIdAndActivityId(userId, activityId); + if (CollUtil.isEmpty(recordList)) { + return; + } + // 过滤出拼团成功的 + // TODO @puhui999:count 要不存一个在 record 里? + List skuIds = convertList(recordList, CombinationRecordDO::getSkuId, + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); + Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList, + CombinationRecordDO::getOrderId, + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); + if (activity.getTotalLimitCount() < countSum) { + throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); + } + } @Override @Transactional(rollbackFor = Exception.class) @@ -105,21 +139,26 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId()); // 1.2 需要校验下,他当前是不是已经参加了该拼团; // TODO @puhui999:拼团应该可以重复参加;应该去校验总共的上限哈,就是 activity.totalLimitCount - CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId()); - if (recordDO != null) { - throw exception(COMBINATION_RECORD_EXISTS); + List records = recordMapper.selectListByUserId(reqDTO.getUserId()); + List orderIds = convertList(records, CombinationRecordDO::getOrderId); + // 1.2.1 如果存在订单才去校验 + if (CollUtil.isNotEmpty(orderIds)) { + } // 1.3 校验用户是否参加了其它拼团 List recordDOList = recordMapper.selectListByUserIdAndStatus(reqDTO.getUserId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); if (CollUtil.isNotEmpty(recordDOList)) { throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED); } - // TODO @puhui999:有个开始时间未校验 - // 1.4 校验当前活动是否过期 + // 1、4 校验活动是否开启 + if (LocalDateTime.now().isAfter(activity.getStartTime())) { + throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START); + } + // 1.5 校验当前活动是否过期 if (LocalDateTime.now().isAfter(activity.getEndTime())) { throw exception(COMBINATION_RECORD_FAILED_TIME_END); } - // 1.5 父拼团是否存在,是否已经满了 + // 1.6 父拼团是否存在,是否已经满了 if (reqDTO.getHeadId() != null) { // 查询进行中的父拼团 CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 42e77fc4b..85f700dd4 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -56,6 +56,7 @@ import cn.iocoder.yudao.module.trade.service.cart.CartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler; import cn.iocoder.yudao.module.trade.service.price.TradePriceService; @@ -333,13 +334,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (updateCount == 0) { throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); } - // 校验活动 - // 1、拼团活动 - // TODO @puhui999:这块也抽象到 handler 里 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 - combinationRecordApi.updateRecordStatusToInProgress(order.getUserId(), order.getId(), LocalDateTime.now()); - } + // 订单支付成功后 + tradeOrderHandlers.forEach(tradeOrderHandler -> tradeOrderHandler.afterPayOrder(new TradeAfterPayOrderReqBO() + .setOrderId(order.getId()).setOrderType(order.getType()).setUserId(order.getUserId()).setPayTime(LocalDateTime.now()))); // TODO 芋艿:发送订单变化的消息 // TODO 芋艿:发送站内信 @@ -742,7 +739,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { } // 3. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 - tradeOrderHandlers.forEach(handler -> handler.rollback()); + tradeOrderHandlers.forEach(handler -> handler.cancelOrder()); // 4. 回滚库存 List orderItems = tradeOrderItemMapper.selectListByOrderId(id); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java new file mode 100644 index 000000000..42aba4380 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.trade.service.order.bo; + +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 订单支付后 Request BO + * + * @author HUIHUI + */ +@Data +public class TradeAfterPayOrderReqBO { + + /** + * 订单编号 + */ + @Schema(description = "订单编号", example = "6") + private Long orderId; + + /** + * 订单类型 + * + * 枚举 {@link TradeOrderTypeEnum} + */ + @Schema(description = "订单类型", example = "3") + private Integer orderType; + + /** + * 用户编号 + */ + @Schema(description = "用户编号", example = "11") + private Long userId; + + /** + * 订单支付时间 + */ + @Schema(description = "订单支付时间", example = "2023-08-15 10:00:00") + private LocalDateTime payTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java index 5d33bc286..95996ab9f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java @@ -1,9 +1,7 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; -import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import org.springframework.core.annotation.Order; @@ -31,7 +29,7 @@ public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator @Override public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { // 1、判断订单类型和是否具有秒杀活动编号 - if (ObjectUtil.notEqual(param.getType(), TradeOrderTypeEnum.SECKILL.getType()) && param.getSeckillActivityId() == null) { + if (param.getSeckillActivityId() == null) { return; } // 2、获取秒杀活动商品信息 From 82210a95832fd7be194af8bd365a085c7ef9a2c4 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 30 Sep 2023 23:34:45 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E8=AE=A2=E5=8D=95=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E6=8B=BC=E5=9B=A2=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/bargain/BargainRecordApi.java | 9 --- .../dto/CombinationRecordCreateReqDTO.java | 5 ++ .../promotion/enums/ErrorCodeConstants.java | 18 ++--- .../api/bargain/BargainRecordApiImpl.java | 5 -- .../CombinationActivityConvert.java | 2 +- .../combination/CombinationRecordDO.java | 4 ++ .../bargain/BargainActivityServiceImpl.java | 8 +-- .../CombinationRecordServiceImpl.java | 66 +++++++++++-------- .../module/trade/api/order/TradeOrderApi.java | 20 ++---- .../trade/api/order/TradeOrderApiImpl.java | 21 ++---- .../vo/AppTradeOrderSettlementReqVO.java | 14 +++- .../convert/order/TradeOrderConvert.java | 44 ++++++++----- .../dal/mysql/order/TradeOrderItemMapper.java | 6 -- .../service/order/TradeOrderQueryService.java | 8 --- .../order/TradeOrderQueryServiceImpl.java | 7 -- .../order/TradeOrderUpdateServiceImpl.java | 22 ++----- .../order/bo/TradeAfterOrderCreateReqBO.java | 65 +++++++++++++++--- .../order/bo/TradeBeforeOrderCreateReqBO.java | 54 ++++++++------- .../order/handler/TradeBargainHandler.java | 5 +- .../handler/TradeCombinationHandler.java | 4 +- .../order/handler/TradeSeckillHandler.java | 5 +- 21 files changed, 209 insertions(+), 183 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApi.java index 397d9cf29..52baa553c 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApi.java @@ -20,13 +20,4 @@ public interface BargainRecordApi { */ void createBargainRecord(@Valid BargainRecordCreateReqDTO reqDTO); - /** - * 查询砍价是否成功 - * - * @param userId 用户编号 - * @param orderId 订单编号 - * @return 砍价是否成功 - */ - boolean isBargainRecordSuccess(Long userId, Long orderId); - } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java index 34d667fe3..76f240599 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java @@ -28,6 +28,11 @@ public class CombinationRecordCreateReqDTO { */ @NotNull(message = "sku 编号不能为空") private Long skuId; + /** + * 购买的商品数量 + */ + @NotNull(message = "购买数量不能为空") + private Integer count; /** * 订单编号 */ 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 c094a72f7..cb0f74f5b 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 @@ -75,19 +75,11 @@ public interface ErrorCodeConstants { ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_011_002, "拼团失败,父拼团不存在"); ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1_013_011_003, "拼团失败,拼团人数已满"); ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1_013_011_004, "拼团失败,已参与其它拼团"); - ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_005, "拼团失败,活动已经结束"); - ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_006, "拼团失败,原因:单次限购超出"); - ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:超出总购买次数"); - // ========== 拼团记录 1013011000 ========== - ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在"); - ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团"); - ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在"); - ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011003, "拼团失败,拼团人数已满"); - ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011004, "拼团失败,已参与其它拼团"); - ErrorCode COMBINATION_RECORD_FAILED_TIME_NOT_START = new ErrorCode(1013011005, "拼团失败,活动未开始"); - ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011006, "拼团失败,活动已经结束"); - ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:单次限购超出"); - ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011008, "拼团失败,原因:超出总购买次数"); + ErrorCode COMBINATION_RECORD_FAILED_TIME_NOT_START = new ErrorCode(1_013_011_005, "拼团失败,活动未开始"); + ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_006, "拼团失败,活动已经结束"); + ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:单次限购超出"); + ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_008, "拼团失败,原因:超出总购买次数"); + ErrorCode COMBINATION_RECORD_FAILED_ORDER_STATUS_UNPAID = new ErrorCode(1_013_011_009, "拼团失败,原因:存在未支付订单,请先支付"); // ========== 砍价活动 1-013-012-000 ========== ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_012_000, "砍价活动不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApiImpl.java index 7432f7914..4df7b07b4 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApiImpl.java @@ -16,9 +16,4 @@ public class BargainRecordApiImpl implements BargainRecordApi { } - @Override - public boolean isBargainRecordSuccess(Long userId, Long orderId) { - return false; - } - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java index f92dbef59..558d93cbd 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java @@ -97,8 +97,8 @@ public interface CombinationActivityConvert { default CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO, CombinationActivityDO activity, MemberUserRespDTO user, ProductSpuRespDTO spu, ProductSkuRespDTO sku) { - // TODO @puhui999:订单付款后需要设置开始时间和结束时间; return convert(reqDTO) + .setCount(reqDTO.getCount()) .setVirtualGroup(false) .setExpireTime(activity.getStartTime().plusHours(activity.getLimitDuration())) .setUserSize(activity.getUserSize()) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java index ea851d67e..1b8a73c24 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java @@ -62,6 +62,10 @@ public class CombinationRecordDO extends BaseDO { * SKU 编号 */ private Long skuId; + /** + * 购买的商品数量 + */ + private Integer count; /** * 用户编号 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java index 546b95041..8ed971f73 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java @@ -116,10 +116,10 @@ public class BargainActivityServiceImpl implements BargainActivityService { public void deleteBargainActivity(Long id) { // 校验存在 BargainActivityDO activityDO = validateBargainActivityExists(id); - // 校验状态 TODO puhui: 测试完成后需要恢复校验 - //if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { - // throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END); - //} + // 校验状态 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { + throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END); + } // 删除 bargainActivityMapper.deleteById(id); 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 index caf5d86b8..e56271445 100644 --- 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 @@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,7 +27,7 @@ import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; // TODO 芋艿:等拼团记录做完,完整 review 下 @@ -101,7 +102,6 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { return recordDO; } - // TODO @puhui999:有一个应该在创建那要做下;就是当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先; @Override public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) { // 1.1 校验拼团活动是否存在 @@ -110,55 +110,69 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); } - // 1.3 校验是否超出单次限购数量 + // 2 校验是否超出单次限购数量 if (count > activity.getSingleLimitCount()) { throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); } - - // 2. 校验是否超出总限购数量 + // 3、校验是否有拼团记录 List recordList = getRecordListByUserIdAndActivityId(userId, activityId); if (CollUtil.isEmpty(recordList)) { return; } - // 过滤出拼团成功的 - // TODO @puhui999:count 要不存一个在 record 里? - List skuIds = convertList(recordList, CombinationRecordDO::getSkuId, - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); - Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList, - CombinationRecordDO::getOrderId, - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); - if (activity.getTotalLimitCount() < countSum) { + // 4、校验是否超出总限购数量 + Integer sumValue = getSumValue(convertList(recordList, CombinationRecordDO::getCount, + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), i -> i, Integer::sum); + if ((sumValue + count) > activity.getTotalLimitCount()) { throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); } + // 5、校验拼团记录是否存在未支付的订单(如果存在未支付的订单则不允许发起新的拼团) + CombinationRecordDO record = findFirst(recordList, item -> ObjectUtil.equals(item.getStatus(), null)); + if (record == null) { + return; + } + // 5.1、查询关联的订单是否已经支付 + // 当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先; + Integer orderStatus = tradeOrderApi.getOrderStatus(record.getOrderId()); + if (ObjectUtil.equal(orderStatus, TradeOrderStatusEnum.UNPAID.getStatus())) { + throw exception(COMBINATION_RECORD_FAILED_ORDER_STATUS_UNPAID); + } } @Override @Transactional(rollbackFor = Exception.class) public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { - // 1.1 校验拼团活动 - CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId()); - // 1.2 需要校验下,他当前是不是已经参加了该拼团; - // TODO @puhui999:拼团应该可以重复参加;应该去校验总共的上限哈,就是 activity.totalLimitCount - List records = recordMapper.selectListByUserId(reqDTO.getUserId()); - List orderIds = convertList(records, CombinationRecordDO::getOrderId); - // 1.2.1 如果存在订单才去校验 - if (CollUtil.isNotEmpty(orderIds)) { + // 1.1、 校验拼团活动 + CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId()); + // 1.2 校验是否超出单次限购数量 + if (reqDTO.getCount() > activity.getSingleLimitCount()) { + throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); } - // 1.3 校验用户是否参加了其它拼团 + // 1.3、校验是否有拼团记录 + List records = getRecordListByUserIdAndActivityId(reqDTO.getUserId(), reqDTO.getActivityId()); + if (CollUtil.isEmpty(records)) { + return; + } + // 1.4、校验是否超出总限购数量 + Integer sumValue = getSumValue(convertList(records, CombinationRecordDO::getCount, + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), i -> i, Integer::sum); + if ((sumValue + reqDTO.getCount()) > activity.getTotalLimitCount()) { + throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); + } + // 2、 校验用户是否参加了其它拼团 List recordDOList = recordMapper.selectListByUserIdAndStatus(reqDTO.getUserId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); if (CollUtil.isNotEmpty(recordDOList)) { throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED); } - // 1、4 校验活动是否开启 + // 3、 校验活动是否开启 if (LocalDateTime.now().isAfter(activity.getStartTime())) { throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START); } - // 1.5 校验当前活动是否过期 + // 4、 校验当前活动是否过期 if (LocalDateTime.now().isAfter(activity.getEndTime())) { throw exception(COMBINATION_RECORD_FAILED_TIME_END); } - // 1.6 父拼团是否存在,是否已经满了 + // 5、 父拼团是否存在,是否已经满了 if (reqDTO.getHeadId() != null) { // 查询进行中的父拼团 CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); @@ -171,8 +185,6 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { } } - // TODO @puhui999:单次限购 - // 2. 创建拼团记录 MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); 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 8f33fff28..d1f49cd80 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 @@ -1,7 +1,5 @@ package cn.iocoder.yudao.module.trade.api.order; -import java.util.Collection; - /** * 订单 API 接口 * @@ -10,21 +8,11 @@ import java.util.Collection; public interface TradeOrderApi { /** - * 验证订单 + * 获取订单状态 * - * @param userId 用户 id - * @param orderItemId 订单项 id - * @return 校验通过返回订单 id + * @param id 订单编号 + * @return 订单状态 */ - Long validateOrder(Long userId, Long orderItemId); - - /** - * 获取订单项商品购买数量总和 - * - * @param orderIds 订单编号 - * @param skuIds sku 编号 - * @return 订单项商品购买数量总和 - */ - Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds); + Integer getOrderStatus(Long id); } 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 3ee315ccb..826a9cd21 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 @@ -1,15 +1,14 @@ package cn.iocoder.yudao.module.trade.api.order; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.Collection; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; /** * 订单 API 接口实现类 @@ -24,18 +23,12 @@ public class TradeOrderApiImpl implements TradeOrderApi { private TradeOrderQueryService tradeOrderQueryService; @Override - public Long validateOrder(Long userId, Long orderItemId) { - // 校验订单项,订单项存在订单就存在 - TradeOrderItemDO item = tradeOrderQueryService.getOrderItem(userId, orderItemId); - if (item == null) { - throw exception(ORDER_ITEM_NOT_FOUND); + public Integer getOrderStatus(Long id) { + TradeOrderDO order = tradeOrderQueryService.getOrder(id); + if (order == null) { + throw exception(ORDER_NOT_FOUND); } - return item.getOrderId(); - } - - @Override - public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds) { - return tradeOrderQueryService.getOrderItemCountSumByOrderIdAndSkuId(orderIds, skuIds); + return order.getStatus(); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java index fb5c844c0..06b7f11fb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java @@ -16,6 +16,7 @@ import java.util.List; @Schema(description = "用户 App - 交易订单结算 Request VO") @Data +@Valid public class AppTradeOrderSettlementReqVO { @Schema(description = "商品项数组", requiredMode = Schema.RequiredMode.REQUIRED) @@ -62,7 +63,16 @@ public class AppTradeOrderSettlementReqVO { @Schema(description = "砍价活动编号", example = "123") private Long bargainActivityId; - // TODO @puhui999:可以写个参数校验,如果 seckillActivityId 或 combinationActivityId 或 combinationHeadId 的情况,items 应该只有一个 + @AssertTrue(message = "活动商品每次只能购买一种规格") + @JsonIgnore + public boolean isValidActivityItems() { + // 校验是否是活动订单 + if (seckillActivityId == null && combinationActivityId == null && combinationHeadId == null) { + return true; + } + // 校验订单项是否超出 + return items.size() == 1; + } @Data @Schema(description = "用户 App - 商品项") @@ -70,7 +80,9 @@ public class AppTradeOrderSettlementReqVO { public static class Item { @Schema(description = "商品 SKU 编号", example = "2048") + @NotNull(message = "商品 SKU 编号不能为空") private Long skuId; + @Schema(description = "购买数量", example = "1") @Min(value = 1, message = "购买数量最小值为 {value}") private Integer count; 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 6312101d6..b254133cd 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 @@ -93,6 +93,7 @@ public interface TradeOrderConvert { new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(item.getCount())); return new ProductSkuUpdateStockReqDTO(items); } + default ProductSkuUpdateStockReqDTO convertNegative(List list) { List items = CollectionUtils.convertList(list, item -> new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(-item.getCount())); @@ -251,17 +252,6 @@ public interface TradeOrderConvert { AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address); - @Mappings({ - @Mapping(target = "activityId", source = "afterOrderCreateReqBO.combinationActivityId"), - @Mapping(target = "spuId", source = "afterOrderCreateReqBO.spuId"), - @Mapping(target = "skuId", source = "afterOrderCreateReqBO.skuId"), - @Mapping(target = "orderId", source = "afterOrderCreateReqBO.orderId"), - @Mapping(target = "userId", source = "afterOrderCreateReqBO.userId"), - @Mapping(target = "headId", source = "afterOrderCreateReqBO.combinationHeadId"), - @Mapping(target = "combinationPrice", source = "afterOrderCreateReqBO.payPrice"), - }) - CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO afterOrderCreateReqBO); - List convertList02(List list); TradeOrderDO convert(TradeOrderUpdateAddressReqVO reqVO); @@ -282,18 +272,36 @@ public interface TradeOrderConvert { return bo; } - TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO); + @Mappings({ + @Mapping(target = "userId", source = "userId"), + @Mapping(target = "orderType", source = "calculateRespBO.type"), + @Mapping(target = "items", source = "createReqVO.items"), + }) + TradeBeforeOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, TradePriceCalculateRespBO calculateRespBO); + + + List convertList(List orderItems); + @Mappings({ - @Mapping(target = "combinationActivityId", source = "createReqVO.combinationActivityId"), - @Mapping(target = "combinationHeadId", source = "createReqVO.combinationHeadId"), - @Mapping(target = "spuId", source = "orderItem.spuId"), - @Mapping(target = "skuId", source = "orderItem.skuId"), - @Mapping(target = "orderId", source = "tradeOrderDO.id"), @Mapping(target = "userId", source = "userId"), + @Mapping(target = "orderId", source = "tradeOrderDO.id"), @Mapping(target = "payPrice", source = "tradeOrderDO.payPrice"), + @Mapping(target = "items", source = "orderItems"), }) TradeAfterOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, - TradeOrderDO tradeOrderDO, TradeOrderItemDO orderItem); + TradeOrderDO tradeOrderDO, List orderItems); + + @Mappings({ + @Mapping(target = "activityId", source = "combinationActivityId"), + @Mapping(target = "spuId", expression = "java(reqBO.getItems().get(0).getSpuId())"), + @Mapping(target = "skuId", expression = "java(reqBO.getItems().get(0).getSkuId())"),// TODO 艿艿看看这里 + @Mapping(target = "count", expression = "java(reqBO.getItems().get(0).getCount())"), + @Mapping(target = "orderId", source = "orderId"), + @Mapping(target = "userId", source = "userId"), + @Mapping(target = "headId", source = "combinationHeadId"), + @Mapping(target = "combinationPrice", source = "payPrice") + }) + CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO reqBO); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java index 4240c6fde..480fe7ddd 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java @@ -26,12 +26,6 @@ public interface TradeOrderItemMapper extends BaseMapperX { return selectList(TradeOrderItemDO::getOrderId, orderIds); } - default List selectListByOrderIdAnSkuId(Collection orderIds, Collection skuIds) { - return selectList(new LambdaQueryWrapperX() - .in(TradeOrderItemDO::getOrderId, orderIds) - .in(TradeOrderItemDO::getSkuId, skuIds)); - } - default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) { return selectOne(new LambdaQueryWrapperX() .eq(TradeOrderItemDO::getId, orderItemId) 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 c64de4a58..6bd9b2b04 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 @@ -119,13 +119,5 @@ public interface TradeOrderQueryService { */ List getOrderItemListByOrderId(Collection orderIds); - /** - * 获取订单项商品购买数量总和 - * - * @param orderIds 订单编号 - * @param skuIds sku 编号 - * @return 订单项商品购买数量总和 - */ - Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds); } 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 910e8c911..f4ffee434 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 @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; @@ -168,10 +167,4 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { return tradeOrderItemMapper.selectListByOrderId(orderIds); } - @Override - public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds) { - List tradeOrderItems = tradeOrderItemMapper.selectListByOrderIdAnSkuId(orderIds, skuIds); - return CollectionUtils.getSumValue(tradeOrderItems, TradeOrderItemDO::getCount, Integer::sum); - } - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 4d2c9dbfb..ba8fa8fc9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -60,7 +60,6 @@ import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO; -import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler; import cn.iocoder.yudao.module.trade.service.price.TradePriceService; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; @@ -254,12 +253,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private void beforeCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, TradePriceCalculateRespBO calculateRespBO) { // 1. 执行订单创建前置处理器 - TradeBeforeOrderCreateReqBO beforeOrderCreateReqBO = TradeOrderConvert.INSTANCE.convert(createReqVO); - beforeOrderCreateReqBO.setOrderType(calculateRespBO.getType()); - beforeOrderCreateReqBO.setUserId(userId); - beforeOrderCreateReqBO.setCount(getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum)); // TODO @puhui999:这里有个纠结点;handler 的定义是只处理指定类型的订单的拓展逻辑;还是通用的 handler,类似可以处理优惠劵等等 - tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO)); + tradeOrderHandlers.forEach(handler -> + handler.beforeOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, calculateRespBO))); // 2. 下单时扣减商品库存 productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(createReqVO.getItems())); @@ -279,9 +275,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { TradeOrderDO order, List orderItems, TradePriceCalculateRespBO calculateRespBO) { // 1. 执行订单创建后置处理器 - // TODO @puhui999:从通用性来说,应该不用 orderItems.get(0) tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate( - TradeOrderConvert.INSTANCE.convert(userId, createReqVO, order, orderItems.get(0)))); + TradeOrderConvert.INSTANCE.convert(userId, createReqVO, order, orderItems))); // 2. 有使用优惠券时更新 // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号 @@ -467,14 +462,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); } } - // 订单类类型:砍价 - if (Objects.equals(TradeOrderTypeEnum.BARGAIN.getType(), order.getType())) { - // 校验订单砍价是否成功 - // TODO @puhui999:砍价的话,应该不用校验。因为是砍价成功后,才可以下单 - if (!bargainRecordApi.isBargainRecordSuccess(order.getUserId(), order.getId())) { - throw exception(ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS); - } - } + return order; } @@ -641,8 +629,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { } // 2. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 - tradeOrderHandlers.forEach(handler -> handler.rollback()); - // 3. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 tradeOrderHandlers.forEach(handler -> handler.cancelOrder()); // 3. 回滚库存 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java index 0a96745d9..0a5af9e0f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.module.trade.service.order.bo; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import javax.validation.Valid; import javax.validation.constraints.NotNull; +import java.util.List; // TODO 芋艿:在想想这些参数的定义 /** @@ -16,25 +17,71 @@ public class TradeAfterOrderCreateReqBO { // ========== 拼团活动相关字段 ========== - @Schema(description = "拼团活动编号", example = "1024") + /** + * 拼团活动编号 + */ private Long combinationActivityId; - @Schema(description = "拼团团长编号", example = "2048") + /** + * 拼团团长编号 + */ private Long combinationHeadId; - @NotNull(message = "SPU 编号不能为空") - private Long spuId; - - @NotNull(message = "SKU 编号活动商品不能为空") - private Long skuId; - + /** + * 订单编号 + */ @NotNull(message = "订单编号不能为空") private Long orderId; + /** + * 用户编号 + */ @NotNull(message = "用户编号不能为空") private Long userId; + /** + * 支付金额 + */ @NotNull(message = "支付金额不能为空") private Integer payPrice; + // ========== 购买商品相关字段 ========== + + /** + * 订单购买的商品信息 + */ + private List items; + + /** + * 订单商品信息 + * 记录购买商品的简要核心信息 + * + * @author HUIHUI + */ + @Data + @Valid + public static class Item { + + /** + * SPU 编号 + */ + @NotNull(message = "SPU 编号不能为空") + private Long spuId; + + /** + * 商品 SKU 编号 + * + * 关联 ProductSkuDO 的 id 编号 + */ + @NotNull(message = "SKU 编号活动商品不能为空") + private Long skuId; + + /** + * 购买的商品数量 + */ + @NotNull(message = "购买数量不能为空") + private Integer count; + + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java index 261683d3d..6add49d50 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.module.trade.service.order.bo; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import javax.validation.Valid; import javax.validation.constraints.NotNull; - +import java.util.List; // TODO 芋艿:在想想这些参数的定义 + /** * 订单创建之前 Request BO * @@ -34,9 +35,8 @@ public class TradeBeforeOrderCreateReqBO { // ========== 秒杀活动相关字段 ========== /** - * + * 秒杀活动编号 */ - @Schema(description = "秒杀活动编号", example = "1024") private Long seckillActivityId; // ========== 拼团活动相关字段 ========== @@ -44,13 +44,11 @@ public class TradeBeforeOrderCreateReqBO { /** * 拼团活动编号 */ - @Schema(description = "拼团活动编号", example = "1024") private Long combinationActivityId; /** * 拼团团长编号 */ - @Schema(description = "拼团团长编号", example = "2048") private Long combinationHeadId; // ========== 砍价活动相关字段 ========== @@ -58,31 +56,39 @@ public class TradeBeforeOrderCreateReqBO { /** * 砍价活动编号 */ - @Schema(description = "砍价活动编号", example = "123") private Long bargainActivityId; - // ========== 活动购买商品相关字段 ========== + // ========== 购买商品相关字段 ========== /** - * 商品 SPU 编号 + * 订单购买的商品信息 + */ + private List items; + + /** + * 订单商品信息 + * 记录购买商品的简要核心信息 * - * 关联 ProductSkuDO 的 spuId 编号 + * @author HUIHUI */ - @NotNull(message = "SPU 编号不能为空") - private Long spuId; + @Data + @Valid + public static class Item { - /** - * 商品 SKU 编号 - * - * 关联 ProductSkuDO 的 id 编号 - */ - @NotNull(message = "SKU 编号活动商品不能为空") - private Long skuId; + /** + * 商品 SKU 编号 + * + * 关联 ProductSkuDO 的 id 编号 + */ + @NotNull(message = "SKU 编号活动商品不能为空") + private Long skuId; - /** - * 购买的商品数量 - */ - @NotNull(message = "购买数量不能为空") - private Integer count; + /** + * 购买的商品数量 + */ + @NotNull(message = "购买数量不能为空") + private Integer count; + + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java index aafd826b9..4f5dc15e6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java @@ -29,8 +29,11 @@ public class TradeBargainHandler extends TradeOrderDefaultHandler { if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) { return; } + + // 获取商品信息 + TradeBeforeOrderCreateReqBO.Item item = reqBO.getItems().get(0); // 扣减砍价活动的库存 - bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount()); + bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), item.getCount()); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java index 91c99d2e8..3887f97a9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java @@ -29,8 +29,10 @@ public class TradeCombinationHandler extends TradeOrderDefaultHandler { return; } + // 获取商品信息 + TradeBeforeOrderCreateReqBO.Item item = reqBO.getItems().get(0); // 校验是否满足拼团活动相关限制 - combinationRecordApi.validateCombinationRecord(reqBO.getCombinationActivityId(), reqBO.getUserId(), reqBO.getSkuId(), reqBO.getCount()); + combinationRecordApi.validateCombinationRecord(reqBO.getCombinationActivityId(), reqBO.getUserId(), item.getSkuId(), item.getCount()); } @Override diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java index cef790cf8..c7d89037b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java @@ -29,8 +29,11 @@ public class TradeSeckillHandler extends TradeOrderDefaultHandler { if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) { return; } + + // 获取商品信息 + TradeBeforeOrderCreateReqBO.Item item = reqBO.getItems().get(0); // 扣减秒杀活动的库存 - seckillActivityApi.updateSeckillStock(reqBO.getSeckillActivityId(), reqBO.getSkuId(), reqBO.getCount()); + seckillActivityApi.updateSeckillStock(reqBO.getSeckillActivityId(), item.getSkuId(), item.getCount()); } }