diff --git a/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java b/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java index aa226c27..c8449df3 100644 --- a/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java @@ -12,6 +12,7 @@ import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.enums.PromotionTypeEnum; import cn.lili.modules.promotion.service.PromotionGoodsService; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; @@ -26,9 +27,12 @@ import java.util.List; * @author Chopper * @date 2020-07-03 11:20 */ +@Slf4j @Service public class StockUpdateExecute implements OrderStatusChangeEvent { + //出库失败消息 + static String outOfStockMessage = "库存不足,出库失败"; //Redis @Autowired private StringRedisTemplate stringRedisTemplate; @@ -52,7 +56,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent { switch (orderMessage.getNewStatus()) { case PAID: { - + //获取订单详情 OrderDetailVO order = orderService.queryDetail(orderMessage.getOrderSn()); //库存key 和 扣减数量 List keys = new ArrayList<>(); @@ -67,33 +71,41 @@ public class StockUpdateExecute implements OrderStatusChangeEvent { Boolean skuResult = stringRedisTemplate.execute(quantityScript, keys, values.toArray()); //如果库存扣减都成功,则记录成交订单 if (Boolean.TRUE.equals(skuResult)) { + log.info("库存扣减成功,参数为{};{}", keys, values); //库存确认之后对结构处理 orderService.afterOrderConfirm(orderMessage.getOrderSn()); //成功之后,同步库存 synchroDB(order); } else { + log.info("库存扣件失败,变更缓存key{} 变更缓存value{}", keys, values); //失败之后取消订单 this.errorOrder(orderMessage.getOrderSn()); } break; } case CANCELLED: { - + //获取订单详情 OrderDetailVO order = orderService.queryDetail(orderMessage.getOrderSn()); - if (order.getOrder().getPayStatus().equals(PayStatusEnum.PAID.name())) { + //判定是否已支付 并且 非库存不足导致库存回滚 则需要考虑订单库存返还业务 + if (order.getOrder().getPayStatus().equals(PayStatusEnum.PAID.name()) && order.getOrder().getCancelReason().equals(outOfStockMessage)) { + //库存key 和 还原数量 + List keys = new ArrayList<>(); + List values = new ArrayList<>(); + + //返还商品库存,促销库存不与返还,不然前台展示层有展示逻辑错误 for (OrderItem orderItem : order.getOrderItems()) { - if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) { - PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType()); - Integer goodsPromotionOriginStock = promotionGoodsService.getPromotionGoodsStock(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId()); - int goodsPromotionStock = goodsPromotionOriginStock + orderItem.getNum(); - String promotionGoodsStockCacheKey = PromotionGoodsService.getPromotionGoodsStockCacheKey(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId()); - stringRedisTemplate.opsForValue().set(promotionGoodsStockCacheKey, Integer.toString(goodsPromotionStock)); - } - String stockCacheKey = GoodsSkuService.getStockCacheKey(orderItem.getSkuId()); - Integer goodsOriginStock = goodsSkuService.getStock(orderItem.getSkuId()); - int goodsStock = goodsOriginStock + orderItem.getNum(); - stringRedisTemplate.opsForValue().set(stockCacheKey, Integer.toString(goodsStock)); + keys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId())); + int i = orderItem.getNum(); + values.add(Integer.toString(i)); } + //批量脚本执行库存回退 + Boolean skuResult = stringRedisTemplate.execute(quantityScript, keys, values.toArray()); + + //返还失败,则记录日志 + if (Boolean.FALSE.equals(skuResult)) { + log.error("库存回退异常,keys:{},回复库存值为: {}", keys, values); + } + rollbackOrderStock(order); } break; } @@ -108,7 +120,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent { * @param orderSn 失败入库订单信息 */ private void errorOrder(String orderSn) { - orderService.systemCancel(orderSn, "库存不足,出库失败"); + orderService.systemCancel(orderSn, outOfStockMessage); } @@ -132,8 +144,9 @@ public class StockUpdateExecute implements OrderStatusChangeEvent { } } + /** - * 写入需要更改促销库存的商品 + * 同步库存和促销库存 * * @param order 订单 */ @@ -159,6 +172,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent { if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) { PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType()); PromotionGoods pGoods = promotionGoodsService.getPromotionGoods(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId()); + //记录需要更新的促销库存信息 promotionKey.add( PromotionGoodsService.getPromotionGoodsStockCacheKey( promotionTypeEnum, @@ -170,6 +184,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent { goodsSkus.add(goodsSku); } + //批量获取商品库存 List skuStocks = cache.multiGet(skuKeys); //循环写入商品库存 for (int i = 0; i < skuStocks.size(); i++) { @@ -188,8 +203,41 @@ public class StockUpdateExecute implements OrderStatusChangeEvent { } promotionGoodsService.updateBatchById(promotionGoods); } + //商品库存,包含sku库存集合,批量更新商品库存相关 goodsSkuService.updateGoodsStuck(goodsSkus); + log.info("订单确认,库存同步:商品信息--{};促销信息---{}", goodsSkus, promotionGoods); + } + /** + * 恢复商品库存 + * + * @param order 订单 + */ + private void rollbackOrderStock(OrderDetailVO order) { + + //sku商品 + List goodsSkus = new ArrayList<>(); + //sku库存key 集合 + List skuKeys = new ArrayList<>(); + // 循环订单 + for (OrderItem orderItem : order.getOrderItems()) { + skuKeys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId())); + GoodsSku goodsSku = new GoodsSku(); + goodsSku.setId(orderItem.getSkuId()); + goodsSkus.add(goodsSku); + } + //批量获取商品库存 + List skuStocks = cache.multiGet(skuKeys); + //循环写入商品SKU库存 + for (int i = 0; i < skuStocks.size(); i++) { + goodsSkus.get(i).setQuantity(Integer.parseInt(skuStocks.get(i).toString())); + } + log.info("订单取消,库存还原:{}", goodsSkus); + //批量修改商品库存 + goodsSkuService.updateBatchById(goodsSkus); + goodsSkuService.updateGoodsStuck(goodsSkus); + + } }