ソースを参照

fix: 给库存加锁,直接加锁到航次上

luofeiyun 2 週間 前
コミット
8a077737c5

+ 31 - 8
ship-module-product/ship-module-product-biz/src/main/java/com/yc/ship/module/product/api/VoyageApiImpl.java

@@ -1,5 +1,6 @@
 package com.yc.ship.module.product.api;
 
+import com.yc.ship.framework.common.exception.ServiceException;
 import com.yc.ship.framework.common.util.collection.CollectionUtils;
 import com.yc.ship.framework.common.util.object.BeanUtils;
 import com.yc.ship.module.product.api.dto.ReduceStockReqDTO;
@@ -13,9 +14,13 @@ import com.yc.ship.module.product.dal.mysql.voyagestockdetail.VoyageStockDetailM
 import com.yc.ship.module.product.dal.mysql.voyagestockdistribute.VoyageStockDistributeMapper;
 import com.yc.ship.module.product.dal.mysql.voyagestockdistribute.VoyageStockDistributeNewMapper;
 import com.yc.ship.module.product.enums.DistributorOrStoreEnum;
+import com.yc.ship.module.product.framework.lock.ProductRedisKeyConstants;
 import com.yc.ship.module.product.service.voyagestockdistribute.VoyageStockDistributeNewService;
 import com.yc.ship.module.resource.api.room.RoomApi;
 import com.yc.ship.module.resource.api.room.dto.RoomRespDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -23,11 +28,13 @@ import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static com.yc.ship.module.product.enums.ErrorCodeConstants.*;
 
 @Service
+@Slf4j
 public class VoyageApiImpl implements VoyageApi{
 
     @Resource
@@ -45,18 +52,34 @@ public class VoyageApiImpl implements VoyageApi{
     @Resource
     private RoomApi roomApi;
 
+    @Resource
+    private RedissonClient redissonClient;
+
     @Transactional(rollbackFor = Exception.class)
     @Override
-    //TODO: 待完善 加锁
     public void preReduceStock(ReduceStockReqDTO reqDTO) {
-        //TODO: 当前阶段不考虑门店库存
-
-        Integer type = reqDTO.getType();//判断是分销商还是门店下单 1:分销商,2:门店
+        //TODO: 当前阶段不考虑门店库存,此处应标记已使用的房间
 
-        if(type == DistributorOrStoreEnum.DISTRIBUTOR.getValue()) {//分销商下单,当前阶段不考虑门店下单
-            //分销商下单只扣分销商库存,默认是OTA,默认OTC只能门店下单
-            //初定扣分销商库存
-            preReduceStockDistributor(reqDTO);
+        Long voyageId = reqDTO.getVoyageId();
+        //现在给整个航次的库存加锁
+        RLock lock = redissonClient.getLock(String.format(ProductRedisKeyConstants.STOCK_REDIS_KEY_PREFIX, voyageId));
+        try {
+            if(lock.tryLock(60,90, TimeUnit.SECONDS)) {
+                Integer type = reqDTO.getType();//判断是分销商还是门店下单 1:分销商,2:门店
+                if (type == DistributorOrStoreEnum.DISTRIBUTOR.getValue()) {//分销商下单,当前阶段不考虑门店下单
+                    //分销商下单只扣分销商库存,默认是OTA,默认OTC只能门店下单
+                    //初定扣分销商库存
+                    preReduceStockDistributor(reqDTO);
+                }
+            }
+        }catch (ServiceException e) {
+            log.error("订单初定扣库存失败:",e);
+        }catch (Exception e) {
+            log.error("订单初定扣库存失败:",e);
+        }finally {
+            if(lock.isHeldByCurrentThread() && lock.isLocked()){
+                lock.unlock();
+            }
         }
     }
 

+ 5 - 0
ship-module-product/ship-module-product-biz/src/main/java/com/yc/ship/module/product/dal/mysql/voyagestockdistribute/VoyageStockDistributeNewMapper.java

@@ -45,4 +45,9 @@ public interface VoyageStockDistributeNewMapper extends BaseMapperX<VoyageStockD
      * @return
      */
     BigDecimal selectTotalDistributeNum(Long voyageId);
+
+    default void deleteByVoyageId(Long id) {
+        delete(new LambdaQueryWrapperX<VoyageStockDistributeNewDO>()
+                .eq(VoyageStockDistributeNewDO::getVoyageId, id));
+    }
 }

+ 12 - 0
ship-module-product/ship-module-product-biz/src/main/java/com/yc/ship/module/product/framework/lock/ProductRedisKeyConstants.java

@@ -0,0 +1,12 @@
+package com.yc.ship.module.product.framework.lock;
+
+/**
+ * 产品的redisKey常量
+ */
+public interface ProductRedisKeyConstants {
+    /**
+     * 给航次库存加锁的key前缀 %s为航次ID
+     */
+    String STOCK_REDIS_KEY_PREFIX = "product:stock:%s";
+
+}

+ 68 - 42
ship-module-product/ship-module-product-biz/src/main/java/com/yc/ship/module/product/service/voyage/VoyageServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DatePattern;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.core.util.IdUtil;
+import com.yc.ship.framework.common.exception.ServiceException;
 import com.yc.ship.framework.common.pojo.PageResult;
 import com.yc.ship.framework.common.util.collection.CollectionUtils;
 import com.yc.ship.framework.common.util.object.BeanUtils;
@@ -16,11 +17,17 @@ import com.yc.ship.module.product.dal.mysql.voyage.VoyageMapper;
 import com.yc.ship.module.product.dal.mysql.voyagestock.VoyageStockMapper;
 import com.yc.ship.module.product.dal.mysql.voyagestockdetail.VoyageStockDetailMapper;
 import com.yc.ship.module.product.dal.mysql.voyagestockdistribute.VoyageStockDistributeMapper;
+import com.yc.ship.module.product.dal.mysql.voyagestockdistribute.VoyageStockDistributeNewMapper;
+import com.yc.ship.module.product.enums.DistributorOrStoreEnum;
 import com.yc.ship.module.product.enums.YesOrNoEnum;
+import com.yc.ship.module.product.framework.lock.ProductRedisKeyConstants;
 import com.yc.ship.module.product.utils.VoyageUUCodeUtils;
 import com.yc.ship.module.resource.api.ship.ShipApi;
 import com.yc.ship.module.resource.api.ship.dto.RoomModelFloorNumDTO;
 import com.yc.ship.module.resource.api.ship.dto.ShipRespDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -33,6 +40,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static com.yc.ship.module.product.enums.ErrorCodeConstants.VOYAGE_NOT_EXISTS;
@@ -44,6 +52,7 @@ import static com.yc.ship.module.product.enums.ErrorCodeConstants.VOYAGE_NOT_EXI
  */
 @Service
 @Validated
+@Slf4j
 public class VoyageServiceImpl implements VoyageService {
 
     @Resource
@@ -62,7 +71,10 @@ public class VoyageServiceImpl implements VoyageService {
     private PriceVoyageMapper priceVoyageMapper;
 
     @Resource
-    private VoyageStockDistributeMapper voyageStockDistributeMapper;
+    private VoyageStockDistributeNewMapper voyageStockDistributeNewMapper;
+
+    @Resource
+    private RedissonClient redissonClient;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -100,46 +112,60 @@ public class VoyageServiceImpl implements VoyageService {
         voyageStockDO.setType(reqVO.getType());
 
         VoyageStockDO stockDO = voyageStockMapper.selectById(voyageId);
-        if(stockDO != null) {
-            voyageStockMapper.updateById(voyageStockDO);
-        }else {
-            //新增时添加统计数据
-            List<RoomModelFloorNumDTO> list = shipApi.queryRoomModelFloorToNum(reqVO.getShipId());
-            int intSum = list.stream().mapToInt(RoomModelFloorNumDTO::getNum).sum();
-            BigDecimal sum = BigDecimal.valueOf(intSum);
-            voyageStockDO.setTotalNum(sum);
-            voyageStockDO.setShareNum(BigDecimal.ZERO);
-            voyageStockDO.setRealTotalNum(sum);
-            voyageStockDO.setNotShelfNum(sum);
-            voyageStockDO.setShelfedNum(BigDecimal.ZERO);
-            voyageStockDO.setBookNum(BigDecimal.ZERO);
-            voyageStockDO.setCanSellNum(BigDecimal.ZERO);
-            voyageStockDO.setVirtualNum(BigDecimal.ZERO);
-            voyageStockDO.setOversoldNum(BigDecimal.ZERO);
-            voyageStockDO.setSurplusNum(sum);
-            voyageStockDO.setVoyageId(voyageId);
-            voyageStockMapper.insert(voyageStockDO);
-            //添加库存详情
-            List<VoyageStockDetailDO> stockDetailDOS = new ArrayList<>();
-            list.stream().forEach(item -> {
-                VoyageStockDetailDO stockDetailDO = new VoyageStockDetailDO();
-                stockDetailDO.setVoyageId(voyageId);
-                stockDetailDO.setRoomModelId(item.getRoomModelId());
-                stockDetailDO.setRoomModelName(item.getRoomModelName());
-                stockDetailDO.setFloor(item.getFloor());
-                stockDetailDO.setTotalNum(BigDecimal.valueOf(item.getNum()));
-                stockDetailDO.setRealTotalNum(BigDecimal.valueOf(item.getNum()));
-                stockDetailDO.setShelfNum(BigDecimal.ZERO);
-                stockDetailDO.setNotShelfNum(BigDecimal.valueOf(item.getNum()));
-                stockDetailDO.setShelfedNum(BigDecimal.ZERO);
-                stockDetailDO.setBookNum(BigDecimal.ZERO);
-                stockDetailDO.setCanSellNum(BigDecimal.ZERO);
-                stockDetailDO.setOversoldNum(BigDecimal.ZERO);
-                stockDetailDO.setVirtualNum(BigDecimal.ZERO);
-                stockDetailDO.setSurplusNum(BigDecimal.valueOf(item.getNum()));
-                stockDetailDOS.add(stockDetailDO);
-            });
-            voyageStockDetailMapper.insertBatch(stockDetailDOS);
+        //现在给整个航次的库存加锁
+        RLock lock = redissonClient.getLock(String.format(ProductRedisKeyConstants.STOCK_REDIS_KEY_PREFIX, voyageId));
+        try {
+            if(lock.tryLock(60,90, TimeUnit.SECONDS)) {
+                if(stockDO != null) {
+                    voyageStockMapper.updateById(voyageStockDO);
+                }else {
+                    //新增时添加统计数据
+                    List<RoomModelFloorNumDTO> list = shipApi.queryRoomModelFloorToNum(reqVO.getShipId());
+                    int intSum = list.stream().mapToInt(RoomModelFloorNumDTO::getNum).sum();
+                    BigDecimal sum = BigDecimal.valueOf(intSum);
+                    voyageStockDO.setTotalNum(sum);
+                    voyageStockDO.setShareNum(BigDecimal.ZERO);
+                    voyageStockDO.setRealTotalNum(sum);
+                    voyageStockDO.setNotShelfNum(sum);
+                    voyageStockDO.setShelfedNum(BigDecimal.ZERO);
+                    voyageStockDO.setBookNum(BigDecimal.ZERO);
+                    voyageStockDO.setCanSellNum(BigDecimal.ZERO);
+                    voyageStockDO.setVirtualNum(BigDecimal.ZERO);
+                    voyageStockDO.setOversoldNum(BigDecimal.ZERO);
+                    voyageStockDO.setSurplusNum(sum);
+                    voyageStockDO.setVoyageId(voyageId);
+                    voyageStockMapper.insert(voyageStockDO);
+                    //添加库存详情
+                    List<VoyageStockDetailDO> stockDetailDOS = new ArrayList<>();
+                    list.stream().forEach(item -> {
+                        VoyageStockDetailDO stockDetailDO = new VoyageStockDetailDO();
+                        stockDetailDO.setVoyageId(voyageId);
+                        stockDetailDO.setRoomModelId(item.getRoomModelId());
+                        stockDetailDO.setRoomModelName(item.getRoomModelName());
+                        stockDetailDO.setFloor(item.getFloor());
+                        stockDetailDO.setTotalNum(BigDecimal.valueOf(item.getNum()));
+                        stockDetailDO.setRealTotalNum(BigDecimal.valueOf(item.getNum()));
+                        stockDetailDO.setShelfNum(BigDecimal.ZERO);
+                        stockDetailDO.setNotShelfNum(BigDecimal.valueOf(item.getNum()));
+                        stockDetailDO.setShelfedNum(BigDecimal.ZERO);
+                        stockDetailDO.setBookNum(BigDecimal.ZERO);
+                        stockDetailDO.setCanSellNum(BigDecimal.ZERO);
+                        stockDetailDO.setOversoldNum(BigDecimal.ZERO);
+                        stockDetailDO.setVirtualNum(BigDecimal.ZERO);
+                        stockDetailDO.setSurplusNum(BigDecimal.valueOf(item.getNum()));
+                        stockDetailDOS.add(stockDetailDO);
+                    });
+                    voyageStockDetailMapper.insertBatch(stockDetailDOS);
+                }
+            }
+        }catch (ServiceException e) {
+            log.error("创建航次失败:",e);
+        }catch (Exception e) {
+            log.error("创建航次失败:",e);
+        }finally {
+            if(lock.isHeldByCurrentThread() && lock.isLocked()){
+                lock.unlock();
+            }
         }
     }
 
@@ -211,7 +237,7 @@ public class VoyageServiceImpl implements VoyageService {
         priceVoyageMapper.deleteByVoyageId(id);
 
         //删除航次分销商库存
-        voyageStockDistributeMapper.deleteByVoyageId(id);
+        voyageStockDistributeNewMapper.deleteByVoyageId(id);
     }
 
     private void validateVoyageExists(Long id) {

+ 37 - 13
ship-module-product/ship-module-product-biz/src/main/java/com/yc/ship/module/product/service/voyagestockdetail/VoyageStockDetailServiceImpl.java

@@ -1,11 +1,17 @@
 package com.yc.ship.module.product.service.voyagestockdetail;
 
+import com.yc.ship.framework.common.exception.ServiceException;
 import com.yc.ship.module.product.controller.admin.voyagestockdetail.vo.VoyageStockDetailSaveReqVO;
 import com.yc.ship.module.product.dal.dataobject.voyagestock.VoyageStockDO;
 import com.yc.ship.module.product.dal.dataobject.voyagestockdetail.VoyageStockDetailDO;
 import com.yc.ship.module.product.dal.mysql.voyagestock.VoyageStockMapper;
 import com.yc.ship.module.product.dal.mysql.voyagestockdistribute.VoyageStockDistributeNewMapper;
+import com.yc.ship.module.product.enums.DistributorOrStoreEnum;
 import com.yc.ship.module.product.enums.ProductStockStaticsName;
+import com.yc.ship.module.product.framework.lock.ProductRedisKeyConstants;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 
@@ -19,6 +25,7 @@ import com.yc.ship.module.product.dal.mysql.voyagestockdetail.VoyageStockDetailM
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 航次库存 Service 实现类
@@ -27,6 +34,7 @@ import java.util.List;
  */
 @Service
 @Validated
+@Slf4j
 public class VoyageStockDetailServiceImpl implements VoyageStockDetailService {
 
     @Resource
@@ -37,6 +45,8 @@ public class VoyageStockDetailServiceImpl implements VoyageStockDetailService {
 
     @Resource
     private VoyageStockDistributeNewMapper voyageStockDistributeNewMapper;
+    @Resource
+    private RedissonClient redissonClient;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -45,20 +55,34 @@ public class VoyageStockDetailServiceImpl implements VoyageStockDetailService {
             return null;
         }
         Long voyageId = createReqVO.get(0).getVoyageId();
-        voyageStockDetailMapper.deleteByVoyageId(voyageId);
-        List<VoyageStockDetailDO> list = BeanUtils.toBean(createReqVO, VoyageStockDetailDO.class);
-        List<VoyageStockDetailDO> insertList = new ArrayList<>();
-        list.stream().forEach(item -> {
-            if(ProductStockStaticsName.TOTAL.equals(item.getRoomModelName())) {
-                VoyageStockDO stockDO = BeanUtils.toBean(item, VoyageStockDO.class);
-                voyageStockMapper.updateById(stockDO);
-                BigDecimal distributeNum = voyageStockDistributeNewMapper.selectTotalDistributeNum(voyageId);
-                handleShareNum(voyageId, distributeNum);
-            }else {
-                insertList.add(item);
+        //现在给整个航次的库存加锁
+        RLock lock = redissonClient.getLock(String.format(ProductRedisKeyConstants.STOCK_REDIS_KEY_PREFIX, voyageId));
+        try {
+            voyageStockDetailMapper.deleteByVoyageId(voyageId);
+            List<VoyageStockDetailDO> list = BeanUtils.toBean(createReqVO, VoyageStockDetailDO.class);
+            List<VoyageStockDetailDO> insertList = new ArrayList<>();
+            list.stream().forEach(item -> {
+                if(ProductStockStaticsName.TOTAL.equals(item.getRoomModelName())) {
+                    VoyageStockDO stockDO = BeanUtils.toBean(item, VoyageStockDO.class);
+                    voyageStockMapper.updateById(stockDO);
+                    BigDecimal distributeNum = voyageStockDistributeNewMapper.selectTotalDistributeNum(voyageId);
+                    handleShareNum(voyageId, distributeNum);
+                }else {
+                    insertList.add(item);
+                }
+            });
+            return voyageStockDetailMapper.insertBatch(insertList);
+        }catch (ServiceException e) {
+            log.error("库存设置失败:",e);
+        }catch (Exception e) {
+            log.error("库存设置失败:",e);
+        }finally {
+            if(lock.isHeldByCurrentThread() && lock.isLocked()){
+                lock.unlock();
             }
-        });
-        return voyageStockDetailMapper.insertBatch(insertList);
+        }
+        return false;
+
     }
 
     /**

+ 67 - 48
ship-module-product/ship-module-product-biz/src/main/java/com/yc/ship/module/product/service/voyagestockdistribute/VoyageStockDistributeNewServiceImpl.java

@@ -1,6 +1,7 @@
 package com.yc.ship.module.product.service.voyagestockdistribute;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yc.ship.framework.common.exception.ServiceException;
 import com.yc.ship.framework.common.pojo.PageResult;
 import com.yc.ship.framework.common.util.collection.CollectionUtils;
 import com.yc.ship.framework.common.util.object.BeanUtils;
@@ -10,11 +11,15 @@ import com.yc.ship.module.product.dal.dataobject.voyagestockdistribute.VoyageSto
 import com.yc.ship.module.product.dal.dataobject.voyagestockdistribute.VoyageStockDistributeRoomDO;
 import com.yc.ship.module.product.dal.mysql.voyagestockdistribute.VoyageStockDistributeNewMapper;
 import com.yc.ship.module.product.enums.DistributorOrStoreEnum;
+import com.yc.ship.module.product.framework.lock.ProductRedisKeyConstants;
 import com.yc.ship.module.product.service.voyagestockdetail.VoyageStockDetailService;
 import com.yc.ship.module.resource.api.room.RoomApi;
 import com.yc.ship.module.resource.api.room.dto.RoomRespDTO;
 import com.yc.ship.module.resource.dal.dataobject.roommodel.ResourceRoomModelDO;
 import com.yc.ship.module.resource.service.roommodel.ResourceRoomModelService;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -24,6 +29,7 @@ import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 
@@ -34,13 +40,12 @@ import java.util.stream.Collectors;
  */
 @Service
 @Validated
+@Slf4j
 public class VoyageStockDistributeNewServiceImpl implements VoyageStockDistributeNewService {
 
-
     @Resource
     private VoyageStockDistributeNewMapper voyageStockDistributeNewMapper;
 
-
     @Resource
     private VoyageStockDistributeRoomService voyageStockDistributeRoomService;
 
@@ -52,7 +57,8 @@ public class VoyageStockDistributeNewServiceImpl implements VoyageStockDistribut
 
     @Resource
     private VoyageStockDetailService voyageStockDetailService;
-
+    @Resource
+    private RedissonClient redissonClient;
 
 
     @Transactional(rollbackFor = Exception.class)
@@ -60,55 +66,68 @@ public class VoyageStockDistributeNewServiceImpl implements VoyageStockDistribut
     public void createVoyageStockDistributeNew(List<VoyageStockDistributeNewSaveReqVO> createReqVO) {
         BigDecimal zero = BigDecimal.ZERO;
         Long voyageId = createReqVO.get(0).getVoyageId();
-        Integer type = createReqVO.get(0).getType();
-        //删除分配的房间
-        voyageStockDistributeRoomService.deleteByVoyageId(voyageId, type);
-        // 分配的房间列表
-        List<VoyageStockDistributeRoomDO> roomList = new ArrayList<>();
-        createReqVO.stream().forEach(item -> {
-            if(!CollectionUtils.isAnyEmpty(item.getRoomList())) {
-                roomList.addAll(BeanUtils.toBean(item.getRoomList(), VoyageStockDistributeRoomDO.class));
-            }
-        });
-        voyageStockDistributeRoomService.createVoyageStockDistributeRoomBatch(roomList);
-        //修改或插入库存表
-        List<VoyageStockDistributeNewDO> list = voyageStockDistributeNewMapper.selectListByVoyageId(voyageId, type);
-        if(CollectionUtils.isAnyEmpty(list)) { // 为空则新增
-            list = BeanUtils.toBean(createReqVO, VoyageStockDistributeNewDO.class);
-            list.stream().forEach(item -> {
-                item.setBookNum(zero);
-            });
-            if(!CollectionUtils.isAnyEmpty(list)) {
-                voyageStockDistributeNewMapper.insertBatch(list);
-            }
-        }else {
-            Map<String, BigDecimal> map = CollectionUtils.convertMap(createReqVO, item -> item.getObjectId() + "_" + item.getRoomModelId() + "_" + item.getFloor(), item -> item.getNum());
-            Map<String, VoyageStockDistributeNewSaveReqVO> mapVO = CollectionUtils.convertMap(createReqVO, item -> item.getObjectId() + "_" + item.getRoomModelId() + "_" + item.getFloor());
-            List<String> existList = CollectionUtils.convertList(list, item -> item.getObjectId() + "_" + item.getRoomModelId() + "_" + item.getFloor());
-            Map<String, VoyageStockDistributeNewDO> existMap = CollectionUtils.convertMap(list, item -> item.getObjectId() + "_" + item.getRoomModelId() + "_" + item.getFloor());
-            List<VoyageStockDistributeNewDO> insertList = new ArrayList<>();// 插入数据
-            List<VoyageStockDistributeNewDO> updateList = new ArrayList<>(); //  修改数据
-            map.keySet().stream().forEach(key -> {
-                if(existList.contains(key)) { //存在,做修改
-                    VoyageStockDistributeNewDO voyageStockDistributeNewDO = existMap.get(key);
-                    voyageStockDistributeNewDO.setNum(map.get(key));
-                    voyageStockDistributeNewDO.setRoomModelNum(mapVO.get(key).getRoomModelNum());
-                    updateList.add(voyageStockDistributeNewDO);
-                }else { //不存在,做插入
-                    VoyageStockDistributeNewDO voyageStockDistributeNewDO = BeanUtils.toBean(mapVO.get(key), VoyageStockDistributeNewDO.class);
-                    insertList.add(voyageStockDistributeNewDO);
+        //现在给整个航次的库存加锁
+        RLock lock = redissonClient.getLock(String.format(ProductRedisKeyConstants.STOCK_REDIS_KEY_PREFIX, voyageId));
+        try {
+            if(lock.tryLock(60,90, TimeUnit.SECONDS)) {
+                Integer type = createReqVO.get(0).getType();
+                //删除分配的房间
+                voyageStockDistributeRoomService.deleteByVoyageId(voyageId, type);
+                // 分配的房间列表
+                List<VoyageStockDistributeRoomDO> roomList = new ArrayList<>();
+                createReqVO.stream().forEach(item -> {
+                    if(!CollectionUtils.isAnyEmpty(item.getRoomList())) {
+                        roomList.addAll(BeanUtils.toBean(item.getRoomList(), VoyageStockDistributeRoomDO.class));
+                    }
+                });
+                voyageStockDistributeRoomService.createVoyageStockDistributeRoomBatch(roomList);
+                //修改或插入库存表
+                List<VoyageStockDistributeNewDO> list = voyageStockDistributeNewMapper.selectListByVoyageId(voyageId, type);
+                if(CollectionUtils.isAnyEmpty(list)) { // 为空则新增
+                    list = BeanUtils.toBean(createReqVO, VoyageStockDistributeNewDO.class);
+                    list.stream().forEach(item -> {
+                        item.setBookNum(zero);
+                    });
+                    if(!CollectionUtils.isAnyEmpty(list)) {
+                        voyageStockDistributeNewMapper.insertBatch(list);
+                    }
+                }else {
+                    Map<String, BigDecimal> map = CollectionUtils.convertMap(createReqVO, item -> item.getObjectId() + "_" + item.getRoomModelId() + "_" + item.getFloor(), item -> item.getNum());
+                    Map<String, VoyageStockDistributeNewSaveReqVO> mapVO = CollectionUtils.convertMap(createReqVO, item -> item.getObjectId() + "_" + item.getRoomModelId() + "_" + item.getFloor());
+                    List<String> existList = CollectionUtils.convertList(list, item -> item.getObjectId() + "_" + item.getRoomModelId() + "_" + item.getFloor());
+                    Map<String, VoyageStockDistributeNewDO> existMap = CollectionUtils.convertMap(list, item -> item.getObjectId() + "_" + item.getRoomModelId() + "_" + item.getFloor());
+                    List<VoyageStockDistributeNewDO> insertList = new ArrayList<>();// 插入数据
+                    List<VoyageStockDistributeNewDO> updateList = new ArrayList<>(); //  修改数据
+                    map.keySet().stream().forEach(key -> {
+                        if(existList.contains(key)) { //存在,做修改
+                            VoyageStockDistributeNewDO voyageStockDistributeNewDO = existMap.get(key);
+                            voyageStockDistributeNewDO.setNum(map.get(key));
+                            voyageStockDistributeNewDO.setRoomModelNum(mapVO.get(key).getRoomModelNum());
+                            updateList.add(voyageStockDistributeNewDO);
+                        }else { //不存在,做插入
+                            VoyageStockDistributeNewDO voyageStockDistributeNewDO = BeanUtils.toBean(mapVO.get(key), VoyageStockDistributeNewDO.class);
+                            insertList.add(voyageStockDistributeNewDO);
+                        }
+                    });
+                    if(!CollectionUtils.isAnyEmpty(updateList)) {
+                        voyageStockDistributeNewMapper.updateBatch(updateList);
+                    }
+                    if(!CollectionUtils.isAnyEmpty(insertList)) {
+                        voyageStockDistributeNewMapper.insertBatch(insertList);
+                    }
                 }
-            });
-            if(!CollectionUtils.isAnyEmpty(updateList)) {
-                voyageStockDistributeNewMapper.updateBatch(updateList);
+                BigDecimal distributeNum = getDistributeNum(voyageId);
+                voyageStockDetailService.handleShareNum(voyageId, distributeNum);
             }
-            if(!CollectionUtils.isAnyEmpty(insertList)) {
-                voyageStockDistributeNewMapper.insertBatch(insertList);
+        }catch (ServiceException e) {
+            log.error("库存分配失败:",e);
+        }catch (Exception e) {
+            log.error("库存分配失败:",e);
+        }finally {
+            if(lock.isHeldByCurrentThread() && lock.isLocked()){
+                lock.unlock();
             }
         }
-        BigDecimal distributeNum = getDistributeNum(voyageId);
-        voyageStockDetailService.handleShareNum(voyageId, distributeNum);
-
     }
 
     @Override