Commit a8c78f3097f482dd6df4e369f67e51c5a08c31ce
1 parent
9e99b043
trade:增加自动收货的 job
Showing
9 changed files
with
232 additions
and
145 deletions
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderOperateTypeEnum.java
| @@ -15,9 +15,10 @@ public enum TradeOrderOperateTypeEnum { | @@ -15,9 +15,10 @@ public enum TradeOrderOperateTypeEnum { | ||
| 15 | 15 | ||
| 16 | MEMBER_CREATE(1, "用户下单"), | 16 | MEMBER_CREATE(1, "用户下单"), |
| 17 | MEMBER_RECEIVE(30, "用户已收货"), | 17 | MEMBER_RECEIVE(30, "用户已收货"), |
| 18 | - MEMBER_COMMENT(31, "用户评价"), | ||
| 19 | - MEMBER_CANCEL(40, "手动取消订单"), | ||
| 20 | - SYSTEM_CANCEL(41, "系统取消订单"), | 18 | + SYSTEM_RECEIVE(31, "到期未收货,系统自动确认收货"), |
| 19 | + MEMBER_COMMENT(33, "用户评价"), | ||
| 20 | + MEMBER_CANCEL(40, "取消订单"), | ||
| 21 | + SYSTEM_CANCEL(41, "到期未支付,系统自动取消订单"), | ||
| 21 | // 42 预留:管理员取消订单 | 22 | // 42 预留:管理员取消订单 |
| 22 | MEMBER_DELETE(43, "删除订单"), | 23 | MEMBER_DELETE(43, "删除订单"), |
| 23 | ; | 24 | ; |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
| @@ -110,7 +110,7 @@ public interface TradeOrderConvert { | @@ -110,7 +110,7 @@ public interface TradeOrderConvert { | ||
| 110 | createReqDTO.setSubject(subject); | 110 | createReqDTO.setSubject(subject); |
| 111 | createReqDTO.setBody(subject); // TODO 芋艿:临时写死 | 111 | createReqDTO.setBody(subject); // TODO 芋艿:临时写死 |
| 112 | // 订单相关字段 | 112 | // 订单相关字段 |
| 113 | - createReqDTO.setPrice(order.getPayPrice()).setExpireTime(addTime(orderProperties.getExpireTime())); | 113 | + createReqDTO.setPrice(order.getPayPrice()).setExpireTime(addTime(orderProperties.getPayExpireTime())); |
| 114 | return createReqDTO; | 114 | return createReqDTO; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| @@ -180,7 +180,7 @@ public interface TradeOrderConvert { | @@ -180,7 +180,7 @@ public interface TradeOrderConvert { | ||
| 180 | TradeOrderProperties tradeOrderProperties, | 180 | TradeOrderProperties tradeOrderProperties, |
| 181 | DeliveryExpressDO express) { | 181 | DeliveryExpressDO express) { |
| 182 | AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); | 182 | AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); |
| 183 | - orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime())); | 183 | + orderVO.setPayExpireTime(addTime(tradeOrderProperties.getPayExpireTime())); |
| 184 | if (StrUtil.isNotEmpty(order.getPayChannelCode())) { | 184 | if (StrUtil.isNotEmpty(order.getPayChannelCode())) { |
| 185 | orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode())); | 185 | orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode())); |
| 186 | } | 186 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java
| @@ -61,10 +61,16 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> { | @@ -61,10 +61,16 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> { | ||
| 61 | .eq(TradeOrderDO::getUserId, loginUserId)); | 61 | .eq(TradeOrderDO::getUserId, loginUserId)); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | - default List<TradeOrderDO> selectListByStatusAndCreateTimeLt(Integer status, LocalDateTime expireTime) { | 64 | + default List<TradeOrderDO> selectListByStatusAndCreateTimeLt(Integer status, LocalDateTime createTime) { |
| 65 | return selectList(new LambdaUpdateWrapper<TradeOrderDO>() | 65 | return selectList(new LambdaUpdateWrapper<TradeOrderDO>() |
| 66 | .eq(TradeOrderDO::getStatus, status) | 66 | .eq(TradeOrderDO::getStatus, status) |
| 67 | - .lt(TradeOrderDO::getCreateTime, expireTime)); | 67 | + .lt(TradeOrderDO::getCreateTime, createTime)); |
| 68 | + } | ||
| 69 | + | ||
| 70 | + default List<TradeOrderDO> selectListByStatusAndDeliveryTimeLt(Integer status, LocalDateTime deliveryTime) { | ||
| 71 | + return selectList(new LambdaUpdateWrapper<TradeOrderDO>() | ||
| 72 | + .eq(TradeOrderDO::getStatus, status) | ||
| 73 | + .lt(TradeOrderDO::getDeliveryTime, deliveryTime)); | ||
| 68 | } | 74 | } |
| 69 | 75 | ||
| 70 | } | 76 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/config/TradeOrderProperties.java
| @@ -28,6 +28,12 @@ public class TradeOrderProperties { | @@ -28,6 +28,12 @@ public class TradeOrderProperties { | ||
| 28 | * 支付超时时间 | 28 | * 支付超时时间 |
| 29 | */ | 29 | */ |
| 30 | @NotNull(message = "支付超时时间不能为空") | 30 | @NotNull(message = "支付超时时间不能为空") |
| 31 | - private Duration expireTime; | 31 | + private Duration payExpireTime; |
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 收货超时时间 | ||
| 35 | + */ | ||
| 36 | + @NotNull(message = "收货超时时间不能为空") | ||
| 37 | + private Duration receiveExpireTime; | ||
| 32 | 38 | ||
| 33 | } | 39 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/order/TradeOrderAutoReceiveJob.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.job.order; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; | ||
| 4 | +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; | ||
| 5 | +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; | ||
| 6 | +import org.springframework.stereotype.Component; | ||
| 7 | + | ||
| 8 | +import javax.annotation.Resource; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 交易订单的自动收货 Job | ||
| 12 | + * | ||
| 13 | + * @author 芋道源码 | ||
| 14 | + */ | ||
| 15 | +@Component | ||
| 16 | +@TenantJob | ||
| 17 | +public class TradeOrderAutoReceiveJob implements JobHandler { | ||
| 18 | + | ||
| 19 | + @Resource | ||
| 20 | + private TradeOrderUpdateService tradeOrderUpdateService; | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public String execute(String param) { | ||
| 24 | + int count = tradeOrderUpdateService.autoReceiveOrder(); | ||
| 25 | + return String.format("自动收货 %s 个", count); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
| @@ -63,7 +63,14 @@ public interface TradeOrderUpdateService { | @@ -63,7 +63,14 @@ public interface TradeOrderUpdateService { | ||
| 63 | void receiveOrder(Long userId, Long id); | 63 | void receiveOrder(Long userId, Long id); |
| 64 | 64 | ||
| 65 | /** | 65 | /** |
| 66 | - * 【会员】取消订单 | 66 | + * 【系统】自动收货交易订单 |
| 67 | + * | ||
| 68 | + * @return 收货数量 | ||
| 69 | + */ | ||
| 70 | + int autoReceiveOrder(); | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * 【会员】取消交易订单 | ||
| 67 | * | 74 | * |
| 68 | * @param userId 用户编号 | 75 | * @param userId 用户编号 |
| 69 | * @param id 订单编号 | 76 | * @param id 订单编号 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| @@ -492,6 +492,50 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -492,6 +492,50 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 492 | // 校验并获得交易订单(可收货) | 492 | // 校验并获得交易订单(可收货) |
| 493 | TradeOrderDO order = validateOrderReceivable(userId, id); | 493 | TradeOrderDO order = validateOrderReceivable(userId, id); |
| 494 | 494 | ||
| 495 | + // 收货订单 | ||
| 496 | + receiveOrder0(order); | ||
| 497 | + } | ||
| 498 | + | ||
| 499 | + @Override | ||
| 500 | + public int autoReceiveOrder() { | ||
| 501 | + // 1. 查询过期的待支付订单 | ||
| 502 | + LocalDateTime expireTime = addTime(tradeOrderProperties.getReceiveExpireTime()); | ||
| 503 | + List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndDeliveryTimeLt( | ||
| 504 | + TradeOrderStatusEnum.DELIVERED.getStatus(), expireTime); | ||
| 505 | + if (CollUtil.isEmpty(orders)) { | ||
| 506 | + return 0; | ||
| 507 | + } | ||
| 508 | + | ||
| 509 | + // 2. 遍历执行,逐个取消 | ||
| 510 | + int count = 0; | ||
| 511 | + for (TradeOrderDO order : orders) { | ||
| 512 | + try { | ||
| 513 | + getSelf().autoReceiveOrder(order); | ||
| 514 | + count ++; | ||
| 515 | + } catch (Throwable e) { | ||
| 516 | + log.error("[autoReceiveOrder][order({}) 自动收货订单异常]", order.getId(), e); | ||
| 517 | + } | ||
| 518 | + } | ||
| 519 | + return count; | ||
| 520 | + } | ||
| 521 | + | ||
| 522 | + /** | ||
| 523 | + * 自动收货单个订单 | ||
| 524 | + * | ||
| 525 | + * @param order 订单 | ||
| 526 | + */ | ||
| 527 | + @Transactional(rollbackFor = Exception.class) | ||
| 528 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_RECEIVE) | ||
| 529 | + public void autoReceiveOrder(TradeOrderDO order) { | ||
| 530 | + receiveOrder0(order); | ||
| 531 | + } | ||
| 532 | + | ||
| 533 | + /** | ||
| 534 | + * 收货订单的核心实现 | ||
| 535 | + * | ||
| 536 | + * @param order 订单 | ||
| 537 | + */ | ||
| 538 | + private void receiveOrder0(TradeOrderDO order) { | ||
| 495 | // 更新 TradeOrderDO 状态为已完成 | 539 | // 更新 TradeOrderDO 状态为已完成 |
| 496 | int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), | 540 | int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), |
| 497 | new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now())); | 541 | new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now())); |
| @@ -499,14 +543,137 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -499,14 +543,137 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 499 | throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); | 543 | throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); |
| 500 | } | 544 | } |
| 501 | 545 | ||
| 502 | - // TODO 芋艿:lili 发送订单变化的消息 | 546 | + // 插入订单日志 |
| 547 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); | ||
| 548 | + } | ||
| 503 | 549 | ||
| 504 | - // TODO 芋艿:lili 发送商品被购买完成的数据 | 550 | + /** |
| 551 | + * 校验交易订单满足可售货的条件 | ||
| 552 | + * | ||
| 553 | + * 1. 交易订单待收货 | ||
| 554 | + * | ||
| 555 | + * @param userId 用户编号 | ||
| 556 | + * @param id 交易订单编号 | ||
| 557 | + * @return 交易订单 | ||
| 558 | + */ | ||
| 559 | + private TradeOrderDO validateOrderReceivable(Long userId, Long id) { | ||
| 560 | + // 校验订单是否存在 | ||
| 561 | + TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId); | ||
| 562 | + if (order == null) { | ||
| 563 | + throw exception(ORDER_NOT_FOUND); | ||
| 564 | + } | ||
| 565 | + // 校验订单是否是待收货状态 | ||
| 566 | + if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) { | ||
| 567 | + throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); | ||
| 568 | + } | ||
| 569 | + return order; | ||
| 570 | + } | ||
| 505 | 571 | ||
| 506 | - // TODO 芋艿:销售佣金的记录; | 572 | + @Override |
| 573 | + @Transactional(rollbackFor = Exception.class) | ||
| 574 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL) | ||
| 575 | + public void cancelOrder(Long userId, Long id) { | ||
| 576 | + // 1.1 校验存在 | ||
| 577 | + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | ||
| 578 | + if (order == null) { | ||
| 579 | + throw exception(ORDER_NOT_FOUND); | ||
| 580 | + } | ||
| 581 | + // 1.2 校验状态 | ||
| 582 | + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { | ||
| 583 | + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | ||
| 584 | + } | ||
| 507 | 585 | ||
| 508 | - // 插入订单日志 | ||
| 509 | - TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); | 586 | + // 2. 取消订单 |
| 587 | + cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); | ||
| 588 | + } | ||
| 589 | + | ||
| 590 | + @Override | ||
| 591 | + public int autoCancelOrder() { | ||
| 592 | + // 1. 查询过期的待支付订单 | ||
| 593 | + LocalDateTime expireTime = addTime(tradeOrderProperties.getPayExpireTime()); | ||
| 594 | + List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt( | ||
| 595 | + TradeOrderStatusEnum.UNPAID.getStatus(), expireTime); | ||
| 596 | + if (CollUtil.isEmpty(orders)) { | ||
| 597 | + return 0; | ||
| 598 | + } | ||
| 599 | + | ||
| 600 | + // 2. 遍历执行,逐个取消 | ||
| 601 | + int count = 0; | ||
| 602 | + for (TradeOrderDO order : orders) { | ||
| 603 | + try { | ||
| 604 | + getSelf().autoCancelOrder(order); | ||
| 605 | + count ++; | ||
| 606 | + } catch (Throwable e) { | ||
| 607 | + log.error("[autoCancelOrder][order({}) 过期订单异常]", order.getId(), e); | ||
| 608 | + } | ||
| 609 | + } | ||
| 610 | + return count; | ||
| 611 | + } | ||
| 612 | + | ||
| 613 | + /** | ||
| 614 | + * 自动取消单个订单 | ||
| 615 | + * | ||
| 616 | + * @param order 订单 | ||
| 617 | + */ | ||
| 618 | + @Transactional(rollbackFor = Exception.class) | ||
| 619 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_CANCEL) | ||
| 620 | + public void autoCancelOrder(TradeOrderDO order) { | ||
| 621 | + cancelOrder0(order, TradeOrderCancelTypeEnum.PAY_TIMEOUT); | ||
| 622 | + } | ||
| 623 | + | ||
| 624 | + /** | ||
| 625 | + * 取消订单的核心实现 | ||
| 626 | + * | ||
| 627 | + * @param order 订单 | ||
| 628 | + * @param cancelType 取消类型 | ||
| 629 | + */ | ||
| 630 | + private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { | ||
| 631 | + Long id = order.getId(); | ||
| 632 | + // 1. 更新 TradeOrderDO 状态为已取消 | ||
| 633 | + int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), | ||
| 634 | + new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) | ||
| 635 | + .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now())); | ||
| 636 | + if (updateCount == 0) { | ||
| 637 | + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | ||
| 638 | + } | ||
| 639 | + | ||
| 640 | + // 2. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 | ||
| 641 | + tradeOrderHandlers.forEach(handler -> handler.rollback()); | ||
| 642 | + | ||
| 643 | + // 3. 回滚库存 | ||
| 644 | + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); | ||
| 645 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | ||
| 646 | + | ||
| 647 | + // 4. 回滚优惠券 | ||
| 648 | + if (order.getCouponId() != null && order.getCouponId() > 0) { | ||
| 649 | + couponApi.returnUsedCoupon(order.getCouponId()); | ||
| 650 | + } | ||
| 651 | + | ||
| 652 | + // 5. 回滚积分(抵扣的) | ||
| 653 | + addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); | ||
| 654 | + | ||
| 655 | + // 6. 增加订单日志 | ||
| 656 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); | ||
| 657 | + } | ||
| 658 | + | ||
| 659 | + @Override | ||
| 660 | + @Transactional(rollbackFor = Exception.class) | ||
| 661 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_DELETE) | ||
| 662 | + public void deleteOrder(Long userId, Long id) { | ||
| 663 | + // 1.1 校验存在 | ||
| 664 | + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | ||
| 665 | + if (order == null) { | ||
| 666 | + throw exception(ORDER_NOT_FOUND); | ||
| 667 | + } | ||
| 668 | + // 1.2 校验状态 | ||
| 669 | + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus())) { | ||
| 670 | + throw exception(ORDER_DELETE_FAIL_STATUS_NOT_CANCEL); | ||
| 671 | + } | ||
| 672 | + // 2. 删除订单 | ||
| 673 | + tradeOrderMapper.deleteById(id); | ||
| 674 | + | ||
| 675 | + // 3. 记录日志 | ||
| 676 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus()); | ||
| 510 | } | 677 | } |
| 511 | 678 | ||
| 512 | @Override | 679 | @Override |
| @@ -604,28 +771,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -604,28 +771,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 604 | tradeOrderMapper.updateById(update); | 771 | tradeOrderMapper.updateById(update); |
| 605 | } | 772 | } |
| 606 | 773 | ||
| 607 | - /** | ||
| 608 | - * 校验交易订单满足可售货的条件 | ||
| 609 | - * | ||
| 610 | - * 1. 交易订单待收货 | ||
| 611 | - * | ||
| 612 | - * @param userId 用户编号 | ||
| 613 | - * @param id 交易订单编号 | ||
| 614 | - * @return 交易订单 | ||
| 615 | - */ | ||
| 616 | - private TradeOrderDO validateOrderReceivable(Long userId, Long id) { | ||
| 617 | - // 校验订单是否存在 | ||
| 618 | - TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId); | ||
| 619 | - if (order == null) { | ||
| 620 | - throw exception(ORDER_NOT_FOUND); | ||
| 621 | - } | ||
| 622 | - // 校验订单是否是待收货状态 | ||
| 623 | - if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) { | ||
| 624 | - throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); | ||
| 625 | - } | ||
| 626 | - return order; | ||
| 627 | - } | ||
| 628 | - | ||
| 629 | // =================== Order Item =================== | 774 | // =================== Order Item =================== |
| 630 | 775 | ||
| 631 | @Override | 776 | @Override |
| @@ -723,113 +868,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -723,113 +868,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 723 | return comment; | 868 | return comment; |
| 724 | } | 869 | } |
| 725 | 870 | ||
| 726 | - @Override | ||
| 727 | - @Transactional(rollbackFor = Exception.class) | ||
| 728 | - @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL) | ||
| 729 | - public void cancelOrder(Long userId, Long id) { | ||
| 730 | - // 1.1 校验存在 | ||
| 731 | - TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | ||
| 732 | - if (order == null) { | ||
| 733 | - throw exception(ORDER_NOT_FOUND); | ||
| 734 | - } | ||
| 735 | - // 1.2 校验状态 | ||
| 736 | - if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { | ||
| 737 | - throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | ||
| 738 | - } | ||
| 739 | - | ||
| 740 | - // 2. 取消订单 | ||
| 741 | - cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); | ||
| 742 | - } | ||
| 743 | - | ||
| 744 | - @Override | ||
| 745 | - public int autoCancelOrder() { | ||
| 746 | - // 1. 查询过期的待支付订单 | ||
| 747 | - LocalDateTime expireTime = addTime(tradeOrderProperties.getExpireTime()); | ||
| 748 | - List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt( | ||
| 749 | - TradeOrderStatusEnum.UNPAID.getStatus(), expireTime); | ||
| 750 | - if (CollUtil.isEmpty(orders)) { | ||
| 751 | - return 0; | ||
| 752 | - } | ||
| 753 | - | ||
| 754 | - // 2. 遍历执行,逐个取消 | ||
| 755 | - int count = 0; | ||
| 756 | - for (TradeOrderDO order : orders) { | ||
| 757 | - try { | ||
| 758 | - getSelf().autoCancelOrder(order); | ||
| 759 | - count ++; | ||
| 760 | - } catch (Throwable e) { | ||
| 761 | - log.error("[autoCancelOrder][order({}) 过期订单异常]", order.getId(), e); | ||
| 762 | - } | ||
| 763 | - } | ||
| 764 | - return count; | ||
| 765 | - } | ||
| 766 | - | ||
| 767 | - /** | ||
| 768 | - * 自动取消单个订单 | ||
| 769 | - * | ||
| 770 | - * @param order 订单 | ||
| 771 | - */ | ||
| 772 | - @Transactional(rollbackFor = Exception.class) | ||
| 773 | - @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_CANCEL) | ||
| 774 | - public void autoCancelOrder(TradeOrderDO order) { | ||
| 775 | - cancelOrder0(order, TradeOrderCancelTypeEnum.PAY_TIMEOUT); | ||
| 776 | - } | ||
| 777 | - | ||
| 778 | - /** | ||
| 779 | - * 取消订单的核心实现 | ||
| 780 | - * | ||
| 781 | - * @param order 订单 | ||
| 782 | - * @param cancelType 取消类型 | ||
| 783 | - */ | ||
| 784 | - private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { | ||
| 785 | - Long id = order.getId(); | ||
| 786 | - // 1. 更新 TradeOrderDO 状态为已取消 | ||
| 787 | - int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), | ||
| 788 | - new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) | ||
| 789 | - .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now())); | ||
| 790 | - if (updateCount == 0) { | ||
| 791 | - throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | ||
| 792 | - } | ||
| 793 | - | ||
| 794 | - // 2. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 | ||
| 795 | - tradeOrderHandlers.forEach(handler -> handler.rollback()); | ||
| 796 | - | ||
| 797 | - // 3. 回滚库存 | ||
| 798 | - List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); | ||
| 799 | - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | ||
| 800 | - | ||
| 801 | - // 4. 回滚优惠券 | ||
| 802 | - if (order.getCouponId() != null && order.getCouponId() > 0) { | ||
| 803 | - couponApi.returnUsedCoupon(order.getCouponId()); | ||
| 804 | - } | ||
| 805 | - | ||
| 806 | - // 5. 回滚积分(抵扣的) | ||
| 807 | - addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); | ||
| 808 | - | ||
| 809 | - // 6. 增加订单日志 | ||
| 810 | - TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); | ||
| 811 | - } | ||
| 812 | - | ||
| 813 | - @Override | ||
| 814 | - @Transactional(rollbackFor = Exception.class) | ||
| 815 | - @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_DELETE) | ||
| 816 | - public void deleteOrder(Long userId, Long id) { | ||
| 817 | - // 1.1 校验存在 | ||
| 818 | - TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | ||
| 819 | - if (order == null) { | ||
| 820 | - throw exception(ORDER_NOT_FOUND); | ||
| 821 | - } | ||
| 822 | - // 1.2 校验状态 | ||
| 823 | - if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus())) { | ||
| 824 | - throw exception(ORDER_DELETE_FAIL_STATUS_NOT_CANCEL); | ||
| 825 | - } | ||
| 826 | - // 2. 删除订单 | ||
| 827 | - tradeOrderMapper.deleteById(id); | ||
| 828 | - | ||
| 829 | - // 3. 记录日志 | ||
| 830 | - TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus()); | ||
| 831 | - } | ||
| 832 | - | ||
| 833 | /** | 871 | /** |
| 834 | * 判断指定订单的所有订单项,是不是都售后成功 | 872 | * 判断指定订单的所有订单项,是不是都售后成功 |
| 835 | * | 873 | * |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java
| @@ -87,7 +87,7 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { | @@ -87,7 +87,7 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { | ||
| 87 | @BeforeEach | 87 | @BeforeEach |
| 88 | public void setUp() { | 88 | public void setUp() { |
| 89 | when(tradeOrderProperties.getAppId()).thenReturn(888L); | 89 | when(tradeOrderProperties.getAppId()).thenReturn(888L); |
| 90 | - when(tradeOrderProperties.getExpireTime()).thenReturn(Duration.ofDays(1)); | 90 | + when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1)); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | @Test | 93 | @Test |
yudao-server/src/main/resources/application.yaml
| @@ -203,7 +203,8 @@ yudao: | @@ -203,7 +203,8 @@ yudao: | ||
| 203 | trade: | 203 | trade: |
| 204 | order: | 204 | order: |
| 205 | app-id: 1 # 商户编号 | 205 | app-id: 1 # 商户编号 |
| 206 | - expire-time: 2h # 支付的过期时间 | 206 | + pay-expire-time: 2h # 支付的过期时间 |
| 207 | + receive-expire-time: 14d # 收货的过期时间 | ||
| 207 | express: | 208 | express: |
| 208 | client: kd_niao | 209 | client: kd_niao |
| 209 | kd-niao: | 210 | kd-niao: |