diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java index 8e1692415..8fb140179 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java @@ -41,7 +41,7 @@ public interface SeckillProductMapper extends BaseMapperX { Assert.isTrue(count > 0); return update(null, new LambdaUpdateWrapper() .eq(SeckillProductDO::getId, id) - .gt(SeckillProductDO::getStock, count) + .ge(SeckillProductDO::getStock, count) .setSql("stock = stock - " + count)); } 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 ec57b1af9..352d0083c 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 @@ -14,23 +14,12 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 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; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; 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.product.api.spu.ProductSpuApi; -import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; -import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; 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; @@ -40,7 +29,6 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; @@ -48,15 +36,11 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO; -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog; import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils; -import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; -import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; -import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; 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; @@ -68,13 +52,15 @@ import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @@ -109,30 +95,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private DeliveryExpressService deliveryExpressService; @Resource private TradeMessageService tradeMessageService; - @Resource - private BrokerageUserService brokerageUserService; - @Resource - private BrokerageRecordService brokerageRecordService; - @Resource - private ProductSpuApi productSpuApi; - @Resource - private ProductSkuApi productSkuApi; @Resource private PayOrderApi payOrderApi; @Resource private AddressApi addressApi; @Resource - private CouponApi couponApi; - @Resource - private CombinationRecordApi combinationRecordApi; - @Resource - private MemberUserApi memberUserApi; - @Resource - private MemberLevelApi memberLevelApi; - @Resource - private MemberPointApi memberPointApi; - @Resource private ProductCommentApi productCommentApi; @Resource @@ -199,7 +167,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { List orderItems = buildTradeOrderItems(order, calculateRespBO); // 2. 订单创建前的逻辑 - beforeCreateTradeOrder(order, orderItems); + tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems)); // 3. 保存订单 tradeOrderMapper.insert(order); @@ -234,11 +202,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { order.setReceiverName(createReqVO.getReceiverName()).setReceiverMobile(createReqVO.getReceiverMobile()); order.setPickUpVerifyCode(RandomUtil.randomNumbers(8)); // 随机一个核销码,长度为 8 位 } - // 设置订单推广人 - BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(order.getUserId()); - if (brokerageUser != null && brokerageUser.getBindUserId() != null) { - order.setBrokerageUserId(brokerageUser.getBindUserId()); - } return order; } @@ -247,21 +210,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { return TradeOrderConvert.INSTANCE.convertList(tradeOrderDO, calculateRespBO); } - /** - * 订单创建前,执行前置逻辑 - * - * @param order 订单 - * @param orderItems 订单项 - */ - private void beforeCreateTradeOrder(TradeOrderDO order, List orderItems) { - // 1. 执行订单创建前置处理器 - // TODO @puhui999:这里有个纠结点;handler 的定义是只处理指定类型的订单的拓展逻辑;还是通用的 handler,类似可以处理优惠劵等等 - tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems)); - - // 2. 下单时扣减商品库存 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); - } - /** * 订单创建后,执行后置逻辑 *

@@ -276,27 +224,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 1. 执行订单创建后置处理器 tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(order, orderItems)); - // 2. 有使用优惠券时更新 - // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号 - if (order.getCouponId() != null) { - couponApi.useCoupon(new CouponUseReqDTO().setId(order.getCouponId()).setUserId(order.getUserId()) - .setOrderId(order.getId())); - } - - // 3. 扣减积分(抵扣) - // 不在前置扣减的原因,是因为积分扣减时,需要记录关联业务 - reduceUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE, order.getId()); - - // 4. 删除购物车商品 + // 2. 删除购物车商品 Set cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); if (CollUtil.isNotEmpty(cartIds)) { cartService.deleteCart(order.getUserId(), cartIds); } - // 5. 生成预支付 + // 3. 生成预支付 createPayOrder(order, orderItems); - // 6. 插入订单日志 + // 4. 插入订单日志 TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus()); // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! @@ -330,18 +267,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); } - // 3、订单支付成功后 + // 3. 执行 TradeOrderHandler 的后置处理 List orderItems = tradeOrderItemMapper.selectListByOrderId(id); tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems)); - // 4.1 增加用户积分(赠送) - addUserPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, order.getId()); - // 4.2 增加用户经验 - getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId()); - // 4.3 增加用户佣金 - getSelf().addBrokerageAsync(order.getUserId(), order.getId()); - - // 5. 记录订单日志 + // 4. 记录订单日志 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue()); } @@ -434,8 +364,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { .put("logisticsNo", express != null ? deliveryReqVO.getLogisticsNo() : "").build()); // 4. 发送站内信 - tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO().setOrderId(order.getId()) - .setUserId(order.getUserId()).setMessage(null)); + tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO() + .setOrderId(order.getId()).setUserId(order.getUserId()).setMessage(null)); } /** @@ -448,18 +378,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { */ private TradeOrderDO validateOrderDeliverable(Long id) { TradeOrderDO order = validateOrderExists(id); - // 校验订单是否退款 + // 1. 校验订单是否未发货 if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); } - // 订单类型:拼团 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - // 校验订单拼团是否成功 - if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { - throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); - } - } + // 2. 执行 TradeOrderHandler 前置处理 + tradeOrderHandlers.forEach(handler -> handler.beforeDeliveryOrder(order)); return order; } @@ -616,30 +541,19 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { * @param cancelType 取消类型 */ private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { - Long id = order.getId(); // 1. 更新 TradeOrderDO 状态为已取消 - int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now())); if (updateCount == 0) { throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); } - List orderItems = tradeOrderItemMapper.selectListByOrderId(id); - // 3. 回滚库存 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); - // 3.1、 活动相关的回滚 - tradeOrderHandlers.forEach(handler -> handler.cancelOrder(order, orderItems)); + // 2. 执行 TradeOrderHandler 的后置处理 + List orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems)); - // 4. 回滚优惠券 - if (order.getCouponId() != null && order.getCouponId() > 0) { - couponApi.returnUsedCoupon(order.getCouponId()); - } - - // 5. 回滚积分(抵扣的) - addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); - - // 6. 增加订单日志 + // 3. 增加订单日志 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); } @@ -660,8 +574,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { .setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); - // 2. 退还优惠券 - couponApi.returnUsedCoupon(order.getCouponId()); + // 2. 执行 TradeOrderHandler 的后置处理 + List orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems)); } @Override @@ -789,13 +704,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Override @Transactional(rollbackFor = Exception.class) public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) { - // 1. 更新订单项 + // 1.1 更新订单项 updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null); - - // 2.1 更新订单的退款金额、积分 + // 1.2 执行 TradeOrderHandler 的后置处理 TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id); TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId()); + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrderItem(order, orderItem)); + + // 2.1 更新订单的退款金额、积分 Integer orderRefundPrice = order.getRefundPrice() + refundPrice; Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint(); Integer refundStatus = isAllOrderItemAfterSaleSuccess(order.getId()) ? @@ -806,23 +723,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint)); // 2.2 如果全部退款,则进行取消订单 getSelf().cancelOrderByAfterSale(order, orderRefundPrice); - - - // 3. 回滚库存 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(Collections.singletonList(orderItem))); - // 3.1、 活动相关的回滚 - tradeOrderHandlers.forEach(handler -> handler.cancelOrder(order, Collections.singletonList(orderItem))); - - // 4.1 回滚积分:扣减用户积分(赠送的) - reduceUserPoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.AFTER_SALE_DEDUCT_GIVE, orderItem.getAfterSaleId()); - // 4.2 回滚积分:增加用户积分(返还抵扣) - addUserPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.AFTER_SALE_REFUND_USED, orderItem.getAfterSaleId()); - - // 5. 回滚经验:扣减用户经验 - getSelf().reduceUserExperienceAsync(order.getUserId(), refundPrice, orderItem.getAfterSaleId()); - - // 6. 回滚佣金:更新分佣记录为已失效 - getSelf().cancelBrokerageAsync(order.getUserId(), id); } @Override @@ -839,6 +739,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (updateCount <= 0) { throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); } + } /** @@ -939,7 +840,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_COMMENT) public void createOrderItemCommentBySystemBySystem(TradeOrderDO order) { // 1. 查询未评论的订单项 - List orderItems = tradeOrderItemMapper.selectListByOrderIdAndCommentStatus(order.getId(), Boolean.FALSE); + List orderItems = tradeOrderItemMapper.selectListByOrderIdAndCommentStatus( + order.getId(), Boolean.FALSE); if (CollUtil.isEmpty(orderItems)) { return; } @@ -982,73 +884,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // =================== 营销相关的操作 =================== - @Async - protected void addUserExperienceAsync(Long userId, Integer payPrice, Long orderId) { - int bizType = MemberExperienceBizTypeEnum.ORDER.getType(); - memberLevelApi.addExperience(userId, payPrice, bizType, String.valueOf(orderId)); - } - - @Async - protected void reduceUserExperienceAsync(Long userId, Integer refundPrice, Long afterSaleId) { - int bizType = MemberExperienceBizTypeEnum.REFUND.getType(); - memberLevelApi.addExperience(userId, -refundPrice, bizType, String.valueOf(afterSaleId)); - } - - /** - * 添加用户积分 - *

- * 目前是支付成功后,就会创建积分记录。 - *

- * 业内还有两种做法,可以根据自己的业务调整: - * 1. 确认收货后,才创建积分记录 - * 2. 支付 or 下单成功时,创建积分记录(冻结),确认收货解冻或者 n 天后解冻 - * - * @param userId 用户编号 - * @param point 增加积分数量 - * @param bizType 业务编号 - * @param bizId 业务编号 - */ - protected void addUserPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { - if (point != null && point > 0) { - memberPointApi.addPoint(userId, point, bizType.getType(), String.valueOf(bizId)); - } - } - - protected void reduceUserPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { - if (point != null && point > 0) { - memberPointApi.reducePoint(userId, point, bizType.getType(), String.valueOf(bizId)); - } - } - - /** - * 创建分销记录 - *

- * 目前是支付成功后,就会创建分销记录。 - *

- * 业内还有两种做法,可以根据自己的业务调整: - * 1. 确认收货后,才创建分销记录 - * 2. 支付 or 下单成功时,创建分销记录(冻结),确认收货解冻或者 n 天后解冻 - * - * @param userId 用户编号 - * @param orderId 订单编号 - */ - @Async - protected void addBrokerageAsync(Long userId, Long orderId) { - MemberUserRespDTO user = memberUserApi.getUser(userId); - Assert.notNull(user); - // 每一个订单项,都会去生成分销记录 - List orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); - List addList = convertList(orderItems, - item -> TradeOrderConvert.INSTANCE.convert(user, item, - productSpuApi.getSpu(item.getSpuId()), productSkuApi.getSku(item.getSkuId()))); - brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList); - } - - @Async - protected void cancelBrokerageAsync(Long userId, Long orderItemId) { - brokerageRecordService.cancelBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, String.valueOf(orderItemId)); - } - /** * 获得自身的代理对象,解决 AOP 生效问题 * 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/TradeBargainOrderHandler.java similarity index 63% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainOrderHandler.java index e856621dc..9af7be670 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/TradeBargainOrderHandler.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; @@ -12,12 +13,12 @@ import javax.annotation.Resource; import java.util.List; /** - * 砍价订单 handler 实现类 + * 砍价订单的 {@link TradeOrderHandler} 实现类 * * @author HUIHUI */ @Component -public class TradeBargainHandler implements TradeOrderHandler { +public class TradeBargainOrderHandler implements TradeOrderHandler { @Resource private BargainActivityApi bargainActivityApi; @@ -26,7 +27,7 @@ public class TradeBargainHandler implements TradeOrderHandler { @Override public void beforeOrderCreate(TradeOrderDO order, List orderItems) { - if (TradeOrderTypeEnum.isBargain(order.getType())) { + if (!TradeOrderTypeEnum.isBargain(order.getType())) { return; } // 明确校验一下 @@ -39,7 +40,7 @@ public class TradeBargainHandler implements TradeOrderHandler { @Override public void afterOrderCreate(TradeOrderDO order, List orderItems) { - if (TradeOrderTypeEnum.isBargain(order.getType())) { + if (!TradeOrderTypeEnum.isBargain(order.getType())) { return; } // 明确校验一下 @@ -50,16 +51,28 @@ public class TradeBargainHandler implements TradeOrderHandler { } @Override - public void cancelOrder(TradeOrderDO order, List orderItems) { - if (TradeOrderTypeEnum.isBargain(order.getType())) { + public void afterCancelOrder(TradeOrderDO order, List orderItems) { + if (!TradeOrderTypeEnum.isBargain(order.getType())) { return; } // 明确校验一下 Assert.isTrue(orderItems.size() == 1, "砍价时,只允许选择一个商品"); - // 恢复砍价活动的库存 - bargainActivityApi.updateBargainActivityStock(order.getBargainActivityId(), - orderItems.get(0).getCount()); + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 + orderItems = filterOrderItemListByNoneAfterSale(orderItems); + if (CollUtil.isEmpty(orderItems)) { + return; + } + afterCancelOrderItem(order, orderItems.get(0)); + } + + @Override + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { + if (!TradeOrderTypeEnum.isBargain(order.getType())) { + return; + } + // 恢复(增加)砍价活动的库存 + bargainActivityApi.updateBargainActivityStock(order.getBargainActivityId(), orderItem.getCount()); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java new file mode 100644 index 000000000..6dd37111a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +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.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +/** + * 订单分销的 {@link TradeOrderHandler} 实现类 + * + * @author 芋道源码 + */ +@Component +public class TradeBrokerageOrderHandler implements TradeOrderHandler { + + @Resource + private MemberUserApi memberUserApi; + @Resource + private ProductSpuApi productSpuApi; + @Resource + private ProductSkuApi productSkuApi; + + @Resource + private BrokerageRecordService brokerageRecordService; + @Resource + private BrokerageUserService brokerageUserService; + + @Override + public void beforeOrderCreate(TradeOrderDO order, List orderItems) { + // 设置订单推广人 + BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(order.getUserId()); + if (brokerageUser != null && brokerageUser.getBindUserId() != null) { + order.setBrokerageUserId(brokerageUser.getBindUserId()); + } + } + + @Override + public void afterPayOrder(TradeOrderDO order, List orderItems) { + if (order.getBrokerageUserId() == null) { + return; + } + addBrokerage(order.getUserId(), orderItems); + } + + @Override + public void afterCancelOrder(TradeOrderDO order, List orderItems) { + // 如果是未支付的订单,不会产生分销结果,所以直接 return + if (!order.getPayStatus()) { + return; + } + if (order.getBrokerageUserId() == null) { + return; + } + + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 + orderItems = filterOrderItemListByNoneAfterSale(orderItems); + if (CollUtil.isEmpty(orderItems)) { + return; + } + orderItems.forEach(orderItem -> afterCancelOrderItem(order, orderItem)); + } + + @Override + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { + if (order.getBrokerageUserId() == null) { + return; + } + cancelBrokerage(order.getId(), orderItem.getOrderId()); + } + + /** + * 创建分销记录 + *

+ * 目前是支付成功后,就会创建分销记录。 + *

+ * 业内还有两种做法,可以根据自己的业务调整: + * 1. 确认收货后,才创建分销记录 + * 2. 支付 or 下单成功时,创建分销记录(冻结),确认收货解冻或者 n 天后解冻 + * + * @param userId 用户编号 + * @param orderItems 订单项 + */ + protected void addBrokerage(Long userId, List orderItems) { + MemberUserRespDTO user = memberUserApi.getUser(userId); + Assert.notNull(user); + ProductSpuRespDTO spu = productSpuApi.getSpu(orderItems.get(0).getSpuId()); + Assert.notNull(spu); + ProductSkuRespDTO sku = productSkuApi.getSku(orderItems.get(0).getSkuId()); + + // 每一个订单项,都会去生成分销记录 + List addList = convertList(orderItems, + item -> TradeOrderConvert.INSTANCE.convert(user, item, spu, sku)); + brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList); + } + + protected void cancelBrokerage(Long userId, Long orderItemId) { + brokerageRecordService.cancelBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, String.valueOf(orderItemId)); + } + +} 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/TradeCombinationOrderHandler.java similarity index 70% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationOrderHandler.java index 05d87fa46..5c00e5a12 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/TradeCombinationOrderHandler.java @@ -18,14 +18,15 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_FAIL_EXIST_UNPAID; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS; /** - * 拼团订单 handler 接口实现类 + * 拼团订单的 {@link TradeOrderHandler} 实现类 * * @author HUIHUI */ @Component -public class TradeCombinationHandler implements TradeOrderHandler { +public class TradeCombinationOrderHandler implements TradeOrderHandler { @Resource @Lazy @@ -41,16 +42,16 @@ public class TradeCombinationHandler implements TradeOrderHandler { @Override public void beforeOrderCreate(TradeOrderDO order, List orderItems) { // 如果不是拼团订单则结束 - if (TradeOrderTypeEnum.isCombination(order.getType())) { + if (!TradeOrderTypeEnum.isCombination(order.getType())) { return; } Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品"); - // 校验是否满足拼团活动相关限制 + // 1. 校验是否满足拼团活动相关限制 TradeOrderItemDO item = orderItems.get(0); combinationRecordApi.validateCombinationRecord(order.getUserId(), order.getCombinationActivityId(), order.getCombinationHeadId(), item.getSkuId(), item.getCount()); - // 校验该用户是否存在未支付的拼团活动订单;就是还没支付的时候,重复下单了;需要校验下;不然的话,一个拼团可以下多个单子了; + // 2. 校验该用户是否存在未支付的拼团活动订单;就是还没支付的时候,重复下单了;需要校验下;不然的话,一个拼团可以下多个单子了; TradeOrderDO activityOrder = orderQueryService.getActivityOrderByUserIdAndActivityIdAndStatus( order.getUserId(), order.getCombinationActivityId(), TradeOrderStatusEnum.UNPAID.getStatus()); if (activityOrder != null) { @@ -61,19 +62,32 @@ public class TradeCombinationHandler implements TradeOrderHandler { @Override public void afterPayOrder(TradeOrderDO order, List orderItems) { // 1.如果不是拼团订单则结束 - if (TradeOrderTypeEnum.isCombination(order.getType())) { + if (!TradeOrderTypeEnum.isCombination(order.getType())) { return; } Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品"); - // 2.获取商品信息 + // 2. 创建拼团记录 TradeOrderItemDO item = orderItems.get(0); - // 2.1.创建拼团记录 KeyValue recordIdAndHeadId = combinationRecordApi.createCombinationRecord( TradeOrderConvert.INSTANCE.convert(order, item)); - // 3.更新拼团相关信息到订单 + + // 3. 更新拼团相关信息到订单 + // TODO 芋艿,只需要更新 record orderUpdateService.updateOrderCombinationInfo(order.getId(), order.getCombinationActivityId(), recordIdAndHeadId.getKey(), recordIdAndHeadId.getValue()); } + @Override + public void beforeDeliveryOrder(TradeOrderDO order) { + if (!TradeOrderTypeEnum.isCombination(order.getType())) { + return; + } + // 校验订单拼团是否成功 + if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { + throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); + } + } + } + diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCouponOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCouponOrderHandler.java new file mode 100644 index 000000000..0f953fec7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCouponOrderHandler.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 优惠劵的 {@link TradeOrderHandler} 实现类 + * + * @author 芋道源码 + */ +@Component +public class TradeCouponOrderHandler implements TradeOrderHandler { + + @Resource + private CouponApi couponApi; + + @Override + public void afterOrderCreate(TradeOrderDO order, List orderItems) { + if (order.getCouponId() == null || order.getCouponId() <= 0) { + return; + } + // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号 + couponApi.useCoupon(new CouponUseReqDTO().setId(order.getCouponId()).setUserId(order.getUserId()) + .setOrderId(order.getId())); + } + + @Override + public void afterCancelOrder(TradeOrderDO order, List orderItems) { + if (order.getCouponId() == null || order.getCouponId() <= 0) { + return; + } + // 退回优惠劵 + couponApi.returnUsedCoupon(order.getCouponId()); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java new file mode 100644 index 000000000..0c1f9d497 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java @@ -0,0 +1,120 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; +import cn.iocoder.yudao.module.member.api.point.MemberPointApi; +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; + +/** + * 会员积分、等级的 {@link TradeOrderHandler} 实现类 + * + * @author owen + */ +@Component +public class TradeMemberPointOrderHandler implements TradeOrderHandler { + + @Resource + private MemberPointApi memberPointApi; + @Resource + private MemberLevelApi memberLevelApi; + + @Resource + private AfterSaleService afterSaleService; + + @Override + public void afterOrderCreate(TradeOrderDO order, List orderItems) { + // 扣减用户积分(订单抵扣)。不在前置扣减的原因,是因为积分扣减时,需要记录关联业务 + reducePoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE, order.getId()); + } + + @Override + public void afterPayOrder(TradeOrderDO order, List orderItems) { + // 增加用户积分(订单赠送) + addPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, + order.getId()); + + // 增加用户经验 + memberLevelApi.addExperience(order.getUserId(), order.getPayPrice(), + MemberExperienceBizTypeEnum.ORDER_GIVE.getType(), String.valueOf(order.getId())); + } + + @Override + public void afterCancelOrder(TradeOrderDO order, List orderItems) { + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 + orderItems = filterOrderItemListByNoneAfterSale(orderItems); + if (CollUtil.isEmpty(orderItems)) { + return; + } + + // 增加(回滚)用户积分(订单抵扣) + Integer usePoint = getSumValue(orderItems, TradeOrderItemDO::getUsePoint, Integer::sum); + addPoint(order.getUserId(), usePoint, MemberPointBizTypeEnum.ORDER_USE_CANCEL, + order.getId()); + + // 如下的返还,需要经过支持,也就是经历 afterPayOrder 流程 + if (!order.getPayStatus()) { + return; + } + // 扣减(回滚)积分(订单赠送) + Integer givePoint = getSumValue(orderItems, TradeOrderItemDO::getGivePoint, Integer::sum); + reducePoint(order.getUserId(), givePoint, MemberPointBizTypeEnum.ORDER_GIVE_CANCEL, + order.getId()); + // 扣减(回滚)用户经验 + int payPrice = order.getPayPrice() - order.getRefundPrice(); + memberLevelApi.addExperience(order.getUserId(), payPrice, + MemberExperienceBizTypeEnum.ORDER_GIVE_CANCEL.getType(), String.valueOf(order.getId())); + } + + @Override + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { + // 扣减(回滚)积分(订单赠送) + reducePoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE_CANCEL_ITEM, + orderItem.getId()); + // 增加(回滚)积分(订单抵扣) + addPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE_CANCEL_ITEM, + orderItem.getId()); + + // 扣减(回滚)用户经验 + AfterSaleDO afterSale = afterSaleService.getAfterSale(orderItem.getAfterSaleId()); + memberLevelApi.reduceExperience(order.getUserId(), afterSale.getRefundPrice(), + MemberExperienceBizTypeEnum.ORDER_GIVE_CANCEL_ITEM.getType(), String.valueOf(orderItem.getId())); + } + + /** + * 添加用户积分 + *

+ * 目前是支付成功后,就会创建积分记录。 + *

+ * 业内还有两种做法,可以根据自己的业务调整: + * 1. 确认收货后,才创建积分记录 + * 2. 支付 or 下单成功时,创建积分记录(冻结),确认收货解冻或者 n 天后解冻 + * + * @param userId 用户编号 + * @param point 增加积分数量 + * @param bizType 业务编号 + * @param bizId 业务编号 + */ + protected void addPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { + if (point != null && point > 0) { + memberPointApi.addPoint(userId, point, bizType.getType(), String.valueOf(bizId)); + } + } + + protected void reducePoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { + if (point != null && point > 0) { + memberPointApi.reducePoint(userId, point, bizType.getType(), String.valueOf(bizId)); + } + } + +} 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 646ebd1b7..4cc5c69a3 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,7 +1,9 @@ package cn.iocoder.yudao.module.trade.service.order.handler; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import java.util.List; @@ -35,16 +37,42 @@ public interface TradeOrderHandler { * @param order 订单 * @param orderItems 订单项 */ - default void afterPayOrder(TradeOrderDO order, List orderItems) { - } + default void afterPayOrder(TradeOrderDO order, List orderItems) {} /** - * 订单取消 + * 订单取消后 * * @param order 订单 * @param orderItems 订单项 */ - default void cancelOrder(TradeOrderDO order, List orderItems) { + default void afterCancelOrder(TradeOrderDO order, List orderItems) {} + + /** + * 订单项取消后 + * + * @param order 订单 + * @param orderItem 订单项 + */ + default void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) {} + + /** + * 订单发货前 + * + * @param order 订单 + */ + default void beforeDeliveryOrder(TradeOrderDO order) {} + + // ========== 公用方法 ========== + + /** + * 过滤“未售后”的订单项列表 + * + * @param orderItems 订单项列表 + * @return 过滤后的订单项列表 + */ + default List filterOrderItemListByNoneAfterSale(List orderItems) { + return CollectionUtils.filterList(orderItems, + item -> TradeOrderItemAfterSaleStatusEnum.isNone(item.getAfterSaleStatus())); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeProductSkuOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeProductSkuOrderHandler.java new file mode 100644 index 000000000..d28a643c6 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeProductSkuOrderHandler.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.trade.service.order.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +import static java.util.Collections.singletonList; + +/** + * 商品 SKU 库存的 {@link TradeOrderHandler} 实现类 + * + * @author 芋道源码 + */ +@Component +public class TradeProductSkuOrderHandler implements TradeOrderHandler { + + @Resource + private ProductSkuApi productSkuApi; + + @Override + public void beforeOrderCreate(TradeOrderDO order, List orderItems) { + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); + } + + @Override + public void afterCancelOrder(TradeOrderDO order, List orderItems) { + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 + orderItems = filterOrderItemListByNoneAfterSale(orderItems); + if (CollUtil.isEmpty(orderItems)) { + return; + } + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); + } + + @Override + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(singletonList(orderItem))); + } + +} 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/TradeSeckillOrderHandler.java similarity index 58% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillOrderHandler.java index 77934cb17..68227df7d 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/TradeSeckillOrderHandler.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; @@ -11,19 +12,19 @@ import javax.annotation.Resource; import java.util.List; /** - * 秒杀订单 handler 实现类 + * 秒杀订单的 {@link TradeOrderHandler} 实现类 * * @author HUIHUI */ @Component -public class TradeSeckillHandler implements TradeOrderHandler { +public class TradeSeckillOrderHandler implements TradeOrderHandler { @Resource private SeckillActivityApi seckillActivityApi; @Override public void beforeOrderCreate(TradeOrderDO order, List orderItems) { - if (TradeOrderTypeEnum.isSeckill(order.getType())) { + if (!TradeOrderTypeEnum.isSeckill(order.getType())) { return; } // 明确校验一下 @@ -35,16 +36,29 @@ public class TradeSeckillHandler implements TradeOrderHandler { } @Override - public void cancelOrder(TradeOrderDO order, List orderItems) { - if (TradeOrderTypeEnum.isSeckill(order.getType())) { + public void afterCancelOrder(TradeOrderDO order, List orderItems) { + if (!TradeOrderTypeEnum.isSeckill(order.getType())) { return; } // 明确校验一下 Assert.isTrue(orderItems.size() == 1, "秒杀时,只允许选择一个商品"); + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 + orderItems = filterOrderItemListByNoneAfterSale(orderItems); + if (CollUtil.isEmpty(orderItems)) { + return; + } + afterCancelOrderItem(order, orderItems.get(0)); + } + + @Override + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { + if (!TradeOrderTypeEnum.isSeckill(order.getType())) { + return; + } // 恢复秒杀活动的库存 seckillActivityApi.updateSeckillStockIncr(order.getSeckillActivityId(), - orderItems.get(0).getSkuId(), orderItems.get(0).getCount()); + orderItem.getSkuId(), orderItem.getCount()); } } diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java index 1ddd899cb..587683797 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java @@ -28,4 +28,14 @@ public interface MemberLevelApi { */ void addExperience(Long userId, Integer experience, Integer bizType, String bizId); + /** + * 扣减会员经验 + * + * @param userId 会员ID + * @param experience 经验 + * @param bizType 业务类型 {@link MemberExperienceBizTypeEnum} + * @param bizId 业务编号 + */ + void reduceExperience(Long userId, Integer experience, Integer bizType, String bizId); + } diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java index c719ab79f..3038dba31 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java @@ -20,10 +20,11 @@ public enum MemberExperienceBizTypeEnum { */ ADMIN(0, "管理员调整", "管理员调整获得 {} 经验", true), INVITE_REGISTER(1, "邀新奖励", "邀请好友获得 {} 经验", true), - ORDER(2, "下单奖励", "下单获得 {} 经验", true), - REFUND(3, "退单扣除", "退单获得 {} 经验", false), SIGN_IN(4, "签到奖励", "签到获得 {} 经验", true), LOTTERY(5, "抽奖奖励", "抽奖获得 {} 经验", true), + ORDER_GIVE(11, "下单奖励", "下单获得 {} 经验", true), + ORDER_GIVE_CANCEL(12, "下单奖励(整单取消)", "取消订单获得 {} 经验", false), // ORDER_GIVE 的取消 + ORDER_GIVE_CANCEL_ITEM(13, "下单奖励(单个退款)", "退款订单获得 {} 经验", false), // ORDER_GIVE 的取消 ; /** diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java index 3450a52aa..ef491f42a 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java @@ -18,11 +18,14 @@ public enum MemberPointBizTypeEnum implements IntArrayValuable { SIGN(1, "签到", "签到获得 {} 积分", true), ADMIN(2, "管理员修改", "管理员修改 {} 积分", true), - ORDER_GIVE(10, "订单奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分 - ORDER_CANCEL(11, "订单取消", "订单取消,退还 {} 积分", true), // 取消订单时,退回积分 - ORDER_USE(12, "订单使用", "下单使用 {} 积分", false), // 下单时,扣减积分 - AFTER_SALE_REFUND_USED(13, "订单退款", "订单退款,退还 {} 积分", true), // 售后订单成功时,退回积分(对应 ORDER_USE 操作) - AFTER_SALE_DEDUCT_GIVE(14, "订单退款", "订单退款,扣除赠送的 {} 积分", false), // 售后订单成功时,扣减积分(对应 ORDER_GIVE 操作) + + ORDER_USE(11, "订单积分抵扣", "下单使用 {} 积分", false), // 下单时,扣减积分 + ORDER_USE_CANCEL(12, "订单积分抵扣(整单取消)", "订单取消,退还 {} 积分", true), // ORDER_USE 的取消 + ORDER_USE_CANCEL_ITEM(13, "订单积分抵扣(单个退款)", "订单退款,退还 {} 积分", true), // ORDER_USE 的取消 + + ORDER_GIVE(21, "订单积分奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分 + ORDER_GIVE_CANCEL(22, "订单积分奖励(整单取消)", "订单取消,退还 {} 积分", false), // ORDER_GIVE 的取消 + ORDER_GIVE_CANCEL_ITEM(23, "订单积分奖励(单个退款)", "订单退款,扣除赠送的 {} 积分", false) // ORDER_GIVE 的取消 ; /** diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java index 519a8e8a1..79fed98eb 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java @@ -38,4 +38,9 @@ public class MemberLevelApiImpl implements MemberLevelApi { memberLevelService.addExperience(userId, experience, bizTypeEnum, bizId); } + @Override + public void reduceExperience(Long userId, Integer experience, Integer bizType, String bizId) { + addExperience(userId, -experience, bizType, bizId); + } + }