diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java new file mode 100644 index 000000000..ec8d5c714 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.promotion.api.combination; + +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; + +/** + * 拼团活动 Api 接口 + * + * @author HUIHUI + */ +public interface CombinationApi { + + /** + * 更新活动库存 + * + * @param reqDTO 请求 + */ + void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO); + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java new file mode 100644 index 000000000..a1d0ebce7 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.promotion.api.combination.dto; + +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +/** + * 拼团活动更新活动库存 Request DTO + * + * @author HUIHUI + */ +@Data +public class CombinationActivityUpdateStockReqDTO { + + @NotNull(message = "活动编号不能为空") + private Long activityId; + + @NotNull(message = "购买数量不能为空") + private Integer count; + + @NotNull(message = "活动商品不能为空") + private Item item; + + @Data + @Valid + public static class Item { + + @NotNull(message = "SPU 编号不能为空") + private Long spuId; + + @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/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 4d4c0dafd..288a83d4c 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 @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.combination.dto; import lombok.Data; -import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; // TODO @芋艿:这块要在看看 @@ -14,65 +13,25 @@ import javax.validation.constraints.NotNull; @Data public class CombinationRecordCreateReqDTO { - /** - * 拼团活动编号 - */ @NotNull(message = "拼团活动编号不能为空") private Long activityId; - /** - * spu 编号 - */ + @NotNull(message = "spu 编号不能为空") private Long spuId; - /** - * sku 编号 - */ + @NotNull(message = "sku 编号不能为空") private Long skuId; - /** - * 用户编号 - */ - @NotNull(message = "用户编号不能为空") - private Long userId; - /** - * 订单编号 - */ + @NotNull(message = "订单编号不能为空") private Long orderId; - /** - * 团长编号 - */ + + @NotNull(message = "用户编号不能为空") + private Long userId; + @NotNull(message = "团长编号不能为空") private Long headId; - /** - * 商品名字 - */ - @NotEmpty(message = "商品名字不能为空") - private String spuName; - /** - * 商品图片 - */ - @NotEmpty(message = "商品图片不能为空") - private String picUrl; - /** - * 拼团商品单价 - */ + @NotNull(message = "拼团商品单价不能为空") private Integer combinationPrice; - /** - * 用户昵称 - */ - @NotEmpty(message = "用户昵称不能为空") - private String nickname; - /** - * 用户头像 - */ - @NotEmpty(message = "用户头像不能为空") - private String avatar; - /** - * 开团状态:正在开团 拼团成功 拼团失败 - */ - @NotNull(message = "开团状态不能为空") - private Integer status; } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java index 07a25b3d6..f3cf1d2b2 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill.dto; import lombok.Data; +import javax.validation.Valid; import javax.validation.constraints.NotNull; /** @@ -22,6 +23,7 @@ public class SeckillActivityUpdateStockReqDTO { private Item item; @Data + @Valid public static class Item { @NotNull(message = "SPU 编号不能为空") 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 baca6c273..4fc58004a 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 @@ -65,18 +65,19 @@ public interface ErrorCodeConstants { // ========== 拼团活动 1013010000 ========== ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在"); ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动"); - ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010002, "拼团活动已关闭不能修改"); + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改"); ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除"); - ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在"); + ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭"); // ========== 拼团记录 1013011000 ========== - ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011000, "拼团失败,已参与过该拼团"); - ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011001, "拼团失败,父拼团不存在"); - ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011002, "拼团失败,拼团人数已满"); - ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011003, "拼团失败,已参与其它拼团"); - ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011004, "拼团失败,活动已经结束"); - ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011005, "拼团失败,单次限购超出"); - ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,单次限购超出"); + 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_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, "拼团失败,原因:超出总购买次数"); // ========== 砍价活动 1013012000 ========== ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/pom.xml b/yudao-module-mall/yudao-module-promotion-biz/pom.xml index 266cb1511..bad2c8a35 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/pom.xml +++ b/yudao-module-mall/yudao-module-promotion-biz/pom.xml @@ -29,6 +29,11 @@ yudao-module-product-api ${revision} + + cn.iocoder.boot + yudao-module-trade-api + ${revision} + cn.iocoder.boot yudao-module-member-api diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java new file mode 100644 index 000000000..767b2e680 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.promotion.api.combination; + +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; +import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; + +import javax.annotation.Resource; + +/** + * 拼团活动 Api 接口实现类 + * + * @author HUIHUI + */ +public class CombinationApiImpl implements CombinationApi { + + @Resource + private CombinationActivityService activityService; + + @Override + public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) { + activityService.validateCombination(reqDTO); + } + +} 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 99b87df6c..c3ee01fcc 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 @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.service.combination; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; @@ -72,4 +73,11 @@ public interface CombinationActivityService { */ List getCombinationProductsByActivityIds(Collection activityIds); + /** + * 更新拼图活动库存 + * + * @param reqDTO 请求 + */ + void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO); + } 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 c6a7c8c49..026c1a0ff 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 @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; @@ -16,8 +17,11 @@ 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.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -28,8 +32,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.convertMap; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 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.*; @@ -48,11 +52,15 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic private CombinationActivityMapper combinationActivityMapper; @Resource private CombinationProductMapper combinationProductMapper; + @Resource + private CombinationRecordService combinationRecordService; @Resource private ProductSpuApi productSpuApi; @Resource private ProductSkuApi productSkuApi; + @Resource + private TradeOrderApi tradeOrderApi; @Override @Transactional(rollbackFor = Exception.class) @@ -97,7 +105,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic * 校验拼团商品是否都存在 * * @param spuId 商品 SPU 编号 - * @param products 秒杀商品 + * @param products 拼团商品 */ private void validateProductExists(Long spuId, List products) { // 1. 校验商品 spu 是否存在 @@ -123,7 +131,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId()); // 校验状态 if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { - throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE); } // 校验商品冲突 validateProductConflict(updateReqVO.getSpuId(), updateReqVO.getId()); @@ -205,4 +213,30 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic return combinationProductMapper.selectListByActivityIds(activityIds); } + @Override + public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) { + // 1、校验拼团活动是否存在 + CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId()); + // 1.1、校验活动是否开启 + if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); + } + // 1.2、校验是否超出单次限购数量 + if (activity.getSingleLimitCount() < reqDTO.getCount()) { + throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); + } + // 1.3、校验是否超出总限购数量 + List recordList = combinationRecordService.getRecordListByUserIdAndActivityId(getLoginUserId(), reqDTO.getActivityId()); + if (CollUtil.isNotEmpty(recordList)) { + // 过滤出拼团成功的 + 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); + } + } + } + } 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 bc9c1df4c..63df4ad0d 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,12 +2,19 @@ package cn.iocoder.yudao.module.promotion.service.combination; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -32,10 +39,18 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @Resource private CombinationActivityService combinationActivityService; - @Resource private CombinationRecordMapper recordMapper; + @Resource + private MemberUserApi memberUserApi; + @Resource + @Lazy + private ProductSpuApi productSpuApi; + @Resource + @Lazy + private ProductSkuApi productSkuApi; + @Override @Transactional(rollbackFor = Exception.class) public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) { @@ -102,12 +117,12 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { // 1.5 父拼团是否存在,是否已经满了 if (reqDTO.getHeadId() != null) { // 查询进行中的父拼团 - CombinationRecordDO recordDO1 = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); - if (recordDO1 == null) { + CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); + if (record == null) { throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS); } // 校验拼团是否满足要求 - if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) { + if (ObjectUtil.equal(record.getUserCount(), record.getUserSize())) { throw exception(COMBINATION_RECORD_USER_FULL); } } @@ -117,6 +132,13 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { record.setVirtualGroup(false); record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration())); record.setUserSize(activity.getUserSize()); + MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); + record.setNickname(user.getNickname()); + record.setAvatar(user.getAvatar()); + ProductSpuRespDTO spu = productSpuApi.getSpu(record.getSpuId()); + record.setSpuName(spu.getName()); + ProductSkuRespDTO sku = productSkuApi.getSku(record.getSkuId()); + record.setPicUrl(sku.getPicUrl()); recordMapper.insert(record); } 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 5f98073d1..8f33fff28 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,5 +1,7 @@ package cn.iocoder.yudao.module.trade.api.order; +import java.util.Collection; + /** * 订单 API 接口 * @@ -16,4 +18,13 @@ public interface TradeOrderApi { */ Long validateOrder(Long userId, Long orderItemId); + /** + * 获取订单项商品购买数量总和 + * + * @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/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 7895386cf..3ee315ccb 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 @@ -6,6 +6,7 @@ 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; @@ -32,4 +33,9 @@ public class TradeOrderApiImpl implements TradeOrderApi { return item.getOrderId(); } + @Override + public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds) { + return tradeOrderQueryService.getOrderItemCountSumByOrderIdAndSkuId(orderIds, skuIds); + } + } 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 feaa1bab0..72fe9ff59 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 @@ -14,7 +14,9 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; @@ -31,6 +33,8 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import org.mapstruct.Mapper; @@ -253,21 +257,15 @@ public interface TradeOrderConvert { AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address); @Mappings({ - @Mapping(target = "activityId", source = "createReqVO.combinationActivityId"), - @Mapping(target = "spuId", source = "orderItem.spuId"), - @Mapping(target = "skuId", source = "orderItem.skuId"), - @Mapping(target = "userId", source = "order.userId"), - @Mapping(target = "orderId", source = "order.id"), - @Mapping(target = "headId", source = "createReqVO.combinationHeadId"), - @Mapping(target = "spuName", source = "orderItem.spuName"), - @Mapping(target = "picUrl", source = "orderItem.picUrl"), - @Mapping(target = "combinationPrice", source = "orderItem.payPrice"), - @Mapping(target = "nickname", source = "user.nickname"), - @Mapping(target = "avatar", source = "user.avatar"), - @Mapping(target = "status", ignore = true) + @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(TradeOrderDO order, TradeOrderItemDO orderItem, - AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user); + CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO afterOrderCreateReqBO); List convertList02(List list); @@ -283,4 +281,24 @@ public interface TradeOrderConvert { .setFirstFixedPrice(sku.getFirstBrokerageRecord()) .setSecondFixedPrice(sku.getSecondBrokerageRecord()); } + + @Mapping(target = "activityId", source = "reqBO.seckillActivityId") + SeckillActivityUpdateStockReqDTO convert(TradeBeforeOrderCreateReqBO reqBO); + + @Mapping(target = "activityId", source = "reqBO.combinationActivityId") + CombinationActivityUpdateStockReqDTO convert1(TradeBeforeOrderCreateReqBO reqBO); + + TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO); + + @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 = "payPrice", source = "tradeOrderDO.payPrice"), + }) + TradeAfterOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, TradeOrderDO tradeOrderDO, TradeOrderItemDO orderItem); + } 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 a9538cc91..e7121077b 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 @@ -29,7 +29,7 @@ public interface TradeOrderItemMapper extends BaseMapperX { default List selectListByOrderIdAnSkuId(Collection orderIds, Collection skuIds) { return selectList(new LambdaQueryWrapperX() .in(TradeOrderItemDO::getOrderId, orderIds) - .eq(TradeOrderItemDO::getSkuId, skuIds)); + .in(TradeOrderItemDO::getSkuId, skuIds)); } default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) { 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 0cd5240bd..c64de4a58 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,4 +119,13 @@ 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 657c6f0f8..733ec9780 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,6 +4,7 @@ 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; @@ -167,4 +168,10 @@ 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 3ea5a76c1..a90c505e3 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 @@ -13,8 +13,6 @@ import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.point.MemberPointApi; -import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; @@ -24,15 +22,10 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; -import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; -import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; -import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; @@ -59,6 +52,8 @@ 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.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; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; @@ -95,6 +90,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private TradeOrderItemMapper tradeOrderItemMapper; @Resource private TradeOrderNoRedisDAO orderNoRedisDAO; + @Resource + private List orderHandlers; @Resource private CartService cartService; @@ -118,12 +115,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private BargainRecordApi bargainRecordApi; @Resource - private SeckillActivityApi seckillActivityApi; - @Resource - private BargainActivityApi bargainActivityApi; - @Resource - private MemberUserApi memberUserApi; - @Resource private MemberLevelApi memberLevelApi; @Resource private MemberPointApi memberPointApi; @@ -188,7 +179,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Override @Transactional(rollbackFor = Exception.class) public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { - // 1. 价格计算 + // 1、执行订单创建前置处理器 + TradeBeforeOrderCreateReqBO beforeOrderCreateReqBO = TradeOrderConvert.INSTANCE.convert(createReqVO); + beforeOrderCreateReqBO.setOrderType(validateActivity(createReqVO)); + beforeOrderCreateReqBO.setCount(CollectionUtils.getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum)); + orderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO)); + + // 2. 价格计算 TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO); // 2.1 插入 TradeOrderDO 订单 @@ -198,37 +195,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 3. 订单创建完后的逻辑 afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO); - // 3.1 拼团的特殊逻辑 - // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去 - // 拼团 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - createCombinationRecord(userId, createReqVO, orderItems, order); - } - // 3.2 秒杀的特殊逻辑 - if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) { - - } - // 3.3 砍价的特殊逻辑 // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! return order; } - private void createCombinationRecord(Long userId, AppTradeOrderCreateReqVO createReqVO, List orderItems, TradeOrderDO order) { - MemberUserRespDTO user = memberUserApi.getUser(userId); - List recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId()); - // TODO 拼团一次应该只能选择一种规格的商品 - TradeOrderItemDO orderItemDO = orderItems.get(0); - if (CollUtil.isNotEmpty(recordRespDTOS)) { - List skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); - List tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS, - CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); - combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(), - CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount()); - } - - combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); - } // TODO @puhui999:订单超时,自动取消; @@ -310,13 +281,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, TradeOrderDO tradeOrderDO, List orderItems, TradePriceCalculateRespBO calculateRespBO) { - Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum); - // 1)如果是秒杀商品:额外扣减秒杀的库存; - if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) { - seckillActivityApi.updateSeckillStock(getSeckillActivityUpdateStockReqDTO(createReqVO, orderItems, count)); - } - // 2)如果是砍价活动:额外扣减砍价的库存; - bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count); + // 执行订单创建后置处理器 + orderHandlers.forEach(handler -> handler.afterOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, tradeOrderDO, orderItems.get(0)))); // 扣减积分 TODO 芋艿:待实现,需要前置; // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣 @@ -341,19 +307,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 增加订单日志 TODO 芋艿:待实现 } - private SeckillActivityUpdateStockReqDTO getSeckillActivityUpdateStockReqDTO(AppTradeOrderCreateReqVO createReqVO, List orderItems, Integer count) { - SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO(); - updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId()); - updateStockReqDTO.setCount(count); - // 秒杀活动只能选择一个商品 - TradeOrderItemDO item = orderItems.get(0); - SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item(); - item1.setSpuId(item.getSpuId()); - item1.setSkuId(item.getSkuId()); - item1.setCount(item.getCount()); - updateStockReqDTO.setItem(item1); - return updateStockReqDTO; - } private void createPayOrder(TradeOrderDO order, List orderItems, TradePriceCalculateRespBO calculateRespBO) { // 创建支付单,用于后续的支付 @@ -768,6 +721,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); } + // TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来 + orderHandlers.forEach(handler -> handler.rollbackStock()); + // 2.回滚库存 List orderItems = tradeOrderItemMapper.selectListByOrderId(id); productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); 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 new file mode 100644 index 000000000..8a33e3eaf --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.trade.service.order.bo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 订单创建之后 Request BO + * + * @author HUIHUI + */ +@Data +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; + +} 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 new file mode 100644 index 000000000..e1b7faa35 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java @@ -0,0 +1,57 @@ +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; + +/** + * 订单创建之前 Request BO + * + * @author HUIHUI + */ +@Data +public class TradeBeforeOrderCreateReqBO { + + @NotNull(message = "订单类型不能为空") + private Integer orderType; + + // ========== 秒杀活动相关字段 ========== + + @Schema(description = "秒杀活动编号", example = "1024") + private Long seckillActivityId; + + // ========== 拼团活动相关字段 ========== + + @Schema(description = "拼团活动编号", example = "1024") + private Long combinationActivityId; + + @Schema(description = "拼团团长编号", example = "2048") + private Long combinationHeadId; + + @Schema(description = "砍价活动编号", example = "123") + private Long bargainActivityId; + + @NotNull(message = "购买数量不能为空") + private Integer count; + + @NotNull(message = "活动商品不能为空") + private Item item; + + @Data + @Valid + public static class Item { + + @NotNull(message = "SPU 编号不能为空") + private Long spuId; + + @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/handler/TradeBargainHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java new file mode 100644 index 000000000..fc410963a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java @@ -0,0 +1,44 @@ +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; + +import javax.annotation.Resource; + +/** + * 砍价订单 handler 实现类 + * + * @author HUIHUI + */ +@Component +public class TradeBargainHandler implements TradeOrderHandler { + + @Resource + private BargainActivityApi bargainActivityApi; + + @Override + public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { + // 如果是秒杀订单 + if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) { + return; + } + + // 额外扣减砍价的库存 + bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount()); + } + + @Override + public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { + + } + + @Override + public void rollbackStock() { + + } + +} 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 new file mode 100644 index 000000000..f9fce744b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.promotion.api.combination.CombinationApi; +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.TradeBeforeOrderCreateReqBO; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 拼团订单 handler 接口实现类 + * + * @author HUIHUI + */ +@Component +public class TradeCombinationHandler implements TradeOrderHandler { + + @Resource + private CombinationApi combinationApi; + @Resource + private CombinationRecordApi combinationRecordApi; + + @Override + public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { + // 如果是拼团订单; + if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) { + return; + } + + // 校验是否满足拼团活动相关限制 + combinationApi.validateCombination(TradeOrderConvert.INSTANCE.convert1(reqBO)); + } + + @Override + public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { + // 创建砍价记录 + combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(reqBO)); + } + + @Override + public void rollbackStock() { + + } + +} 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 new file mode 100644 index 000000000..37dda82ce --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java @@ -0,0 +1,32 @@ +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.TradeBeforeOrderCreateReqBO; + +/** + * 订单活动特殊逻辑处理器 handler 接口 + * + * @author HUIHUI + */ +public interface TradeOrderHandler { + + /** + * 订单创建前 + * + * @param reqBO 请求 + */ + void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO); + + /** + * 订单创建后 + * + * @param reqBO 请求 + */ + void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO); + + /** + * 回滚活动相关库存 + */ + void rollbackStock(); + +} 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 new file mode 100644 index 000000000..0774543a5 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java @@ -0,0 +1,44 @@ +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.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.TradeBeforeOrderCreateReqBO; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 秒杀订单 handler 实现类 + * + * @author HUIHUI + */ +@Component +public class TradeSeckillHandler implements TradeOrderHandler { + + @Resource + private SeckillActivityApi seckillActivityApi; + + @Override + public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { + // 如果是秒杀订单:额外扣减秒杀的库存; + if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) { + return; + } + + seckillActivityApi.updateSeckillStock(TradeOrderConvert.INSTANCE.convert(reqBO)); + } + + @Override + public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { + + } + + @Override + public void rollbackStock() { + + } + +}