Commit bc07e1dbf43941b51655ad8287d129a66c03d19c
1 parent
74ef98f8
售后:重构售后更新订单的逻辑
Showing
3 changed files
with
84 additions
and
76 deletions
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
| ... | ... | @@ -85,7 +85,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa |
| 85 | 85 | |
| 86 | 86 | @Override |
| 87 | 87 | public TradeAfterSaleDO getAfterSale(Long userId, Long id) { |
| 88 | - return tradeAfterSaleMapper.selectByIdAndUserId(id, userId); | |
| 88 | + return tradeAfterSaleMapper.selectByIdAndUserId(id, userId); | |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | @Override |
| ... | ... | @@ -167,9 +167,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa |
| 167 | 167 | tradeAfterSaleMapper.insert(afterSale); |
| 168 | 168 | |
| 169 | 169 | // 更新交易订单项的售后状态 |
| 170 | - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(orderItem.getId(), | |
| 171 | - TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), | |
| 172 | - afterSale.getId(), null); | |
| 170 | + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCreate(orderItem.getId(), afterSale.getId()); | |
| 173 | 171 | |
| 174 | 172 | // 记录售后日志 |
| 175 | 173 | createAfterSaleLog(orderItem.getUserId(), UserTypeEnum.MEMBER.getValue(), |
| ... | ... | @@ -219,8 +217,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa |
| 219 | 217 | // TODO 发送售后消息 |
| 220 | 218 | |
| 221 | 219 | // 更新交易订单项的售后状态为【未申请】 |
| 222 | - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), | |
| 223 | - TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); | |
| 220 | + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); | |
| 224 | 221 | } |
| 225 | 222 | |
| 226 | 223 | /** |
| ... | ... | @@ -313,8 +310,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa |
| 313 | 310 | // TODO 发送售后消息 |
| 314 | 311 | |
| 315 | 312 | // 更新交易订单项的售后状态为【未申请】 |
| 316 | - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), | |
| 317 | - TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); | |
| 313 | + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); | |
| 318 | 314 | } |
| 319 | 315 | |
| 320 | 316 | /** |
| ... | ... | @@ -360,9 +356,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa |
| 360 | 356 | // TODO 发送售后消息 |
| 361 | 357 | |
| 362 | 358 | // 更新交易订单项的售后状态为【已完成】 |
| 363 | - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), | |
| 364 | - TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), | |
| 365 | - null, afterSale.getRefundPrice()); | |
| 359 | + tradeOrderUpdateService.updateOrderItemWhenAfterSaleSuccess(afterSale.getOrderItemId(), afterSale.getRefundPrice()); | |
| 366 | 360 | } |
| 367 | 361 | |
| 368 | 362 | private void createPayRefund(String userIp, TradeAfterSaleDO afterSale) { |
| ... | ... | @@ -403,8 +397,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa |
| 403 | 397 | // TODO 发送售后消息 |
| 404 | 398 | |
| 405 | 399 | // 更新交易订单项的售后状态为【未申请】 |
| 406 | - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), | |
| 407 | - TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); | |
| 400 | + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); | |
| 408 | 401 | } |
| 409 | 402 | |
| 410 | 403 | @Override | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.service.order; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; | |
| 4 | -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO; | |
| 5 | 3 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; |
| 6 | 4 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; | |
| 6 | +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO; | |
| 7 | 7 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; |
| 8 | 8 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; |
| 9 | 9 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; |
| 10 | 10 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; |
| 11 | 11 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 12 | 12 | |
| 13 | +import javax.validation.constraints.NotNull; | |
| 14 | + | |
| 13 | 15 | /** |
| 14 | 16 | * 交易订单【写】Service 接口 |
| 15 | 17 | * |
| ... | ... | @@ -116,27 +118,28 @@ public interface TradeOrderUpdateService { |
| 116 | 118 | // =================== Order Item =================== |
| 117 | 119 | |
| 118 | 120 | /** |
| 119 | - * 更新交易订单项的售后状态 | |
| 121 | + * 当售后申请后,更新交易订单项的售后状态 | |
| 122 | + * | |
| 123 | + * @param id 交易订单项编号 | |
| 124 | + * @param afterSaleId 售后单编号 | |
| 125 | + */ | |
| 126 | + void updateOrderItemWhenAfterSaleCreate(@NotNull Long id, @NotNull Long afterSaleId); | |
| 127 | + | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * 当售后完成后,更新交易订单项的售后状态 | |
| 120 | 131 | * |
| 121 | - * @param id 交易订单项编号 | |
| 122 | - * @param oldAfterSaleStatus 当前售后状态;如果不符,更新后会抛出异常 | |
| 123 | - * @param newAfterSaleStatus 目标售后状态 | |
| 132 | + * @param id 交易订单项编号 | |
| 133 | + * @param refundPrice 退款金额 | |
| 124 | 134 | */ |
| 125 | - default void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus) { | |
| 126 | - updateOrderItemAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus, null, null); | |
| 127 | - } | |
| 135 | + void updateOrderItemWhenAfterSaleSuccess(@NotNull Long id, @NotNull Integer refundPrice); | |
| 128 | 136 | |
| 129 | 137 | /** |
| 130 | - * 更新交易订单项的售后状态 | |
| 138 | + * 当售后取消(用户取消、管理员驳回、管理员拒绝收货)后,更新交易订单项的售后状态 | |
| 131 | 139 | * |
| 132 | - * @param id 交易订单项编号 | |
| 133 | - * @param oldAfterSaleStatus 当前售后状态;如果不符,更新后会抛出异常 | |
| 134 | - * @param newAfterSaleStatus 目标售后状态 | |
| 135 | - * @param afterSaleId 售后单编号;当订单项发起售后时,必须传递该字段 | |
| 136 | - * @param refundPrice 退款金额;当订单项退款成功时,必须传递该值 | |
| 140 | + * @param id 交易订单项编号 | |
| 137 | 141 | */ |
| 138 | - void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, | |
| 139 | - Long afterSaleId, Integer refundPrice); | |
| 142 | + void updateOrderItemWhenAfterSaleCancel(@NotNull Long id); | |
| 140 | 143 | |
| 141 | 144 | /** |
| 142 | 145 | * 创建订单项的评论 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| ... | ... | @@ -508,7 +508,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 508 | 508 | for (TradeOrderDO order : orders) { |
| 509 | 509 | try { |
| 510 | 510 | getSelf().receiveOrderBySystem(order); |
| 511 | - count ++; | |
| 511 | + count++; | |
| 512 | 512 | } catch (Throwable e) { |
| 513 | 513 | log.error("[autoReceiveOrder][order({}) 自动收货订单异常]", order.getId(), e); |
| 514 | 514 | } |
| ... | ... | @@ -599,7 +599,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 599 | 599 | for (TradeOrderDO order : orders) { |
| 600 | 600 | try { |
| 601 | 601 | getSelf().cancelOrderBySystem(order); |
| 602 | - count ++; | |
| 602 | + count++; | |
| 603 | 603 | } catch (Throwable e) { |
| 604 | 604 | log.error("[autoCancelOrder][order({}) 过期订单异常]", order.getId(), e); |
| 605 | 605 | } |
| ... | ... | @@ -621,7 +621,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 621 | 621 | /** |
| 622 | 622 | * 取消订单的核心实现 |
| 623 | 623 | * |
| 624 | - * @param order 订单 | |
| 624 | + * @param order 订单 | |
| 625 | 625 | * @param cancelType 取消类型 |
| 626 | 626 | */ |
| 627 | 627 | private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { |
| ... | ... | @@ -770,69 +770,81 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { |
| 770 | 770 | |
| 771 | 771 | // =================== Order Item =================== |
| 772 | 772 | |
| 773 | - // TODO 疯狂:帮我重构下: | |
| 774 | - // 1. updateOrderItemAfterSaleStatus 拆分成三个方法:发起;同意;拒绝。原因是,职责更清晰,操作日志也更容易记录; | |
| 775 | - | |
| 776 | 773 | @Override |
| 777 | - @Transactional(rollbackFor = Exception.class) | |
| 778 | - public void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, | |
| 779 | - Long afterSaleId, Integer refundPrice) { | |
| 780 | - // 如果退款成功,则 refundPrice 非空 | |
| 781 | - if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()) | |
| 782 | - && refundPrice == null) { | |
| 783 | - throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); | |
| 784 | - } | |
| 785 | - // 如果退款发起,则 afterSaleId 非空 | |
| 786 | - if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus()) | |
| 787 | - && afterSaleId == null) { | |
| 774 | + public void updateOrderItemWhenAfterSaleCreate(Long id, Long afterSaleId) { | |
| 775 | + if (afterSaleId == null) { | |
| 788 | 776 | throw new IllegalArgumentException(StrUtil.format("id({}) 退款发起,售后单编号不能为空", id)); |
| 789 | 777 | } |
| 790 | 778 | |
| 791 | 779 | // 更新订单项 |
| 792 | - int updateCount = tradeOrderItemMapper.updateAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus, afterSaleId); | |
| 793 | - if (updateCount <= 0) { | |
| 794 | - throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); | |
| 795 | - } | |
| 780 | + updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), | |
| 781 | + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), afterSaleId); | |
| 782 | + } | |
| 796 | 783 | |
| 797 | - // 如果有退款金额,则需要更新订单 | |
| 784 | + @Override | |
| 785 | + @Transactional(rollbackFor = Exception.class) | |
| 786 | + public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) { | |
| 798 | 787 | if (refundPrice == null) { |
| 799 | - return; | |
| 788 | + throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); | |
| 800 | 789 | } |
| 801 | - // 计算总的退款金额 | |
| 790 | + | |
| 791 | + // 1. 更新订单项 | |
| 792 | + updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), | |
| 793 | + TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null); | |
| 794 | + | |
| 795 | + // 2. 计算总的退款金额、退回积分 | |
| 802 | 796 | TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id); |
| 803 | 797 | TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId()); |
| 804 | 798 | Integer orderRefundPrice = order.getRefundPrice() + refundPrice; |
| 805 | - // TODO @疯狂:809 到 817 改成:cancelOrderByAfterSale:相当于全部售后成功后,就是要取消胆子; | |
| 799 | + Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint(); | |
| 806 | 800 | if (isAllOrderItemAfterSaleSuccess(order.getId())) { // 如果都售后成功,则需要取消订单 |
| 807 | - tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) | |
| 808 | - .setRefundStatus(TradeOrderRefundStatusEnum.ALL.getStatus()).setRefundPrice(orderRefundPrice).setRefundPoint(order.getRefundPoint() + orderItem.getUsePoint()) | |
| 809 | - .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); | |
| 810 | - | |
| 811 | - // TODO 芋艿:记录订单日志 | |
| 812 | - | |
| 813 | - // TODO 芋艿:要不要退优惠劵 | |
| 814 | - | |
| 801 | + cancelOrderByAfterSale(order, orderRefundPrice, orderRefundPoint); | |
| 815 | 802 | } else { // 如果部分售后,则更新退款金额 |
| 816 | 803 | tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) |
| 817 | - .setRefundStatus(TradeOrderRefundStatusEnum.PART.getStatus()).setRefundPrice(orderRefundPrice)); | |
| 804 | + .setRefundStatus(TradeOrderRefundStatusEnum.PART.getStatus()) | |
| 805 | + .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint)); | |
| 818 | 806 | } |
| 819 | 807 | |
| 820 | 808 | // TODO 芋艿:这块扣减规则,需要在考虑下 |
| 821 | - // 售后成功后,执行数据回滚逻辑 | |
| 822 | - if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus())) { | |
| 823 | - // 增加 SKU 库存 | |
| 824 | - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(Collections.singletonList(orderItem))); | |
| 825 | - // 扣减用户积分(赠送的) | |
| 826 | - reduceUserPoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.AFTER_SALE_DEDUCT_GIVE, afterSaleId); | |
| 827 | - // 增加用户积分(返还抵扣) | |
| 828 | - addUserPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.AFTER_SALE_REFUND_USED, afterSaleId); | |
| 829 | - // 扣减用户经验 | |
| 830 | - getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, afterSaleId); | |
| 831 | - // 更新分佣记录为已失效 | |
| 832 | - getSelf().cancelBrokerageAsync(order.getUserId(), id); | |
| 809 | + // 3.1 回滚数据:增加 SKU 库存 | |
| 810 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(Collections.singletonList(orderItem))); | |
| 811 | + // 3.2 回滚数据:扣减用户积分(赠送的) | |
| 812 | + reduceUserPoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.AFTER_SALE_DEDUCT_GIVE, orderItem.getAfterSaleId()); | |
| 813 | + // 3.3 回滚数据:增加用户积分(返还抵扣) | |
| 814 | + addUserPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.AFTER_SALE_REFUND_USED, orderItem.getAfterSaleId()); | |
| 815 | + // 3.4 回滚数据:扣减用户经验 | |
| 816 | + getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, orderItem.getAfterSaleId()); | |
| 817 | + // 3.5 回滚数据:更新分佣记录为已失效 | |
| 818 | + getSelf().cancelBrokerageAsync(order.getUserId(), id); | |
| 819 | + } | |
| 820 | + | |
| 821 | + @Override | |
| 822 | + public void updateOrderItemWhenAfterSaleCancel(Long id) { | |
| 823 | + // 更新订单项 | |
| 824 | + updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), | |
| 825 | + TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); | |
| 826 | + } | |
| 827 | + | |
| 828 | + private void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, | |
| 829 | + Long afterSaleId) { | |
| 830 | + // 更新订单项 | |
| 831 | + int updateCount = tradeOrderItemMapper.updateAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus, afterSaleId); | |
| 832 | + if (updateCount <= 0) { | |
| 833 | + throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); | |
| 833 | 834 | } |
| 834 | 835 | } |
| 835 | 836 | |
| 837 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL) | |
| 838 | + private void cancelOrderByAfterSale(TradeOrderDO order, Integer orderRefundPrice, Integer refundPoint) { | |
| 839 | + // 1. 更新订单 | |
| 840 | + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) | |
| 841 | + .setRefundStatus(TradeOrderRefundStatusEnum.ALL.getStatus()) | |
| 842 | + .setRefundPrice(orderRefundPrice).setRefundPoint(refundPoint) | |
| 843 | + .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); | |
| 844 | + // 2. 退还优惠券 | |
| 845 | + couponApi.returnUsedCoupon(order.getCouponId()); | |
| 846 | + } | |
| 847 | + | |
| 836 | 848 | @Override |
| 837 | 849 | @Transactional(rollbackFor = Exception.class) |
| 838 | 850 | @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_COMMENT) | ... | ... |