Selaa lähdekoodia

fix: 添加初定时扣库存

luofeiyun 2 viikkoa sitten
vanhempi
commit
0750989f96

+ 1 - 1
ship-module-product/ship-module-product-api/src/main/java/com/yc/ship/module/product/api/VoyageApi.java

@@ -8,7 +8,7 @@ import com.yc.ship.module.product.api.dto.ReduceStockReqDTO;
 public interface VoyageApi {
 
     /**
-     * 预减库存
+     * 初定预减库存
      * @param reqDTO 请求参数
      */
     void preReduceStock(ReduceStockReqDTO reqDTO);

+ 3 - 0
ship-module-product/ship-module-product-api/src/main/java/com/yc/ship/module/product/api/dto/ReduceStockReqDTO.java

@@ -25,6 +25,9 @@ public class ReduceStockReqDTO {
     @Schema(description = "门店ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long storeId;
 
+    @Schema(description = "当前订单使用的房间数量")
+    private BigDecimal useRoomNum;
+
     @Schema(description = "订单使用房间列表")
     List<OrderRoomDTO> orderRoomList;
 

+ 10 - 0
ship-module-product/ship-module-product-api/src/main/java/com/yc/ship/module/product/enums/ErrorCodeConstants.java

@@ -41,5 +41,15 @@ public interface ErrorCodeConstants {
 
     ErrorCode USER_NOT_DISTRIBUTOR = new ErrorCode(10_027, "该用户不是分销商");
 
+    ErrorCode VOYAGE_NO_STOCK = new ErrorCode(10_028, "该航次未设置库存");
+
+    ErrorCode VOYAGE_SHARE_STOCK_NOT_ENOUGH = new ErrorCode(10_029, "该航次共享库存不足");
+
+    ErrorCode VOYAGE_SHARE_ROOM_NOT_ENOUGH = new ErrorCode(10_030, "共享库存-%s-%s可售房间不足");
+
+    ErrorCode VOYAGE_DISTRIBUTOR_ROOM_NOT_ENOUGH = new ErrorCode(10_031, "分销商库存-%s-%s可售房间不足");
+
+
+
 
 }

+ 191 - 89
ship-module-product/ship-module-product-biz/src/main/java/com/yc/ship/module/product/api/VoyageApiImpl.java

@@ -1,31 +1,37 @@
 package com.yc.ship.module.product.api;
 
 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;
+import com.yc.ship.module.product.controller.admin.voyagestockdistributeNew.vo.VoyageStockDistributeNewDetailReqVO;
+import com.yc.ship.module.product.controller.admin.voyagestockdistributeNew.vo.VoyageStockDistributeNewRespVO;
 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.dataobject.voyagestockdistribute.VoyageStockDistributeDO;
+import com.yc.ship.module.product.dal.dataobject.voyagestockdistribute.VoyageStockDistributeNewDO;
 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.service.voyagestockdistribute.VoyageStockDistributeNewService;
+import com.yc.ship.module.resource.api.room.RoomApi;
+import com.yc.ship.module.resource.api.room.dto.RoomRespDTO;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
 
-import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception0;
+import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static com.yc.ship.module.product.enums.ErrorCodeConstants.*;
 
 @Service
 public class VoyageApiImpl implements VoyageApi{
 
     @Resource
-    private VoyageStockDistributeMapper voyageStockDistributeMapper;
+    private VoyageStockDistributeNewMapper voyageStockDistributeNewMapper;
 
     @Resource
     private VoyageStockMapper voyageStockMapper;
@@ -33,102 +39,198 @@ public class VoyageApiImpl implements VoyageApi{
     @Resource
     private VoyageStockDetailMapper voyageStockDetailMapper;
 
+    @Resource
+    private VoyageStockDistributeNewService voyageStockDistributeNewService;
+
+    @Resource
+    private RoomApi roomApi;
+
     @Transactional(rollbackFor = Exception.class)
     @Override
     //TODO: 待完善 加锁
     public void preReduceStock(ReduceStockReqDTO reqDTO) {
-        // 1.扣门店库存
-        // 2.扣分销商库存
-        // 3.扣分销商类型库存
-        // 4.扣航次库存,优先扣虚拟库存
+        //TODO: 当前阶段不考虑门店库存
 
         Integer type = reqDTO.getType();//判断是分销商还是门店下单 1:分销商,2:门店
+
+        if(type == DistributorOrStoreEnum.DISTRIBUTOR.getValue()) {//分销商下单,当前阶段不考虑门店下单
+            //分销商下单只扣分销商库存,默认是OTA,默认OTC只能门店下单
+            //初定扣分销商库存
+            preReduceStockDistributor(reqDTO);
+        }
+    }
+
+    /**
+     * 预定扣分销商库存
+     * @param reqDTO
+     */
+    private void preReduceStockDistributor(ReduceStockReqDTO reqDTO) {
+        Integer type = reqDTO.getType();
         Long voyageId = reqDTO.getVoyageId(); //航次ID
         Long distributorId = reqDTO.getDistributorId(); //分销商ID
         Long storeId = reqDTO.getStoreId(); //门店ID
-        List<ReduceStockReqDTO.OrderRoomDTO> orderRoomList = reqDTO.getOrderRoomList();//订单使用房间详情
-
-        if(type == DistributorOrStoreEnum.DISTRIBUTOR.getValue()) {//分销商下单
-            //分销商下单只扣分销商库存,默认是OTA,默认OTC只能门店下单
+        BigDecimal totalUseNum = reqDTO.getUseRoomNum(); //总共使用房间数量
 
+        // 获取航次总库存
+        VoyageStockDO stockDO = voyageStockMapper.selectById(voyageId);
+        if(stockDO == null) {
+            throw exception(VOYAGE_NO_STOCK);
         }
+        //共享库存
+        BigDecimal shareNum = stockDO.getShareNum();
+
+        ///航次库存详情
+        List<VoyageStockDetailDO> stockDetailList = voyageStockDetailMapper.selectListByVoyageId(voyageId);
+
+        //判断分销商库存是否存在
+        VoyageStockDistributeNewDetailReqVO detailReqVO = new VoyageStockDistributeNewDetailReqVO();
+        detailReqVO.setVoyageId(voyageId);
+        detailReqVO.setType(type);
+        detailReqVO.setObjectId(distributorId);
+        List<VoyageStockDistributeNewRespVO> distributeNewRespVOS =  voyageStockDistributeNewService.getDetail(detailReqVO);
+        if(distributeNewRespVOS.isEmpty()) {//分销商未分配库存,扣共享库存
+            //判断共享库存是否充足
+            if(shareNum.compareTo(totalUseNum) < 0) {
+                throw exception(VOYAGE_SHARE_STOCK_NOT_ENOUGH);
+            }
+            //判断航次房型楼层库存是否充足
+            List<ReduceStockReqDTO.OrderRoomDTO> orderRoomList = reqDTO.getOrderRoomList();//订单使用房间详情
+            Map<Long, BigDecimal> roomMap = CollectionUtils.convertMap(orderRoomList, item -> item.getRoomId(), item -> item.getNum());
+            List<Long> roomIds = CollectionUtils.convertList(orderRoomList, ReduceStockReqDTO.OrderRoomDTO::getRoomId);
+            List<RoomRespDTO> roomList = roomApi.getRoomListByIds(roomIds);
+            Map<String, BigDecimal> roomModelFloorNumMap = CollectionUtils.convertMap(roomList,
+                    item -> item.getRoomModelId() + "_" + item.getFloors(),
+                    item -> roomMap.get(item.getId()) == null ? BigDecimal.ZERO : roomMap.get(item.getId()));
+            // 判断库存是否充足
+            stockDetailList.stream().forEach(item -> {
+                BigDecimal canSellNum = item.getCanSellNum();
+                BigDecimal useNum = roomModelFloorNumMap.get(item.getRoomModelId() + "_" + item.getFloor());
+                if(useNum == null) {
+                    useNum = BigDecimal.ZERO;
+                }
+                if(canSellNum.compareTo(useNum) < 0) {
+                    throw exception(VOYAGE_SHARE_ROOM_NOT_ENOUGH.getCode(), String.format(VOYAGE_SHARE_ROOM_NOT_ENOUGH.getMsg(), item.getRoomModelName(), item.getFloor()));
+                }
+            });
+            // 库存充足,扣库存详情
+            stockDetailList.stream().forEach(item -> {
+                BigDecimal useNum = roomModelFloorNumMap.get(item.getRoomModelId() + "_" + item.getFloor());
+                if(useNum == null) {
+                    useNum = BigDecimal.ZERO;
+                }
+                // 减可售房间数
+                item.setCanSellNum(item.getCanSellNum().subtract(useNum));
+                // 减剩余房间数
+                item.setSurplusNum(item.getSurplusNum().subtract(useNum));
+                // 减虚拟房间数,此处初定,先扣虚拟库存,虚拟库存不足再扣实际库存
+                if(item.getVirtualNum().compareTo(useNum) >= 0) {
+                    item.setVirtualNum(item.getVirtualNum().subtract(useNum));
+                }else {
+                    item.setVirtualNum(BigDecimal.ZERO);
+                    // 扣实际房间数
+                    item.setRealTotalNum(item.getRealTotalNum().subtract(useNum.subtract(item.getVirtualNum())));
+                }
+                // 加预定房间数
+                item.setBookNum(item.getBookNum().add(useNum));
+
+            });
+            voyageStockDetailMapper.updateBatch(stockDetailList);
+
+            // 扣总库存
+            // 减可售房间数
+            stockDO.setCanSellNum(stockDO.getCanSellNum().subtract(totalUseNum));
+            // 减剩余房间数
+            stockDO.setSurplusNum(stockDO.getSurplusNum().subtract(totalUseNum));
+            // 减虚拟房间数,此处初定,先扣虚拟库存,虚拟库存不足再扣实际库存
+            if(stockDO.getVirtualNum().compareTo(totalUseNum) >= 0) {
+                stockDO.setVirtualNum(stockDO.getVirtualNum().subtract(totalUseNum));
+            }else {
+                stockDO.setVirtualNum(BigDecimal.ZERO);
+                // 扣实际房间数
+                stockDO.setRealTotalNum(stockDO.getRealTotalNum().subtract(totalUseNum.subtract(stockDO.getVirtualNum())));
+            }
+            // 加预定房间数
+            stockDO.setBookNum(stockDO.getBookNum().add(totalUseNum));
+            // 扣共享库存
+            stockDO.setShareNum(stockDO.getShareNum().subtract(totalUseNum));
+            voyageStockMapper.updateById(stockDO);
+        }else {
+            //分销商已分配库存,扣自身库存
 
+            //判断航次房型楼层库存是否充足
+            List<ReduceStockReqDTO.OrderRoomDTO> orderRoomList = reqDTO.getOrderRoomList();//订单使用房间详情
+            Map<Long, BigDecimal> roomMap = CollectionUtils.convertMap(orderRoomList, item -> item.getRoomId(), item -> item.getNum());
+            List<Long> roomIds = CollectionUtils.convertList(orderRoomList, ReduceStockReqDTO.OrderRoomDTO::getRoomId);
+            List<RoomRespDTO> roomList = roomApi.getRoomListByIds(roomIds);
+            Map<String, BigDecimal> roomModelFloorNumMap = CollectionUtils.convertMap(roomList,
+                    item -> item.getRoomModelId() + "_" + item.getFloors(),
+                    item -> roomMap.get(item.getId()) == null ? BigDecimal.ZERO : roomMap.get(item.getId()));
 
-        // 1.扣门店库存
-        // 2.扣分销商库存
-        // 3.扣分销商类型库存
-//        List<VoyageStockDistributeDO> distributeDOList = voyageStockDistributeMapper.selectListByVoyageId(voyageId);
-//        List<ReduceStockReqDTO.OrderDetailReqDTO> orderDetailList = reqDTO.getOrderDetailList();
-//        Map<String, ReduceStockReqDTO.OrderDetailReqDTO> map = CollectionUtils.convertMap(orderDetailList, item -> {
-//            String key = distributorType + "_" + distributorId + "_" + storeId + "_" + item.getRoomModelId() + "_" + item.getFloor();
-//            return key;
-//        });
-//        AtomicReference<BigDecimal> totalNum = new AtomicReference<>(BigDecimal.ZERO);
-//        List<VoyageStockDistributeDO> updateList = new ArrayList<>();
-//        distributeDOList.stream().forEach(item -> {
-//            String key = item.getDistributorType() + "_" + item.getDistributorId() + "_" + item.getStoreId() + "_" + item.getRoomModelId() + "_" + item.getFloor();
-//            ReduceStockReqDTO.OrderDetailReqDTO orderDetailReqDTO = map.get(key);
-//            if (orderDetailReqDTO != null) {
-//                item.setSurplusNum(item.getSurplusNum().subtract(orderDetailReqDTO.getNum()));
-//                item.setBookNum(item.getBookNum().add(orderDetailReqDTO.getNum()));
-//                updateList.add(item);
-//            }
-//            totalNum.updateAndGet(v -> v.add(item.getNum()));
-//        });
-//        BigDecimal total = totalNum.get();
-//        voyageStockDistributeMapper.updateBatch(updateList);
-//
-//        // 4.扣航次库存,优先扣虚拟库存
-//        VoyageStockDO stockDO = voyageStockMapper.selectById(voyageId);
-//        //判断可售房间数是否大于等于订单的房间数
-//        if(stockDO.getCanSellNum().compareTo(total) == -1) {
-//            throw exception0(500,"可售房间数不足");
-//        }
-//        //减虚拟房间数
-//        if(stockDO.getVirtualNum().compareTo(total) >=0 ) {
-//            stockDO.setVirtualNum(stockDO.getVirtualNum().subtract(totalNum.get()));
-//        }else {
-//            stockDO.setVirtualNum(BigDecimal.ZERO);
-//            // 加超卖房间数
-//            stockDO.setOversoldNum(stockDO.getOversoldNum().add(total.subtract(stockDO.getVirtualNum())));
-//        }
-//        //减可售房间数
-//        stockDO.setCanSellNum(stockDO.getCanSellNum().subtract(total));
-//        //加预定房间数
-//        stockDO.setBookNum(stockDO.getBookNum().add(total));
-//        voyageStockMapper.updateById(stockDO);
-//
-//        // 5.扣库存详情
-//        Map<String, ReduceStockReqDTO.OrderDetailReqDTO> detailMap = CollectionUtils.convertMap(orderDetailList, item -> {
-//            String key = item.getRoomModelId() + "_" + item.getFloor();
-//            return key;
-//        });
-//        List<VoyageStockDetailDO> stockDetailList = voyageStockDetailMapper.selectListByVoyageId(voyageId);
-//        List<VoyageStockDetailDO> updateDetailList = new ArrayList<>();
-//        stockDetailList.stream().forEach(item -> {
-//            String key = item.getRoomModelId() + "_" + item.getFloor();
-//            ReduceStockReqDTO.OrderDetailReqDTO orderDetailReqDTO = detailMap.get(key);
-//            BigDecimal num = orderDetailReqDTO.getNum();
-//            if (orderDetailReqDTO != null) {
-//                //判断可售房间数是否大于等于订单的房间数
-//                if(item.getCanSellNum().compareTo(num) < 0) {
-//                    throw exception0(500,"房型楼层可售房间数不足");
-//                }
-//                //减虚拟房间数
-//                if(item.getVirtualNum().compareTo(num) >= 0) {
-//                    item.setVirtualNum(item.getVirtualNum().subtract(num));
-//                }else {
-//                    item.setVirtualNum(BigDecimal.ZERO);
-//                    // 加超卖房间数
-//                    item.setOversoldNum(item.getOversoldNum().add(num.subtract(item.getVirtualNum())));
-//                }
-//                //减可售房间数
-//                item.setCanSellNum(item.getCanSellNum().subtract(num));
-//                //加预定房间数
-//                item.setBookNum(item.getBookNum().add(num));
-//                updateDetailList.add(item);
-//            }
-//        });
-//        voyageStockDetailMapper.updateBatch(updateDetailList);
+            distributeNewRespVOS.stream().forEach(item -> {
+                BigDecimal canSellNum = item.getNum();
+                BigDecimal useNum = roomModelFloorNumMap.get(item.getRoomModelId() + "_" + item.getFloor());
+                if(useNum == null) {
+                    useNum = BigDecimal.ZERO;
+                }
+                if(canSellNum.compareTo(useNum) < 0) {
+                    throw exception(VOYAGE_DISTRIBUTOR_ROOM_NOT_ENOUGH.getCode(), String.format(VOYAGE_DISTRIBUTOR_ROOM_NOT_ENOUGH.getMsg(), item.getRoomModelName(), item.getFloor()));
+                }
+            });
+            // 扣分销商库存
+            // 库存充足,扣库存详情
+            distributeNewRespVOS.stream().forEach(item -> {
+                BigDecimal useNum = roomModelFloorNumMap.get(item.getRoomModelId() + "_" + item.getFloor());
+                if(useNum == null) {
+                    useNum = BigDecimal.ZERO;
+                }
+                // 减可售房间数
+                item.setNum(item.getNum().subtract(useNum));
+            });
+            List<VoyageStockDistributeNewDO> list = BeanUtils.toBean(distributeNewRespVOS, VoyageStockDistributeNewDO.class);
+            voyageStockDistributeNewMapper.updateBatch(list);
+
+            // 库存充足,扣库存详情
+            stockDetailList.stream().forEach(item -> {
+                BigDecimal useNum = roomModelFloorNumMap.get(item.getRoomModelId() + "_" + item.getFloor());
+                if(useNum == null) {
+                    useNum = BigDecimal.ZERO;
+                }
+                // 减可售房间数
+                item.setCanSellNum(item.getCanSellNum().subtract(useNum));
+                // 减剩余房间数
+                item.setSurplusNum(item.getSurplusNum().subtract(useNum));
+                // 减虚拟房间数,此处初定,先扣虚拟库存,虚拟库存不足再扣实际库存
+                if(item.getVirtualNum().compareTo(useNum) >= 0) {
+                    item.setVirtualNum(item.getVirtualNum().subtract(useNum));
+                }else {
+                    item.setVirtualNum(BigDecimal.ZERO);
+                    // 扣实际房间数
+                    item.setRealTotalNum(item.getRealTotalNum().subtract(useNum.subtract(item.getVirtualNum())));
+                }
+                // 加预定房间数
+                item.setBookNum(item.getBookNum().add(useNum));
+
+            });
+            voyageStockDetailMapper.updateBatch(stockDetailList);
+
+            // 扣总库存
+            // 减可售房间数
+            stockDO.setCanSellNum(stockDO.getCanSellNum().subtract(totalUseNum));
+            // 减剩余房间数
+            stockDO.setSurplusNum(stockDO.getSurplusNum().subtract(totalUseNum));
+            // 减虚拟房间数,此处初定,先扣虚拟库存,虚拟库存不足再扣实际库存
+            if(stockDO.getVirtualNum().compareTo(totalUseNum) >= 0) {
+                stockDO.setVirtualNum(stockDO.getVirtualNum().subtract(totalUseNum));
+            }else {
+                stockDO.setVirtualNum(BigDecimal.ZERO);
+                // 扣实际房间数
+                stockDO.setRealTotalNum(stockDO.getRealTotalNum().subtract(totalUseNum.subtract(stockDO.getVirtualNum())));
+            }
+            // 加预定房间数
+            stockDO.setBookNum(stockDO.getBookNum().add(totalUseNum));
+            // 扣共享库存
+            stockDO.setShareNum(stockDO.getShareNum().subtract(totalUseNum));
+            voyageStockMapper.updateById(stockDO);
+        }
     }
 }

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

@@ -108,7 +108,7 @@ public class VoyageServiceImpl implements VoyageService {
             int intSum = list.stream().mapToInt(RoomModelFloorNumDTO::getNum).sum();
             BigDecimal sum = BigDecimal.valueOf(intSum);
             voyageStockDO.setTotalNum(sum);
-            voyageStockDO.setShareNum(sum);
+            voyageStockDO.setShareNum(BigDecimal.ZERO);
             voyageStockDO.setRealTotalNum(sum);
             voyageStockDO.setNotShelfNum(sum);
             voyageStockDO.setShelfedNum(BigDecimal.ZERO);

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

@@ -69,6 +69,9 @@ public class VoyageStockDetailServiceImpl implements VoyageStockDetailService {
     @Override
     public void handleShareNum(Long voyageId,  BigDecimal distributeNum) {
         VoyageStockDO stockDO = voyageStockMapper.selectById(voyageId);
+        if(distributeNum == null) {
+            distributeNum = BigDecimal.ZERO;
+        }
         stockDO.setShareNum(stockDO.getTotalNum().subtract(distributeNum));
         voyageStockMapper.updateById(stockDO);
     }

+ 2 - 0
ship-module-product/ship-module-product-biz/src/main/resources/mapper/voyagestockdistribute/VoyageStockDistributeNewMapper.xml

@@ -35,6 +35,8 @@
           AND t1.type = #{params.type}
         GROUP BY
             voyage_id
+        order by
+            t3.start_time asc
     </select>
     <select id="selectTotalDistributeNum" resultType="java.math.BigDecimal">
         select sum(num) from product_voyage_stock_distribute_new