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

之前存在商品取消后,自动回滚库存,可是忽略了商品取消可能是因为库存不足导致的问题。
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.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<String> 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<String> keys = new ArrayList<>();
List<String> 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));
keys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
int i = orderItem.getNum();
values.add(Integer.toString(i));
}
String stockCacheKey = GoodsSkuService.getStockCacheKey(orderItem.getSkuId());
Integer goodsOriginStock = goodsSkuService.getStock(orderItem.getSkuId());
int goodsStock = goodsOriginStock + orderItem.getNum();
stringRedisTemplate.opsForValue().set(stockCacheKey, Integer.toString(goodsStock));
//批量脚本执行库存回退
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<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);
}
}