diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java index 80acf9b99..a41b73ec3 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java +++ b/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 @Override public TradeAfterSaleDO getAfterSale(Long userId, Long id) { - return tradeAfterSaleMapper.selectByIdAndUserId(id, userId); + return tradeAfterSaleMapper.selectByIdAndUserId(id, userId); } @Override @@ -167,9 +167,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa tradeAfterSaleMapper.insert(afterSale); // 更新交易订单项的售后状态 - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(orderItem.getId(), - TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), - afterSale.getId(), null); + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCreate(orderItem.getId(), afterSale.getId()); // 记录售后日志 createAfterSaleLog(orderItem.getUserId(), UserTypeEnum.MEMBER.getValue(), @@ -219,8 +217,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa // TODO 发送售后消息 // 更新交易订单项的售后状态为【未申请】 - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), - TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); } /** @@ -313,8 +310,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa // TODO 发送售后消息 // 更新交易订单项的售后状态为【未申请】 - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), - TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); } /** @@ -360,9 +356,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa // TODO 发送售后消息 // 更新交易订单项的售后状态为【已完成】 - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), - TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), - null, afterSale.getRefundPrice()); + tradeOrderUpdateService.updateOrderItemWhenAfterSaleSuccess(afterSale.getOrderItemId(), afterSale.getRefundPrice()); } private void createPayRefund(String userIp, TradeAfterSaleDO afterSale) { @@ -403,8 +397,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa // TODO 发送售后消息 // 更新交易订单项的售后状态为【未申请】 - tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), - TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); } @Override diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java index 18a75b679..f612d0ca4 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java @@ -1,15 +1,17 @@ package cn.iocoder.yudao.module.trade.service.order; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO; 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; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; 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.dal.dataobject.order.TradeOrderDO; +import javax.validation.constraints.NotNull; + /** * 交易订单【写】Service 接口 * @@ -116,27 +118,28 @@ public interface TradeOrderUpdateService { // =================== Order Item =================== /** - * 更新交易订单项的售后状态 + * 当售后申请后,更新交易订单项的售后状态 * - * @param id 交易订单项编号 - * @param oldAfterSaleStatus 当前售后状态;如果不符,更新后会抛出异常 - * @param newAfterSaleStatus 目标售后状态 + * @param id 交易订单项编号 + * @param afterSaleId 售后单编号 */ - default void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus) { - updateOrderItemAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus, null, null); - } + void updateOrderItemWhenAfterSaleCreate(@NotNull Long id, @NotNull Long afterSaleId); + /** - * 更新交易订单项的售后状态 + * 当售后完成后,更新交易订单项的售后状态 * - * @param id 交易订单项编号 - * @param oldAfterSaleStatus 当前售后状态;如果不符,更新后会抛出异常 - * @param newAfterSaleStatus 目标售后状态 - * @param afterSaleId 售后单编号;当订单项发起售后时,必须传递该字段 - * @param refundPrice 退款金额;当订单项退款成功时,必须传递该值 + * @param id 交易订单项编号 + * @param refundPrice 退款金额 */ - void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, - Long afterSaleId, Integer refundPrice); + void updateOrderItemWhenAfterSaleSuccess(@NotNull Long id, @NotNull Integer refundPrice); + + /** + * 当售后取消(用户取消、管理员驳回、管理员拒绝收货)后,更新交易订单项的售后状态 + * + * @param id 交易订单项编号 + */ + void updateOrderItemWhenAfterSaleCancel(@NotNull Long id); /** * 创建订单项的评论 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 98abc349a..6f980594b 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 @@ -508,7 +508,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { for (TradeOrderDO order : orders) { try { getSelf().receiveOrderBySystem(order); - count ++; + count++; } catch (Throwable e) { log.error("[autoReceiveOrder][order({}) 自动收货订单异常]", order.getId(), e); } @@ -599,7 +599,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { for (TradeOrderDO order : orders) { try { getSelf().cancelOrderBySystem(order); - count ++; + count++; } catch (Throwable e) { log.error("[autoCancelOrder][order({}) 过期订单异常]", order.getId(), e); } @@ -621,7 +621,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { /** * 取消订单的核心实现 * - * @param order 订单 + * @param order 订单 * @param cancelType 取消类型 */ private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { @@ -770,67 +770,79 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // =================== Order Item =================== - // TODO 疯狂:帮我重构下: - // 1. updateOrderItemAfterSaleStatus 拆分成三个方法:发起;同意;拒绝。原因是,职责更清晰,操作日志也更容易记录; - @Override - @Transactional(rollbackFor = Exception.class) - public void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, - Long afterSaleId, Integer refundPrice) { - // 如果退款成功,则 refundPrice 非空 - if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()) - && refundPrice == null) { - throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); - } - // 如果退款发起,则 afterSaleId 非空 - if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus()) - && afterSaleId == null) { + public void updateOrderItemWhenAfterSaleCreate(Long id, Long afterSaleId) { + if (afterSaleId == null) { throw new IllegalArgumentException(StrUtil.format("id({}) 退款发起,售后单编号不能为空", id)); } + // 更新订单项 + updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), afterSaleId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) { + if (refundPrice == null) { + throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); + } + + // 1. 更新订单项 + updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), + TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null); + + // 2. 计算总的退款金额、退回积分 + TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id); + TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId()); + Integer orderRefundPrice = order.getRefundPrice() + refundPrice; + Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint(); + if (isAllOrderItemAfterSaleSuccess(order.getId())) { // 如果都售后成功,则需要取消订单 + cancelOrderByAfterSale(order, orderRefundPrice, orderRefundPoint); + } else { // 如果部分售后,则更新退款金额 + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) + .setRefundStatus(TradeOrderRefundStatusEnum.PART.getStatus()) + .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint)); + } + + // TODO 芋艿:这块扣减规则,需要在考虑下 + // 3.1 回滚数据:增加 SKU 库存 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(Collections.singletonList(orderItem))); + // 3.2 回滚数据:扣减用户积分(赠送的) + reduceUserPoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.AFTER_SALE_DEDUCT_GIVE, orderItem.getAfterSaleId()); + // 3.3 回滚数据:增加用户积分(返还抵扣) + addUserPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.AFTER_SALE_REFUND_USED, orderItem.getAfterSaleId()); + // 3.4 回滚数据:扣减用户经验 + getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, orderItem.getAfterSaleId()); + // 3.5 回滚数据:更新分佣记录为已失效 + getSelf().cancelBrokerageAsync(order.getUserId(), id); + } + + @Override + public void updateOrderItemWhenAfterSaleCancel(Long id) { + // 更新订单项 + updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), + TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); + } + + private void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, + Long afterSaleId) { // 更新订单项 int updateCount = tradeOrderItemMapper.updateAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus, afterSaleId); if (updateCount <= 0) { throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); } + } - // 如果有退款金额,则需要更新订单 - if (refundPrice == null) { - return; - } - // 计算总的退款金额 - TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id); - TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId()); - Integer orderRefundPrice = order.getRefundPrice() + refundPrice; - // TODO @疯狂:809 到 817 改成:cancelOrderByAfterSale:相当于全部售后成功后,就是要取消胆子; - if (isAllOrderItemAfterSaleSuccess(order.getId())) { // 如果都售后成功,则需要取消订单 - tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) - .setRefundStatus(TradeOrderRefundStatusEnum.ALL.getStatus()).setRefundPrice(orderRefundPrice).setRefundPoint(order.getRefundPoint() + orderItem.getUsePoint()) - .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); - - // TODO 芋艿:记录订单日志 - - // TODO 芋艿:要不要退优惠劵 - - } else { // 如果部分售后,则更新退款金额 - tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) - .setRefundStatus(TradeOrderRefundStatusEnum.PART.getStatus()).setRefundPrice(orderRefundPrice)); - } - - // TODO 芋艿:这块扣减规则,需要在考虑下 - // 售后成功后,执行数据回滚逻辑 - if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus())) { - // 增加 SKU 库存 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(Collections.singletonList(orderItem))); - // 扣减用户积分(赠送的) - reduceUserPoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.AFTER_SALE_DEDUCT_GIVE, afterSaleId); - // 增加用户积分(返还抵扣) - addUserPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.AFTER_SALE_REFUND_USED, afterSaleId); - // 扣减用户经验 - getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, afterSaleId); - // 更新分佣记录为已失效 - getSelf().cancelBrokerageAsync(order.getUserId(), id); - } + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL) + private void cancelOrderByAfterSale(TradeOrderDO order, Integer orderRefundPrice, Integer refundPoint) { + // 1. 更新订单 + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) + .setRefundStatus(TradeOrderRefundStatusEnum.ALL.getStatus()) + .setRefundPrice(orderRefundPrice).setRefundPoint(refundPoint) + .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); + // 2. 退还优惠券 + couponApi.returnUsedCoupon(order.getCouponId()); } @Override