Commit 9c0d0c809a340169816183b5874ebdfb5544295d

Authored by YunaiV
2 parents 68c1113e b3fcefa6

Merge branch 'mall_order_cancel' of https://gitee.com/CrazyWorld/ruoyi-vue-pro i…

…nto feature/mall_product

 Conflicts:
	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
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
... ... @@ -37,6 +37,7 @@ public interface ErrorCodeConstants {
37 37 ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用");
38 38 ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态");
39 39 ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内");
  40 + ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1013005004, "优惠劵不是已使用状态");
40 41  
41 42 // ========== 满减送活动 1013006000 ==========
42 43 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
... ... @@ -116,4 +116,11 @@ public interface CouponService {
116 116 default void takeCouponByRegister(Long templateId, Long userId) {
117 117 takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER);
118 118 }
  119 +
  120 + /**
  121 + * 退还已使用的优惠券
  122 + *
  123 + * @param id 优惠券编号
  124 + */
  125 + void returnUsedCoupon(Long id);
119 126 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
... ... @@ -202,4 +202,27 @@ public class CouponServiceImpl implements CouponService {
202 202 userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount());
203 203 }
204 204  
  205 + @Override
  206 + public void returnUsedCoupon(Long id) {
  207 + // 校验存在
  208 + CouponDO coupon = couponMapper.selectById(id);
  209 + if (coupon == null) {
  210 + throw exception(COUPON_NOT_EXISTS);
  211 + }
  212 +
  213 + // 校验状态
  214 + if (!CouponStatusEnum.USED.getStatus().equals(coupon.getStatus())) {
  215 + throw exception(COUPON_STATUS_NOT_USED);
  216 + }
  217 +
  218 + // 退还
  219 + Integer status = LocalDateTimeUtils.beforeNow(coupon.getValidEndTime())
  220 + // 退还时可能已经过期了
  221 + ? CouponStatusEnum.EXPIRE.getStatus()
  222 + : CouponStatusEnum.UNUSED.getStatus();
  223 + couponMapper.updateById(new CouponDO().setId(id).setStatus(status));
  224 +
  225 + // TODO 增加优惠券变动记录?
  226 + }
  227 +
205 228 }
... ...
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
... ... @@ -149,7 +149,7 @@ public class AppTradeOrderController {
149 149 @Operation(summary = "取消交易订单")
150 150 @Parameter(name = "id", description = "交易订单编号")
151 151 public CommonResult<Boolean> cancelOrder(@RequestParam("id") Long id) {
152   - // TODO @芋艿:未实现,mock 用
  152 + tradeOrderUpdateService.cancelOrder(getLoginUserId(), id);
153 153 return success(true);
154 154 }
155 155  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
... ... @@ -88,6 +88,11 @@ public interface TradeOrderConvert {
88 88 return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list));
89 89 }
90 90  
  91 + default ProductSkuUpdateStockReqDTO convertNegative(List<TradeOrderItemDO> list) {
  92 + List<ProductSkuUpdateStockReqDTO.Item> items = TradeOrderConvert.INSTANCE.convertList(list);
  93 + items.forEach(item -> item.setIncrCount(-item.getIncrCount()));
  94 + return new ProductSkuUpdateStockReqDTO(items);
  95 + }
91 96 List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
92 97  
93 98 @Mappings({
... ...
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
... ... @@ -299,7 +299,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
299 299 // 1)如果是秒杀商品:额外扣减秒杀的库存;
300 300 // 2)如果是拼团活动:额外扣减拼团的库存;
301 301 // 3)如果是砍价活动:额外扣减砍价的库存;
302   - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
  302 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems));
303 303  
304 304 // 删除购物车商品
305 305 Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
... ... @@ -308,6 +308,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
308 308 }
309 309  
310 310 // 扣减积分 TODO 芋艿:待实现,需要前置;
  311 + // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣
311 312  
312 313 // 有使用优惠券时更新 TODO 芋艿:需要前置;
313 314 if (createReqVO.getCouponId() != null) {
... ... @@ -670,6 +671,41 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
670 671 return comment;
671 672 }
672 673  
  674 + @Override
  675 + public void cancelOrder(Long userId, Long id) {
  676 + // 校验存在
  677 + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId);
  678 + if (order == null) {
  679 + throw exception(ORDER_NOT_FOUND);
  680 + }
  681 + // 校验状态
  682 + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) {
  683 + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
  684 + }
  685 +
  686 + // 1.更新 TradeOrderDO 状态为已取消
  687 + int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(),
  688 + new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus())
  689 + .setCancelTime(LocalDateTime.now())
  690 + .setCancelType(TradeOrderCancelTypeEnum.MEMBER_CANCEL.getType()));
  691 + if (updateCount == 0) {
  692 + throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
  693 + }
  694 +
  695 + // 2.回滚库存
  696 + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
  697 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
  698 +
  699 + // 3.回滚优惠券
  700 + couponApi.returnUsedCoupon(order.getCouponId());
  701 +
  702 + // 4.回滚积分:积分是支付成功后才增加的吧?
  703 +
  704 + // TODO 芋艿:OrderLog
  705 +
  706 + // TODO 芋艿:lili 发送订单变化的消息
  707 + }
  708 +
673 709 /**
674 710 * 判断指定订单的所有订单项,是不是都售后成功
675 711 *
... ...