库存扣减,库存回滚问题处理。

之前存在商品取消后,自动回滚库存,可是忽略了商品取消可能是因为库存不足导致的问题。
This commit is contained in:
Chopper 2021-06-17 10:37:45 +08:00
parent 7ce5b517fc
commit e4b968e0af

View File

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