Commit b3fcefa677bda5be09a6e44647daa3abb75d5b5d

Authored by owen
1 parent 361ad2e2

trade: 会员取消订单

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 28 */
29 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 33 ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用");
34 34 ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态");
35 35 ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内");
  36 + ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1013005004, "优惠劵不是已使用状态");
36 37  
37 38 // ========== 满减送活动 1013006000 ==========
38 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 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 75 */
76 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 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 33 ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功");
34 34 ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000023, "交易订单发货失败,砍价未成功");
35 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 38 // ========== After Sale 模块 1011000100 ==========
38 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 150 @Operation(summary = "取消交易订单")
151 151 @Parameter(name = "id", description = "交易订单编号")
152 152 public CommonResult<Boolean> cancelOrder(@RequestParam("id") Long id) {
153   - // TODO @芋艿:未实现,mock 用
  153 + tradeOrderUpdateService.cancelOrder(getLoginUserId(), id);
154 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 86 default ProductSkuUpdateStockReqDTO convert(List<TradeOrderItemDO> list) {
87 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 95 List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
90 96 @Mappings({
91 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 117 */
118 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 291 TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems,
292 292 TradePriceCalculateRespBO calculateRespBO) {
293 293 // 下单时扣减商品库存
294   - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
  294 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems));
295 295  
296 296 // 删除购物车商品
297 297 Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
... ... @@ -299,7 +299,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
299 299 cartService.deleteCart(userId, cartIds);
300 300 }
301 301  
302   - // 扣减积分 TODO 芋艿:待实现
  302 + // 扣减积分 TODO 芋艿:待实现, 这个是不是应该放到支付成功之后?
303 303  
304 304 // 有使用优惠券时更新
305 305 if (createReqVO.getCouponId() != null) {
... ... @@ -655,6 +655,41 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
655 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 *
... ...