Commit b3fcefa677bda5be09a6e44647daa3abb75d5b5d
1 parent
361ad2e2
trade: 会员取消订单
Showing
10 changed files
with
93 additions
and
3 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java
| @@ -28,4 +28,10 @@ public interface CouponApi { | @@ -28,4 +28,10 @@ public interface CouponApi { | ||
| 28 | */ | 28 | */ |
| 29 | CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO); | 29 | CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO); |
| 30 | 30 | ||
| 31 | + /** | ||
| 32 | + * 退还已使用的优惠券 | ||
| 33 | + * | ||
| 34 | + * @param id 优惠券编号 | ||
| 35 | + */ | ||
| 36 | + void returnUsedCoupon(Long id); | ||
| 31 | } | 37 | } |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
| @@ -33,6 +33,7 @@ public interface ErrorCodeConstants { | @@ -33,6 +33,7 @@ public interface ErrorCodeConstants { | ||
| 33 | ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用"); | 33 | ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用"); |
| 34 | ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态"); | 34 | ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态"); |
| 35 | ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内"); | 35 | ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内"); |
| 36 | + ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1013005004, "优惠劵不是已使用状态"); | ||
| 36 | 37 | ||
| 37 | // ========== 满减送活动 1013006000 ========== | 38 | // ========== 满减送活动 1013006000 ========== |
| 38 | ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1013006000, "满减送活动不存在"); | 39 | ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1013006000, "满减送活动不存在"); |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java
| @@ -34,4 +34,9 @@ public class CouponApiImpl implements CouponApi { | @@ -34,4 +34,9 @@ public class CouponApiImpl implements CouponApi { | ||
| 34 | return CouponConvert.INSTANCE.convert(coupon); | 34 | return CouponConvert.INSTANCE.convert(coupon); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | + @Override | ||
| 38 | + public void returnUsedCoupon(Long id) { | ||
| 39 | + couponService.returnUsedCoupon(id); | ||
| 40 | + } | ||
| 41 | + | ||
| 37 | } | 42 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
| @@ -75,4 +75,10 @@ public interface CouponService { | @@ -75,4 +75,10 @@ public interface CouponService { | ||
| 75 | */ | 75 | */ |
| 76 | Long getUnusedCouponCount(Long userId); | 76 | Long getUnusedCouponCount(Long userId); |
| 77 | 77 | ||
| 78 | + /** | ||
| 79 | + * 退还已使用的优惠券 | ||
| 80 | + * | ||
| 81 | + * @param id 优惠券编号 | ||
| 82 | + */ | ||
| 83 | + void returnUsedCoupon(Long id); | ||
| 78 | } | 84 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
| @@ -125,4 +125,27 @@ public class CouponServiceImpl implements CouponService { | @@ -125,4 +125,27 @@ public class CouponServiceImpl implements CouponService { | ||
| 125 | return couponMapper.selectCountByUserIdAndStatus(userId, CouponStatusEnum.UNUSED.getStatus()); | 125 | return couponMapper.selectCountByUserIdAndStatus(userId, CouponStatusEnum.UNUSED.getStatus()); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | + @Override | ||
| 129 | + public void returnUsedCoupon(Long id) { | ||
| 130 | + // 校验存在 | ||
| 131 | + CouponDO coupon = couponMapper.selectById(id); | ||
| 132 | + if (coupon == null) { | ||
| 133 | + throw exception(COUPON_NOT_EXISTS); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + // 校验状态 | ||
| 137 | + if (!CouponStatusEnum.USED.getStatus().equals(coupon.getStatus())) { | ||
| 138 | + throw exception(COUPON_STATUS_NOT_USED); | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + // 退还 | ||
| 142 | + Integer status = LocalDateTimeUtils.beforeNow(coupon.getValidEndTime()) | ||
| 143 | + // 退还时可能已经过期了 | ||
| 144 | + ? CouponStatusEnum.EXPIRE.getStatus() | ||
| 145 | + : CouponStatusEnum.UNUSED.getStatus(); | ||
| 146 | + couponMapper.updateById(new CouponDO().setId(id).setStatus(status)); | ||
| 147 | + | ||
| 148 | + // TODO 增加优惠券变动记录? | ||
| 149 | + } | ||
| 150 | + | ||
| 128 | } | 151 | } |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
| @@ -33,6 +33,7 @@ public interface ErrorCodeConstants { | @@ -33,6 +33,7 @@ public interface ErrorCodeConstants { | ||
| 33 | ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功"); | 33 | ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功"); |
| 34 | ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000023, "交易订单发货失败,砍价未成功"); | 34 | ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000023, "交易订单发货失败,砍价未成功"); |
| 35 | ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1011000024, "交易订单发货失败,发货类型不是快递"); | 35 | ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1011000024, "交易订单发货失败,发货类型不是快递"); |
| 36 | + ErrorCode ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID = new ErrorCode(1011000025, "交易订单取消失败,订单不是【待支付】状态"); | ||
| 36 | 37 | ||
| 37 | // ========== After Sale 模块 1011000100 ========== | 38 | // ========== After Sale 模块 1011000100 ========== |
| 38 | ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); | 39 | ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
| @@ -150,7 +150,7 @@ public class AppTradeOrderController { | @@ -150,7 +150,7 @@ public class AppTradeOrderController { | ||
| 150 | @Operation(summary = "取消交易订单") | 150 | @Operation(summary = "取消交易订单") |
| 151 | @Parameter(name = "id", description = "交易订单编号") | 151 | @Parameter(name = "id", description = "交易订单编号") |
| 152 | public CommonResult<Boolean> cancelOrder(@RequestParam("id") Long id) { | 152 | public CommonResult<Boolean> cancelOrder(@RequestParam("id") Long id) { |
| 153 | - // TODO @芋艿:未实现,mock 用 | 153 | + tradeOrderUpdateService.cancelOrder(getLoginUserId(), id); |
| 154 | return success(true); | 154 | return success(true); |
| 155 | } | 155 | } |
| 156 | 156 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
| @@ -86,6 +86,12 @@ public interface TradeOrderConvert { | @@ -86,6 +86,12 @@ public interface TradeOrderConvert { | ||
| 86 | default ProductSkuUpdateStockReqDTO convert(List<TradeOrderItemDO> list) { | 86 | default ProductSkuUpdateStockReqDTO convert(List<TradeOrderItemDO> list) { |
| 87 | return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list)); | 87 | return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list)); |
| 88 | } | 88 | } |
| 89 | + | ||
| 90 | + default ProductSkuUpdateStockReqDTO convertNegative(List<TradeOrderItemDO> list) { | ||
| 91 | + List<ProductSkuUpdateStockReqDTO.Item> items = TradeOrderConvert.INSTANCE.convertList(list); | ||
| 92 | + items.forEach(item -> item.setIncrCount(-item.getIncrCount())); | ||
| 93 | + return new ProductSkuUpdateStockReqDTO(items); | ||
| 94 | + } | ||
| 89 | List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list); | 95 | List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list); |
| 90 | @Mappings({ | 96 | @Mappings({ |
| 91 | @Mapping(source = "skuId", target = "id"), | 97 | @Mapping(source = "skuId", target = "id"), |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
| @@ -117,4 +117,11 @@ public interface TradeOrderUpdateService { | @@ -117,4 +117,11 @@ public interface TradeOrderUpdateService { | ||
| 117 | */ | 117 | */ |
| 118 | Long createOrderItemComment(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO); | 118 | Long createOrderItemComment(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO); |
| 119 | 119 | ||
| 120 | + /** | ||
| 121 | + * 【会员】取消订单 | ||
| 122 | + * | ||
| 123 | + * @param userId 用户ID | ||
| 124 | + * @param id 订单编号 | ||
| 125 | + */ | ||
| 126 | + void cancelOrder(Long userId, Long id); | ||
| 120 | } | 127 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| @@ -291,7 +291,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -291,7 +291,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 291 | TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems, | 291 | TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems, |
| 292 | TradePriceCalculateRespBO calculateRespBO) { | 292 | TradePriceCalculateRespBO calculateRespBO) { |
| 293 | // 下单时扣减商品库存 | 293 | // 下单时扣减商品库存 |
| 294 | - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | 294 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); |
| 295 | 295 | ||
| 296 | // 删除购物车商品 | 296 | // 删除购物车商品 |
| 297 | Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); | 297 | Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); |
| @@ -299,7 +299,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -299,7 +299,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 299 | cartService.deleteCart(userId, cartIds); | 299 | cartService.deleteCart(userId, cartIds); |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | - // 扣减积分 TODO 芋艿:待实现 | 302 | + // 扣减积分 TODO 芋艿:待实现, 这个是不是应该放到支付成功之后? |
| 303 | 303 | ||
| 304 | // 有使用优惠券时更新 | 304 | // 有使用优惠券时更新 |
| 305 | if (createReqVO.getCouponId() != null) { | 305 | if (createReqVO.getCouponId() != null) { |
| @@ -655,6 +655,41 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -655,6 +655,41 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 655 | return comment; | 655 | return comment; |
| 656 | } | 656 | } |
| 657 | 657 | ||
| 658 | + @Override | ||
| 659 | + public void cancelOrder(Long userId, Long id) { | ||
| 660 | + // 校验存在 | ||
| 661 | + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | ||
| 662 | + if (order == null) { | ||
| 663 | + throw exception(ORDER_NOT_FOUND); | ||
| 664 | + } | ||
| 665 | + // 校验状态 | ||
| 666 | + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { | ||
| 667 | + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | ||
| 668 | + } | ||
| 669 | + | ||
| 670 | + // 1.更新 TradeOrderDO 状态为已取消 | ||
| 671 | + int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), | ||
| 672 | + new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) | ||
| 673 | + .setCancelTime(LocalDateTime.now()) | ||
| 674 | + .setCancelType(TradeOrderCancelTypeEnum.MEMBER_CANCEL.getType())); | ||
| 675 | + if (updateCount == 0) { | ||
| 676 | + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | ||
| 677 | + } | ||
| 678 | + | ||
| 679 | + // 2.回滚库存 | ||
| 680 | + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); | ||
| 681 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | ||
| 682 | + | ||
| 683 | + // 3.回滚优惠券 | ||
| 684 | + couponApi.returnUsedCoupon(order.getCouponId()); | ||
| 685 | + | ||
| 686 | + // 4.回滚积分:积分是支付成功后才增加的吧? | ||
| 687 | + | ||
| 688 | + // TODO 芋艿:OrderLog | ||
| 689 | + | ||
| 690 | + // TODO 芋艿:lili 发送订单变化的消息 | ||
| 691 | + } | ||
| 692 | + | ||
| 658 | /** | 693 | /** |
| 659 | * 判断指定订单的所有订单项,是不是都售后成功 | 694 | * 判断指定订单的所有订单项,是不是都售后成功 |
| 660 | * | 695 | * |