Commit 708af92a0f5597527fddf166641c6b1bae0c1d4f

Authored by 芋道源码
Committed by Gitee
2 parents 7181ccbc b0179457

!660 优化订单 OrderHandler 实现

Merge pull request !660 from 芋道源码/feature/mall_product_tmp
Showing 14 changed files with 481 additions and 232 deletions
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<SeckillProductDO> { @@ -41,7 +41,7 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
41 Assert.isTrue(count > 0); 41 Assert.isTrue(count > 0);
42 return update(null, new LambdaUpdateWrapper<SeckillProductDO>() 42 return update(null, new LambdaUpdateWrapper<SeckillProductDO>()
43 .eq(SeckillProductDO::getId, id) 43 .eq(SeckillProductDO::getId, id)
44 - .gt(SeckillProductDO::getStock, count) 44 + .ge(SeckillProductDO::getStock, count)
45 .setSql("stock = stock - " + count)); 45 .setSql("stock = stock - " + count));
46 } 46 }
47 47
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; @@ -14,23 +14,12 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
14 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 14 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
15 import cn.iocoder.yudao.module.member.api.address.AddressApi; 15 import cn.iocoder.yudao.module.member.api.address.AddressApi;
16 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 16 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
17 -import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;  
18 -import cn.iocoder.yudao.module.member.api.point.MemberPointApi;  
19 -import cn.iocoder.yudao.module.member.api.user.MemberUserApi;  
20 -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;  
21 -import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;  
22 -import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;  
23 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; 17 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
24 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; 18 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
25 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; 19 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
26 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 20 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
27 import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; 21 import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
28 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; 22 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
29 -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;  
30 -import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;  
31 -import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;  
32 -import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;  
33 -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;  
34 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; 23 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
35 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; 24 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
36 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; 25 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 @@ -40,7 +29,6 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle
40 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; 29 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
41 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; 30 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
42 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; 31 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
43 -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;  
44 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; 32 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
45 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; 33 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
46 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 34 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
@@ -48,15 +36,11 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; @@ -48,15 +36,11 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
48 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; 36 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
49 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; 37 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
50 import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO; 38 import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO;
51 -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;  
52 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; 39 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
53 import cn.iocoder.yudao.module.trade.enums.order.*; 40 import cn.iocoder.yudao.module.trade.enums.order.*;
54 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; 41 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
55 import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog; 42 import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog;
56 import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils; 43 import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils;
57 -import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;  
58 -import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;  
59 -import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;  
60 import cn.iocoder.yudao.module.trade.service.cart.CartService; 44 import cn.iocoder.yudao.module.trade.service.cart.CartService;
61 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; 45 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
62 import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; 46 import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
@@ -68,13 +52,15 @@ import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; @@ -68,13 +52,15 @@ import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
68 import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper; 52 import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper;
69 import lombok.extern.slf4j.Slf4j; 53 import lombok.extern.slf4j.Slf4j;
70 import org.jetbrains.annotations.NotNull; 54 import org.jetbrains.annotations.NotNull;
71 -import org.springframework.scheduling.annotation.Async;  
72 import org.springframework.stereotype.Service; 55 import org.springframework.stereotype.Service;
73 import org.springframework.transaction.annotation.Transactional; 56 import org.springframework.transaction.annotation.Transactional;
74 57
75 import javax.annotation.Resource; 58 import javax.annotation.Resource;
76 import java.time.LocalDateTime; 59 import java.time.LocalDateTime;
77 -import java.util.*; 60 +import java.util.ArrayList;
  61 +import java.util.List;
  62 +import java.util.Objects;
  63 +import java.util.Set;
78 64
79 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 65 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
80 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 66 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@@ -109,30 +95,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -109,30 +95,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
109 private DeliveryExpressService deliveryExpressService; 95 private DeliveryExpressService deliveryExpressService;
110 @Resource 96 @Resource
111 private TradeMessageService tradeMessageService; 97 private TradeMessageService tradeMessageService;
112 - @Resource  
113 - private BrokerageUserService brokerageUserService;  
114 - @Resource  
115 - private BrokerageRecordService brokerageRecordService;  
116 98
117 @Resource 99 @Resource
118 - private ProductSpuApi productSpuApi;  
119 - @Resource  
120 - private ProductSkuApi productSkuApi;  
121 - @Resource  
122 private PayOrderApi payOrderApi; 100 private PayOrderApi payOrderApi;
123 @Resource 101 @Resource
124 private AddressApi addressApi; 102 private AddressApi addressApi;
125 @Resource 103 @Resource
126 - private CouponApi couponApi;  
127 - @Resource  
128 - private CombinationRecordApi combinationRecordApi;  
129 - @Resource  
130 - private MemberUserApi memberUserApi;  
131 - @Resource  
132 - private MemberLevelApi memberLevelApi;  
133 - @Resource  
134 - private MemberPointApi memberPointApi;  
135 - @Resource  
136 private ProductCommentApi productCommentApi; 104 private ProductCommentApi productCommentApi;
137 105
138 @Resource 106 @Resource
@@ -199,7 +167,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -199,7 +167,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
199 List<TradeOrderItemDO> orderItems = buildTradeOrderItems(order, calculateRespBO); 167 List<TradeOrderItemDO> orderItems = buildTradeOrderItems(order, calculateRespBO);
200 168
201 // 2. 订单创建前的逻辑 169 // 2. 订单创建前的逻辑
202 - beforeCreateTradeOrder(order, orderItems); 170 + tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems));
203 171
204 // 3. 保存订单 172 // 3. 保存订单
205 tradeOrderMapper.insert(order); 173 tradeOrderMapper.insert(order);
@@ -234,11 +202,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -234,11 +202,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
234 order.setReceiverName(createReqVO.getReceiverName()).setReceiverMobile(createReqVO.getReceiverMobile()); 202 order.setReceiverName(createReqVO.getReceiverName()).setReceiverMobile(createReqVO.getReceiverMobile());
235 order.setPickUpVerifyCode(RandomUtil.randomNumbers(8)); // 随机一个核销码,长度为 8 位 203 order.setPickUpVerifyCode(RandomUtil.randomNumbers(8)); // 随机一个核销码,长度为 8 位
236 } 204 }
237 - // 设置订单推广人  
238 - BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(order.getUserId());  
239 - if (brokerageUser != null && brokerageUser.getBindUserId() != null) {  
240 - order.setBrokerageUserId(brokerageUser.getBindUserId());  
241 - }  
242 return order; 205 return order;
243 } 206 }
244 207
@@ -248,21 +211,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -248,21 +211,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
248 } 211 }
249 212
250 /** 213 /**
251 - * 订单创建前,执行前置逻辑  
252 - *  
253 - * @param order 订单  
254 - * @param orderItems 订单项  
255 - */  
256 - private void beforeCreateTradeOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {  
257 - // 1. 执行订单创建前置处理器  
258 - // TODO @puhui999:这里有个纠结点;handler 的定义是只处理指定类型的订单的拓展逻辑;还是通用的 handler,类似可以处理优惠劵等等  
259 - tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems));  
260 -  
261 - // 2. 下单时扣减商品库存  
262 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems));  
263 - }  
264 -  
265 - /**  
266 * 订单创建后,执行后置逻辑 214 * 订单创建后,执行后置逻辑
267 * <p> 215 * <p>
268 * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等 216 * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等
@@ -276,27 +224,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -276,27 +224,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
276 // 1. 执行订单创建后置处理器 224 // 1. 执行订单创建后置处理器
277 tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(order, orderItems)); 225 tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(order, orderItems));
278 226
279 - // 2. 有使用优惠券时更新  
280 - // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号  
281 - if (order.getCouponId() != null) {  
282 - couponApi.useCoupon(new CouponUseReqDTO().setId(order.getCouponId()).setUserId(order.getUserId())  
283 - .setOrderId(order.getId()));  
284 - }  
285 -  
286 - // 3. 扣减积分(抵扣)  
287 - // 不在前置扣减的原因,是因为积分扣减时,需要记录关联业务  
288 - reduceUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE, order.getId());  
289 -  
290 - // 4. 删除购物车商品 227 + // 2. 删除购物车商品
291 Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); 228 Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
292 if (CollUtil.isNotEmpty(cartIds)) { 229 if (CollUtil.isNotEmpty(cartIds)) {
293 cartService.deleteCart(order.getUserId(), cartIds); 230 cartService.deleteCart(order.getUserId(), cartIds);
294 } 231 }
295 232
296 - // 5. 生成预支付 233 + // 3. 生成预支付
297 createPayOrder(order, orderItems); 234 createPayOrder(order, orderItems);
298 235
299 - // 6. 插入订单日志 236 + // 4. 插入订单日志
300 TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus()); 237 TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus());
301 238
302 // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! 239 // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来!
@@ -330,18 +267,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -330,18 +267,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
330 throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); 267 throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
331 } 268 }
332 269
333 - // 3、订单支付成功后 270 + // 3. 执行 TradeOrderHandler 的后置处理
334 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); 271 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
335 tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems)); 272 tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems));
336 273
337 - // 4.1 增加用户积分(赠送)  
338 - addUserPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, order.getId());  
339 - // 4.2 增加用户经验  
340 - getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId());  
341 - // 4.3 增加用户佣金  
342 - getSelf().addBrokerageAsync(order.getUserId(), order.getId());  
343 -  
344 - // 5. 记录订单日志 274 + // 4. 记录订单日志
345 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); 275 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
346 TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue()); 276 TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue());
347 } 277 }
@@ -434,8 +364,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -434,8 +364,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
434 .put("logisticsNo", express != null ? deliveryReqVO.getLogisticsNo() : "").build()); 364 .put("logisticsNo", express != null ? deliveryReqVO.getLogisticsNo() : "").build());
435 365
436 // 4. 发送站内信 366 // 4. 发送站内信
437 - tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO().setOrderId(order.getId())  
438 - .setUserId(order.getUserId()).setMessage(null)); 367 + tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO()
  368 + .setOrderId(order.getId()).setUserId(order.getUserId()).setMessage(null));
439 } 369 }
440 370
441 /** 371 /**
@@ -448,18 +378,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -448,18 +378,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
448 */ 378 */
449 private TradeOrderDO validateOrderDeliverable(Long id) { 379 private TradeOrderDO validateOrderDeliverable(Long id) {
450 TradeOrderDO order = validateOrderExists(id); 380 TradeOrderDO order = validateOrderExists(id);
451 - // 校验订单是否退款 381 + // 1. 校验订单是否未发货
452 if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { 382 if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) {
453 throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); 383 throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE);
454 } 384 }
455 - // 订单类型:拼团  
456 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {  
457 - // 校验订单拼团是否成功  
458 - if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) {  
459 - throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);  
460 - }  
461 - }  
462 385
  386 + // 2. 执行 TradeOrderHandler 前置处理
  387 + tradeOrderHandlers.forEach(handler -> handler.beforeDeliveryOrder(order));
463 return order; 388 return order;
464 } 389 }
465 390
@@ -616,30 +541,19 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -616,30 +541,19 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
616 * @param cancelType 取消类型 541 * @param cancelType 取消类型
617 */ 542 */
618 private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { 543 private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) {
619 - Long id = order.getId();  
620 // 1. 更新 TradeOrderDO 状态为已取消 544 // 1. 更新 TradeOrderDO 状态为已取消
621 - int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), 545 + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(),
622 new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) 546 new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus())
623 .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now())); 547 .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now()));
624 if (updateCount == 0) { 548 if (updateCount == 0) {
625 throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); 549 throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
626 } 550 }
627 551
628 - List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);  
629 - // 3. 回滚库存  
630 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));  
631 - // 3.1、 活动相关的回滚  
632 - tradeOrderHandlers.forEach(handler -> handler.cancelOrder(order, orderItems));  
633 -  
634 - // 4. 回滚优惠券  
635 - if (order.getCouponId() != null && order.getCouponId() > 0) {  
636 - couponApi.returnUsedCoupon(order.getCouponId());  
637 - }  
638 -  
639 - // 5. 回滚积分(抵扣的)  
640 - addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); 552 + // 2. 执行 TradeOrderHandler 的后置处理
  553 + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
  554 + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems));
641 555
642 - // 6. 增加订单日志 556 + // 3. 增加订单日志
643 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); 557 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus());
644 } 558 }
645 559
@@ -660,8 +574,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -660,8 +574,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
660 .setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) 574 .setStatus(TradeOrderStatusEnum.CANCELED.getStatus())
661 .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); 575 .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now()));
662 576
663 - // 2. 退还优惠券  
664 - couponApi.returnUsedCoupon(order.getCouponId()); 577 + // 2. 执行 TradeOrderHandler 的后置处理
  578 + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
  579 + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems));
665 } 580 }
666 581
667 @Override 582 @Override
@@ -789,13 +704,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -789,13 +704,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
789 @Override 704 @Override
790 @Transactional(rollbackFor = Exception.class) 705 @Transactional(rollbackFor = Exception.class)
791 public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) { 706 public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) {
792 - // 1. 更新订单项 707 + // 1.1 更新订单项
793 updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), 708 updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(),
794 TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null); 709 TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null);
795 -  
796 - // 2.1 更新订单的退款金额、积分 710 + // 1.2 执行 TradeOrderHandler 的后置处理
797 TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id); 711 TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id);
798 TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId()); 712 TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId());
  713 + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrderItem(order, orderItem));
  714 +
  715 + // 2.1 更新订单的退款金额、积分
799 Integer orderRefundPrice = order.getRefundPrice() + refundPrice; 716 Integer orderRefundPrice = order.getRefundPrice() + refundPrice;
800 Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint(); 717 Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint();
801 Integer refundStatus = isAllOrderItemAfterSaleSuccess(order.getId()) ? 718 Integer refundStatus = isAllOrderItemAfterSaleSuccess(order.getId()) ?
@@ -806,23 +723,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -806,23 +723,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
806 .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint)); 723 .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint));
807 // 2.2 如果全部退款,则进行取消订单 724 // 2.2 如果全部退款,则进行取消订单
808 getSelf().cancelOrderByAfterSale(order, orderRefundPrice); 725 getSelf().cancelOrderByAfterSale(order, orderRefundPrice);
809 -  
810 -  
811 - // 3. 回滚库存  
812 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(Collections.singletonList(orderItem)));  
813 - // 3.1、 活动相关的回滚  
814 - tradeOrderHandlers.forEach(handler -> handler.cancelOrder(order, Collections.singletonList(orderItem)));  
815 -  
816 - // 4.1 回滚积分:扣减用户积分(赠送的)  
817 - reduceUserPoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.AFTER_SALE_DEDUCT_GIVE, orderItem.getAfterSaleId());  
818 - // 4.2 回滚积分:增加用户积分(返还抵扣)  
819 - addUserPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.AFTER_SALE_REFUND_USED, orderItem.getAfterSaleId());  
820 -  
821 - // 5. 回滚经验:扣减用户经验  
822 - getSelf().reduceUserExperienceAsync(order.getUserId(), refundPrice, orderItem.getAfterSaleId());  
823 -  
824 - // 6. 回滚佣金:更新分佣记录为已失效  
825 - getSelf().cancelBrokerageAsync(order.getUserId(), id);  
826 } 726 }
827 727
828 @Override 728 @Override
@@ -839,6 +739,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -839,6 +739,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
839 if (updateCount <= 0) { 739 if (updateCount <= 0) {
840 throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); 740 throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL);
841 } 741 }
  742 +
842 } 743 }
843 744
844 /** 745 /**
@@ -939,7 +840,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -939,7 +840,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
939 @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_COMMENT) 840 @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_COMMENT)
940 public void createOrderItemCommentBySystemBySystem(TradeOrderDO order) { 841 public void createOrderItemCommentBySystemBySystem(TradeOrderDO order) {
941 // 1. 查询未评论的订单项 842 // 1. 查询未评论的订单项
942 - List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderIdAndCommentStatus(order.getId(), Boolean.FALSE); 843 + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderIdAndCommentStatus(
  844 + order.getId(), Boolean.FALSE);
943 if (CollUtil.isEmpty(orderItems)) { 845 if (CollUtil.isEmpty(orderItems)) {
944 return; 846 return;
945 } 847 }
@@ -982,73 +884,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -982,73 +884,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
982 884
983 // =================== 营销相关的操作 =================== 885 // =================== 营销相关的操作 ===================
984 886
985 - @Async  
986 - protected void addUserExperienceAsync(Long userId, Integer payPrice, Long orderId) {  
987 - int bizType = MemberExperienceBizTypeEnum.ORDER.getType();  
988 - memberLevelApi.addExperience(userId, payPrice, bizType, String.valueOf(orderId));  
989 - }  
990 -  
991 - @Async  
992 - protected void reduceUserExperienceAsync(Long userId, Integer refundPrice, Long afterSaleId) {  
993 - int bizType = MemberExperienceBizTypeEnum.REFUND.getType();  
994 - memberLevelApi.addExperience(userId, -refundPrice, bizType, String.valueOf(afterSaleId));  
995 - }  
996 -  
997 - /**  
998 - * 添加用户积分  
999 - * <p>  
1000 - * 目前是支付成功后,就会创建积分记录。  
1001 - * <p>  
1002 - * 业内还有两种做法,可以根据自己的业务调整:  
1003 - * 1. 确认收货后,才创建积分记录  
1004 - * 2. 支付 or 下单成功时,创建积分记录(冻结),确认收货解冻或者 n 天后解冻  
1005 - *  
1006 - * @param userId 用户编号  
1007 - * @param point 增加积分数量  
1008 - * @param bizType 业务编号  
1009 - * @param bizId 业务编号  
1010 - */  
1011 - protected void addUserPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) {  
1012 - if (point != null && point > 0) {  
1013 - memberPointApi.addPoint(userId, point, bizType.getType(), String.valueOf(bizId));  
1014 - }  
1015 - }  
1016 -  
1017 - protected void reduceUserPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) {  
1018 - if (point != null && point > 0) {  
1019 - memberPointApi.reducePoint(userId, point, bizType.getType(), String.valueOf(bizId));  
1020 - }  
1021 - }  
1022 -  
1023 - /**  
1024 - * 创建分销记录  
1025 - * <p>  
1026 - * 目前是支付成功后,就会创建分销记录。  
1027 - * <p>  
1028 - * 业内还有两种做法,可以根据自己的业务调整:  
1029 - * 1. 确认收货后,才创建分销记录  
1030 - * 2. 支付 or 下单成功时,创建分销记录(冻结),确认收货解冻或者 n 天后解冻  
1031 - *  
1032 - * @param userId 用户编号  
1033 - * @param orderId 订单编号  
1034 - */  
1035 - @Async  
1036 - protected void addBrokerageAsync(Long userId, Long orderId) {  
1037 - MemberUserRespDTO user = memberUserApi.getUser(userId);  
1038 - Assert.notNull(user);  
1039 - // 每一个订单项,都会去生成分销记录  
1040 - List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(orderId);  
1041 - List<BrokerageAddReqBO> addList = convertList(orderItems,  
1042 - item -> TradeOrderConvert.INSTANCE.convert(user, item,  
1043 - productSpuApi.getSpu(item.getSpuId()), productSkuApi.getSku(item.getSkuId())));  
1044 - brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList);  
1045 - }  
1046 -  
1047 - @Async  
1048 - protected void cancelBrokerageAsync(Long userId, Long orderItemId) {  
1049 - brokerageRecordService.cancelBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, String.valueOf(orderItemId));  
1050 - }  
1051 -  
1052 /** 887 /**
1053 * 获得自身的代理对象,解决 AOP 生效问题 888 * 获得自身的代理对象,解决 AOP 生效问题
1054 * 889 *
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainOrderHandler.java
1 package cn.iocoder.yudao.module.trade.service.order.handler; 1 package cn.iocoder.yudao.module.trade.service.order.handler;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
4 import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; 5 import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi;
5 import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; 6 import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi;
@@ -12,12 +13,12 @@ import javax.annotation.Resource; @@ -12,12 +13,12 @@ import javax.annotation.Resource;
12 import java.util.List; 13 import java.util.List;
13 14
14 /** 15 /**
15 - * 砍价订单 handler 实现类 16 + * 砍价订单的 {@link TradeOrderHandler} 实现类
16 * 17 *
17 * @author HUIHUI 18 * @author HUIHUI
18 */ 19 */
19 @Component 20 @Component
20 -public class TradeBargainHandler implements TradeOrderHandler { 21 +public class TradeBargainOrderHandler implements TradeOrderHandler {
21 22
22 @Resource 23 @Resource
23 private BargainActivityApi bargainActivityApi; 24 private BargainActivityApi bargainActivityApi;
@@ -26,7 +27,7 @@ public class TradeBargainHandler implements TradeOrderHandler { @@ -26,7 +27,7 @@ public class TradeBargainHandler implements TradeOrderHandler {
26 27
27 @Override 28 @Override
28 public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { 29 public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
29 - if (TradeOrderTypeEnum.isBargain(order.getType())) { 30 + if (!TradeOrderTypeEnum.isBargain(order.getType())) {
30 return; 31 return;
31 } 32 }
32 // 明确校验一下 33 // 明确校验一下
@@ -39,7 +40,7 @@ public class TradeBargainHandler implements TradeOrderHandler { @@ -39,7 +40,7 @@ public class TradeBargainHandler implements TradeOrderHandler {
39 40
40 @Override 41 @Override
41 public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { 42 public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
42 - if (TradeOrderTypeEnum.isBargain(order.getType())) { 43 + if (!TradeOrderTypeEnum.isBargain(order.getType())) {
43 return; 44 return;
44 } 45 }
45 // 明确校验一下 46 // 明确校验一下
@@ -50,16 +51,28 @@ public class TradeBargainHandler implements TradeOrderHandler { @@ -50,16 +51,28 @@ public class TradeBargainHandler implements TradeOrderHandler {
50 } 51 }
51 52
52 @Override 53 @Override
53 - public void cancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {  
54 - if (TradeOrderTypeEnum.isBargain(order.getType())) { 54 + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  55 + if (!TradeOrderTypeEnum.isBargain(order.getType())) {
55 return; 56 return;
56 } 57 }
57 // 明确校验一下 58 // 明确校验一下
58 Assert.isTrue(orderItems.size() == 1, "砍价时,只允许选择一个商品"); 59 Assert.isTrue(orderItems.size() == 1, "砍价时,只允许选择一个商品");
59 60
60 - // 恢复砍价活动的库存  
61 - bargainActivityApi.updateBargainActivityStock(order.getBargainActivityId(),  
62 - orderItems.get(0).getCount()); 61 + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚
  62 + orderItems = filterOrderItemListByNoneAfterSale(orderItems);
  63 + if (CollUtil.isEmpty(orderItems)) {
  64 + return;
  65 + }
  66 + afterCancelOrderItem(order, orderItems.get(0));
  67 + }
  68 +
  69 + @Override
  70 + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) {
  71 + if (!TradeOrderTypeEnum.isBargain(order.getType())) {
  72 + return;
  73 + }
  74 + // 恢复(增加)砍价活动的库存
  75 + bargainActivityApi.updateBargainActivityStock(order.getBargainActivityId(), orderItem.getCount());
63 } 76 }
64 77
65 } 78 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.order.handler;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
  5 +import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
  6 +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
  7 +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
  8 +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
  9 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  10 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
  11 +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
  12 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
  13 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
  14 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
  15 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
  16 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
  17 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
  18 +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
  19 +import org.springframework.stereotype.Component;
  20 +
  21 +import javax.annotation.Resource;
  22 +import java.util.List;
  23 +
  24 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  25 +
  26 +/**
  27 + * 订单分销的 {@link TradeOrderHandler} 实现类
  28 + *
  29 + * @author 芋道源码
  30 + */
  31 +@Component
  32 +public class TradeBrokerageOrderHandler implements TradeOrderHandler {
  33 +
  34 + @Resource
  35 + private MemberUserApi memberUserApi;
  36 + @Resource
  37 + private ProductSpuApi productSpuApi;
  38 + @Resource
  39 + private ProductSkuApi productSkuApi;
  40 +
  41 + @Resource
  42 + private BrokerageRecordService brokerageRecordService;
  43 + @Resource
  44 + private BrokerageUserService brokerageUserService;
  45 +
  46 + @Override
  47 + public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  48 + // 设置订单推广人
  49 + BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(order.getUserId());
  50 + if (brokerageUser != null && brokerageUser.getBindUserId() != null) {
  51 + order.setBrokerageUserId(brokerageUser.getBindUserId());
  52 + }
  53 + }
  54 +
  55 + @Override
  56 + public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  57 + if (order.getBrokerageUserId() == null) {
  58 + return;
  59 + }
  60 + addBrokerage(order.getUserId(), orderItems);
  61 + }
  62 +
  63 + @Override
  64 + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  65 + // 如果是未支付的订单,不会产生分销结果,所以直接 return
  66 + if (!order.getPayStatus()) {
  67 + return;
  68 + }
  69 + if (order.getBrokerageUserId() == null) {
  70 + return;
  71 + }
  72 +
  73 + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚
  74 + orderItems = filterOrderItemListByNoneAfterSale(orderItems);
  75 + if (CollUtil.isEmpty(orderItems)) {
  76 + return;
  77 + }
  78 + orderItems.forEach(orderItem -> afterCancelOrderItem(order, orderItem));
  79 + }
  80 +
  81 + @Override
  82 + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) {
  83 + if (order.getBrokerageUserId() == null) {
  84 + return;
  85 + }
  86 + cancelBrokerage(order.getId(), orderItem.getOrderId());
  87 + }
  88 +
  89 + /**
  90 + * 创建分销记录
  91 + * <p>
  92 + * 目前是支付成功后,就会创建分销记录。
  93 + * <p>
  94 + * 业内还有两种做法,可以根据自己的业务调整:
  95 + * 1. 确认收货后,才创建分销记录
  96 + * 2. 支付 or 下单成功时,创建分销记录(冻结),确认收货解冻或者 n 天后解冻
  97 + *
  98 + * @param userId 用户编号
  99 + * @param orderItems 订单项
  100 + */
  101 + protected void addBrokerage(Long userId, List<TradeOrderItemDO> orderItems) {
  102 + MemberUserRespDTO user = memberUserApi.getUser(userId);
  103 + Assert.notNull(user);
  104 + ProductSpuRespDTO spu = productSpuApi.getSpu(orderItems.get(0).getSpuId());
  105 + Assert.notNull(spu);
  106 + ProductSkuRespDTO sku = productSkuApi.getSku(orderItems.get(0).getSkuId());
  107 +
  108 + // 每一个订单项,都会去生成分销记录
  109 + List<BrokerageAddReqBO> addList = convertList(orderItems,
  110 + item -> TradeOrderConvert.INSTANCE.convert(user, item, spu, sku));
  111 + brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList);
  112 + }
  113 +
  114 + protected void cancelBrokerage(Long userId, Long orderItemId) {
  115 + brokerageRecordService.cancelBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, String.valueOf(orderItemId));
  116 + }
  117 +
  118 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java renamed to 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; @@ -18,14 +18,15 @@ import java.util.List;
18 18
19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
20 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_FAIL_EXIST_UNPAID; 20 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_FAIL_EXIST_UNPAID;
  21 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS;
21 22
22 /** 23 /**
23 - * 拼团订单 handler 接口实现类 24 + * 拼团订单的 {@link TradeOrderHandler} 实现类
24 * 25 *
25 * @author HUIHUI 26 * @author HUIHUI
26 */ 27 */
27 @Component 28 @Component
28 -public class TradeCombinationHandler implements TradeOrderHandler { 29 +public class TradeCombinationOrderHandler implements TradeOrderHandler {
29 30
30 @Resource 31 @Resource
31 @Lazy 32 @Lazy
@@ -41,16 +42,16 @@ public class TradeCombinationHandler implements TradeOrderHandler { @@ -41,16 +42,16 @@ public class TradeCombinationHandler implements TradeOrderHandler {
41 @Override 42 @Override
42 public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { 43 public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
43 // 如果不是拼团订单则结束 44 // 如果不是拼团订单则结束
44 - if (TradeOrderTypeEnum.isCombination(order.getType())) { 45 + if (!TradeOrderTypeEnum.isCombination(order.getType())) {
45 return; 46 return;
46 } 47 }
47 Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品"); 48 Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品");
48 49
49 - // 校验是否满足拼团活动相关限制 50 + // 1. 校验是否满足拼团活动相关限制
50 TradeOrderItemDO item = orderItems.get(0); 51 TradeOrderItemDO item = orderItems.get(0);
51 combinationRecordApi.validateCombinationRecord(order.getUserId(), order.getCombinationActivityId(), 52 combinationRecordApi.validateCombinationRecord(order.getUserId(), order.getCombinationActivityId(),
52 order.getCombinationHeadId(), item.getSkuId(), item.getCount()); 53 order.getCombinationHeadId(), item.getSkuId(), item.getCount());
53 - // 校验该用户是否存在未支付的拼团活动订单;就是还没支付的时候,重复下单了;需要校验下;不然的话,一个拼团可以下多个单子了; 54 + // 2. 校验该用户是否存在未支付的拼团活动订单;就是还没支付的时候,重复下单了;需要校验下;不然的话,一个拼团可以下多个单子了;
54 TradeOrderDO activityOrder = orderQueryService.getActivityOrderByUserIdAndActivityIdAndStatus( 55 TradeOrderDO activityOrder = orderQueryService.getActivityOrderByUserIdAndActivityIdAndStatus(
55 order.getUserId(), order.getCombinationActivityId(), TradeOrderStatusEnum.UNPAID.getStatus()); 56 order.getUserId(), order.getCombinationActivityId(), TradeOrderStatusEnum.UNPAID.getStatus());
56 if (activityOrder != null) { 57 if (activityOrder != null) {
@@ -61,19 +62,32 @@ public class TradeCombinationHandler implements TradeOrderHandler { @@ -61,19 +62,32 @@ public class TradeCombinationHandler implements TradeOrderHandler {
61 @Override 62 @Override
62 public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { 63 public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
63 // 1.如果不是拼团订单则结束 64 // 1.如果不是拼团订单则结束
64 - if (TradeOrderTypeEnum.isCombination(order.getType())) { 65 + if (!TradeOrderTypeEnum.isCombination(order.getType())) {
65 return; 66 return;
66 } 67 }
67 Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品"); 68 Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品");
68 69
69 - // 2.获取商品信息 70 + // 2. 创建拼团记录
70 TradeOrderItemDO item = orderItems.get(0); 71 TradeOrderItemDO item = orderItems.get(0);
71 - // 2.1.创建拼团记录  
72 KeyValue<Long, Long> recordIdAndHeadId = combinationRecordApi.createCombinationRecord( 72 KeyValue<Long, Long> recordIdAndHeadId = combinationRecordApi.createCombinationRecord(
73 TradeOrderConvert.INSTANCE.convert(order, item)); 73 TradeOrderConvert.INSTANCE.convert(order, item));
74 - // 3.更新拼团相关信息到订单 74 +
  75 + // 3. 更新拼团相关信息到订单
  76 + // TODO 芋艿,只需要更新 record
75 orderUpdateService.updateOrderCombinationInfo(order.getId(), order.getCombinationActivityId(), 77 orderUpdateService.updateOrderCombinationInfo(order.getId(), order.getCombinationActivityId(),
76 recordIdAndHeadId.getKey(), recordIdAndHeadId.getValue()); 78 recordIdAndHeadId.getKey(), recordIdAndHeadId.getValue());
77 } 79 }
78 80
  81 + @Override
  82 + public void beforeDeliveryOrder(TradeOrderDO order) {
  83 + if (!TradeOrderTypeEnum.isCombination(order.getType())) {
  84 + return;
  85 + }
  86 + // 校验订单拼团是否成功
  87 + if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) {
  88 + throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);
  89 + }
  90 + }
  91 +
79 } 92 }
  93 +
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCouponOrderHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.order.handler;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
  4 +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
  5 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
  6 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import javax.annotation.Resource;
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 优惠劵的 {@link TradeOrderHandler} 实现类
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Component
  18 +public class TradeCouponOrderHandler implements TradeOrderHandler {
  19 +
  20 + @Resource
  21 + private CouponApi couponApi;
  22 +
  23 + @Override
  24 + public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  25 + if (order.getCouponId() == null || order.getCouponId() <= 0) {
  26 + return;
  27 + }
  28 + // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号
  29 + couponApi.useCoupon(new CouponUseReqDTO().setId(order.getCouponId()).setUserId(order.getUserId())
  30 + .setOrderId(order.getId()));
  31 + }
  32 +
  33 + @Override
  34 + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  35 + if (order.getCouponId() == null || order.getCouponId() <= 0) {
  36 + return;
  37 + }
  38 + // 退回优惠劵
  39 + couponApi.returnUsedCoupon(order.getCouponId());
  40 + }
  41 +
  42 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.order.handler;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
  5 +import cn.iocoder.yudao.module.member.api.point.MemberPointApi;
  6 +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
  7 +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
  8 +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO;
  9 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
  10 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
  11 +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import javax.annotation.Resource;
  15 +import java.util.List;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
  18 +
  19 +/**
  20 + * 会员积分、等级的 {@link TradeOrderHandler} 实现类
  21 + *
  22 + * @author owen
  23 + */
  24 +@Component
  25 +public class TradeMemberPointOrderHandler implements TradeOrderHandler {
  26 +
  27 + @Resource
  28 + private MemberPointApi memberPointApi;
  29 + @Resource
  30 + private MemberLevelApi memberLevelApi;
  31 +
  32 + @Resource
  33 + private AfterSaleService afterSaleService;
  34 +
  35 + @Override
  36 + public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  37 + // 扣减用户积分(订单抵扣)。不在前置扣减的原因,是因为积分扣减时,需要记录关联业务
  38 + reducePoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE, order.getId());
  39 + }
  40 +
  41 + @Override
  42 + public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  43 + // 增加用户积分(订单赠送)
  44 + addPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE,
  45 + order.getId());
  46 +
  47 + // 增加用户经验
  48 + memberLevelApi.addExperience(order.getUserId(), order.getPayPrice(),
  49 + MemberExperienceBizTypeEnum.ORDER_GIVE.getType(), String.valueOf(order.getId()));
  50 + }
  51 +
  52 + @Override
  53 + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  54 + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚
  55 + orderItems = filterOrderItemListByNoneAfterSale(orderItems);
  56 + if (CollUtil.isEmpty(orderItems)) {
  57 + return;
  58 + }
  59 +
  60 + // 增加(回滚)用户积分(订单抵扣)
  61 + Integer usePoint = getSumValue(orderItems, TradeOrderItemDO::getUsePoint, Integer::sum);
  62 + addPoint(order.getUserId(), usePoint, MemberPointBizTypeEnum.ORDER_USE_CANCEL,
  63 + order.getId());
  64 +
  65 + // 如下的返还,需要经过支持,也就是经历 afterPayOrder 流程
  66 + if (!order.getPayStatus()) {
  67 + return;
  68 + }
  69 + // 扣减(回滚)积分(订单赠送)
  70 + Integer givePoint = getSumValue(orderItems, TradeOrderItemDO::getGivePoint, Integer::sum);
  71 + reducePoint(order.getUserId(), givePoint, MemberPointBizTypeEnum.ORDER_GIVE_CANCEL,
  72 + order.getId());
  73 + // 扣减(回滚)用户经验
  74 + int payPrice = order.getPayPrice() - order.getRefundPrice();
  75 + memberLevelApi.addExperience(order.getUserId(), payPrice,
  76 + MemberExperienceBizTypeEnum.ORDER_GIVE_CANCEL.getType(), String.valueOf(order.getId()));
  77 + }
  78 +
  79 + @Override
  80 + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) {
  81 + // 扣减(回滚)积分(订单赠送)
  82 + reducePoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE_CANCEL_ITEM,
  83 + orderItem.getId());
  84 + // 增加(回滚)积分(订单抵扣)
  85 + addPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE_CANCEL_ITEM,
  86 + orderItem.getId());
  87 +
  88 + // 扣减(回滚)用户经验
  89 + AfterSaleDO afterSale = afterSaleService.getAfterSale(orderItem.getAfterSaleId());
  90 + memberLevelApi.reduceExperience(order.getUserId(), afterSale.getRefundPrice(),
  91 + MemberExperienceBizTypeEnum.ORDER_GIVE_CANCEL_ITEM.getType(), String.valueOf(orderItem.getId()));
  92 + }
  93 +
  94 + /**
  95 + * 添加用户积分
  96 + * <p>
  97 + * 目前是支付成功后,就会创建积分记录。
  98 + * <p>
  99 + * 业内还有两种做法,可以根据自己的业务调整:
  100 + * 1. 确认收货后,才创建积分记录
  101 + * 2. 支付 or 下单成功时,创建积分记录(冻结),确认收货解冻或者 n 天后解冻
  102 + *
  103 + * @param userId 用户编号
  104 + * @param point 增加积分数量
  105 + * @param bizType 业务编号
  106 + * @param bizId 业务编号
  107 + */
  108 + protected void addPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) {
  109 + if (point != null && point > 0) {
  110 + memberPointApi.addPoint(userId, point, bizType.getType(), String.valueOf(bizId));
  111 + }
  112 + }
  113 +
  114 + protected void reducePoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) {
  115 + if (point != null && point > 0) {
  116 + memberPointApi.reducePoint(userId, point, bizType.getType(), String.valueOf(bizId));
  117 + }
  118 + }
  119 +
  120 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java
1 package cn.iocoder.yudao.module.trade.service.order.handler; 1 package cn.iocoder.yudao.module.trade.service.order.handler;
2 2
  3 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
3 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 4 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
4 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; 5 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
  6 +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
5 7
6 import java.util.List; 8 import java.util.List;
7 9
@@ -35,16 +37,42 @@ public interface TradeOrderHandler { @@ -35,16 +37,42 @@ public interface TradeOrderHandler {
35 * @param order 订单 37 * @param order 订单
36 * @param orderItems 订单项 38 * @param orderItems 订单项
37 */ 39 */
38 - default void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {  
39 - } 40 + default void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {}
40 41
41 /** 42 /**
42 - * 订单取消 43 + * 订单取消后
43 * 44 *
44 * @param order 订单 45 * @param order 订单
45 * @param orderItems 订单项 46 * @param orderItems 订单项
46 */ 47 */
47 - default void cancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { 48 + default void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {}
  49 +
  50 + /**
  51 + * 订单项取消后
  52 + *
  53 + * @param order 订单
  54 + * @param orderItem 订单项
  55 + */
  56 + default void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) {}
  57 +
  58 + /**
  59 + * 订单发货前
  60 + *
  61 + * @param order 订单
  62 + */
  63 + default void beforeDeliveryOrder(TradeOrderDO order) {}
  64 +
  65 + // ========== 公用方法 ==========
  66 +
  67 + /**
  68 + * 过滤“未售后”的订单项列表
  69 + *
  70 + * @param orderItems 订单项列表
  71 + * @return 过滤后的订单项列表
  72 + */
  73 + default List<TradeOrderItemDO> filterOrderItemListByNoneAfterSale(List<TradeOrderItemDO> orderItems) {
  74 + return CollectionUtils.filterList(orderItems,
  75 + item -> TradeOrderItemAfterSaleStatusEnum.isNone(item.getAfterSaleStatus()));
48 } 76 }
49 77
50 } 78 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeProductSkuOrderHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.order.handler;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
  5 +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
  6 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
  7 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import javax.annotation.Resource;
  11 +import java.util.List;
  12 +
  13 +import static java.util.Collections.singletonList;
  14 +
  15 +/**
  16 + * 商品 SKU 库存的 {@link TradeOrderHandler} 实现类
  17 + *
  18 + * @author 芋道源码
  19 + */
  20 +@Component
  21 +public class TradeProductSkuOrderHandler implements TradeOrderHandler {
  22 +
  23 + @Resource
  24 + private ProductSkuApi productSkuApi;
  25 +
  26 + @Override
  27 + public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  28 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems));
  29 + }
  30 +
  31 + @Override
  32 + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  33 + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚
  34 + orderItems = filterOrderItemListByNoneAfterSale(orderItems);
  35 + if (CollUtil.isEmpty(orderItems)) {
  36 + return;
  37 + }
  38 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
  39 + }
  40 +
  41 + @Override
  42 + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) {
  43 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(singletonList(orderItem)));
  44 + }
  45 +
  46 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillOrderHandler.java
1 package cn.iocoder.yudao.module.trade.service.order.handler; 1 package cn.iocoder.yudao.module.trade.service.order.handler;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
4 import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; 5 import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
5 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 6 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
@@ -11,19 +12,19 @@ import javax.annotation.Resource; @@ -11,19 +12,19 @@ import javax.annotation.Resource;
11 import java.util.List; 12 import java.util.List;
12 13
13 /** 14 /**
14 - * 秒杀订单 handler 实现类 15 + * 秒杀订单的 {@link TradeOrderHandler} 实现类
15 * 16 *
16 * @author HUIHUI 17 * @author HUIHUI
17 */ 18 */
18 @Component 19 @Component
19 -public class TradeSeckillHandler implements TradeOrderHandler { 20 +public class TradeSeckillOrderHandler implements TradeOrderHandler {
20 21
21 @Resource 22 @Resource
22 private SeckillActivityApi seckillActivityApi; 23 private SeckillActivityApi seckillActivityApi;
23 24
24 @Override 25 @Override
25 public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { 26 public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
26 - if (TradeOrderTypeEnum.isSeckill(order.getType())) { 27 + if (!TradeOrderTypeEnum.isSeckill(order.getType())) {
27 return; 28 return;
28 } 29 }
29 // 明确校验一下 30 // 明确校验一下
@@ -35,16 +36,29 @@ public class TradeSeckillHandler implements TradeOrderHandler { @@ -35,16 +36,29 @@ public class TradeSeckillHandler implements TradeOrderHandler {
35 } 36 }
36 37
37 @Override 38 @Override
38 - public void cancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {  
39 - if (TradeOrderTypeEnum.isSeckill(order.getType())) { 39 + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  40 + if (!TradeOrderTypeEnum.isSeckill(order.getType())) {
40 return; 41 return;
41 } 42 }
42 // 明确校验一下 43 // 明确校验一下
43 Assert.isTrue(orderItems.size() == 1, "秒杀时,只允许选择一个商品"); 44 Assert.isTrue(orderItems.size() == 1, "秒杀时,只允许选择一个商品");
44 45
  46 + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚
  47 + orderItems = filterOrderItemListByNoneAfterSale(orderItems);
  48 + if (CollUtil.isEmpty(orderItems)) {
  49 + return;
  50 + }
  51 + afterCancelOrderItem(order, orderItems.get(0));
  52 + }
  53 +
  54 + @Override
  55 + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) {
  56 + if (!TradeOrderTypeEnum.isSeckill(order.getType())) {
  57 + return;
  58 + }
45 // 恢复秒杀活动的库存 59 // 恢复秒杀活动的库存
46 seckillActivityApi.updateSeckillStockIncr(order.getSeckillActivityId(), 60 seckillActivityApi.updateSeckillStockIncr(order.getSeckillActivityId(),
47 - orderItems.get(0).getSkuId(), orderItems.get(0).getCount()); 61 + orderItem.getSkuId(), orderItem.getCount());
48 } 62 }
49 63
50 } 64 }
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 { @@ -28,4 +28,14 @@ public interface MemberLevelApi {
28 */ 28 */
29 void addExperience(Long userId, Integer experience, Integer bizType, String bizId); 29 void addExperience(Long userId, Integer experience, Integer bizType, String bizId);
30 30
  31 + /**
  32 + * 扣减会员经验
  33 + *
  34 + * @param userId 会员ID
  35 + * @param experience 经验
  36 + * @param bizType 业务类型 {@link MemberExperienceBizTypeEnum}
  37 + * @param bizId 业务编号
  38 + */
  39 + void reduceExperience(Long userId, Integer experience, Integer bizType, String bizId);
  40 +
31 } 41 }
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 { @@ -20,10 +20,11 @@ public enum MemberExperienceBizTypeEnum {
20 */ 20 */
21 ADMIN(0, "管理员调整", "管理员调整获得 {} 经验", true), 21 ADMIN(0, "管理员调整", "管理员调整获得 {} 经验", true),
22 INVITE_REGISTER(1, "邀新奖励", "邀请好友获得 {} 经验", true), 22 INVITE_REGISTER(1, "邀新奖励", "邀请好友获得 {} 经验", true),
23 - ORDER(2, "下单奖励", "下单获得 {} 经验", true),  
24 - REFUND(3, "退单扣除", "退单获得 {} 经验", false),  
25 SIGN_IN(4, "签到奖励", "签到获得 {} 经验", true), 23 SIGN_IN(4, "签到奖励", "签到获得 {} 经验", true),
26 LOTTERY(5, "抽奖奖励", "抽奖获得 {} 经验", true), 24 LOTTERY(5, "抽奖奖励", "抽奖获得 {} 经验", true),
  25 + ORDER_GIVE(11, "下单奖励", "下单获得 {} 经验", true),
  26 + ORDER_GIVE_CANCEL(12, "下单奖励(整单取消)", "取消订单获得 {} 经验", false), // ORDER_GIVE 的取消
  27 + ORDER_GIVE_CANCEL_ITEM(13, "下单奖励(单个退款)", "退款订单获得 {} 经验", false), // ORDER_GIVE 的取消
27 ; 28 ;
28 29
29 /** 30 /**
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 { @@ -18,11 +18,14 @@ public enum MemberPointBizTypeEnum implements IntArrayValuable {
18 18
19 SIGN(1, "签到", "签到获得 {} 积分", true), 19 SIGN(1, "签到", "签到获得 {} 积分", true),
20 ADMIN(2, "管理员修改", "管理员修改 {} 积分", true), 20 ADMIN(2, "管理员修改", "管理员修改 {} 积分", true),
21 - ORDER_GIVE(10, "订单奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分  
22 - ORDER_CANCEL(11, "订单取消", "订单取消,退还 {} 积分", true), // 取消订单时,退回积分  
23 - ORDER_USE(12, "订单使用", "下单使用 {} 积分", false), // 下单时,扣减积分  
24 - AFTER_SALE_REFUND_USED(13, "订单退款", "订单退款,退还 {} 积分", true), // 售后订单成功时,退回积分(对应 ORDER_USE 操作)  
25 - AFTER_SALE_DEDUCT_GIVE(14, "订单退款", "订单退款,扣除赠送的 {} 积分", false), // 售后订单成功时,扣减积分(对应 ORDER_GIVE 操作) 21 +
  22 + ORDER_USE(11, "订单积分抵扣", "下单使用 {} 积分", false), // 下单时,扣减积分
  23 + ORDER_USE_CANCEL(12, "订单积分抵扣(整单取消)", "订单取消,退还 {} 积分", true), // ORDER_USE 的取消
  24 + ORDER_USE_CANCEL_ITEM(13, "订单积分抵扣(单个退款)", "订单退款,退还 {} 积分", true), // ORDER_USE 的取消
  25 +
  26 + ORDER_GIVE(21, "订单积分奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分
  27 + ORDER_GIVE_CANCEL(22, "订单积分奖励(整单取消)", "订单取消,退还 {} 积分", false), // ORDER_GIVE 的取消
  28 + ORDER_GIVE_CANCEL_ITEM(23, "订单积分奖励(单个退款)", "订单退款,扣除赠送的 {} 积分", false) // ORDER_GIVE 的取消
26 ; 29 ;
27 30
28 /** 31 /**
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 { @@ -38,4 +38,9 @@ public class MemberLevelApiImpl implements MemberLevelApi {
38 memberLevelService.addExperience(userId, experience, bizTypeEnum, bizId); 38 memberLevelService.addExperience(userId, experience, bizTypeEnum, bizId);
39 } 39 }
40 40
  41 + @Override
  42 + public void reduceExperience(Long userId, Integer experience, Integer bizType, String bizId) {
  43 + addExperience(userId, -experience, bizType, bizId);
  44 + }
  45 +
41 } 46 }