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,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
@@ -37,6 +37,7 @@ public interface ErrorCodeConstants { @@ -37,6 +37,7 @@ public interface ErrorCodeConstants {
37 ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用"); 37 ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用");
38 ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态"); 38 ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态");
39 ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内"); 39 ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内");
  40 + ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1013005004, "优惠劵不是已使用状态");
40 41
41 // ========== 满减送活动 1013006000 ========== 42 // ========== 满减送活动 1013006000 ==========
42 ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1013006000, "满减送活动不存在"); 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,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
@@ -116,4 +116,11 @@ public interface CouponService { @@ -116,4 +116,11 @@ public interface CouponService {
116 default void takeCouponByRegister(Long templateId, Long userId) { 116 default void takeCouponByRegister(Long templateId, Long userId) {
117 takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER); 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,4 +202,27 @@ public class CouponServiceImpl implements CouponService {
202 userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount()); 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,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
@@ -149,7 +149,7 @@ public class AppTradeOrderController { @@ -149,7 +149,7 @@ public class AppTradeOrderController {
149 @Operation(summary = "取消交易订单") 149 @Operation(summary = "取消交易订单")
150 @Parameter(name = "id", description = "交易订单编号") 150 @Parameter(name = "id", description = "交易订单编号")
151 public CommonResult<Boolean> cancelOrder(@RequestParam("id") Long id) { 151 public CommonResult<Boolean> cancelOrder(@RequestParam("id") Long id) {
152 - // TODO @芋艿:未实现,mock 用 152 + tradeOrderUpdateService.cancelOrder(getLoginUserId(), id);
153 return success(true); 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,6 +88,11 @@ public interface TradeOrderConvert {
88 return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list)); 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 List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list); 96 List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
92 97
93 @Mappings({ 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,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
@@ -299,7 +299,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -299,7 +299,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
299 // 1)如果是秒杀商品:额外扣减秒杀的库存; 299 // 1)如果是秒杀商品:额外扣减秒杀的库存;
300 // 2)如果是拼团活动:额外扣减拼团的库存; 300 // 2)如果是拼团活动:额外扣减拼团的库存;
301 // 3)如果是砍价活动:额外扣减砍价的库存; 301 // 3)如果是砍价活动:额外扣减砍价的库存;
302 - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); 302 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems));
303 303
304 // 删除购物车商品 304 // 删除购物车商品
305 Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); 305 Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
@@ -308,6 +308,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -308,6 +308,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
308 } 308 }
309 309
310 // 扣减积分 TODO 芋艿:待实现,需要前置; 310 // 扣减积分 TODO 芋艿:待实现,需要前置;
  311 + // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣
311 312
312 // 有使用优惠券时更新 TODO 芋艿:需要前置; 313 // 有使用优惠券时更新 TODO 芋艿:需要前置;
313 if (createReqVO.getCouponId() != null) { 314 if (createReqVO.getCouponId() != null) {
@@ -670,6 +671,41 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -670,6 +671,41 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
670 return comment; 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 *