package com.prolog.eis.service.shelves.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.codingapi.tx.annotation.TxTransaction;
import com.google.common.collect.Lists;
import com.prolog.cs.basic.item.model.vo.ItemSyncQueryByIdVO;
import com.prolog.eis.common.util.ListHelper;
import com.prolog.eis.common.util.PrologStringUtils;
import com.prolog.eis.common.util.location.LocationConstants;
import com.prolog.eis.constants.base.*;
import com.prolog.eis.constants.cfg.LocationCfgConstants;
import com.prolog.eis.constants.cfg.StationCfgConstants;
import com.prolog.eis.constants.station.StationTaskTypeConstants;
import com.prolog.eis.constants.sys.SysParamConstants;
import com.prolog.eis.constants.wms.WmsConstants;
import com.prolog.eis.core.dto.route.*;
import com.prolog.eis.core.model.biz.carry.CarryTask;
import com.prolog.eis.core.model.biz.route.ContainerLocation;
import com.prolog.eis.dao.BizPropertyMapper;
import com.prolog.eis.dao.device.DeviceInfoMapper;
import com.prolog.eis.dao.out.*;
import com.prolog.eis.dao.shelves.*;
import com.prolog.eis.dao.shelves.area.CategoryAreaNoMapper;
import com.prolog.eis.dao.shelves.sys.SysParamMapper;
import com.prolog.eis.dto.inbound.*;
import com.prolog.eis.dto.item.ItemSyncVO;
import com.prolog.eis.dto.page.PageUtilDto;
import com.prolog.eis.dto.shelves.*;
import com.prolog.eis.dto.strategy.ContainerInfoDto;
import com.prolog.eis.dto.wms.WmsContainerStatusUpdateDto;
import com.prolog.eis.dto.wms.WmsTaskFinishDto;
import com.prolog.eis.dto.wms.WmsWarehouseChangeDto;
import com.prolog.eis.enums.base.BaseStatusEnum;
import com.prolog.eis.enums.base.LayerEnum;
import com.prolog.eis.enums.wms.WmsCarryTaskInCode;
import com.prolog.eis.feign.ItemFeign;
import com.prolog.eis.feign.WarehouseFeign;
import com.prolog.eis.model.container.*;
import com.prolog.eis.model.device.DeviceInfo;
import com.prolog.eis.model.inbound.BizInboundTask;
import com.prolog.eis.model.inbound.BizInboundTaskDetail;
import com.prolog.eis.model.inbound.InboundRecord;
import com.prolog.eis.model.outbound.*;
import com.prolog.eis.model.shelves.*;
import com.prolog.eis.model.sys.SysParam;
import com.prolog.eis.router.vo.ContainerLocationVo;
import com.prolog.eis.service.container.EmptyContainerTaskService;
import com.prolog.eis.service.feign.RouteFeignService;
import com.prolog.eis.service.out.*;
import com.prolog.eis.service.shelves.*;
import com.prolog.eis.service.wms.WmsContainerStatusUpdateService;
import com.prolog.eis.service.wms.WmsTaskFinishBackService;
import com.prolog.eis.service.wms.WmsWarehouseChangeService;
import com.prolog.eis.utils.ABCSurplusLocation;
import com.prolog.eis.utils.AngleConversionAB;
import com.prolog.eis.vo.ContainerVO;
import com.prolog.eis.vo.GoodsInfoVO;
import com.prolog.eis.vo.GoodsShelvesVO;
import com.prolog.eis.vo.InboundTaskVO;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.authority.user.UserTemplate;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.framework.utils.AssertUtils;
import com.prolog.framework.utils.MapUtils;
import com.prolog.fx.inf.core.InterfaceType;
import com.prolog.fx.inf.core.annotation.InterfaceMethod;
import com.prolog.upcloud.base.inventory.model.BatchNumberSync;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.prolog.eis.constants.item.CategoryAreaNoConstants.MEDICINE_TYPE;


@Service
@Slf4j
public class InboundTaskServiceImpl implements InboundTaskService {

    @Resource
    StationService stationService;

    @Resource
    StationCfgMapper stationCfgMapper;

    @Resource
    WarehouseFeign warehouseFeign;

    @Resource
    ItemService itemService;
    @Resource
    InventoryService inventoryService;
    @Resource
    BizInboundTaskMapper bizInboundTaskMapper;

    @Resource
    PalletMoveExecuteService palletMoveExecuteService;

    @Resource
    BizInboundTaskDetailMapper bizInboundTaskDetailMapper;

    @Resource
    ContainerInfoMapper containerInfoMapper;

    @Resource
    ContainerInfoDetailMapper containerInfoDetailMapper;

    @Resource
    PalletLocationMapper palletLocationMapper;

    @Resource
    InboundRecordMapper inboundRecordMapper;

    @Resource
    BizPropertyMapper bizPropertyMapper;

    @Resource
    PalletInfoMapper palletInfoMapper;

    @Resource
    ContainerStoreChangeService containerStoreChangeService;

    @Resource
    CategoryAreaNoMapper categoryAreaNoMapper;

    @Resource
    GoodsInfoService goodsInfoService;

    @Resource
    UserService userService;

    @Resource
    ItemFeign itemFeign;

    @Resource
    private UserTemplate userTemplate;

    @Resource
    private ContainerInfoService containerInfoService;

    @Resource
    private ContainerInfoDetailService containerInfoDetailService;

    @Resource
    private StationCfgService stationCfgService;
    @Resource
    private RouteFeignService routeFeignService;
    @Resource
    private BizOutboundTaskService bizOutboundTaskService;
    @Resource
    private BizOutboundTaskDetailService bizOutboundTaskDetailService;
    @Resource
    private ContainerTaskService containerTaskService;
    @Resource
    private BizOutboundTaskHisService bizOutboundTaskHisService;
    @Resource
    private BizOutboundTaskDetailHisService bizOutboundTaskDetailHisService;
    @Resource
    private ContainerTaskHisService containerTaskHisService;
    @Resource
    private WmsTaskFinishBackService wmsTaskFinishBackService;
    @Resource
    private EmptyContainerTaskService emptyContainerTaskService;
    @Resource
    private ContainerStoreChangeMapper containerStoreChangeMapper;
    @Resource
    private LocationCfgService locationCfgService;
    @Resource
    private WmsWarehouseChangeService wmsWarehouseChangeService;

    @Autowired
    private OrderLogMapper orderLogMapper;
    @Resource
    private DismantlingLocationHitRecordService dismantlingLocationHitRecordService;

    @Resource
    private DeviceInfoMapper deviceInfoMapper;

    @Resource
    SysParamMapper sysParamMapper;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private WmsContainerStatusUpdateService wmsContainerStatusUpdateService;


    @Value("${prolog.goods.wms-item-url:}")
    private String wmsItemUrl;

    @Override
    public RestMessage<InboundTaskVO> checkStation(String stationNo) throws Exception {

        List<StationCfg> list = stationCfgMapper.findByMap(MapUtils.put("stationNo", stationNo).put("taskType", StationCfgConstants.UP).getMap(), StationCfg.class);
        if (list.isEmpty()) {
            return RestMessage.newInstance(false, "201", "站台未配置，请检查", null);
        }

        final List<StationCfg> stationCfgs = list.stream().filter(x -> x.getIsLock().equals(0) && x.getIsAsk().equals(0)).collect(Collectors.toList());

        if (stationCfgs.isEmpty()) {
            return RestMessage.newInstance(false, "201", "站台被锁或索取任务被关，请检查", null);
        }

        if (null == stationCfgs.get(0).getMaxCachePosition() || stationCfgs.get(0).getMaxCachePosition() <= 0) {
            return RestMessage.newInstance(false, "201", "站台缓存配置错误，请检查", null);
        }
//        RestMessage<WhArea> whAreaRestMessage = warehouseFeign.getAreaByAreaNo(stationCfgs.get(0).getAreaNo());
//        if (!whAreaRestMessage.isSuccess()) {
//            throw new Exception("查询区域仓库服务报错" + whAreaRestMessage.getMessage());
//        }
//        WhArea whArea = whAreaRestMessage.getData();
//
//        if (null == whArea) {
//            throw new Exception(String.format("%s区域不存在", stationCfgs.get(0).getStationNo()));
//        }
//
//        RestMessage<List<WhAreaDirection>> areaOrEndArea = warehouseFeign
//                .findStartAreaOrEndArea(stationCfgs.stream().map(StationCfg::getAreaNo).collect(Collectors.toList()));
//
//        if (!areaOrEndArea.isSuccess()) {
//            throw new Exception("查询区域方向仓库服务报错" + whAreaRestMessage.getMessage());
//        }
//
//        if (null == areaOrEndArea) {
//            throw new Exception(String.format("%s区域方向不存在", stationCfgs.get(0).getStationNo()));
//        }

        InboundTaskVO resultInfo = new InboundTaskVO();
        List<GoodsInfoVO> result = bizInboundTaskMapper.getInboundTaskList(null, stationCfgs.get(0).getId());
        List<GoodsShelvesVO> shelves = bizInboundTaskDetailMapper.findCacheTasks(stationCfgs.get(0).getId(), WmsConstants.AGVHJ01);

        if (result.size() > 0 && shelves.size() > 0) {
            result.forEach(p -> p.setStationNo(stationNo));
            GoodsInfoVO param = result.get(0);
            GoodsShelvesVO goodsShelve = null;
            List<GoodsShelvesVO> collect = shelves.stream().filter(p -> StrUtil.isNotBlank(p.getPlanes()) && p.getPlanes().equals(AngleConversionAB.getDirectionStr(p.getAngle(), stationCfgs.get(0).getAngle()))).collect(Collectors.toList());
            if (collect.size() > 0) {
                goodsShelve = collect.get(0);
                List<GoodsInfoVO> collects = goodsInfoService.getGoodsInfo(Lists.newArrayList(param));
                resultInfo.setResults(collects);
            } else {
                return RestMessage.newInstance(true, "验证通过", null);
            }
            param.setPalletNo(goodsShelve.getPalletNo());
            param.setPalletLocation(goodsShelve.getPalletLocation());
            param.setPlanes(goodsShelve.getPlanes());
            resultInfo = getPalletNoLocation(resultInfo, goodsShelve.getPalletLocation(), param.getPalletNo(), goodsShelve.getPlanes());
            return RestMessage.newInstance(true, "验证通过", resultInfo);
        } else {
            return RestMessage.newInstance(true, "验证通过");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    public void scanContainerNo(ScanContainerNoDto dto) throws Exception {
        List<String> itemIds = bizInboundTaskDetailMapper.findInboundTask(dto.getContainerNo(), WmsConstants.AGVHJ01);
        Assert.notEmpty(itemIds, "此托盘暂无上架任务！");
        /*StationCfg stationCfg = stationCfgMapper.findByMap(MapUtils.put("stationNo",dto.getStationNo()).getMap(), StationCfg.class).get(0);
        //查询已经有任务货架的数量
        final List<PalletInfo> palletInfoList = palletInfoMapper.findByMap(MapUtils.put("subArea", stationCfg.getAreaNo()).getMap(), PalletInfo.class);
        int palletNum =  palletInfoList.size();
        if(palletNum < stationCfg.getMaxCachePosition()){
           *//* Criteria criteria = Criteria.forClass(BizProperty.class);
            criteria.setRestriction(Restrictions.in("id",bizPropertyIds.toArray()));
            List<BizProperty> bizPropertyList = bizPropertyMapper.findByCriteria(criteria);
            // 判断未入库的入库任务商品大类数量
            List<String> goodsIds = ListHelper.distinct(ListHelper.select(bizPropertyList, BizProperty::getGoodsId));
            List<ItemSyncVO> itemSyncVOS = itemService.queryItemMst(goodsIds);*//*

            Criteria criteriaGoodsInfo = Criteria.forClass(GoodsInfo.class);
            criteriaGoodsInfo.restrictionBuilder().in(GoodsInfo::getItemId, itemIds.toArray()).build();
            List<GoodsInfo> goodsInfos =  goodsInfoService.findByCriteria(criteriaGoodsInfo);
            //查询出所有需要入库的商品大类
            List<GoodsInfo> syncVOList = ListHelper.distinct(goodsInfos, GoodsInfo::getItemType);

            List<String> itemCategoryCodes = ListHelper.select(syncVOList, GoodsInfo::getItemType);
            Assert.notEmpty(itemCategoryCodes,"商品大类为空！");
            itemCategoryCodes.removeAll(ListHelper.distinct(ListHelper.select(palletInfoList, PalletInfo::getPalletType)));

            //依据商品大类查询货架信息
            if(itemCategoryCodes.size() > palletNum){
                for(GoodsInfo itemSyncVO : syncVOList){
                    List<GoodsShelvesVO> goodsShelvesVOList = bizInboundTaskDetailMapper.findPalletNo(null, Lists.newArrayList(itemSyncVO.getItemType()),
                            Lists.newArrayList(itemSyncVO.getAbcType()), null, WmsConstants.AGVHJ01);

                    if(!goodsShelvesVOList.isEmpty()){
                        goodsShelvesVOList = ListHelper.distinct(goodsShelvesVOList, GoodsShelvesVO::getPalletType);

                        final List<GoodsShelvesVO> shelvesVOS = goodsShelvesVOList.stream()
                                .filter(x -> !"0".equals(x.getPalletType()) && !Objects.isNull(x.getProperty()))
                                .collect(Collectors.toList());
                        // 呼叫有容积的货架
                        if (!shelvesVOS.isEmpty() && palletNum <stationCfg.getMaxCachePosition()) {
                            if(!shelvesVOS.isEmpty()){
                                palletNum = callPalletNum(shelvesVOS, palletNum, stationCfg);
                                continue;
                            }
                        }
                        // 呼叫有空货位的货架
                        if (palletNum <stationCfg.getMaxCachePosition()) {
                            List<GoodsShelvesVO>  shelves = goodsShelvesVOList.stream()
                                    .filter(x -> !"0".equals(x.getPalletType()) && Objects.isNull(x.getProperty()))
                                    .collect(Collectors.toList());
                            if(!shelves.isEmpty()){
                                palletNum = callPalletNum(shelves, palletNum, stationCfg);
                                continue;
                            }
                        }
                        // 呼叫空货架
                        if (palletNum <stationCfg.getMaxCachePosition()) {
                            List<GoodsShelvesVO>  shelves = goodsShelvesVOList.stream()
                                    .filter(x -> "0".equals(x.getPalletType())&& !Objects.isNull(x.getProperty()))
                                    .collect(Collectors.toList());
                            if(!shelves.isEmpty()){
                                palletNum = callPalletNum(shelves, palletNum, stationCfg);
                                continue;
                            }
                        }
                        itemCategoryCodes.remove(itemSyncVO.getItemType());
                    };
                }
            }
            // 查询出无货架匹配的商品大类
            if(palletNum < stationCfg.getMaxCachePosition() && itemCategoryCodes.size() > palletNum){
                Criteria criteria1 = Criteria.forClass(CategoryAreaNo.class);
                criteria1.setRestriction(Restrictions.in(CategoryAreaNo::getItemHealthCategory,itemCategoryCodes));
                final List<CategoryAreaNo> categoryAreaNos = categoryAreaNoMapper.findByCriteria(criteria1);
                Assert.notEmpty(categoryAreaNos,String.format("商品大类%s区域未维护！", JSON.toJSONString(itemCategoryCodes)));

                List<PalletInfoVo> palletInfoVos = palletInfoMapper.queryEmptyPalletList(ListHelper.distinct(ListHelper.select(categoryAreaNos, CategoryAreaNo::getAreaNo)));
                if(!palletInfoVos.isEmpty()){
                    palletInfoVos = ListHelper.distinct(palletInfoVos,PalletInfoVo::getPalletNo);
                    for(PalletInfoVo  palletInfoVo :palletInfoVos) {
                        if(palletNum >= stationCfg.getMaxCachePosition() || palletNum >= itemCategoryCodes.size()){
                            break;
                        }
                        final GoodsShelvesVO goodsShelvesVO = new GoodsShelvesVO();
                        BeanUtils.copyProperties(palletInfoVo,goodsShelvesVO);
                        //goodsShelvesVO.setBizPropertyId(0L);
                        callPalletNum(Lists.newArrayList(goodsShelvesVO), palletNum, stationCfg);
                        palletNum +=1;
                    }
                }else {
                    //throw new Exception(String.format("区域%s无货架!",ListHelper.select(categoryAreaNos,CategoryAreaNo::getAreaNo)).toString());
                    log.error(String.format("区域%s无货架!",ListHelper.select(categoryAreaNos,CategoryAreaNo::getAreaNo)).toString());
                }
            }
        }*/
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    public boolean callShelves(BizInboundTask inboundTask) throws Exception {
        List<BizInboundTaskDetail> bizInboundTaskDetails = inboundTask.getSubList();
        String[] itemIds = bizInboundTaskDetails.stream().map(BizInboundTaskDetail::getItemId).distinct().toArray(String[]::new);
        List<ItemSyncVO> itemSyncVOS = itemService.queryItemMst(Arrays.asList(itemIds));
        Assert.isTrue(CollectionUtil.isNotEmpty(itemSyncVOS), "商品信息查询为空");

        Criteria criteriaStation = Criteria.forClass(StationCfg.class);
        String[] stationNos = new String[]{StationTypeConstant.STATION_TYP_70, StationTypeConstant.STATION_TYP_71};
        criteriaStation.restrictionBuilder().in(StationCfg::getStationType, stationNos).eq(StationCfg::getTaskType, StationCfgConstants.UP).build();
        List<StationCfg> stationCfgs = stationCfgService.findByCriteria(criteriaStation);
        StationCfg stationCfg = stationCfgs.stream().filter(item -> StrUtil.equals(item.getId().toString(), inboundTask.getExtend1())).findFirst().orElseThrow(() -> new PrologException("未查询到拆零上架托盘到位的站台"));
        //匹配任务数最少的拆零库上架站台
//        StationCfg stationCfg = getLeastTaskStation(areaNos, uStationCfgs);
        StationCfg cStationCfg = stationCfgs.stream().filter(c -> c.getStationType().equals(StationCfgConstants.CL_C) && stationCfg.getId().equals(c.getRelationalId())).findFirst().orElse(null);
        Assert.notNull(cStationCfg, String.format("站台" + stationCfg.getStationNo() + "对应叫料站台为空，请配置拆零库叫料站台！"));
        //定位托盘或者货架
        ContainerVO containerVO = getContainer(inboundTask, bizInboundTaskDetails, itemSyncVOS);
        log.info(String.format(">>>>>入库单【%s】拆零上架定位到的货架为:【%s】]", inboundTask.getBillNo(), JSONUtil.toJsonStr(containerVO)));
        //呼叫货架
        callPalletNum(containerVO, cStationCfg);
        //呼叫容器
        callContainer(containerVO, cStationCfg);
        return true;
    }


    /**
     * 查询足够容器
     *
     * @param details
     * @param itemSyncVOS
     */
    private ContainerVO getContainer(BizInboundTask inboundTask, List<BizInboundTaskDetail> details, List<ItemSyncVO> itemSyncVOS) throws Exception {
        ContainerVO containerVO = new ContainerVO();
        List<String> itemSyncVOA = itemSyncVOS.stream().filter(i -> AbcTypeConstant.TYPE_A.equals(i.getAbcType())).map(ItemSyncVO::getItemId).collect(Collectors.toList());
        List<String> itemSyncVOBc = itemSyncVOS.stream().filter(i -> AbcTypeConstant.TYPE_B.equals(i.getAbcType()) || AbcTypeConstant.TYPE_C.equals(i.getAbcType())).map(ItemSyncVO::getItemId).collect(Collectors.toList());
        List<ItemSyncVO> itemSyncVOAs = itemSyncVOS.stream().filter(i -> AbcTypeConstant.TYPE_A.equals(i.getAbcType())).collect(Collectors.toList());

        //BizInboundTaskDetail detail = details.get(0);
        //ItemSyncVO itemSyncVO = itemSyncVOS.stream().filter(i -> i.getItemId().equals(detail.getItemId())).findFirst().orElse(null);
        List<BizInboundTaskDetail> taskDetailsA = details.stream().filter(i -> itemSyncVOA.contains(i.getItemId())).collect(Collectors.toList());
        List<BizInboundTaskDetail> taskDetailsBc = details.stream().filter(i -> itemSyncVOBc.contains(i.getItemId())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(taskDetailsA)) {
            //查询拆零区的所有空托和料托
            List<String> lotIds = taskDetailsA.stream().map(BizInboundTaskDetail::getLotId).collect(Collectors.toList());
            List<ContainerInfoDto> containerInfoDtos = containerInfoService.getContainerInfo();
            List<ContainerInfoDto> thisContainerInfo = containerInfoDtos.stream().filter(c -> (itemSyncVOA.contains(c.getItemId()) && lotIds.contains(c.getLotId())) || ContainerTypeConstants.CONTAINER_TYPE_KT.equals(c.getContainerType().toString())).collect(Collectors.toList());
            containerVO = locatingContainer(taskDetailsA, itemSyncVOAs, thisContainerInfo, inboundTask.getContainerNo());
        }
        if (CollectionUtils.isNotEmpty(taskDetailsBc)) {
            //BC品直接找货架
            List<BizInboundTaskDetail> detailListTag = bizInboundTaskDetailGroupByItemInfo(taskDetailsBc);
            Map<String, List<BizInboundTaskDetail>> detailsMap = taskDetailsBc.stream().collect(Collectors.groupingBy(group -> group.getItemId() + "-" + group.getLotId()));
            List<GoodsShelvesVO> goodsShelvesVOS = new ArrayList<>();
            for (BizInboundTaskDetail taskDetail : detailListTag) {
                ItemSyncVO itemSyncVO = itemSyncVOS.stream().filter(i -> i.getItemId().equals(taskDetail.getItemId())).findFirst().orElse(null);
                Assert.notNull(itemSyncVO, String.format("物料" + taskDetail.getItemId() + "查询wms信息为空！"));
                //定位托盘
                List<GoodsShelvesVO> tShelvesVOList = findPalletInfo(taskDetail, itemSyncVO, taskDetail.getQty());
                goodsShelvesVOS.addAll(tShelvesVOList);
                List<BizInboundTaskDetail> taskDetails = detailsMap.get(taskDetail.getItemId() + "-" + taskDetail.getLotId());
                dismantlingLocationHitRecordSaveBatch(taskDetails, tShelvesVOList, null, inboundTask.getContainerNo());
            }

            containerVO.setGoodsShelvesVOS(goodsShelvesVOS);
        }
        containerVO.setContainerNo(inboundTask.getContainerNo());
        //containerVO.setTaskDetailId(inboundTask.getId().toString());
        containerVO.setWorkType(inboundTask.getWorkType());
        return containerVO;
    }


    private void dismantlingLocationHitRecordSaveBatch(List<BizInboundTaskDetail> details, List<GoodsShelvesVO> goodsShelvesVOS, List<ContainerInfoDto> containerInfoDtos, String containerNo) {
        List<DismantlingLocationHitRecord> dismantlingLocationHitRecords = new ArrayList();
        if (CollectionUtils.isNotEmpty(goodsShelvesVOS)) {
            for (GoodsShelvesVO vo : goodsShelvesVOS) {
                for (BizInboundTaskDetail taskDetail : details) {
                    DismantlingLocationHitRecord record = new DismantlingLocationHitRecord();
                    record.setTaskDetailId(taskDetail.getId().toString());
                    record.setLocationNo(vo.getPalletLocation());
                    record.setContainerNo(containerNo);
                    record.setLocationType(LocationType.LOCATION_TYPE_SHELVES);
                    record.setPalletNo(vo.getPalletNo());
                    //record.setEndAreaNo(stationCfg.getAreaNo());
                    record.setStatus(0);
                    dismantlingLocationHitRecords.add(record);
                }

            }
        }

        if (CollectionUtils.isNotEmpty(containerInfoDtos)) {
            for (BizInboundTaskDetail taskDetail : details) {
                for (ContainerInfoDto vo : containerInfoDtos) {
                    DismantlingLocationHitRecord record = new DismantlingLocationHitRecord();
                    record.setTaskDetailId(taskDetail.getId().toString());
                    record.setLocationNo(vo.getContainerNo());
                    record.setContainerNo(containerNo);
                    record.setLocationType(LocationType.LOCATION_TYPE_CONTAINER);
                    record.setPalletNo(vo.getContainerNo());//存托盘号
                    //record.setEndAreaNo(stationCfg.getAreaNo());
                    record.setStatus(0);
                    dismantlingLocationHitRecords.add(record);
                }
            }
        }
        dismantlingLocationHitRecordService.saveBatch(dismantlingLocationHitRecords);
    }

    /**
     * A品定位托盘和货架
     *
     * @param details
     * @param itemSyncVOs
     * @param thisContainerInfo
     */
    private ContainerVO locatingContainer(List<BizInboundTaskDetail> details, List<ItemSyncVO> itemSyncVOs, List<ContainerInfoDto> thisContainerInfo, String containerNo) throws Exception {

        List<BizInboundTaskDetail> detailListTag = bizInboundTaskDetailGroupByItemInfo(details);
        Map<String, List<BizInboundTaskDetail>> detailsMap = details.stream().collect(Collectors.groupingBy(group -> group.getItemId() + "-" + group.getLotId()));

        ContainerVO containerVO = new ContainerVO();
        List<ContainerInfoDto> totalHitContainerInfoDtos = new ArrayList<>();
        List<GoodsShelvesVO> totalHitshelvesVOS = new ArrayList<>();
        for (BizInboundTaskDetail detail : detailListTag) {
            ItemSyncVO itemSyncVO = itemSyncVOs.stream().filter(i -> detail.getItemId().equals(i.getItemId())).findFirst().orElse(null);
            Assert.notNull(itemSyncVO, String.format("物料" + detail.getItemId() + "查询wms信息为空！"));
            List<ContainerInfoDto> hitContainerInfoDtos = new ArrayList<>();
            List<GoodsShelvesVO> hitshelvesVOS = new ArrayList<>();
            BigDecimal needQty = detail.getQty();
            BigDecimal conversionRate = itemSyncVO.getUomList().get(0).getConversionRate();
            if (Objects.isNull(conversionRate)) {
                throw new PrologException("物料包装数量为空");
            }
            BigDecimal palletStdQuantity = itemSyncVO.getPalletStdQuantity();
            if (Objects.isNull(palletStdQuantity)) {
                throw new PrologException("托盘标准件数不能为空");
            }
            //当前物料托盘容积总数
            BigDecimal sumQty = conversionRate.multiply(palletStdQuantity);
            //取可用容积大于0的容器
            List<ContainerInfoDto> lTContainerInfos = thisContainerInfo.stream().filter(l -> detail.getItemId().equals(l.getItemId()) && detail.getLotId().equals(l.getLotId()) && sumQty.subtract(l.getQty()).compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
            //空托
            List<ContainerInfoDto> kTContainerInfos = thisContainerInfo.stream().filter(l -> ContainerTypeConstants.CONTAINER_TYPE_KT.equals(l.getContainerType().toString())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(thisContainerInfo)) {
                List<ContainerInfoDto> ltHitContainerInfoDtos = new ArrayList<>();
                List<ContainerInfoDto> ktHitContainerInfoDtos = new ArrayList<>();
                //计算容器可收量
                for (ContainerInfoDto containerInfo : thisContainerInfo) {
                    BigDecimal qty = sumQty.subtract(containerInfo.getQty());
                    containerInfo.setQty(qty);
                }
                BigDecimal validVolume = thisContainerInfo.stream().map(ContainerInfoDto::getQty).reduce(BigDecimal.ZERO, BigDecimal::add);
                if (validVolume.compareTo(needQty) >= 0) {
                    BigDecimal finalNeedQty = needQty;
                    ContainerInfoDto containerInfoDto = lTContainerInfos.stream().filter(s -> finalNeedQty.compareTo(s.getQty()) <= 0).findFirst().orElse(null);
                    //找到一个容器入库数，返回
                    if (!Objects.isNull(containerInfoDto)) {
                        containerVO.setContainerInfoDtos(Arrays.asList(containerInfoDto));
                        ltHitContainerInfoDtos.add(containerInfoDto);
                    } else {
                        boolean flg = true;
                        int ltTag = lTContainerInfos.size();
                        int ktTag = kTContainerInfos.size();
                        BigDecimal qtyflg = BigDecimal.ZERO;
                        if (CollectionUtils.isNotEmpty(lTContainerInfos)) {
                            ContainerInfoDto bigContainerInfoDto = lTContainerInfos.get(lTContainerInfos.size() - 1);//得到可用容积最大的托盘
                            qtyflg = qtyflg.add(bigContainerInfoDto.getQty());
                            ltHitContainerInfoDtos.add(bigContainerInfoDto);
                        }
                        {
                            while (flg) {
                                if (ltHitContainerInfoDtos.size() < ltTag && flg) {
                                    //每轮循环前去掉上一轮最大的那个库存
                                    lTContainerInfos.remove(lTContainerInfos.size() - 1);
                                    for (ContainerInfoDto containerInfo : lTContainerInfos) {
                                        //从可用最小可用容积的托盘开始累加
                                        if (needQty.compareTo(qtyflg.add(containerInfo.getQty())) <= 0) {
                                            //如果累加到足够容积数量，跳出循环
                                            ltHitContainerInfoDtos.add(containerInfo);
                                            qtyflg = qtyflg.add(containerInfo.getQty());
                                            flg = false;
                                            break;
                                        }
                                        //如果本轮循环没有取到足够容积托盘，取最大可用容积托盘，开始下一轮循环
                                        if (containerInfo == lTContainerInfos.get(lTContainerInfos.size() - 1)) {
                                            ltHitContainerInfoDtos.add(containerInfo);
                                            qtyflg = qtyflg.add(containerInfo.getQty());
                                            flg = false;
                                            break;
                                        }
                                    }
                                }
                                if (ltHitContainerInfoDtos.size() == ltTag && ktHitContainerInfoDtos.size() < ktTag && flg) {
                                    if (ktHitContainerInfoDtos.size() == 0) {
                                        ContainerInfoDto ktcContainerInfoDto = kTContainerInfos.get(kTContainerInfos.size() - 1);
                                        ktHitContainerInfoDtos.add(ktcContainerInfoDto);
                                        qtyflg = qtyflg.add(ktcContainerInfoDto.getQty());
//                                        if (needQty.compareTo(qtyflg) <= 0) {
//                                            flg = false;
//                                        }
                                        flg = false;
                                        break;
                                    }
                                    if (flg) {
                                        //每轮循环前去掉上一轮最大容积托盘
                                        kTContainerInfos.remove(kTContainerInfos.size() - 1);
                                        for (ContainerInfoDto containerInfo : kTContainerInfos) {
                                            //从可用库存最小的库存开始累加到取件数,
                                            if (needQty.compareTo(qtyflg.add(containerInfo.getQty())) <= 0) {
                                                //如果累加到足够库存，跳出循环
                                                ktHitContainerInfoDtos.add(containerInfo);
                                                qtyflg = qtyflg.add(containerInfo.getQty());
                                                flg = false;
                                                break;
                                            }
                                            //如果本轮循环没有取到足够容积托盘，取最大可用容积托盘，开始下一轮循环
                                            if (containerInfo == kTContainerInfos.get(kTContainerInfos.size() - 1)) {
                                                ktHitContainerInfoDtos.add(containerInfo);
                                                qtyflg = qtyflg.add(containerInfo.getQty());
                                                flg = false;
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (needQty.compareTo(qtyflg) <= 0) {
                                    //如果累加到足够库存跳出循环
                                    flg = false;
                                }
                            }
                        }
                    }
                    hitContainerInfoDtos.addAll(ltHitContainerInfoDtos);
                    if (CollectionUtils.isNotEmpty(ktHitContainerInfoDtos) && ktHitContainerInfoDtos.size() > 0) {
                        hitContainerInfoDtos.addAll(ktHitContainerInfoDtos);
                    }
                    totalHitContainerInfoDtos.addAll(hitContainerInfoDtos);
                } else {
                    //托盘数不够，找货架
                    hitContainerInfoDtos.addAll(thisContainerInfo);
                    needQty = needQty.subtract(validVolume);
                    List<GoodsShelvesVO> goodsShelvesVOS = findPalletInfo(detail, itemSyncVO, needQty);
                    hitshelvesVOS.addAll(goodsShelvesVOS);
                    totalHitContainerInfoDtos.addAll(hitContainerInfoDtos);
                    totalHitshelvesVOS.addAll(hitshelvesVOS);
                }

            } else {
                //没有可用托盘找货架
                List<GoodsShelvesVO> goodsShelvesVOS = findPalletInfo(detail, itemSyncVO, needQty);
                hitshelvesVOS.addAll(goodsShelvesVOS);
                totalHitshelvesVOS.addAll(hitshelvesVOS);
            }
            List<BizInboundTaskDetail> tTaskDetails = detailsMap.get(detail.getItemId() + "-" + detail.getLotId());
            dismantlingLocationHitRecordSaveBatch(tTaskDetails, hitshelvesVOS, hitContainerInfoDtos, containerNo);
        }
        containerVO.setContainerInfoDtos(totalHitContainerInfoDtos);
        containerVO.setGoodsShelvesVOS(totalHitshelvesVOS);
        return containerVO;
    }

    private List<BizInboundTaskDetail> bizInboundTaskDetailGroupByItemInfo(List<BizInboundTaskDetail> details) {
        Map<String, List<BizInboundTaskDetail>> detailsMap = details.stream().collect(Collectors.groupingBy(group -> group.getItemId() + "-" + group.getLotId()));
        Map<String, BigDecimal> qtyMap = details.stream().collect(Collectors.toMap(o -> o.getItemId() + "-" + o.getLotId(), BizInboundTaskDetail::getQty, BigDecimal::add));
        List<BizInboundTaskDetail> detailListTag = new ArrayList<>();
        for (String key : detailsMap.keySet()) {
            BizInboundTaskDetail taskDetail = detailsMap.get(key).get(0);
            taskDetail.setQty(qtyMap.get(key));
            detailListTag.add(taskDetail);
        }
        return detailListTag;
    }

    private List<GoodsShelvesVO> filterCondition(List<GoodsShelvesVO> goodsShelvesVOList, String abcType) throws Exception {
        List<GoodsShelvesVO> sameShelvesVOList = goodsShelvesVOList.stream().filter(x -> x.getAbcType().equals(abcType)).collect(Collectors.toList());
        List<String> itemIds = sameShelvesVOList.stream().map(GoodsShelvesVO::getItemId).distinct().collect(Collectors.toList());
        List<ItemSyncVO> itemSyncVOS = itemService.queryItemMst(itemIds);
        List<PalletItemQtyInfoDto> palletItemQtyInfoDtoList = genInfo(sameShelvesVOList, itemSyncVOS);
        if (palletItemQtyInfoDtoList == null) {
            return sameShelvesVOList;
        }
        List<String> containerNos = new ArrayList<>();
        getContainerNos(abcType, palletItemQtyInfoDtoList, containerNos);
        return sameShelvesVOList.stream().filter(x -> !containerNos.contains(x.getPalletNo())).collect(Collectors.toList());
    }

    private void getContainerNos(String abcType, List<PalletItemQtyInfoDto> palletItemQtyInfoDtoList, List<String> containerNos) {
        Integer itemNum = null;
        Integer packNum = null;
        if (abcType.equals(AbcTypeConstant.TYPE_B)) {
            itemNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.B_ITEM_NUM_LIMIT_PALLET)));
            packNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.B_PACK_NUM_LIMIT_PALLET)));
        } else {
            itemNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.C_ITEM_NUM_LIMIT_PALLET)));
            packNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.C_PACK_NUM_LIMIT_PALLET)));
        }
        for (PalletItemQtyInfoDto palletItemQtyInfoDto : palletItemQtyInfoDtoList.stream().filter(x -> x.getAbcType().equals(abcType)).collect(Collectors.toList())) {
            List<ItemQtyInfoDto> itemQtyInfoDtpList = palletItemQtyInfoDto.getItemQtyInfoDtpList();
            if (CollectionUtil.isNotEmpty(itemQtyInfoDtpList)) {
                // B品 品种数大于3
                boolean itemCheck = itemQtyInfoDtpList.stream().filter(x -> x.getAbcType().equals(abcType)).count() >= itemNum;
                // B品 件数小于4
                Integer finalPackNum = packNum;
                boolean packCheck = itemQtyInfoDtpList.stream().noneMatch(x -> x.getAbcType().equals(abcType) && x.getPackNum() < finalPackNum);
                if (itemCheck || packCheck) {
                    log.info("货架：{}不满足{}品规则", palletItemQtyInfoDto.getPalletNo(), abcType);
                    containerNos.add(palletItemQtyInfoDto.getPalletNo());
                }
            }
        }
    }

    private void shelfGetContainerNos(String abcType, List<PalletItemQtyInfoDto> palletItemQtyInfoDtoList, List<String> containerNos, BigDecimal qty, ItemSyncVO itemSyncVO) {
        Integer itemNum = null;
        Integer packNum = null;
        if (abcType.equals(AbcTypeConstant.TYPE_B)) {
            itemNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.B_ITEM_NUM_LIMIT_PALLET)));
            packNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.B_PACK_NUM_LIMIT_PALLET)));
        } else {
            itemNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.C_ITEM_NUM_LIMIT_PALLET)));
            packNum = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.C_PACK_NUM_LIMIT_PALLET)));
        }
        for (PalletItemQtyInfoDto palletItemQtyInfoDto : palletItemQtyInfoDtoList.stream().filter(x -> x.getAbcType().equals(abcType)).collect(Collectors.toList())) {
            List<ItemQtyInfoDto> itemQtyInfoDtpList = palletItemQtyInfoDto.getItemQtyInfoDtpList();
            long count = itemQtyInfoDtpList.stream().filter(x -> x.getItemId().equals(itemSyncVO.getItemId())).count();
            // B品 品种数大于3
            boolean itemCheck = itemQtyInfoDtpList.stream().filter(x -> x.getAbcType().equals(abcType)).count() + (count > 0 ? 0 : 1) > itemNum;
            // B品 件数小于4
            Integer finalPackNum = packNum;
            Integer num = getNum(qty, itemSyncVO.getUomList().get(0).getConversionRate());
            int sum = itemQtyInfoDtpList.stream().filter(x -> x.getItemId().equals(itemSyncVO.getItemId())).mapToInt(ItemQtyInfoDto::getPackNum).sum();
            if (itemCheck || sum + num > finalPackNum) {
                containerNos.add(palletItemQtyInfoDto.getPalletNo());
                log.info("货架：{}不满足{}品规则，最大品种数{}，最大件数{}，实际现在品种数{}，实际件数{}", palletItemQtyInfoDto.getPalletNo(), abcType, itemNum, finalPackNum
                        , itemQtyInfoDtpList.stream().filter(x -> x.getAbcType().equals(abcType)).count() + (count > 0 ? 0 : 1), sum + num);
                throw new PrologException(String.format("货架：%s不满足%s品规则，最大品种数%s，最大件数%s，实际现在品种数%s，实际件数%s",
                        palletItemQtyInfoDto.getPalletNo(), abcType, itemNum, finalPackNum
                        , itemQtyInfoDtpList.stream().filter(x -> x.getAbcType().equals(abcType)).count() + (count > 0 ? 0 : 1), sum + num));
            }
        }

    }

    /**
     * 获取货架信息件数和品种数
     *
     * @param goodsShelvesVOList
     * @param itemSyncVOS
     * @return
     */
    @Override
    public List<PalletItemQtyInfoDto> genInfo(List<GoodsShelvesVO> goodsShelvesVOList, List<ItemSyncVO> itemSyncVOS) {
        Map<String, List<GoodsShelvesVO>> palletMap = goodsShelvesVOList.stream().collect(Collectors.groupingBy(GoodsShelvesVO::getPalletNo));
        List<PalletItemQtyInfoDto> palletItemQtyInfoDtoList = new ArrayList<>();
        for (String palletNo : palletMap.keySet()) {
            PalletItemQtyInfoDto palletItemQtyInfoDto = new PalletItemQtyInfoDto();
            palletItemQtyInfoDto.setPalletNo(palletNo);
            List<GoodsShelvesVO> goodsShelvesVOS = palletMap.get(palletNo);
            palletItemQtyInfoDto.setAbcType(goodsShelvesVOS.get(0).getAbcType());
            List<ItemQtyInfoDto> itemQtyInfoDtoList = new ArrayList<>();
            goodsShelvesVOS.forEach(o -> {
                if (Objects.nonNull(o.getItemId())) {
                    ItemSyncVO itemSyncVO = itemSyncVOS.stream().filter(x -> x.getItemId().equals(o.getItemId())).collect(Collectors.toList()).get(0);
                    Integer packNum = getNum(o.getQty(), itemSyncVO.getUomList().get(0).getConversionRate());
                    List<ItemQtyInfoDto> collect = itemQtyInfoDtoList.stream().filter(x -> x.getItemId().equals(o.getItemId())).collect(Collectors.toList());
                    if (CollectionUtil.isEmpty(collect)) {
                        ItemQtyInfoDto itemQtyInfoDto = new ItemQtyInfoDto();
                        itemQtyInfoDto.setItemId(o.getItemId());
                        itemQtyInfoDto.setAbcType(itemSyncVO.getAbcType());
                        itemQtyInfoDto.setPackNum(packNum);
                        itemQtyInfoDtoList.add(itemQtyInfoDto);
                    } else {
                        collect.get(0).setPackNum(collect.get(0).getPackNum() + packNum);
                    }
                }
            });
            palletItemQtyInfoDto.setItemQtyInfoDtpList(itemQtyInfoDtoList);
            palletItemQtyInfoDtoList.add(palletItemQtyInfoDto);
        }
        return palletItemQtyInfoDtoList;
    }

    private Integer getNum(BigDecimal qty, BigDecimal conversionRate) {
        BigDecimal divide = qty.divide(conversionRate, 0, RoundingMode.UP);
        return divide.intValue();
    }

    /**
     * 定位货架
     *
     * @param detail
     * @param itemSyncVO
     * @param needQty
     */
    private List<GoodsShelvesVO> findPalletInfo(BizInboundTaskDetail detail, ItemSyncVO itemSyncVO, BigDecimal needQty) throws Exception {
        BigDecimal needVolume = needQty.multiply((itemSyncVO.getUomList().get(0).getVolume().divide(itemSyncVO.getUomList().get(0).getConversionRate(), 2, BigDecimal.ROUND_DOWN)));
        LocationCfg locationCfg = locationCfgService.findOneByMap(com.prolog.eis.utils.MapUtils.put(LocationCfg::getType, 3).put(LocationCfg::getWmsAreaNo, WmsCarryTaskInCode.AGVL.getCode()).getMap());
        //查询所有货架
        List<GoodsShelvesVO> goodsShelvesVOList = bizInboundTaskDetailMapper.findPalletNo(null, Lists.newArrayList(itemSyncVO.getItemHealthCategory()), null, null, locationCfg.getAreaNo());
        //过滤掉有料货架中存在同品但是不同批的货架
        List<String> collect = goodsShelvesVOList.stream().filter(item -> StrUtil.isNotBlank(item.getItemId()) && StrUtil.equals(item.getItemId(), detail.getItemId()) && !StrUtil.equals(item.getLotId(), detail.getLotId())).map(GoodsShelvesVO::getPalletNo).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            goodsShelvesVOList = goodsShelvesVOList.stream().filter(item -> !collect.contains(item.getPalletNo())).collect(Collectors.toList());
        }
        goodsShelvesVOList = filterCondition(goodsShelvesVOList, itemSyncVO.getAbcType());
        //优先找有同品同批或不同品的有物料货架
        List<GoodsShelvesVO> shelvesVOS = goodsShelvesVOList.stream().filter(s -> (!"0".equals(s.getPalletType()) && detail.getLotId().equals(s.getLotId()) && detail.getItemId().equals(s.getItemId()))
                || (!detail.getItemId().equals(s.getItemId()) && !"0".equals(s.getPalletType()))).collect(Collectors.toList());
        //有同品同批或不同品的有物料货架货格按货架面分组
        Map<String, List<GoodsShelvesVO>> shelvesMap = shelvesVOS.stream().collect(Collectors.groupingBy(group -> group.getPalletNo() + "-" + group.getPlanes()));
        //有料货架
        List<GoodsShelvesVO> ljShelvesVos = new ArrayList<>();
        for (String key : shelvesMap.keySet()) {
            String[] str = key.split("-");
            //根据存在同品同批或同品的货格找当前货架同面的所有可用货格(同品同批和空货格)
            List<GoodsShelvesVO> goodsShelvesVOS = goodsShelvesVOList.stream().filter(s -> (checkPlanes(str, s) && detail.getLotId().equals(s.getLotId()) && detail.getItemId().equals(s.getItemId()))
                    || (checkPlanes(str, s) && StringUtils.isEmpty(s.getItemId()) && StringUtils.isEmpty(s.getLotId()))).collect(Collectors.toList());
            ljShelvesVos.addAll(goodsShelvesVOS);
        }
        //有物料货架，有效容积
        BigDecimal ljShelvesVolume = ljShelvesVos.stream().map(GoodsShelvesVO::getAvailableVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
        Map<String, List<GoodsShelvesVO>> ljMap = ljShelvesVos.stream().collect(Collectors.groupingBy(group -> group.getPalletNo()));
        Map<String, BigDecimal> ljVolumeMap = ljShelvesVos.stream().collect(Collectors.toMap(o -> o.getPalletNo(), GoodsShelvesVO::getAvailableVolume, BigDecimal::add));
        List<GoodsShelvesVO> ljShelvesTag = new ArrayList<>();
        for (String key : ljMap.keySet()) {
            GoodsShelvesVO vo = ljMap.get(key).get(0);
            vo.setAvailableVolume(ljVolumeMap.get(key));
            ljShelvesTag.add(vo);
        }
        ljShelvesTag = ljShelvesTag.stream().sorted(Comparator.comparing(GoodsShelvesVO::getAvailableVolume)).collect(Collectors.toList());


        //空货架
        List<GoodsShelvesVO> kiShelvesVOList = goodsShelvesVOList.stream().filter(e -> "0".equals(e.getPalletType())).collect(Collectors.toList());
        //空货架有效容积
        BigDecimal kjValidVolume = kiShelvesVOList.stream().map(GoodsShelvesVO::getAvailableVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
        Map<String, List<GoodsShelvesVO>> kjMap = kiShelvesVOList.stream().collect(Collectors.groupingBy(group -> group.getPalletNo()));
        Map<String, BigDecimal> kjVolumeMap = kiShelvesVOList.stream().collect(Collectors.toMap(o -> o.getPalletNo(), GoodsShelvesVO::getAvailableVolume, BigDecimal::add));
        List<GoodsShelvesVO> kjShelvesTag = new ArrayList<>();
        for (String key : kjMap.keySet()) {
            GoodsShelvesVO vo = kjMap.get(key).get(0);
            vo.setAvailableVolume(kjVolumeMap.get(key));
            kjShelvesTag.add(vo);
        }
        kjShelvesTag = kjShelvesTag.stream().sorted(Comparator.comparing(GoodsShelvesVO::getAvailableVolume)).collect(Collectors.toList());

        List<GoodsShelvesVO> ljHitShelves = new ArrayList<>();
        List<GoodsShelvesVO> kjHitShelves = new ArrayList<>();
        List<GoodsShelvesVO> hitShelves = new ArrayList<>();
        //有料货架加空货架容积大于需要容积
        log.info("--->需要上架的商品容量：{}", needVolume);
        if (ljShelvesVolume.add(kjValidVolume).compareTo(needVolume) >= 0) {
            GoodsShelvesVO goodsShelvesVO = null;
            //判断相同品种的货架
            GoodsShelvesVO sameGoodsShelvesVO = ljShelvesTag.stream().filter(x -> StrUtil.isNotBlank(x.getItemId()) && x.getItemId().equals(detail.getItemId()) && needVolume.compareTo(x.getAvailableVolume()) <= 0).findFirst().orElse(null);
            if (!Objects.isNull(sameGoodsShelvesVO)) {
                goodsShelvesVO = sameGoodsShelvesVO;
            } else {
                goodsShelvesVO = ljShelvesTag.stream().filter(s -> needVolume.compareTo(s.getAvailableVolume()) <= 0).findFirst().orElse(null);
            }

            //找到一条满足需求容积返回
            if (!Objects.isNull(goodsShelvesVO)) {
                hitShelves.add(goodsShelvesVO);
            } else {
                boolean flg = true;
                int ljTag = ljShelvesTag.size();
                int kjTag = kjShelvesTag.size();
                GoodsShelvesVO bigGoodsShelvesVO = new GoodsShelvesVO();
                BigDecimal qtyflg = BigDecimal.ZERO;
                if (CollectionUtils.isNotEmpty(ljShelvesTag)) {
                    //找一个相同品种体积最大的有料货架
                    List<GoodsShelvesVO> sameGoodsShelvesList = ljShelvesTag.stream().filter(x -> StrUtil.isNotBlank(x.getItemId()) && x.getItemId().equals(detail.getItemId())).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(sameGoodsShelvesList)) {
                        sameGoodsShelvesList.sort(Comparator.comparing(GoodsShelvesVO::getAvailableVolume).reversed());
                        bigGoodsShelvesVO = sameGoodsShelvesList.get(0);
                    } else {
                        bigGoodsShelvesVO = ljShelvesTag.get(ljShelvesTag.size() - 1);//得到可用容积最大的托盘
                    }
                    ljHitShelves.add(bigGoodsShelvesVO);
                } else {
                    while (flg) {
                        //判断已经定位的货架是否小于过滤货架数量
                        if (ljHitShelves.size() < ljTag && flg) {
                            //每轮循环前去掉上一轮最大容积的货架
                            ljShelvesTag.remove(ljShelvesTag.size() - 1);
                            for (GoodsShelvesVO shelvesVO : ljShelvesTag) {
                                //从可用最小可用容积的货架开始累加
                                if (needVolume.compareTo(qtyflg.add(shelvesVO.getAvailableVolume())) <= 0) {
                                    //如果累加到足够容积数量，跳出循环
                                    ljHitShelves.add(shelvesVO);
                                    qtyflg = qtyflg.add(shelvesVO.getAvailableVolume());
                                    flg = false;
                                    break;
                                }
                                //如果本轮循环没有取到足够容积货架，取最大可用容积货架，开始下一轮循环
                                if (shelvesVO == ljShelvesTag.get(ljShelvesTag.size() - 1)) {
                                    ljHitShelves.add(shelvesVO);
                                    qtyflg = qtyflg.add(shelvesVO.getAvailableVolume());
                                    flg = false;
                                    break;
                                }
                            }
                        }
                        //有料货架全部定位|| 有料货架为空   && 定位的空货架小于过滤的空货架
                        if (ljHitShelves.size() == ljTag && kjHitShelves.size() < kjTag && flg) {
                            if (kjHitShelves.size() == 0) {
                                //找一个相同品种体积最大的空货架
                                GoodsShelvesVO kjShelves = kjShelvesTag.get(kjShelvesTag.size() - 1);
                                kjHitShelves.add(kjShelves);
                                qtyflg = qtyflg.add(kjShelves.getAvailableVolume());
                                flg = false;
                                break;
                            }
                            //一个空货架不够继续循环
                            if (flg && kjShelvesTag.size() > 0) {
                                //每轮循环前去掉上一轮最大容积货架
                                kjShelvesTag.remove(kjShelvesTag.size() - 1);
                                for (GoodsShelvesVO shelvesVO : kjShelvesTag) {
                                    //从可用库存最小的库存开始累加容积,
                                    if (needVolume.compareTo(qtyflg.add(shelvesVO.getAvailableVolume())) <= 0) {
                                        //如果累加到足够容积，跳出循环
                                        kjHitShelves.add(shelvesVO);
                                        qtyflg = qtyflg.add(shelvesVO.getAvailableVolume());
                                        flg = false;
                                        break;
                                    }
                                    //如果本轮循环没有取到足够容积货架，取最大可用容积托盘，开始下一轮循环
                                    if (shelvesVO == kjShelvesTag.get(kjShelvesTag.size() - 1)) {
                                        kjHitShelves.add(shelvesVO);
                                        qtyflg = qtyflg.add(shelvesVO.getAvailableVolume());
                                        flg = false;
                                        break;
                                    }
                                }
                            }
                        }

                        if (needVolume.compareTo(qtyflg) <= 0) {
                            //如果累加到足够容积跳出循环
                            flg = false;
                        }
                    }
                }

                hitShelves.addAll(ljHitShelves);
                if (CollectionUtils.isNotEmpty(kjHitShelves) && kjHitShelves.size() > 0) {
                    hitShelves.addAll(kjHitShelves);
                }
            }
        } else {
            throw new PrologException("货架容积不够");
        }
        log.info("--->匹配的货架信息：{}", JSONUtil.toJsonStr(hitShelves));
        return hitShelves;
    }


    //货架同面检验
    private Boolean checkPlanes(String[] str, GoodsShelvesVO vo) {
        Boolean flg = false;
        if (str[0].equals(vo.getPalletNo()) && str[1].equals(vo.getPlanes())) {
            flg = true;
        }
        return flg;
    }


    //入拆零库
    private void sortingInboundCarryTask(BizInboundTask item, StationCfg stationCfg) throws Exception {
        //带了此字段为 补货追加了库存导致第二次请求，此时无需再次搬运
        if (Objects.nonNull(item.getExtend3()) && StrUtil.equals(BaseConstant.SUPPLY_APPEND_FLAG, item.getExtend3())) {
            return;
        }
        //修改入库单状态为已开始
        this.updateInboundTaskStatus(item, stationCfg);
        //创建点位
        final List<ContainerLocationVo> locationByContainerList = routeFeignService.findLocationByContainerListNotVail(Arrays.asList(item.getContainerNo()));
        log.info(">>>>>拆零上架查询容器点位结果:{}", JSONUtil.toJsonStr(locationByContainerList));
        if (CollectionUtil.isEmpty(locationByContainerList) || Objects.isNull(locationByContainerList.get(0))) {
            log.info(">>>>>拆零上架查询容器点位为空，开始创建点位信息：{}", JSONUtil.toJsonStr(item));
            ItemContainerReqDto itemContainerReqDto = new ItemContainerReqDto();
            itemContainerReqDto.setLocationNo(item.getOriginalLocation());
            itemContainerReqDto.setContainerNo(item.getContainerNo());
            itemContainerReqDto.setContainerType(item.getContainerType().toString());
            itemContainerReqDto.setBusinessProperty(item.getItemContainerBusinessProperty());
            routeFeignService.createItemContainer(itemContainerReqDto);
        }
        if (!routeFeignService.checkAreaIn(stationCfg.getAreaNo())) {
            throw new PrologException("料托站台已满，稍后搬运");
        }
        //6 发送搬运
        routeFeignService.createCarryTask(item.getContainerNo(), null, item.getOriginalArea(), item.getOriginalLocation(), stationCfg.getAreaNo(), null, String.valueOf(BaseTaskTypeConstants.AGVL_TYPE), 1, "入拆零库上架站台", item.getItemContainerBusinessProperty());
    }


    //A品单批入拆零库
    private void InboundCarryTask(BizInboundTask item, LocationCfg locationCfg, ItemSyncVO vo) throws Exception {
        //带了此字段为 补货追加了库存导致第二次请求，此时无需再次搬运
        if (Objects.nonNull(item.getExtend3()) && StrUtil.equals(BaseConstant.SUPPLY_APPEND_FLAG, item.getExtend3())) {
            return;
        }
        //修改入库单状态为已开始
        bizInboundTaskMapper.updateMapById(item.getId(), MapUtils.put("status", BaseStatusEnum.STATUS_STARTED.getCode()).put("updateTime", LocalDateTime.now()).put("extend3", BaseConstant.AGVL_INBOUND_TAG).getMap(), BizInboundTask.class);
        //创建点位
        final List<ContainerLocationVo> locationByContainerList = routeFeignService.findLocationByContainerListNotVail(Arrays.asList(item.getContainerNo()));
        log.info(">>>>>拆零上架查询容器点位结果:{}", JSONUtil.toJsonStr(locationByContainerList));
        if (CollectionUtil.isEmpty(locationByContainerList) || Objects.isNull(locationByContainerList.get(0))) {
            log.info(">>>>>拆零上架查询容器点位为空，开始创建点位信息：{}", JSONUtil.toJsonStr(item));
            ItemContainerReqDto itemContainerReqDto = new ItemContainerReqDto();
            itemContainerReqDto.setLocationNo(item.getOriginalLocation());
            itemContainerReqDto.setContainerNo(item.getContainerNo());
            itemContainerReqDto.setContainerType(item.getContainerType().toString());
            itemContainerReqDto.setBusinessProperty(item.getItemContainerBusinessProperty());
            routeFeignService.createItemContainer(itemContainerReqDto);
        }
        //创建库存
        intoStore(item, vo);
        //6 发送搬运
        routeFeignService.createCarryTask(item.getContainerNo(), null, null, null, locationCfg.getAreaNo(), null, String.valueOf(BaseTaskTypeConstants.AGVL_TYPE), 1, "入拆零库托盘区", item.getItemContainerBusinessProperty());
    }

    /**
     * 容器库存处理
     *
     * @throws Exception
     */
    private void intoStore(BizInboundTask item, ItemSyncVO vo) throws Exception {
        List<ContainerInfo> containerInfos = containerInfoMapper.findByMap(MapUtils.put("containerNo", item.getContainerNo()).getMap(), ContainerInfo.class);
        BigDecimal changeQty = BigDecimal.ZERO;
        BigDecimal targetQty = BigDecimal.ZERO;
        if (CollectionUtils.isEmpty(containerInfos)) {
            BizInboundTaskDetail detail = item.getSubList().get(0);
            BigDecimal qty = item.getSubList().stream().map(BizInboundTaskDetail::getQty).reduce(BigDecimal.ZERO, BigDecimal::add);
            ContainerInfoDetail containerInfoDetail = new ContainerInfoDetail();
            containerInfoDetail.setContainerNo(item.getContainerNo());
            containerInfoDetail.setContainerSubNo(item.getContainerNo());
            containerInfoDetail.setAreaType(AreaTypeConstant.AGV_CL);
            containerInfoDetail.setItemId(vo.getItemId());
            containerInfoDetail.setLotId(detail.getLotId());
            containerInfoDetail.setOwnerId(detail.getOwnerId());
            containerInfoDetail.setPackId(detail.getPackId());
            containerInfoDetail.setIsLock(0);
            containerInfoDetail.setQty(qty);
            containerInfoDetail.setTaskType(0);
            containerInfoDetail.setLockQty(BigDecimal.ZERO);
            containerInfoDetail.setCreateTime(LocalDateTime.now());
            if (Objects.isNull(vo.getUomList().get(0).getVolume())) {
                throw new PrologException("商品资料volume字段不能为空");
            }
            containerInfoDetail.setSingleVolume(vo.getUomList().get(0).getVolume().divide(vo.getUomList().get(0).getConversionRate(), 2, BigDecimal.ROUND_DOWN));
            containerInfoDetail.setVolume(containerInfoDetail.getSingleVolume().multiply(qty));
            containerInfoDetail.setMaxVolume(vo.getPalletStdQuantity());
            changeQty = changeQty.add(containerInfoDetail.getQty());
            targetQty = targetQty.add(containerInfoDetail.getQty());
            containerInfoDetailMapper.save(containerInfoDetail);

            ContainerInfo containerInfo = new ContainerInfo();
            containerInfo.setContainerNo(item.getContainerNo());
            containerInfo.setContainerType(ContainerInfoTypeConstants.GOODS_PALLET);
            containerInfo.setAreaType(AreaTypeConstant.AGV_CL);
            containerInfo.setIsLock(0);
            containerInfo.setTaskType(ContainerTaskTypeConstants.INBOUND);
            containerInfo.setCreateTime(LocalDateTime.now());
            containerInfo.setWarehouseArea(WmsCarryTaskInCode.AGVL.getCode());
            containerInfoMapper.save(containerInfo);

            containerStoreChangeService.saveStoreChange(containerInfoDetail, changeQty, targetQty, BaseWorkTypeConstants.INBOUND_TYPE, "入库拆零库托盘区");
        }
    }


    //匹配任务数最少的拆零库上架站台
    private StationCfg getLeastTaskStation(List<String> areaNos, List<StationCfg> cStationCfgs) throws Exception {
        List<ContainerLocation> containerLocationByAreaNos = routeFeignService.findContainerLocationByAreaNos(areaNos);
        for (StationCfg cStationCfg : cStationCfgs) {
            long count = containerLocationByAreaNos.stream().filter(item -> StrUtil.equals(item.getCurrentArea(), cStationCfg.getAreaNo()) || StrUtil.equals(item.getTargetArea(), cStationCfg.getAreaNo())).count();
            cStationCfg.setTaskNum(count);
        }
        StationCfg stationCfg = cStationCfgs.stream().sorted(Comparator.comparing(StationCfg::getTaskNum)).findFirst().orElse(null);
        return stationCfg;
    }


    public CarryTask setCarryTask(String containerNo, Integer taskType, String startRegion, String startLocation, String endRegion, String endLocation, String businessType, Integer height, String describe, String businessProperty) throws Exception {
        CarryTask carryTask = new CarryTask();
        carryTask.setTaskType(LocationConstants.PATH_TASK_TYPE_CARRY);
        if (Objects.nonNull(taskType)) {
            //20清点位
            carryTask.setTaskType(taskType);
        }
        carryTask.setId(PrologStringUtils.newGUID());
        carryTask.setContainerNo(containerNo);
        carryTask.setPalletNo(containerNo);
        carryTask.setStartRegion(startRegion);
        carryTask.setStartLocation(startLocation);
        if (com.prolog.framework.utils.StringUtils.isBlank(startRegion) || com.prolog.framework.utils.StringUtils.isBlank(startLocation)) {
            ContainerLocation containerLocation = routeFeignService.seachLocationNo(MapUtils.put("containerNo", containerNo).getMap());
            carryTask.setStartRegion(containerLocation.getCurrentArea());
            carryTask.setStartLocation(containerLocation.getCurrentLocation());
        }
        carryTask.setEndRegion(endRegion);
        if (org.apache.commons.lang.StringUtils.isNotEmpty(endLocation)) {
            carryTask.setEndLocation(endLocation);
        }
        if (Objects.nonNull(height)) {
            carryTask.setHeight(height);
        }

        if (com.prolog.framework.utils.StringUtils.isEmpty(businessProperty)) {
            businessProperty = "EMPTY";
            ContainerInfo containerInfo = containerInfoMapper.findByMap(MapUtils.put("containerNo", containerNo).getMap(), ContainerInfo.class).stream().findFirst().orElse(null);
            if (containerInfo != null && "3".equals(containerInfo.getContainerType())) {
                List<ContainerInfoDetail> containerInfoDetailDtos = containerInfoDetailMapper.findByMap(MapUtils.put("containerNo", containerInfo.getContainerNo()).getMap(), ContainerInfoDetail.class);
                if (CollectionUtils.isNotEmpty(containerInfoDetailDtos)) {
                    StringBuilder businessTypeBuilder = new StringBuilder();
                    for (ContainerInfoDetail containerInfoDetailDto : containerInfoDetailDtos) {
                        //businessProperty
                        businessTypeBuilder.append(containerInfoDetailDto.getItemId() + "@@" + containerInfoDetailDto.getLotId() + "&");
                    }
                    //设置BusinessType
                    businessProperty = businessTypeBuilder.deleteCharAt(businessTypeBuilder.length() - 1).toString();
                }
            }
        }


        carryTask.setBusinessProperty(businessProperty);
        carryTask.setBusinessType(String.valueOf(businessType));
        carryTask.setBusinessDescribe(describe);
        carryTask.setPriority(99);
        return carryTask;
    }


    public void updateInboundTaskStatus(BizInboundTask inboundTask, StationCfg stationCfg) {
        bizInboundTaskMapper.updateInboundStatusById(inboundTask.getId(), BaseStatusEnum.STATUS_STARTED.getCode());
//        Criteria criteria = Criteria.forClass(BizInboundTaskDetail.class);
//        criteria.setRestriction(Restrictions.eq("inboundId", inboundTask.getId()));
//        bizInboundTaskDetailMapper.updateMapByCriteria(MapUtils.put("stationId", stationCfg.getId()).getMap(), criteria);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestMessage<InboundTaskVO> getInboundTaskList(InboundRequestDto inbound) throws Exception {

        /*RestMessage<InboundTaskVO> restMessage = checkStation(inbound.getStationNo());
        if(!restMessage.isSuccess()){
            return restMessage;
        }*/

        if (Objects.isNull(inbound.getContainerNo()) || StringUtils.isEmpty(inbound.getContainerNo())) {
            return RestMessage.newInstance(false, "201", "请输入容器号", null);
        }
        InboundTaskVO resultInfo = new InboundTaskVO();

        List<GoodsInfoVO> result = bizInboundTaskMapper.getInboundTaskList(inbound.getContainerNo(), null);
        if (result.isEmpty()) {
            return RestMessage.newInstance(false, "201", "暂无商品无上架任务", null);
        } else {

            List<GoodsInfoVO> collect = goodsInfoService.getGoodsInfoNew(result);
            if (!Objects.isNull(inbound.getItemCode())) {
                collect = collect.stream().filter(v -> (!Objects.isNull(v.getPieceBarcode()) && v.getPieceBarcode().contains(inbound.getItemCode())) || (!Objects.isNull(v.getItemCode()) && v.getItemCode().contains(inbound.getItemCode()))).collect(Collectors.toList());
            }
            if (collect.isEmpty()) {
                return RestMessage.newInstance(false, "201", "暂无" + inbound.getItemCode() + "商品无上架任务", null);
            }
            final StationCfg stationCfg = stationCfgMapper.findByMap(MapUtils.put("stationNo", inbound.getStationNo().trim()).getMap(), StationCfg.class).stream().findFirst().orElse(new StationCfg());
            collect.forEach(x -> {
                x.setStationId(stationCfg.getId());
                x.setStationNo(stationCfg.getStationNo());
                x.setContainerNo(inbound.getContainerNo());
            });
            if (collect.size() == 1 || !Objects.isNull(inbound.getGoodsAllocation())) {
                return getOneInboundTask(collect.get(0));
            } else {
                resultInfo.setResults(collect);
                return RestMessage.newInstance(true, "请求成功！", resultInfo);
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    public RestMessage<InboundTaskVO> getOneInboundTask(GoodsInfoVO param) throws Exception {

        List<StationCfg> stationCfgs = stationCfgMapper.getStationCfg(param.getStationNo());
        Assert.notEmpty(stationCfgs, "叫料站台未配置！");
        StationCfg stationCfg = stationCfgs.get(0);
        InboundTaskVO resultInfo = new InboundTaskVO();
        BizInboundTaskDetail task = bizInboundTaskDetailMapper.findById(param.getTaskId(), BizInboundTaskDetail.class);

        bizInboundTaskDetailMapper.updateMapById(task.getId(), MapUtils.put("stationId", stationCfg.getId()).put("updateTime", new Date()).getMap(), BizInboundTaskDetail.class);

        //如果是托盘 扫托盘号 查询托盘对应的命中记录，没有托盘号按 货架的逻辑处理找货格
        DismantlingLocationHitRecord dismantlingLocationHitRecord = new DismantlingLocationHitRecord();
        if (!Objects.isNull(param.getInPalletLocation())) {
            Criteria criteria = Criteria.forClass(DismantlingLocationHitRecord.class);
            criteria.restrictionBuilder().eq(DismantlingLocationHitRecord::getLocationNo, param.getInPalletLocation()).eq(DismantlingLocationHitRecord::getTaskDetailId, param.getTaskId()).build();
            List<DismantlingLocationHitRecord> records = dismantlingLocationHitRecordService.findByCriteria(criteria);
            Assert.isTrue(CollectionUtils.isNotEmpty(records), "目标货位" + param.getInPalletLocation() + "未找到托盘记录");
            dismantlingLocationHitRecord = records.get(0);
        }
        if (Objects.isNull(dismantlingLocationHitRecord.getId())) {
            Criteria criteria = Criteria.forClass(DismantlingLocationHitRecord.class);
            criteria.restrictionBuilder().eq(DismantlingLocationHitRecord::getContainerNo, param.getContainerNo()).eq(DismantlingLocationHitRecord::getTaskDetailId, param.getTaskId()).build();
            List<DismantlingLocationHitRecord> dismantlingLocationHitRecords = dismantlingLocationHitRecordService.findByCriteria(criteria);
            if (CollectionUtils.isNotEmpty(dismantlingLocationHitRecords)) {
                dismantlingLocationHitRecords.stream().sorted(Comparator.comparing(DismantlingLocationHitRecord::getId)).collect(Collectors.toList());
                dismantlingLocationHitRecord = dismantlingLocationHitRecords.get(0);
            }
        }
        param.setAbcType(param.getAbcType());
        param.setQty(task.getQty().subtract(null == task.getRealQty() ? BigDecimal.ZERO : task.getRealQty()));
        param.setPackId(task.getPackId());
        param.setLocationType(LocationType.LOCATION_TYPE_SHELVES);
        if (LocationType.LOCATION_TYPE_CONTAINER.equals(dismantlingLocationHitRecord.getLocationType())) {
//            List<PalletLocation> palletLocationList = bizInboundTaskDetailMapper.findLocation(param.getInPalletLocation());
//            Assert.isTrue( CollectionUtils.isNotEmpty(palletLocationList),"目标货位" + param.getInPalletLocation() + "未找到容器记录");
//            resultInfo.setPalletLocationList(palletLocationList);
            param.setLocationType(LocationType.LOCATION_TYPE_CONTAINER);
            param.setPalletNo(dismantlingLocationHitRecord.getPalletNo());
            param.setPalletLocation(dismantlingLocationHitRecord.getLocationNo());
            resultInfo.setResults(Lists.newArrayList(param));
            PalletLocation palletLocation = new PalletLocation();
            return RestMessage.newInstance(true, "请上架！", resultInfo);
        }
        resultInfo.setResults(Lists.newArrayList(param));
        if (LocationType.LOCATION_TYPE_SHELVES.equals(dismantlingLocationHitRecord.getLocationType()) || Objects.isNull(param.getInPalletLocation())) {
            List<PalletInfo> arrivePalletInfoList = palletInfoMapper.findByMap(MapUtils.put("status", BaseConstant.NO).put("subArea", stationCfg.getAreaNo()).getMap(), PalletInfo.class);
            // 无货架情况
            if (arrivePalletInfoList.isEmpty()) {
                return RestMessage.newInstance(true, "501", "当前站台无可用货架！", resultInfo);
            } else {
                //分2种情况 1.空货架 2.不是空货架(1.有剩余货位容积(A面或B面，进行上架) 2.没有货位容积(AB面都没有，提示归还货架))
                //1.查询需要的商品大类货架是否在移动中，且当前站台区域没有此商品大类的货架移动中提示信息
                List<PalletInfo> palletInfos = palletInfoMapper.findByMap(MapUtils.put("subArea", stationCfg.getAreaNo()).getMap(), PalletInfo.class);
                //已经停在当前站台的货架
                List<PalletInfo> collect = palletInfos.stream().filter(x -> x.getStatus().equals(BaseConstant.NO)).collect(Collectors.toList());
                //查询停在当前站台所有的可用的货位,符合ABC的，有容积的，有空货位的(不包含空货架)
                List<GoodsShelvesVO> goodsShelvesVOS = bizInboundTaskDetailMapper.findPalletNo(collect.stream().map(PalletInfo::getPalletNo).collect(Collectors.toList()), Arrays.asList(param.getItemHealthCategory()), null, null, stationCfg.getAreaNo());
                GoodsShelvesVO goodsShelve = null;
                if (!goodsShelvesVOS.isEmpty()) {
                    final List<String> palletNos = goodsShelvesVOS.stream().map(GoodsShelvesVO::getPalletNo).distinct().collect(Collectors.toList());
                    for (String palletNo : palletNos) {
                        PalletInfo palletInfo = collect.stream().filter(x -> x.getPalletNo().equals(palletNo)).findFirst().orElse(new PalletInfo());
                        List<GoodsShelvesVO> shelvesVOS = goodsShelvesVOS.stream().filter(x -> x.getPalletNo().equals(palletNo)).collect(Collectors.toList());
                        String directionStr = AngleConversionAB.getDirectionStr(palletInfo.getAngle(), stationCfg.getAngle());
                        shelvesVOS = ABCSurplusLocation.queryGoodsShelf(shelvesVOS, param.getAbcType(), param, directionStr);
                        for (GoodsShelvesVO sel : shelvesVOS) {
                            BigDecimal surplusSize = sel.getVolume().subtract(sel.getQty().multiply(sel.getSingleVolume()));
                            if (surplusSize.compareTo(BigDecimal.ZERO) == 1) {
                                goodsShelve = sel;
                                break;
                            }
                        }
                        if (null != goodsShelve) {
                            break;
                        }
                    }
                    if (null == goodsShelve) {
                        final List<PalletInfo> palletInfoList = palletInfoMapper.findByMap(MapUtils.put("status", ContainerTaskTypeConstants.IDLE).put("subArea", stationCfg.getAreaNo()).put("palletType", param.getItemHealthCategory()).getMap(), PalletInfo.class);
                        if (!palletInfoList.isEmpty()) {
                            resultInfo.getResults().get(0).setPalletNo(palletInfoList.get(0).getPalletNo());
                            resultInfo.getResults().get(0).setInQty(task.getQty().subtract(null == task.getRealQty() ? BigDecimal.ZERO : task.getRealQty()));
                        } else {
                            return RestMessage.newInstance(true, "202", "商品" + param.getAbcType() + "类型货位已满,请重新分配!", resultInfo);
                        }
                    }
//                    String directionStr = AngleConversionAB.getDirectionStr(goodsShelve.getAngle(), stationCfg.getAngle());
//                    if (!goodsShelve.getPlanes().equals(directionStr)) {
//                        resultInfo.getResults().get(0).setPalletNo(goodsShelve.getPalletNo());
//                        resultInfo.getResults().get(0).setInQty(task.getQty().subtract(null == task.getRealQty() ? BigDecimal.ZERO : task.getRealQty()));
//                        return RestMessage.newInstance(true, "202", "货架需货位调整！", resultInfo);
//                    }
                } else {
                    //查询有没有空货架可以进行上架
                    collect = collect.stream().filter(v -> "0".equals(v.getPalletType()) || Objects.isNull(v.getPalletType())).collect(Collectors.toList());
                    if (collect.isEmpty()) {
                        final List<PalletInfo> infos = palletInfoMapper.findByMap(MapUtils.put("status", BaseConstant.NO).put("subArea", stationCfg.getAreaNo()).getMap(), PalletInfo.class);
                        if (!infos.isEmpty()) {
                            final List<PalletInfo> collect2 = infos.stream().filter(x -> x.getPalletType().equals(param.getItemHealthCategory())).collect(Collectors.toList());
                            if (!collect2.isEmpty()) {
                                resultInfo.getResults().get(0).setPalletNo(collect2.get(0).getPalletNo());
                            } else {
                                return RestMessage.newInstance(true, "201", "货位已满，请重新分配！", resultInfo);
                            }
                        }
                    } else {
                        String directionStr = AngleConversionAB.getDirectionStr(collect.get(0).getAngle(), stationCfg.getAngle());
                        final List<PalletLocation> palletLocations = palletLocationMapper.findByMap(MapUtils.put("palletNo", collect.get(0).getPalletNo()).getMap(), PalletLocation.class);
                        List<GoodsShelvesVO> goodsShelvesVOList = palletLocations.stream().map(v -> {
                            GoodsShelvesVO shelvesVO = new GoodsShelvesVO();
                            shelvesVO.setPalletNo(v.getPalletNo());
                            shelvesVO.setPlanes(v.getPlanes());
                            shelvesVO.setPalletLocation(v.getPalletLocation());
                            shelvesVO.setAbcType(v.getAbcType());
                            return shelvesVO;
                        }).collect(Collectors.toList());
                        goodsShelvesVOList = ABCSurplusLocation.queryGoodsShelf(goodsShelvesVOList, param.getAbcType(), param, directionStr);
                        goodsShelve = goodsShelvesVOList.get(0);
                    }
                }
                if (StrUtil.isBlank(param.getPalletLocation())) {
                    param.setPalletNo(goodsShelve.getPalletNo());
                    param.setPalletLocation(goodsShelve.getPalletLocation());
                    param.setPlanes(goodsShelve.getPlanes());
                }
                resultInfo = getPalletNoLocation(resultInfo, param.getPalletLocation(), param.getPalletNo(), goodsShelve.getPlanes());
            }

        }
        return RestMessage.newInstance(true, "请上架！", resultInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    public RestMessage<String> agvInboundConfirm(GoodsInfoVO inbound) throws Exception {
        if (Objects.isNull(inbound.getInQty()) || StringUtils.isEmpty(inbound.getInQty())) {
            return RestMessage.newInstance(false, "201", "上架数量不能为空", null);
        }
        if (inbound.getInQty().compareTo(new BigDecimal(1)) == -1) {
            return RestMessage.newInstance(false, "201", "上架数量必须大于0", null);
        }
        if (Objects.isNull(inbound.getInPalletLocation()) || StringUtils.isEmpty(inbound.getInPalletLocation())) {
            return RestMessage.newInstance(false, "201", "上架货位编码不能为空", null);
        }
        if (!StrUtil.equals(inbound.getPalletLocation(), inbound.getInPalletLocation())) {
            return RestMessage.newInstance(false, "201", "必须按照推荐货位号进行上架", null);
        }

        List<ContainerInfo> containerInfoList = new ArrayList<>();
        if (AbcTypeConstant.TYPE_A.equals(inbound.getAbcType())) {
            Criteria criteria = Criteria.forClass(ContainerInfo.class);
            criteria.restrictionBuilder().eq(ContainerInfo::getContainerNo, inbound.getInPalletLocation()).build();
            containerInfoList = containerInfoService.findByCriteria(criteria);

        }

        List<PalletLocation> palletLocations1 = new ArrayList<>();
        if ((AbcTypeConstant.TYPE_A.equals(inbound.getAbcType()) && CollectionUtils.isEmpty(containerInfoList)) || !AbcTypeConstant.TYPE_A.equals(inbound.getAbcType())) {
            palletLocations1 = palletLocationMapper.findByMap(MapUtils.put("palletLocation", inbound.getInPalletLocation()).getMap(), PalletLocation.class);
        }


        if (!AbcTypeConstant.TYPE_A.equals(inbound.getAbcType()) && (palletLocations1.isEmpty() || !palletLocations1.get(0).getPalletNo().equals(inbound.getPalletNo()))) {
            return RestMessage.newInstance(false, "201", "货架信息与货位信息不匹配", null);
        }

//        StationCfg stationCfg = stationCfgMapper.findByMap(MapUtils.put("stationNo", inbound.getStationNo()).getMap(), StationCfg.class).stream().findFirst().get();
        List<StationCfg> stationCfgs = stationCfgMapper.getStationCfg(inbound.getStationNo());
        inbound.setInPalletLocation(inbound.getInPalletLocation().trim().toUpperCase());

        BizInboundTaskDetail inboundTaskDetail = bizInboundTaskDetailMapper.findById(inbound.getTaskId(), BizInboundTaskDetail.class);
        Assert.notNull(inboundTaskDetail, String.format("不存在任务号%s的入库任务！", inbound.getTaskId()));
        if (!AbcTypeConstant.TYPE_A.equals(inbound.getAbcType())) {
            Assert.notEmpty(palletLocations1, "货位编号错误，不存在的货位！");
            PalletInfo palletNo = palletInfoMapper.findByMap(MapUtils.put("palletNo", inbound.getPalletNo()).getMap(), PalletInfo.class).stream().findFirst().orElseThrow(() -> new PrologException(String.format("%s货架信息为空！", inbound.getPalletNo())));

//            if (!StringUtils.isEmpty(palletNo.getPalletType()) && !"0".equals(palletNo.getPalletType())) {
//                if (!palletNo.getPalletType().equals(inbound.getItemHealthCategory())) {
//                    return RestMessage.newInstance(false, "201", "当前入库任务商品大类与货架商品大类不一致", null);
//                }
//            }

            if (!palletNo.getSubArea().equals(stationCfgs.get(0).getAreaNo()) || !palletNo.getStatus().equals(BaseStatusEnum.STATUS_INIT.getCode())) {
                return RestMessage.newInstance(false, "201", "当前站台不存在此货架！", null);
            }
        }

        if (!Objects.isNull(inboundTaskDetail.getStationId()) && !inboundTaskDetail.getStationId().equals(stationCfgs.get(0).getId())) {
            return RestMessage.newInstance(false, "201", "此任务已被其他站台索取！", null);
        }

        BigDecimal realQty = Objects.isNull(inboundTaskDetail.getRealQty()) ? BigDecimal.ZERO : inboundTaskDetail.getRealQty();
        if (realQty.add(inbound.getInQty()).compareTo(inboundTaskDetail.getQty()) == 1) {
            throw new Exception(String.format("上架数量超过订单数据，请检查", inbound.getPalletLocation()));
        }

        if (realQty.add(inbound.getInQty()).compareTo(inboundTaskDetail.getQty()) == 1) {
            inboundTaskDetail.setDetailStatus(BaseStatusEnum.STATUS_FINISH.getCode());
            inboundTaskDetail.setStationId(0);
        }


        List<ContainerInfoDetail> containerInfoDetails = containerInfoDetailMapper.findLocationOtherStore(inbound.getInPalletLocation(), inbound.getGoodsId(), inbound.getOwnerId(), inbound.getLotId(), inbound.getPackId());

        if (!containerInfoDetails.isEmpty()) {
            throw new Exception(String.format("货格%s存在其他类型的商品，无法上架", inbound.getInPalletLocation()));
        }

        //处理库存
        intoStoreLocation(inbound.getPalletNo(), inbound.getInPalletLocation(), inbound.getInQty(), inbound, inbound.getSingleVolume(), inbound.getBatchProductionDate(), inbound.getBatchExpiredDate(), inboundTaskDetail.getSeqNo(), inbound.getItemHealthCategory(), inbound.getLocationType());

        BizInboundTask inboundTask = bizInboundTaskMapper.findById(inboundTaskDetail.getInboundId(), BizInboundTask.class);

        inboundTaskDetail.setRealQty(realQty.add(inbound.getInQty()));
        inboundTaskDetail.setUpdateTime(LocalDateTime.now());
        inboundTaskDetail.setStationId(stationCfgs.get(0).getId());
        inboundTaskDetail.setContainerSubNo(null);
        boolean flag = false;
        if (realQty.add(inbound.getInQty()).compareTo(inboundTaskDetail.getQty()) == 0) {
            inboundTaskDetail.setDetailStatus(BaseStatusEnum.STATUS_FINISH.getCode());
            inboundTaskDetail.setStationId(0);
            //正常拆零上架 原托盘搬到叠盘机
            if (!StrUtil.equals(inboundTask.getWorkType(), BizInboundTask.SUPPLY_WORK_TYPE)) {
                emptyContainerTaskService.save(inboundTask.getContainerNo(), LayerEnum.TWO, WmsCarryTaskInCode.MJZ);
                wmsContainerStatusUpdateService.execute(WmsContainerStatusUpdateDto.builder().containerCode(inboundTask.getContainerNo()).enterpriseId(inboundTask.getEnterpriseId()).warehouseId(inboundTask.getWmsWarehouseId()).build());
            }
            flag = true;
        }
        long update = bizInboundTaskDetailMapper.update(inboundTaskDetail);
        Assert.isTrue(!(update <= 0), String.format("货架%s入库任务不存在或已被取消", inbound.getPalletLocation()));
        if (flag) {
            final List<BizInboundTaskDetail> bizInboundTaskDetails = bizInboundTaskDetailMapper.findByMap(MapUtils.put("inboundId", inboundTaskDetail.getInboundId()).getMap(), BizInboundTaskDetail.class);
            final long l = bizInboundTaskDetails.stream().filter(x -> !BaseStatusEnum.STATUS_FINISH.getCode().equals(x.getDetailStatus())).count();
            if (0 == l) {
                bizInboundTaskMapper.updateMapById(inboundTaskDetail.getInboundId(), MapUtils.put("status", BaseStatusEnum.STATUS_FINISH.getCode()).put("finishTime", new Date()).getMap(), BizInboundTask.class);
                //补货后续流程
                supplyFinishTask(inboundTask, bizInboundTaskDetails.get(0));
            }
            return RestMessage.newInstance(true, "200", "上架完成,请归还货架！", null);
        }

        /*Criteria criteria = new Criteria(DismantlingLocationHitRecord.class);
        criteria.restrictionBuilder().eq(DismantlingLocationHitRecord::getPalletNo, inbound.getPalletNo()).eq(DismantlingLocationHitRecord::getTaskDetailId,inbound.getTaskId()).build();
        List<DismantlingLocationHitRecord> hitRecords = dismantlingLocationHitRecordService.findByCriteria(criteria);
        if(CollectionUtils.isEmpty(hitRecords)){
            return RestMessage.newInstance(true, "200", "上架成功,该货架已无可用货格,请归还货架！", null);
        }*/

        return RestMessage.newInstance(true, "202", "上架成功", null);
    }


    //补货上架流程
    private void supplyFinishTask(BizInboundTask inboundTask, BizInboundTaskDetail inboundTaskDetail) throws Exception {
        if (!StrUtil.equals(inboundTask.getWorkType(), BizInboundTask.SUPPLY_WORK_TYPE)) {
            return;
        }
        //1 扣减库存
        ContainerInfoDetail containerInfoDetail = containerInfoDetailMapper.findByMap(MapUtils.put("containerNo", inboundTask.getContainerNo()).getMap(), ContainerInfoDetail.class).stream().findFirst().orElseThrow(() -> new PrologException("为查询到库存"));
        BigDecimal remainQty = containerInfoDetail.getQty().subtract(inboundTaskDetail.getQty());
        saveOutReduceChange(Arrays.asList(containerInfoDetail), null, inboundTaskDetail.getQty().negate(), remainQty, "补货出库");
        containerInfoDetail.setQty(remainQty);
        containerInfoDetail.setUpdateTime(LocalDateTime.now());
        containerInfoDetailMapper.update(containerInfoDetail);
        //回告w
        supplyOutboundBack(inboundTask.getContainerNo());

        //回库 空托搬到叠盘机
        if (remainQty.compareTo(BigDecimal.ZERO) == 0) {
            emptyContainerTaskService.save(inboundTask.getContainerNo(), LayerEnum.TWO, WmsCarryTaskInCode.MJZ);
            wmsContainerStatusUpdateService.execute(WmsContainerStatusUpdateDto.builder().containerCode(inboundTask.getContainerNo()).enterpriseId(inboundTask.getEnterpriseId()).warehouseId(inboundTask.getWmsWarehouseId()).build());
        } else {
            //非空托回库 先判断是否能入agv整件托盘库，不能就回原库区
            containerCallBack(containerInfoDetail);
        }
        //判断补货出库是否全部完成，全部完成转历史
        supplyOutboundFinish(inboundTask.getContainerNo());
    }

    private void supplyOutboundBack(String containerNo) throws Exception {
        //根据此容器号查出对应所有补货容器任务对应的所有订单
        List<ContainerTask> containerTaskList = containerTaskService.findByMap(MapUtils.put("containerNo", containerNo)
                .put("taskType", BaseBillTypeConstants.REPLENISH_TYPE).getMap());
        List<Integer> outboundIds = containerTaskList.stream().map(ContainerTask::getOutboundId).collect(Collectors.toList());
        //查询此容器对应的所有订单
        Criteria criteria1 = new Criteria(BizOutboundTask.class);
        criteria1.restrictionBuilder().in(BizOutboundTask::getId, outboundIds).build();
        List<BizOutboundTask> bizOutboundTaskList = bizOutboundTaskService.findByCriteria(criteria1);

        for (ContainerTask containerTask : containerTaskList) {
            final BizOutboundTask bizOutboundTask = bizOutboundTaskList.stream().filter(item -> Objects.equals(item.getId(), containerTask.getOutboundId())).findFirst().get();
            taskFinishBack(bizOutboundTask, containerTask);
        }
    }

    private void containerCallBack(ContainerInfoDetail containerInfoDetail) throws Exception {
        //查询对应的补货出库任务
        List<ContainerTask> containerTaskList = containerTaskService.findByMap(MapUtils.put("containerNo", containerInfoDetail.getContainerNo())
                .put("taskType", BaseBillTypeConstants.REPLENISH_TYPE).getMap());
        BizOutboundTask outboundTask = bizOutboundTaskService.findById(containerTaskList.get(0).getOutboundId());
        //查询agv阴凉库配置的空闲百分比
        double backFlagNum = Double.parseDouble(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.AGV_FULL_WARE_SIZE)));
        BigDecimal backQty = new BigDecimal(String.valueOf(redisTemplate.opsForValue().get(SysParamConstants.SYSPRE_FIX + SysParamConstants.SUPPLY_BACK_CONTAINER_MAX_NUM)));

        LocationCfg locationCfg = locationCfgService.findOneByMap(MapUtils.put("type", LocationCfgConstants.EISKQ).put("wmsAreaNo", WmsCarryTaskInCode.AGVZ.getCode()).getMap());
        LocationCfg backWarehouse = locationCfgService.findOneByMap(MapUtils.put("type", LocationCfgConstants.EISKQ).put("wmsAreaNo", outboundTask.getWmsLocationCode()).getMap());
        String adjustTaskId = null;
        ItemSyncVO itemInfo = itemService.queryItemMst(Arrays.asList(containerInfoDetail.getItemId())).stream().findFirst().get();
        //四项库的托盘，并且是A品，并且回库托盘库存大于等于配置的数量
        if (backWarehouse.getWmsAreaNo().equals(WmsCarryTaskInCode.MJZ.getCode()) && AbcTypeConstant.TYPE_A.equals(itemInfo.getAbcType()) && containerInfoDetail.getQty().compareTo(backQty) >= 0) {
            //计算agv阴凉库的空闲百分比
            DswRequestDto dswRequest = new DswRequestDto();
            dswRequest.setAreaNoList(Arrays.asList(locationCfg.getAreaNo()));
            DswAreaDto dswAreaDto = routeFeignService.queryDswAreaList(dswRequest).get(0);
            int totalCount = dswAreaDto.getTotalCount();
            int freeLocatorCount = dswAreaDto.getFreeLocatorCount();
            double div = NumberUtil.div(freeLocatorCount, totalCount);
            if (backFlagNum <= div) {
                //满足百分比 请求wms看是否可入
                RestMessage execute = wmsWarehouseChangeService.execute(WmsWarehouseChangeDto.builder().containerNo(containerInfoDetail.getContainerNo()).enterpriseId(outboundTask.getEnterpriseId()).warehouseId(outboundTask.getWmsWarehouseId()).itemId(containerInfoDetail.getItemId()).lotId(containerInfoDetail.getLotId()).qty(containerInfoDetail.getQty()).build());
                Integer change = JSONUtil.parseObj(execute.getData()).getInt("change");
                if (change == 1) {
                    adjustTaskId = JSONUtil.parseObj(execute.getData()).getStr("taskId");
                    //可入二楼agv整件库
                    backWarehouse = locationCfg;
                    ContainerInfo containerInfo = containerInfoMapper.findByMap(MapUtils.put("containerNo", containerInfoDetail.getContainerNo()).getMap(), ContainerInfo.class).get(0);
                    containerInfo.setWarehouseArea(backWarehouse.getWmsAreaNo());
                    containerInfo.setAreaType(Integer.parseInt(WmsCarryTaskInCode.AREA_TYPE.get(backWarehouse.getWmsAreaNo()).toString()));
                    containerInfo.setUpdateTime(LocalDateTime.now());
                    containerInfoMapper.update(containerInfo);
                    containerInfoDetail.setAreaType(containerInfo.getAreaType());
                    containerInfoDetail.setUpdateTime(LocalDateTime.now());
                    containerInfoDetailMapper.update(containerInfoDetail);
                }
            }
        }
        ContainerLocationVo containerLocationVo = routeFeignService.findLocationByContainerList(Arrays.asList(containerInfoDetail.getContainerNo())).stream().findFirst().orElseThrow(() -> new PrologException("容器点位不存在"));
        if (backWarehouse.getWmsAreaNo().equals(WmsCarryTaskInCode.MJZ.getCode())) {
            Criteria criteriaDetail = new Criteria(ContainerInfo.class);
            criteriaDetail.setRestriction(Restrictions.eq("containerNo", containerInfoDetail.getContainerNo()));
            containerInfoService.updateByMap(MapUtils.put("taskType", ContainerTaskTypeConstants.SUPPLY_BACK_TYPE).put("updateTime", LocalDateTime.now()).getMap(), criteriaDetail);

            List<DeviceInfo> deviceInfoList = deviceInfoMapper.findByMap(MapUtils.put("isLock", 0).getMap(), DeviceInfo.class);
            List<String> areaNoList = deviceInfoList.stream().map(DeviceInfo::getDeviceNo).collect(Collectors.toList());
            List<AreaLocationCountDto> areaLocationCountDtos = routeFeignService.queryAreaLocationCountDtoList(areaNoList);
            areaLocationCountDtos = areaLocationCountDtos.stream().filter(item -> item.getFreeCount() > 0).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(areaLocationCountDtos)) {
                throw new Exception("没有可用的四向库楼层");
            }
            AreaTaskReqDto ad = new AreaTaskReqDto();
            ad.setAreaNos(areaLocationCountDtos.stream().map(AreaLocationCountDto::getAreaNo).collect(Collectors.toList()));
            Map<String, Integer> sxkTaskByAreaNos = routeFeignService.getSxkTaskByAreaNos(ad);
            areaLocationCountDtos.forEach(item -> item.setLocatorCount(sxkTaskByAreaNos.get(item.getAreaNo())));
            AreaLocationCountDto areaLocationCountDto = areaLocationCountDtos.stream().sorted(Comparator.comparing(AreaLocationCountDto::getLocatorCount).thenComparing(Comparator.comparing(AreaLocationCountDto::getFreeCount, Comparator.reverseOrder()))).findFirst().get();
            routeFeignService.createCarryTask(containerInfoDetail.getContainerNo(), null, containerLocationVo.getCurrentArea(), containerLocationVo.getCurrentLocation(), areaLocationCountDto.getAreaNo(), null, String.valueOf(BaseTaskTypeConstants.SUPPLER_BACK), 1, "回库", containerInfoDetail.getItemId() + "@@" + containerInfoDetail.getLotId(), adjustTaskId, outboundTask.getWmsWarehouseId(), outboundTask.getEnterpriseId());
        } else {
            routeFeignService.createCarryTask(containerInfoDetail.getContainerNo(), null, containerLocationVo.getCurrentArea(), containerLocationVo.getCurrentLocation(), backWarehouse.getAreaNo(), null, String.valueOf(BaseTaskTypeConstants.SUPPLER_BACK), 1, "回库", containerInfoDetail.getItemId() + "@@" + containerInfoDetail.getLotId(), adjustTaskId, outboundTask.getWmsWarehouseId(), outboundTask.getEnterpriseId());
        }

    }

    private void saveOutReduceChange(List<ContainerInfoDetail> containerInfoDetails, Integer workType, BigDecimal change, BigDecimal target, String remark) {
        List<ContainerStoreChange> storeChangeList = new ArrayList<>();
        ContainerStoreChange changeChange = null;
        for (ContainerInfoDetail containerInfoDetail : containerInfoDetails) {
            changeChange = new ContainerStoreChange();
            changeChange.setContainerNo(containerInfoDetail.getContainerNo());
            changeChange.setContainerSubNo(containerInfoDetail.getContainerSubNo());
            changeChange.setTaskType(workType);
            changeChange.setSoureQty(containerInfoDetail.getQty());
            changeChange.setChangeQty(change);
            changeChange.setTargetQty(target);
            changeChange.setRemark(remark);
            changeChange.setCreateTime(LocalDateTime.now());
            changeChange.setUpdateTime(LocalDateTime.now());
            changeChange.setPackId(containerInfoDetail.getPackId());
            changeChange.setOwnerId(containerInfoDetail.getOwnerId());
            changeChange.setLotId(containerInfoDetail.getLotId());
            changeChange.setItemId(containerInfoDetail.getItemId());
            storeChangeList.add(changeChange);
        }
        containerStoreChangeMapper.saveBatch(storeChangeList);
    }

    private void supplyOutboundFinish(String containerNo) throws Exception {
        //修改当前容器所有补货出库任务状态为已上架
        Criteria criteria = new Criteria(ContainerTask.class);
        criteria.restrictionBuilder().eq(ContainerTask::getContainerNo, containerNo)
                .eq(ContainerTask::getTaskType, BaseBillTypeConstants.REPLENISH_TYPE).build();
        containerTaskService.updateMapByCriteria(MapUtils.put("shelvesState", 1).getMap(), criteria);

        //根据此容器号查出对应所有容器任务对应的所有订单
        List<ContainerTask> containerTaskList = containerTaskService.findByMap(MapUtils.put("containerNo", containerNo)
                .put("taskType", BaseBillTypeConstants.REPLENISH_TYPE).getMap());
        List<Integer> outboundIds = containerTaskList.stream().map(ContainerTask::getOutboundId).collect(Collectors.toList());
        //查询此容器对应的所有订单
        Criteria criteria1 = new Criteria(BizOutboundTask.class);
        criteria1.restrictionBuilder().in(BizOutboundTask::getId, outboundIds).build();
        List<BizOutboundTask> bizOutboundTaskList = bizOutboundTaskService.findByCriteria(criteria1);
        //查询此容器对应的所有订单 对应的所有容器任务
        Criteria criteria2 = new Criteria(ContainerTask.class);
        criteria2.restrictionBuilder().in(ContainerTask::getOutboundId, outboundIds).build();
        List<ContainerTask> containerTasks = containerTaskService.findByCriteria(criteria2);
        //遍历订单查询容器任务是否都上架完成，全部完成转历史和回告wms
        for (BizOutboundTask bizOutboundTask : bizOutboundTaskList) {
            List<ContainerTask> outboundContainerTaskList = containerTasks.stream().filter(item -> Objects.equals(item.getOutboundId(), bizOutboundTask.getId())).collect(Collectors.toList());
            long count = outboundContainerTaskList.stream().filter(item -> item.getShelvesState() != 1).count();
            if (count == 0) {
                orderLogMapper.save(OrderLog.builder().orderId(bizOutboundTask.getId().toString()).orderNo(bizOutboundTask.getBillNo()).type("补货完成").createTime(new Date()).build());
                //转历史
                toHis(bizOutboundTask, outboundContainerTaskList);
            }
        }
    }

    private void toHis(BizOutboundTask bizOutboundTask, List<ContainerTask> containerTaskList) {
        List<BizOutboundTaskDetail> bizOutboundTaskDetailList = bizOutboundTaskDetailService.findByMap(MapUtils.put("outboundId", bizOutboundTask.getId()).getMap());
        for (BizOutboundTaskDetail bizOutboundTaskDetail : bizOutboundTaskDetailList) {
            BizOutboundTaskDetailHis bizOutboundTaskDetailHis = new BizOutboundTaskDetailHis();
            BeanUtil.copyProperties(bizOutboundTaskDetail, bizOutboundTaskDetailHis);
            bizOutboundTaskDetailHisService.save(bizOutboundTaskDetailHis);
            bizOutboundTaskDetailService.deleteById(bizOutboundTaskDetail.getId());
        }

        BizOutboundTaskHis bizOutboundTaskHis = new BizOutboundTaskHis();
        BeanUtil.copyProperties(bizOutboundTask, bizOutboundTaskHis);
        bizOutboundTaskHisService.save(bizOutboundTaskHis);
        bizOutboundTaskService.deleteById(bizOutboundTask.getId());

        for (ContainerTask containerTask : containerTaskList) {
            ContainerTaskHis taskHis = new ContainerTaskHis();
            containerTask.setStatus(ContainerTaskStatusConstants.FINISH_STATUS);
            containerTask.setUpdateTime(LocalDateTime.now());
            BeanUtil.copyProperties(containerTask, taskHis);
            containerTaskHisService.save(taskHis);
            containerTaskService.deleteById(containerTask.getId());
        }

    }

    private void taskFinishBack(BizOutboundTask bizOutboundTask, ContainerTask containerTask) throws Exception {
        BizOutboundTaskDetail outboundTaskDetail = bizOutboundTaskDetailService.findById(containerTask.getOutboundDetailId());
        wmsTaskFinishBackService.execute(Arrays.asList(WmsTaskFinishDto.builder().msgId(StrUtil.uuid()).billNo(bizOutboundTask.getBillNo()).containerNo(containerTask.getContainerNo()).businessType(bizOutboundTask.getBusinessType()).workType(bizOutboundTask.getWorkType()).warehouseId(bizOutboundTask.getWmsWarehouseId()).taskId(bizOutboundTask.getUpperSystemTaskId()).taskLineId(outboundTaskDetail.getSeqNo()).itemId(outboundTaskDetail.getItemId()).lotId(outboundTaskDetail.getLotId()).ownerId(outboundTaskDetail.getOwnerId()).packId(outboundTaskDetail.getPackId()).employeeId(getUserId()).inventoryQty(containerTask.getQty()).wmsLocationCode(bizOutboundTask.getWmsLocationCode()).lackQty("0").isLack(1).build()));
    }

    public String getUserId() {
        final UserDTO userDTO = userTemplate.getUserDTO();
        if (null != userDTO) {
            return userDTO.getUserBizModel().getEmployeeNo();
        }
        throw new PrologException("获取用户信息为空");
    }

    @Override
    public void saveContainerStore(String containerNo, String containerSubNo, BizProperty bizProperty, int qty, String palletType) throws Exception {
        final List<PalletInfo> palletInfos = palletInfoMapper.findByMap(MapUtils.put("palletNo", containerNo).getMap(), PalletInfo.class);

        if (!palletInfos.isEmpty() && null == palletInfos.get(0).getPalletType()) {
            palletInfoMapper.updateMapById(palletInfos.get(0).getId(), MapUtils.put("palletType", palletType).put("updateTime", new Date()).getMap(), PalletInfo.class);
        }
    }

    @Override
    public void taskHangUp(Long taskId) throws Exception {
        String username = userTemplate.getUserDTO().getUsername();
        bizInboundTaskDetailMapper.updateMapById(taskId, MapUtils.put("isHangUp", 1).put("updateTime", new Date()).put("extend1", username).put("extend2", new Date()).getMap(), BizInboundTaskDetail.class);
    }

    @Override
    public Page<GoodsInfoVO> findNowPalletNo(String palletNo, String itemId, String lotId, String packId, String ownerId, int pageSize, int pageNum) throws Exception {
        PageUtils.startPage(pageNum, pageSize);
        List<GoodsInfoVO> goodsInfoVOS = bizInboundTaskDetailMapper.findNowPalletNo(palletNo, itemId, lotId, packId, ownerId);
        Page<GoodsInfoVO> page = PageUtils.getPage(goodsInfoVOS);
        final List<GoodsInfoVO> itemGoods = getItemGoods(page.getList());
        page.setList(itemGoods);
        return page;
    }

    @Override
    public Page<GoodsInfoVO> findNewPalletNo(QueryLocationDto dto) throws Exception {
        final List<CategoryAreaNo> categoryAreaNoList = categoryAreaNoMapper.findByMap(MapUtils.put("itemHealthCategory", dto.getItemHealthCategory()).getMap(), CategoryAreaNo.class);
        if (categoryAreaNoList.isEmpty()) {
            throw new Exception("依据商品大类编码" + dto.getItemHealthCategory() + "查询货位限定表无数据！");
        }
        final List<StationCfg> stationCfgs = stationCfgMapper.findByMap(MapUtils.put("stationNo", dto.getStationNo()).getMap(), StationCfg.class);
        Assert.notEmpty(stationCfgs, String.format("依据站台号%s查询出站台信息为空", dto.getStationNo()));
        PageUtils.startPage(dto.getPageNum(), dto.getPageSize());
        List<GoodsInfoVO> goodsInfoVOS = bizInboundTaskDetailMapper.findNewPalletNo(dto.getPalletNo(), dto.getPalletLocation(), stationCfgs.get(0).getAreaNo(), categoryAreaNoList.get(0).getAreaNo(), dto.getItemId(), dto.getLotId(), dto.getOwnerId(), dto.getItemHealthCategory(), AbcTypeConstant.TYPE_A.equals(dto.getAbcType()) ? "1" : null, dto.getAbcType());
        Page<GoodsInfoVO> page = PageUtils.getPage(goodsInfoVOS);

        final List<GoodsInfoVO> infoVOS = getItemGoods(page.getList());
        page.setList(infoVOS);
        return page;
    }

    @Override
    public RestMessage<String> getPallet(ScanContainerNoDto dto) throws Exception {
        scanContainerNo(dto);
        return RestMessage.newInstance(true, "请求成功！");
    }

    @Override
    public void taskHangUpRelease(Long taskId) throws Exception {
        bizInboundTaskDetailMapper.updateMapById(taskId, MapUtils.put("isHangUp", 0).put("updateTime", new Date()).getMap(), BizInboundTaskDetail.class);
    }


    @Override
    public List<GoodsInfoVO> queryHangUp(String itemCode, String cargoOwnerName, String itemName, String billNo, String hangUpUser, String startTime, String endTime) throws ParseException {
        Date startDate = null;
        Date endDate = null;
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        if (!StringUtils.isEmpty(startTime)) {
            startDate = sf.parse(startTime);
        }
        if (!StringUtils.isEmpty(endTime)) {
            endDate = sf.parse(endTime);
        }
        List<GoodsInfoVO> goodsInfoVOS = bizInboundTaskMapper.findBasicInfo();

        if (CollectionUtil.isEmpty(goodsInfoVOS)) {
            return null;
        }
        if (!StringUtils.isEmpty(billNo)) {
            goodsInfoVOS = goodsInfoVOS.stream().filter(s -> s.getBillNo().equals(billNo)).collect(Collectors.toList());
        }

        if (CollectionUtil.isEmpty(goodsInfoVOS)) {
            return null;
        }
        if (startDate != null) {
            Date finalStartDate = startDate;
            goodsInfoVOS = goodsInfoVOS.stream().filter(s -> s.getCreateTime().getTime() > finalStartDate.getTime()).collect(Collectors.toList());
        }

        if (CollectionUtil.isEmpty(goodsInfoVOS)) {
            return null;
        }
        if (endDate != null) {
            Date finalStartDate = endDate;
            goodsInfoVOS = goodsInfoVOS.stream().filter(s -> s.getCreateTime().getTime() < finalStartDate.getTime()).collect(Collectors.toList());
        }

        if (CollectionUtil.isEmpty(goodsInfoVOS)) {
            return null;
        }
        List<String> items = goodsInfoVOS.stream().map(GoodsInfoVO::getGoodsId).collect(Collectors.toList());
        ItemSyncQueryByIdVO itemSyncQueryByIdVO = new ItemSyncQueryByIdVO();
        itemSyncQueryByIdVO.setItemIds(items);
        RestMessage<Page<ItemSyncVO>> pageRestMessage = itemFeign.queryItemMst(itemSyncQueryByIdVO);
        Assert.isTrue(pageRestMessage.isSuccess(), "调用获取商品信息失败");
        List<ItemSyncVO> itemSyncVOS = pageRestMessage.getData().getList();
        if (CollectionUtil.isEmpty(itemSyncVOS)) {
            return null;
        }
        for (GoodsInfoVO goodsInfoVO : goodsInfoVOS) {
            List<ItemSyncVO> collect = itemSyncVOS.stream().filter(s -> s.getItemId().equals(goodsInfoVO.getGoodsId())).collect(Collectors.toList());
            ItemSyncVO itemSyncVO = collect.get(0);
            BeanUtils.copyProperties(itemSyncVO, goodsInfoVO);
        }

        if (CollectionUtil.isEmpty(goodsInfoVOS)) {
            return null;
        }
        if (!StringUtils.isEmpty(itemCode)) {
            goodsInfoVOS = goodsInfoVOS.stream().filter(s -> itemCode.equals(s.getItemCode())).collect(Collectors.toList());
        }

        if (CollectionUtil.isEmpty(goodsInfoVOS)) {
            return null;
        }
        if (!StringUtils.isEmpty(itemName)) {
            goodsInfoVOS = goodsInfoVOS.stream().filter(s -> itemName.contains(s.getItemName())).collect(Collectors.toList());
        }
        if (CollectionUtil.isEmpty(goodsInfoVOS)) {
            return null;
        }
        if (!StringUtils.isEmpty(cargoOwnerName)) {
            goodsInfoVOS = goodsInfoVOS.stream().filter(s -> cargoOwnerName.equals(s.getCargoOwnerName())).collect(Collectors.toList());
        }
        if (CollectionUtil.isEmpty(goodsInfoVOS)) {
            return null;
        }
        if (!StringUtils.isEmpty(hangUpUser)) {
            goodsInfoVOS = goodsInfoVOS.stream().filter(s -> hangUpUser.equals(s.getHangUpUser())).collect(Collectors.toList());
        }
        return goodsInfoVOS;
    }


    @Override
    public Integer queryConfirmABC(String abcType, Long bizPropertyId, String palletNo, String palletLocation) {
        return bizInboundTaskDetailMapper.queryConfirmABC(abcType, bizPropertyId, palletNo, palletLocation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    public void newPalletNoConfirm(NewPalletNoConfirmDto dto) throws Exception {
        final List<CategoryAreaNo> categoryAreaNoList = categoryAreaNoMapper.findByMap(MapUtils.put("itemHealthCategory", dto.getItemHealthCategory()).getMap(), CategoryAreaNo.class);
        Assert.notEmpty(categoryAreaNoList, "商品大类" + dto.getItemHealthCategory() + "对应的区域为空！");
        List<StationCfg> stationCfgList = stationCfgMapper.findByMap(MapUtils.put("stationNo", dto.getStationNo()).getMap(), StationCfg.class);
        Assert.notEmpty(stationCfgList, String.format("站台【%s】未配置", dto.getStationNo()));
        StationCfg stationCfg = stationCfgMapper.findByMap(MapUtils.put("relationalId", stationCfgList.get(0).getId()).getMap(), StationCfg.class).stream().findFirst().orElseThrow(() -> new PrologException(String.format("上架站台【%s】对应叫料站台未配置", dto.getStationNo())));

        if (LocationType.LOCATION_TYPE_SHELVES.equals(dto.getOldLocationType())) {
            //原货架离站
            updateContainerInfo(dto.getOldPalletNo(), ContainerTaskTypeConstants.IDLE);
            palletMoveExecuteService.palletLeaveIng(dto.getOldPalletNo(), stationCfgList.get(0).getAreaNo(), ContainerTaskTypeConstants.OLD_PALLET_RETURN, dto.getItemHealthCategory());
        } else if (LocationType.LOCATION_TYPE_CONTAINER.equals(dto.getOldLocationType())) {
            //原容器回库
            createBatchRerurenCarry(dto.getOldPalletNo(), dto.getItemHealthCategory());
        }

        if (LocationType.LOCATION_TYPE_SHELVES.equals(dto.getNewLocationType())) {
            List<PalletInfo> palletInfos = palletInfoMapper.findByMap(MapUtils.put("palletNo", dto.getNewPalletNo()).put("status", BaseConstant.NO).put("subArea", categoryAreaNoList.get(0).getAreaNo()).getMap(), PalletInfo.class);

            Assert.notEmpty(palletInfos, "货架任务进行中，请重新选择！");
            //新货架搬运到站台
            Criteria criteriaPalletInfo = new Criteria(PalletInfo.class);
            criteriaPalletInfo.restrictionBuilder().eq(PalletInfo::getPalletNo, dto.getNewPalletNo()).build();
            List<PalletInfo> palletInfoList = palletInfoMapper.findByCriteria(criteriaPalletInfo);
            Assert.notEmpty(palletInfoList, String.format("货架【%s】信息为查询到", dto.getNewPalletNo()));
            updateContainerInfo(dto.getNewPalletNo(), ContainerTaskTypeConstants.INBOUND);
            palletMoveExecuteService.palletArriveIng(dto.getNewPalletNo(), palletInfoList.get(0).getSubArea(), stationCfg.getAreaNo(), dto.getPlanes(), stationCfg.getAngle(), BaseTaskTypeConstants.HJ_TYPE);

        } else if (LocationType.LOCATION_TYPE_CONTAINER.equals(dto.getNewLocationType())) {
            //新容器搬运到站台
            CarryTask carryTask = new CarryTask();
            carryTask.setId(StrUtil.uuid());
            carryTask.setPalletNo(dto.getNewPalletNo());
            carryTask.setContainerNo(dto.getNewPalletNo());
            carryTask.setTaskType(LocationConstants.PATH_TASK_TYPE_CARRY);
            carryTask.setEndRegion(stationCfg.getAreaNo());
            carryTask.setCreateTime(new Date());
            carryTask.setBusinessType(String.valueOf(BaseTaskTypeConstants.AGVL_TYPE)); //todo 类型确认
            carryTask.setExtend2(WmsLocationCodeConstants.SX01);
            carryTask.setTaskRemark("拆零入库容器出库");
            carryTask.setPriority(99);
            routeFeignService.createBatchCarry(Arrays.asList(carryTask));

        }

        Criteria criteriaDismantling = Criteria.forClass(DismantlingLocationHitRecord.class);
        criteriaDismantling.setRestriction(Restrictions.and(Restrictions.eq(DismantlingLocationHitRecord::getPalletNo, dto.getOldPalletNo()), Restrictions.eq(DismantlingLocationHitRecord::getTaskDetailId, dto.getTaskId())));
        dismantlingLocationHitRecordService.updateMapByCriteria(MapUtils.put("locationNo", dto.getPalletLocation()).put("palletNo", dto.getNewPalletNo()).getMap(), criteriaDismantling);

        Criteria criteria = new Criteria(DismantlingLocationHitRecord.class);
        criteria.setRestriction(Restrictions.eq(DismantlingLocationHitRecord::getTaskDetailId, dto.getTaskId()).and(Restrictions.eq(DismantlingLocationHitRecord::getPalletNo, dto.getNewPalletNo())));
        bizOutboundTaskDetailService.updateMapByCriteria(MapUtils.put("palletNo", dto.getNewPalletNo()).put("locationNo", dto.getPalletLocation()).put("locationType", dto.getNewLocationType()).getMap(), criteria);

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    public void nowPalletNoConfirm(String stationNo, String palletNo, String planes, Long taskId, String palletLocation, String oldPalletLocation) throws Exception {
        final List<StationCfg> stationCfgs = stationCfgMapper.getStationCfg(stationNo);
        //final List<StationCfg> stationCfgs = stationCfgMapper.findByMap(MapUtils.put("stationNo", stationNo).getMap(), StationCfg.class);
        Assert.notEmpty(stationCfgs, "站台未配置！");
        List<PalletInfo> palletInfoList = palletInfoMapper.findByMap(MapUtils.put("subArea", stationCfgs.get(0).getAreaNo()).put("status", BaseConstant.NO).put("palletNo", palletNo).getMap(), PalletInfo.class);
        Assert.notEmpty(palletInfoList, "货架未到位！");

        String directionStr = AngleConversionAB.getDirectionStr(palletInfoList.get(0).getAngle(), stationCfgs.get(0).getAngle());
        if (!directionStr.equals(planes)) {
            palletMoveExecuteService.palletRotate(palletNo, stationCfgs.get(0).getAreaNo(), planes, stationCfgs.get(0).getAngle());
        }

        Criteria criteriaDismantling = Criteria.forClass(DismantlingLocationHitRecord.class);
        criteriaDismantling.setRestriction(Restrictions.and(Restrictions.eq(DismantlingLocationHitRecord::getPalletNo, palletNo), Restrictions.eq(DismantlingLocationHitRecord::getTaskDetailId, taskId)));
        dismantlingLocationHitRecordService.updateMapByCriteria(MapUtils.put("locationNo", palletLocation).getMap(), criteriaDismantling);

        bizInboundTaskDetailMapper.updateMapById(taskId, MapUtils.put("containerSubNo", palletLocation).put("updateTime", new Date()).getMap(), BizInboundTaskDetail.class);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    public RestMessage<?> shelfReturn(ShelfReturnDto dto) throws Exception {

        final RestMessage<?> restMessage = stationService.checkWorkStationNo(dto.getStationNo(), StationTaskTypeConstants.STATION_TYPE_INBOUND);
        if (!restMessage.isSuccess()) {
            return restMessage;
        }
        Criteria criteria1 = new Criteria(DismantlingLocationHitRecord.class);
        criteria1.restrictionBuilder().eq(DismantlingLocationHitRecord::getPalletNo, dto.getPalletNo()).build();
        List<DismantlingLocationHitRecord> records = dismantlingLocationHitRecordService.findByCriteria(criteria1);
        criteria1 = new Criteria(DismantlingLocationHitRecord.class);
        criteria1.restrictionBuilder().eq(DismantlingLocationHitRecord::getTaskDetailId, records.get(0).getTaskDetailId()).build();
        records = dismantlingLocationHitRecordService.findByCriteria(criteria1);
        BizInboundTaskDetail inboundTaskDetail = bizInboundTaskDetailMapper.findById(records.get(0).getTaskDetailId(), BizInboundTaskDetail.class);
        if (CollectionUtil.isNotEmpty(records) && records.size() == 1 && Objects.nonNull(inboundTaskDetail) && inboundTaskDetail.getRealQty().compareTo(inboundTaskDetail.getQty()) != 0) {
            throw new PrologException("此任务还未上架完成，容器不能归还");
        }


        Criteria criteria = Criteria.forClass(BizInboundTaskDetail.class);
        criteria.setRestriction(Restrictions.like(BizInboundTaskDetail::getContainerSubNo, dto.getPalletNo()));
        bizInboundTaskDetailMapper.updateMapByCriteria(MapUtils.put("containerSubNo", null).put("updateTime", new Date()).getMap(), criteria);

        updateContainerInfo(dto.getPalletNo(), BaseTaskTypeConstants.INBOUND_RETURN);


        List<StationCfg> stationCfgList = stationCfgMapper.getStationCfg(dto.getStationNo());
        Assert.notEmpty(stationCfgList, "叫料站台未配置！");


        if (LocationType.LOCATION_TYPE_SHELVES.equals(dto.getLocationType())) {
            List<PalletInfo> palletInfoList = palletInfoMapper.findByMap(MapUtils.put("subArea", stationCfgList.get(0).getAreaNo()).put("status", BaseConstant.NO).put("palletNo", dto.getPalletNo()).getMap(), PalletInfo.class);


            if (palletInfoList.isEmpty()) {
                return RestMessage.newInstance(false, "201", "当前站台区域无货架", null);
            }
            final List<PalletInfo> palletInfos = palletInfoMapper.findByMap(MapUtils.put("palletNo", dto.getPalletNo()).getMap(), PalletInfo.class);

            if (palletInfos.isEmpty()) {
                return RestMessage.newInstance(false, "201", "此货架信息为空", null);
            }


            String itemHealthCategory = dto.getItemHealthCategory();
            if (StringUtils.isEmpty(dto.getItemHealthCategory())) {
                itemHealthCategory = palletInfoMapper.findByMap(MapUtils.put("palletNo", dto.getPalletNo()).getMap(), PalletInfo.class).get(0).getPalletType();
            }
            palletMoveExecuteService.palletLeaveIng(dto.getPalletNo(), stationCfgList.get(0).getAreaNo(), ContainerTaskTypeConstants.INBOUND_RETURN, itemHealthCategory);
        } else if (LocationType.LOCATION_TYPE_CONTAINER.equals(dto.getLocationType())) {
            this.createBatchRerurenCarry(dto.getPalletNo(), dto.getItemHealthCategory());
        }
        dismantlingLocationHitRecordService.toHis(dto.getTaskId(), dto.getPalletNo());
        return RestMessage.newInstance(true, "200", "货架归还成功！", null);
    }


    private void createBatchRerurenCarry(String containerNo, String itemHealthCategory) throws Exception {
        // 生成搬运任务
//        String targetSubAreaNo = null;
//        List<CategoryAreaNo> healthCategory = categoryAreaNoMapper
//                .findByMap(com.prolog.framework.utils.MapUtils.put("itemHealthCategory", itemHealthCategory).getMap(), CategoryAreaNo.class);
//        if (!healthCategory.isEmpty() && !Objects.isNull(healthCategory.get(0).getAreaNo())) {
//            targetSubAreaNo = healthCategory.get(0).getAreaNo();
//        } else {
//            targetSubAreaNo = sysParamMapper
//                    .findByMap(com.prolog.framework.utils.MapUtils.put("paramNo", WmsConstants.DEFAULT_SUB_AREA_NO).getMap(), SysParam.class)
//                    .stream().findFirst().orElse(new SysParam()).getParamValue();
//        }
//
//        if (Objects.isNull(targetSubAreaNo)) {
//            throw new BizException(String.format("商品大类%s子区域为空", itemHealthCategory));
//        }

        String targetAreaNo = sysParamMapper.findByMap(com.prolog.framework.utils.MapUtils.put("paramNo", WmsConstants.DEFAULT_TP_AREA_NO).getMap(), SysParam.class).stream().findFirst().orElse(new SysParam()).getParamValue();

        if (Objects.isNull(targetAreaNo)) {
            throw new BizException(String.format("货位存储区为空"));
        }
        CarryTask carryTask = new CarryTask();
        carryTask.setId(StrUtil.uuid());
        carryTask.setPalletNo(containerNo);
        carryTask.setContainerNo(containerNo);
        carryTask.setTaskType(LocationConstants.PATH_TASK_TYPE_CARRY);
        carryTask.setEndRegion(targetAreaNo);
        carryTask.setSubAreaNo(targetAreaNo);
        carryTask.setCreateTime(new Date());
        carryTask.setBusinessType(String.valueOf(BaseTaskTypeConstants.AGVL_TYPE)); //todo 类型确认
        carryTask.setExtend2(WmsLocationCodeConstants.SX01);
        carryTask.setTaskRemark("拆零入库容器出库");
        carryTask.setPriority(99);
        routeFeignService.createBatchCarry(Arrays.asList(carryTask));
    }

    InboundTaskVO getPalletNoLocation(InboundTaskVO resultInfo, String palletLocation, String palletNo, String plane) {
        Criteria criteria = Criteria.forClass(PalletLocation.class);
        criteria.setRestriction(Restrictions.and(Restrictions.eq("palletNo", palletNo), Restrictions.eq("planes", plane)));
        criteria.setOrder(Order.newInstance().asc("palletLocation"));
        final List<PalletLocation> palletLocations = palletLocationMapper.findByCriteria(criteria);
        final PalletLocation location = palletLocations.stream().filter(p -> p.getPalletLocation().equals(palletLocation)).findFirst().orElse(new PalletLocation());
        palletLocations.stream().forEach(x -> {
            if (x.getPalletLocation().equals(location.getPalletLocation())) {
                location.setIsPower(1);
            }
            x.setLocationType(LocationType.LOCATION_TYPE_SHELVES);
        });
        resultInfo.setPalletLocationList(palletLocations);
        return resultInfo;
    }

    private void callPalletNum(ContainerVO vo, StationCfg stationCfg) {
        if (!Objects.isNull(vo) && CollectionUtil.isNotEmpty(vo.getGoodsShelvesVOS())) {
            List<DismantlingLocationHitRecord> dismantlingLocationHitRecords = new ArrayList<>();
            List<GoodsShelvesVO> shelvesVOList = ListHelper.distinct(vo.getGoodsShelvesVOS(), x -> x.getPalletNo());

            String[] palletNos = shelvesVOList.stream().map(GoodsShelvesVO::getPalletNo).toArray(String[]::new);
            Criteria criteriaB = Criteria.forClass(PalletInfo.class);
            criteriaB.restrictionBuilder().in(PalletInfo::getPalletNo, palletNos).build();
            List<PalletInfo> palletInfoList = palletInfoMapper.findByCriteria(criteriaB);
            if (CollectionUtils.isEmpty(palletInfoList)) {
                throw new BizException(String.format("货架" + StrUtil.join(",", palletNos) + "信息为空！"));
            }
            Map<String, List<PalletInfo>> palletInfoMap = palletInfoList.stream().collect(Collectors.groupingBy(PalletInfo::getPalletNo));
            for (GoodsShelvesVO goodsShelvesVO : shelvesVOList) {
                PalletInfo palletInfo = Objects.isNull(palletInfoMap.get(goodsShelvesVO.getPalletNo())) ? null : palletInfoMap.get(goodsShelvesVO.getPalletNo()).get(0);
                Assert.notNull(palletInfo, "货架" + palletInfo.getPalletNo() + "信息为空！");
                Assert.notNull(palletInfo.getSubArea(), "货架" + palletInfo.getPalletNo() + "区域为空！");
                Assert.notNull(stationCfg.getAreaNo(), "站台区域为空");
                palletMoveExecuteService.palletArriveIng(goodsShelvesVO.getPalletNo(), palletInfo.getSubArea(), stationCfg.getAreaNo(), goodsShelvesVO.getPlanes(), stationCfg.getAngle(), BaseTaskTypeConstants.AGVL_TYPE);
                updateContainerInfo(goodsShelvesVO.getPalletNo(), ContainerTaskTypeConstants.INBOUND);
            }
        }
    }

    /**
     * 呼叫拆零区托盘
     *
     * @param stationCfg
     * @return
     */
    @InterfaceMethod(key = "callContainer", name = "呼叫容器", type = InterfaceType.Send)
    private void callContainer(ContainerVO vo, StationCfg stationCfg) throws Exception {
        if (!Objects.isNull(vo) && CollectionUtils.isNotEmpty(vo.getContainerInfoDtos())) {
            List<String> containerNo = vo.getContainerInfoDtos().stream().map(ContainerInfoDto::getContainerNo).collect(Collectors.toList());
            //查询点位
            List<ContainerLocationVo> locationByContainerList = routeFeignService.findLocationByContainerList(containerNo);
            Map<String, List<ContainerLocationVo>> containerMap = locationByContainerList.stream().collect(Collectors.groupingBy(group -> group.getContainerNo()));
            List<CarryTask> tasks = new ArrayList<>();
            for (ContainerInfoDto containerInfoDto : vo.getContainerInfoDtos()) {
                if (!CollectionUtil.isEmpty(containerMap.get(containerInfoDto.getContainerNo()))) {

                    // TODO: 2023/10/8 删除搬运任务  走整体调度逻辑
                    CarryTask carryTask = new CarryTask();
                    carryTask.setId(StrUtil.uuid());
                    carryTask.setPalletNo(containerInfoDto.getContainerNo());
                    carryTask.setContainerNo(containerInfoDto.getContainerNo());
                    carryTask.setTaskType(LocationConstants.PATH_TASK_TYPE_CARRY);
                    carryTask.setEndRegion(stationCfg.getAreaNo());
                    carryTask.setCreateTime(new Date());
                    carryTask.setBusinessType(String.valueOf(BaseTaskTypeConstants.AGVL_TYPE)); //todo 类型确认
                    carryTask.setBusinessProperty(String.valueOf(BaseTaskTypeConstants.HJ_TYPE));
                    carryTask.setExtend2(WmsLocationCodeConstants.SX01);
                    carryTask.setTaskRemark("拆零入库容器出库");
                    carryTask.setPriority(99);
                    tasks.add(carryTask);

                } else {
                    Assert.notNull(containerInfoDto, String.format("容器未查询到点位！", containerNo));
                }
            }
            routeFeignService.createBatchCarry(tasks);
            Criteria criteriaDetail = new Criteria(ContainerInfo.class);
            criteriaDetail.setRestriction(Restrictions.in("containerNo", containerNo.toArray()));
            containerInfoService.updateByMap(MapUtils.put("taskType", ContainerTaskTypeConstants.INBOUND).put("updateTime", LocalDateTime.now()).getMap(), criteriaDetail);
        }
    }


    void saveInboundRecord(GoodsInfoVO inbound) {
        final InboundRecord inboundRecord = InboundRecord.builder().lotId(inbound.getLotId()).goodsId(inbound.getGoodsId()).packId(inbound.getPackId()).ownerId(inbound.getOwnerId()).taskId(inbound.getTaskId()).qty(inbound.getQty()).realQty(inbound.getInQty()).wareHouse(inbound.getWareHouse()).stationNo(inbound.getStationNo()).palletLocation(inbound.getPalletLocation()).companyName("").createBy(Objects.isNull(userService.getUserInfo()) ? "" : userService.getUserInfo()).createTime(new Date()).build();
        inboundRecordMapper.save(inboundRecord);
    }

    /**
     * 容器库存处理
     *
     * @param containerNo
     * @param containerSubNo
     * @param qty
     * @param vo
     * @param singleVolume
     * @param prodDate
     * @param expireDate
     * @param seqNo
     * @param itemHealthCategory
     * @throws Exception
     */
    private void intoStoreLocation(String containerNo, String containerSubNo, BigDecimal qty, GoodsInfoVO vo, BigDecimal singleVolume, Date prodDate, Date expireDate, String seqNo, String itemHealthCategory, String locationType) throws Exception {
        BigDecimal changeQty = BigDecimal.ZERO;
        BigDecimal targetQty = BigDecimal.ZERO;
        BigDecimal sigleVolume = Objects.isNull(singleVolume) ? BigDecimal.ZERO : singleVolume;

        if (StrUtil.equals(containerNo, containerSubNo)) {
            //托盘
            ContainerInfo containerInfo = containerInfoMapper.findByMap(MapUtils.put("containerNo", containerNo).getMap(), ContainerInfo.class).stream().findFirst().orElseThrow(() -> new PrologException(String.format("容器%s没有库存信息", containerNo)));
            ContainerInfoDetail containerInfoDetail = containerInfoDetailService.findOneByMap(MapUtils.put("containerNo", containerNo).getMap());
            if (containerInfo.getContainerType() == ContainerInfoTypeConstants.EMPTY_PALLET) {
                containerInfoDetail.setQty(qty);
                containerInfoDetail.setItemId(vo.getGoodsId());
                containerInfoDetail.setLotId(vo.getLotId());
                containerInfoDetail.setPackId(vo.getPackId());
                containerInfoDetail.setOwnerId(vo.getOwnerId());
                ItemSyncVO itemSyncVO = itemService.queryItemMst(Arrays.asList(vo.getGoodsId())).get(0);
                containerInfoDetail.setMaxVolume(itemSyncVO.getPalletStdQuantity());
                containerInfoDetail.setSingleVolume(sigleVolume);
                containerInfoDetail.setVolume(sigleVolume.multiply(qty));
            } else {
                if (!StrUtil.equals(containerInfoDetail.getItemId(), vo.getGoodsId()) || !StrUtil.equals(containerInfoDetail.getLotId(), vo.getLotId()) || !StrUtil.equals(containerInfoDetail.getPackId(), vo.getPackId()) || !StrUtil.equals(containerInfoDetail.getOwnerId(), vo.getOwnerId())) {
                    throw new PrologException("托盘商品不是同品同批");
                }
                containerInfoDetail.setQty(containerInfoDetail.getQty().add(qty));
                containerInfoDetail.setSingleVolume(sigleVolume);
                containerInfoDetail.setVolume(sigleVolume.multiply(qty));
            }
            containerInfo.setContainerType(ContainerInfoTypeConstants.GOODS_PALLET);
            containerInfo.setAreaType(AreaTypeConstant.AGV_CL);
            containerInfo.setTaskType(ContainerTaskTypeConstants.INBOUND);
            containerInfo.setWarehouseArea(WmsCarryTaskInCode.AGVL.getCode());
            containerInfoMapper.update(containerInfo);
            containerInfoDetailService.update(containerInfoDetail);

        } else {
            ContainerInfo containerInfo = containerInfoMapper.findByMap(MapUtils.put("containerNo", containerNo).getMap(), ContainerInfo.class).stream().findFirst().orElse(null);
            if (Objects.isNull(containerInfo)) {
                containerInfo = new ContainerInfo();
                final List<PalletInfo> palletInfoList = palletInfoMapper.findByMap(MapUtils.put("palletNo", containerNo).getMap(), PalletInfo.class);
                Assert.notEmpty(palletInfoList, String.format("货架%s未维护！", containerNo));
                final List<PalletInfo> palletInfos = palletInfoList.stream().filter(x -> "0".equals(x.getPalletType()) || Objects.isNull(x.getPalletType())).collect(Collectors.toList());
                if (!palletInfos.isEmpty()) {
                    Criteria criteria = Criteria.forClass(PalletInfo.class);
                    criteria.setRestriction(Restrictions.eq("palletNo", containerNo));
                    palletInfoMapper.updateMapByCriteria(MapUtils.put("palletType", itemHealthCategory).put("updateTime", new Date()).getMap(), criteria);
                }
                containerInfo.setContainerType(ContainerInfoTypeConstants.GOODS_SHELF);
                containerInfo.setContainerNo(containerNo);
                containerInfo.setAreaType(AreaTypeConstant.AGV_CL);
                containerInfo.setIsLock(0);
                containerInfo.setTaskType(ContainerTaskTypeConstants.INBOUND);
                containerInfo.setCreateTime(LocalDateTime.now());
                containerInfo.setWarehouseArea(WmsCarryTaskInCode.AGVL.getCode());
                containerInfoMapper.save(containerInfo);
            }
            //货架
            final List<ContainerInfoDetail> containerInfoDetailList = containerInfoDetailMapper.findByMap(MapUtils.put("containerSubNo", containerSubNo).put("lotId", vo.getLotId()).put("itemId", vo.getGoodsId()).put("ownerId", vo.getOwnerId()).put("packId", vo.getPackId()).getMap(), ContainerInfoDetail.class);
            if (containerInfoDetailList.isEmpty()) {
                ContainerInfoDetail containerInfoDetail = new ContainerInfoDetail();
                containerInfoDetail.setContainerNo(containerNo);
                containerInfoDetail.setContainerSubNo(containerSubNo);
                containerInfoDetail.setAreaType(AreaTypeConstant.AGV_CL);
                //containerInfoDetail.setBizPropertyId(bizProperty.getId());
                containerInfoDetail.setItemId(vo.getGoodsId());
                containerInfoDetail.setLotId(vo.getLotId());
                containerInfoDetail.setOwnerId(vo.getOwnerId());
                containerInfoDetail.setPackId(vo.getPackId());
                containerInfoDetail.setIsLock(0);
                containerInfoDetail.setQty(qty);
                containerInfoDetail.setTaskType(0);
                containerInfoDetail.setSingleVolume(sigleVolume);
                containerInfoDetail.setVolume(sigleVolume.multiply(qty));
                containerInfoDetail.setProdDate(prodDate);
                containerInfoDetail.setExpireDate(expireDate);
                containerInfoDetail.setCreateTime(LocalDateTime.now());
                containerInfoDetail.setLockQty(BigDecimal.ZERO);
                ItemSyncVO itemSyncVO = itemService.queryItemMst(Arrays.asList(vo.getGoodsId())).get(0);
                containerInfoDetail.setMaxVolume(itemSyncVO.getPalletStdQuantity());
                changeQty = changeQty.add(containerInfoDetail.getQty());
                targetQty = targetQty.add(containerInfoDetail.getQty());
                containerInfoDetailMapper.save(containerInfoDetail);
            } else {
                ContainerInfoDetail containerInfoDetail = containerInfoDetailList.get(0);
                changeQty = changeQty.add(qty);
                containerInfoDetail.setSingleVolume(sigleVolume);
                containerInfoDetail.setQty(qty.add(containerInfoDetail.getQty()));
                targetQty = targetQty.add(containerInfoDetail.getQty());
                containerInfoDetail.setVolume(sigleVolume.multiply(containerInfoDetail.getQty()));
                containerInfoDetail.setUpdateTime(LocalDateTime.now());
                containerInfoDetail.setPackId(vo.getPackId());
                containerInfoDetailMapper.update(containerInfoDetail);
            }
        }
        containerStoreChangeService.saveContainerStoreChange(containerNo, containerSubNo, vo, ContainerTaskTypeConstants.INBOUND, targetQty, changeQty, "入库新增", seqNo);
    }

    public List<GoodsInfoVO> getItemGoods(List<GoodsInfoVO> goodsInfoVOS) throws Exception {
        List<GoodsInfoVO> goodsInfoVOList = goodsInfoService.getGoodsInfo(goodsInfoVOS);
        return goodsInfoVOList.isEmpty() ? Lists.newArrayList() : goodsInfoVOList;
    }

    private void updateContainerInfo(String palletNo, int taskType) {
        Criteria criteria = Criteria.forClass(ContainerInfo.class);
        criteria.setRestriction(Restrictions.eq(ContainerInfo::getContainerNo, palletNo));
        containerInfoMapper.updateMapByCriteria(MapUtils.put("taskType", taskType).put("updateTime", new Date()).getMap(), criteria);

        Criteria criteria2 = Criteria.forClass(ContainerInfoDetail.class);
        criteria2.setRestriction(Restrictions.eq(ContainerInfoDetail::getContainerNo, palletNo));
        containerInfoMapper.updateMapByCriteria(MapUtils.put("taskType", taskType).put("updateTime", new Date()).getMap(), criteria2);
    }


    @Override
    public List<ShelvesTaskListDto> shelvesTaskList(PageUtilDto pageUtilDto) {
        PageUtils.startPage(pageUtilDto.getPageNum(), pageUtilDto.getPageSize());
        return bizInboundTaskMapper.shelvesTaskList();
    }

    @Override
    public List<ShelvesTaskDetailRespDto> shelvesTaskDetail(ShelvesTaskDetailReqDto req) throws Exception {
        List<ShelvesTaskDetailRespDto> list = bizInboundTaskMapper.shelvesTaskDetail(req);
        if (CollectionUtil.isEmpty(list)) {
            return list;
        }
        Set<String> itemIds = new HashSet<>();
        Set<String> lotIds = new HashSet<>();
        Set<Integer> detailIds = new HashSet<>();
        list.forEach(item -> {
            itemIds.add(item.getItemId());
            lotIds.add(item.getLotId());
            detailIds.add(item.getDetailId());
        });
        ContainerLocationVo containerLocationVo = routeFeignService.findLocationByContainerListNotVail(Arrays.asList(list.get(0).getContainerNo())).stream().findFirst().get();
        List<BatchNumberSync> batchNumberSyncs = inventoryService.getBatchNumberSync(new ArrayList<>(lotIds));
        List<ItemSyncVO> itemSyncVOS = itemService.queryItemMst(new ArrayList<>(itemIds));
        Criteria criteria = new Criteria(DismantlingLocationHitRecord.class);
        criteria.restrictionBuilder().in(DismantlingLocationHitRecord::getTaskDetailId, detailIds).build();
        List<DismantlingLocationHitRecord> hitRecords = dismantlingLocationHitRecordService.findByCriteria(criteria);
        if (CollectionUtils.isEmpty(hitRecords)) {
            throw new PrologException("容器还未到位，请稍等");
        }
        List<ContainerLocationVo> containerLocationVoList = routeFeignService.findLocationByContainerListNotVail(hitRecords.stream().map(DismantlingLocationHitRecord::getPalletNo).distinct().collect(Collectors.toList()));
        list.forEach(item -> {
            ItemSyncVO itemSyncVO = itemSyncVOS.stream().filter(i -> StrUtil.equals(i.getItemId(), item.getItemId())).findFirst().get();
            BatchNumberSync batchNumberSync = batchNumberSyncs.stream().filter(i -> StrUtil.equals(i.getBatchId(), item.getLotId())).findFirst().get();
            item.setItemCode(itemSyncVO.getItemCode());
            item.setPieceBarcode(itemSyncVO.getPieceBarcode());
            item.setItemName(itemSyncVO.getItemName());
            item.setLotNo(batchNumberSync.getManufacturerLotNum());
            item.setBatchExpiredDateShow(batchNumberSync.getBatchExpiredDateShow());
            item.setBatchProductionDateShow(batchNumberSync.getBatchProductionDateShow());
            BigDecimal[] bigDecimals = item.getQty().divideAndRemainder(itemSyncVO.getUomList().get(0).getConversionRate());
            item.setPieceQty(bigDecimals[0]);
            item.setScatteredQty(bigDecimals[1]);
            item.setPackQty(itemSyncVO.getUomList().get(0).getConversionRate());
            //判断订单托是否到站
            if (containerLocationVo.getCurrentArea().contains("CLSJ")) {
                //判断定位到的料托或货架是否到站
                List<ContainerLocationVo> endContainerLocations = containerLocationVoList.stream().filter(i -> i.getCurrentArea().contains("CLJL") && StrUtil.equals(i.getTargetArea(), i.getCurrentArea())).collect(Collectors.toList());
                if (CollectionUtil.isEmpty(endContainerLocations)) {
                    return;
                }
                //筛选当前入库明细定位到的所有料托或货架
                List<DismantlingLocationHitRecord> recordList = hitRecords.stream().filter(i -> StrUtil.equals(i.getTaskDetailId(), item.getDetailId().toString())).collect(Collectors.toList());
                List<String> containerNos = recordList.stream().map(DismantlingLocationHitRecord::getPalletNo).distinct().collect(Collectors.toList());
                endContainerLocations = endContainerLocations.stream().filter(i -> containerNos.contains(i.getContainerNo())).collect(Collectors.toList());
                if (CollectionUtil.isEmpty(endContainerLocations)) {
                    return;
                }
                //从到位的料托或货架中找出第一个到位的进行有序上架
                endContainerLocations = endContainerLocations.stream().sorted(Comparator.comparing(ContainerLocationVo::getUpdateTime)).collect(Collectors.toList());
                for (ContainerLocationVo endContainerLocation : endContainerLocations) {
                    DismantlingLocationHitRecord dismantlingLocationHitRecord = recordList.stream().filter(i -> StrUtil.equals(i.getPalletNo(), endContainerLocation.getContainerNo()) && i.getStatus() == 0).findFirst().orElse(null);
                    if (Objects.nonNull(dismantlingLocationHitRecord)) {
                        //有到位的货架并未作业的货格
                        item.setUpContainerNo(endContainerLocation.getContainerNo());
                        item.setSuggestLocationNo(dismantlingLocationHitRecord.getLocationNo());
                        item.setCurLocationNo(endContainerLocation.getCurrentLocation());
                        break;
                    }
                }
                if (StrUtil.isBlank(item.getUpContainerNo()) && CollectionUtils.isNotEmpty(endContainerLocations)) {
                    ContainerLocationVo endContainerLocations1 = endContainerLocations.stream().sorted(Comparator.comparing(ContainerLocationVo::getUpdateTime)).findFirst().get();
                    DismantlingLocationHitRecord dismantlingLocationHitRecord = recordList.stream().filter(i -> StrUtil.equals(i.getPalletNo(), endContainerLocations1.getContainerNo())).findFirst().get();
                    item.setUpContainerNo(endContainerLocations1.getContainerNo());
                    item.setSuggestLocationNo(dismantlingLocationHitRecord.getLocationNo());
                    item.setCurLocationNo(endContainerLocations1.getCurrentLocation());
                }
            }
        });
        return list;
    }


    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    @Override
    public void shelvesTaskSubmit(ShelvesTaskSubmitDto req) throws Exception {
        AssertUtils.isNotTrue(!StrUtil.equals(req.getContainerSubNo(), req.getScanContainerSubNo()), "推荐储位和扫描储位不一致");
        ItemSyncVO itemInfo = itemService.queryItemMst(Arrays.asList(req.getItemId())).stream().findFirst().orElseThrow(() -> new PrologException(String.format("未查询到物料id%s的物料信息", req.getItemId())));
        BizInboundTaskDetail inboundTaskDetail = bizInboundTaskDetailMapper.findById(req.getDetailId(), BizInboundTaskDetail.class);
        Assert.notNull(inboundTaskDetail, String.format("不存在上架明细id%s的入库任务！", req.getDetailId()));

        String locationType = LocationType.LOCATION_TYPE_CONTAINER;
        //判断是否上架在货架上
        if (!StrUtil.equals(req.getContainerNo(), req.getContainerSubNo())) {
            locationType = LocationType.LOCATION_TYPE_SHELVES;
            PalletInfo palletNo = palletInfoMapper.findByMap(MapUtils.put("palletNo", req.getContainerNo()).getMap(), PalletInfo.class).stream().findFirst().orElseThrow(() -> new PrologException(String.format("%s货架信息为空！", req.getContainerNo())));
            PalletLocation palletLocation = palletLocationMapper.findByMap(MapUtils.put("palletLocation", req.getContainerSubNo()).getMap(), PalletLocation.class).stream().findFirst().orElseThrow(() -> new PrologException(String.format("%s货格信息为空！", req.getContainerSubNo())));
            AssertUtils.isNotTrue(!StrUtil.equals(palletNo.getPalletNo(), palletLocation.getPalletNo()), String.format("%s货格不存在于%s货架上！", req.getContainerSubNo(), req.getContainerNo()));
//            //校验商品大类
//            if (!StringUtils.isEmpty(palletNo.getPalletType()) && !"0".equals(palletNo.getPalletType())) {
//                AssertUtils.isNotTrue(!palletNo.getPalletType().equals(itemInfo.getItemHealthCategory()), "当前入库任务商品大类与货架商品大类不一致");
//            }
            //校验同货架同品必须同批
            List<ContainerInfoDetail> containerInfoDetailList = containerInfoDetailService.findByMap(MapUtils.put("containerNo", req.getContainerNo()).put("itemId", inboundTaskDetail.getItemId()).getMap());
            if (CollectionUtils.isNotEmpty(containerInfoDetailList)) {
                long count = containerInfoDetailList.stream().filter(item -> !StrUtil.equals(item.getLotId(), inboundTaskDetail.getLotId())).count();
                AssertUtils.isNotTrue(count > 0, String.format("货架%s已存在此商品，批次必须相同", req.getContainerNo()));
            }
            if (!AbcTypeConstant.TYPE_A.equals(itemInfo.getAbcType())) {
                List<GoodsShelvesVO> goodsShelvesVOList = bizInboundTaskDetailMapper.findPalletNo(Collections.singletonList(req.getContainerNo()), Lists.newArrayList(itemInfo.getItemHealthCategory()), null, null, palletNo.getSubArea());
                List<String> itemIds = goodsShelvesVOList.stream().map(GoodsShelvesVO::getItemId).distinct().collect(Collectors.toList());
                List<ItemSyncVO> itemSyncVOS = itemService.queryItemMst(itemIds);
                List<PalletItemQtyInfoDto> palletItemQtyInfoDtos = this.genInfo(goodsShelvesVOList, itemSyncVOS);
                List<String> containerNos = new ArrayList<>();
                this.shelfGetContainerNos(itemInfo.getAbcType(), palletItemQtyInfoDtos, containerNos, req.getQty(), itemInfo);
            }
        }
        //校验同品同批
        ContainerInfoDetail containerInfoDetail = containerInfoDetailService.findOneByMap(MapUtils.put("containerSubNo", req.getContainerSubNo()).getMap());
        if (Objects.nonNull(containerInfoDetail) && !StrUtil.equals(containerInfoDetail.getItemId(), BasePropertyConstants.EMPTY_PALLET_PILE)) {
            AssertUtils.isNotTrue(!StrUtil.equals(containerInfoDetail.getItemId(), inboundTaskDetail.getItemId()) || !StrUtil.equals(containerInfoDetail.getLotId(), inboundTaskDetail.getLotId()), "同一托盘或同一货格必须同品同批存放");
        }
        //校验上架数量
        BigDecimal realQty = Objects.isNull(inboundTaskDetail.getRealQty()) ? BigDecimal.ZERO : inboundTaskDetail.getRealQty();
        AssertUtils.isNotTrue(realQty.add(req.getQty()).compareTo(inboundTaskDetail.getQty()) > 0, "上架数量超过订单数量，请检查");

        //处理库存
        GoodsInfoVO vo = GoodsInfoVO.builder().goodsId(inboundTaskDetail.getItemId()).lotId(inboundTaskDetail.getLotId()).packId(inboundTaskDetail.getPackId()).ownerId(inboundTaskDetail.getOwnerId()).build();
        BigDecimal singleVolume = null == itemInfo.getUomList() || itemInfo.getUomList().isEmpty() ? BigDecimal.ZERO : itemInfo.getUomList().get(0).getVolume().divide(itemInfo.getUomList().get(0).getConversionRate(), 2, BigDecimal.ROUND_DOWN);
        BatchNumberSync batchNumberSync = inventoryService.getBatchNumberSync(Arrays.asList(req.getLotId())).stream().findFirst().orElseThrow(() -> new PrologException(String.format("批次id%s未查询到批次信息", req.getLotId())));
        intoStoreLocation(req.getContainerNo(), req.getContainerSubNo(), req.getQty(), vo, singleVolume, batchNumberSync.getBatchProductionDate(), batchNumberSync.getBatchExpiredDate(), inboundTaskDetail.getSeqNo(), itemInfo.getItemHealthCategory(), locationType);

        BizInboundTask inboundTask = bizInboundTaskMapper.findById(inboundTaskDetail.getInboundId(), BizInboundTask.class);
        inboundTaskDetail.setRealQty(realQty.add(req.getQty()));
        inboundTaskDetail.setUpdateTime(LocalDateTime.now());
        boolean flag = false;
        if (realQty.add(req.getQty()).compareTo(inboundTaskDetail.getQty()) == 0) {
            inboundTaskDetail.setDetailStatus(BaseStatusEnum.STATUS_FINISH.getCode());
            inboundTaskDetail.setStationId(0);
            //当前明细已上架完成，清理残余的
            dismantlingLocationHitRecordService.toHis(req.getDetailId() + "");
            //正常拆零上架 原托盘搬到叠盘机
            if (!StrUtil.equals(inboundTask.getWorkType(), BizInboundTask.SUPPLY_WORK_TYPE)) {
                emptyContainerTaskService.save(inboundTask.getContainerNo(), LayerEnum.TWO, WmsCarryTaskInCode.MJZ);
                wmsContainerStatusUpdateService.execute(WmsContainerStatusUpdateDto.builder().containerCode(inboundTask.getContainerNo()).enterpriseId(inboundTask.getEnterpriseId()).warehouseId(inboundTask.getWmsWarehouseId()).build());
            }
            flag = true;
        }
        long update = bizInboundTaskDetailMapper.update(inboundTaskDetail);
        Criteria criteria = new Criteria(DismantlingLocationHitRecord.class);
        criteria.restrictionBuilder().eq(DismantlingLocationHitRecord::getTaskDetailId, req.getDetailId()).eq(DismantlingLocationHitRecord::getPalletNo, req.getContainerNo()).eq(DismantlingLocationHitRecord::getLocationNo, req.getContainerSubNo()).build();
        dismantlingLocationHitRecordService.updateMapByCriteria(MapUtils.put("status", 1).getMap(), criteria);
//        dismantlingLocationHitRecordService.toHis(req.getDetailId()+"", req.getContainerNo());
        Assert.isTrue(!(update <= 0), String.format("货架%s入库任务不存在或已被取消", req.getContainerNo()));
        if (flag) {
            final List<BizInboundTaskDetail> bizInboundTaskDetails = bizInboundTaskDetailMapper.findByMap(MapUtils.put("inboundId", inboundTaskDetail.getInboundId()).getMap(), BizInboundTaskDetail.class);
            final long l = bizInboundTaskDetails.stream().filter(x -> !BaseStatusEnum.STATUS_FINISH.getCode().equals(x.getDetailStatus())).count();
            if (0 == l) {
                bizInboundTaskMapper.updateMapById(inboundTaskDetail.getInboundId(), MapUtils.put("status", BaseStatusEnum.STATUS_FINISH.getCode()).put("finishTime", new Date()).getMap(), BizInboundTask.class);
                //补货后续流程
                supplyFinishTask(inboundTask, bizInboundTaskDetails.get(0));
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    public void shelfReturnPda(ShelvesReturnDto req, boolean checkTask) throws Exception {
        ContainerLocationVo containerLocationVo = routeFeignService.findLocationByContainerList(Arrays.asList(req.getContainerNo())).stream().findFirst().orElseThrow(() -> new PrologException(String.format("容器%s点位未查询到", req.getContainerNo())));
        List<String> stationAreaList = stationCfgService.findByMap(MapUtils.put("stationType", 71).getMap()).stream().map(StationCfg::getAreaNo).collect(Collectors.toList());
        if (!stationAreaList.contains(containerLocationVo.getCurrentArea())) {
            throw new PrologException("容器不在拆零叫料站台中，无法归还");
        }
        ContainerInfo containerInfo = containerInfoMapper.findByMap(MapUtils.put("containerNo", req.getContainerNo()).getMap(), ContainerInfo.class).get(0);
        if (containerInfo.getTaskType() != BaseTaskTypeConstants.INBOUND_TYPE) {
            throw new PrologException("容器已下发归还，请勿重复归还");
        }
        Criteria criteria1 = new Criteria(DismantlingLocationHitRecord.class);
        criteria1.restrictionBuilder().eq(DismantlingLocationHitRecord::getPalletNo, req.getContainerNo()).build();
        List<DismantlingLocationHitRecord> records = dismantlingLocationHitRecordService.findByCriteria(criteria1);
        if (CollectionUtils.isNotEmpty(records) && checkTask) {
            criteria1 = new Criteria(DismantlingLocationHitRecord.class);
            criteria1.restrictionBuilder().eq(DismantlingLocationHitRecord::getTaskDetailId, records.get(0).getTaskDetailId()).build();
            records = dismantlingLocationHitRecordService.findByCriteria(criteria1);
            long count = records.stream().map(DismantlingLocationHitRecord::getPalletNo).distinct().count();
            BizInboundTaskDetail inboundTaskDetail = bizInboundTaskDetailMapper.findById(records.get(0).getTaskDetailId(), BizInboundTaskDetail.class);
            if (count == 1 && Objects.nonNull(inboundTaskDetail)) {
                if (Objects.isNull(inboundTaskDetail.getRealQty())) {
                    inboundTaskDetail.setRealQty(BigDecimal.ZERO);
                }
                if (inboundTaskDetail.getRealQty().compareTo(inboundTaskDetail.getQty()) != 0) {
                    throw new PrologException("此任务还未上架完成，容器不能归还");
                }
            }
        }
        //货架归还时此货架有出库任务，直接调度到拣选站台
        List<ContainerTask> containerTaskList = containerTaskService.findByMap(MapUtils.put("containerNo", req.getContainerNo()).put("status", ContainerTaskStatusConstants.INIT_STATUS).getMap());
        if (CollectionUtils.isNotEmpty(containerTaskList)) {
            Criteria criteria = new Criteria(ContainerTask.class);
            criteria.restrictionBuilder().eq(ContainerTask::getContainerNo, req.getContainerNo()).build();
            containerTaskService.updateMapByCriteria(MapUtils.put("priorty", 10).getMap(), criteria);
            updateContainerInfo(req.getContainerNo(), ContainerTaskTypeConstants.IDLE);
        } else {
            updateContainerInfo(req.getContainerNo(), BaseTaskTypeConstants.INBOUND_RETURN);
            PalletInfo palletNo = palletInfoMapper.findByMap(MapUtils.put("palletNo", req.getContainerNo()).getMap(), PalletInfo.class).stream().findFirst().orElse(null);
            if (Objects.nonNull(palletNo)) {
                palletMoveExecuteService.palletLeaveIng(req.getContainerNo(), containerLocationVo.getAreaNo(), ContainerTaskTypeConstants.INBOUND_RETURN, palletNo.getPalletType());
            } else {
                this.createBatchRerurenCarry(req.getContainerNo(), null);
            }
        }
    }

    @Override
    public List<AgainListRespDto> againList(AgainListReqDto req) throws Exception {
        BizInboundTaskDetail taskDetail = bizInboundTaskDetailMapper.findById(req.getDetailId(), BizInboundTaskDetail.class);
        req.setItemId(taskDetail.getItemId());
        req.setLotId(taskDetail.getLotId());
        req.setOwnerId(taskDetail.getOwnerId());
        req.setPackId(taskDetail.getPackId());
        ItemSyncVO itemInfoVo = itemService.queryItemMst(Arrays.asList(req.getItemId())).stream().findFirst().orElseThrow(() -> new PrologException("未查询到商品信息"));


        List<CategoryAreaNo> categoryAreaNoList = categoryAreaNoMapper.findByMap(null, CategoryAreaNo.class);
        Map<String, List<CategoryAreaNo>> collect = categoryAreaNoList.stream().collect(Collectors.groupingBy(CategoryAreaNo::getItemHealthCategory));
        //如果传入的为中药饮片则只过滤对应大类商品
        if (itemInfoVo.getItemCategoryCode().equals(MEDICINE_TYPE)) {
            req.setCategory(itemInfoVo.getItemCategoryCode());
        }

        PageUtils.startPage(req.getPageNum(), req.getPageSize());
        List<AgainListRespDto> list = bizInboundTaskMapper.againList(req);
        ListIterator<AgainListRespDto> againListRespDtoListIterator = list.listIterator();
        while (againListRespDtoListIterator.hasNext()) {
            AgainListRespDto next = againListRespDtoListIterator.next();
            if (StrUtil.equals(next.getCategory(), "0")) {
                next.setCategory("空货架");
            } else if (StrUtil.equals(next.getCategory(), "-1")) {
                next.setCategory(itemInfoVo.getItemHealthCategoryName());
            } else {
                List<CategoryAreaNo> categoryAreaNos = collect.get(next.getCategory().toString());
                //判断是否为中药饮片
                if (itemInfoVo.getItemCategoryCode().equals(MEDICINE_TYPE)) {
                    //过滤不是中药饮片的货架
                    if (!next.getCategory().equals(MEDICINE_TYPE)) {
                        againListRespDtoListIterator.remove();
                        continue;
                    }
                } else {
                    //如果上架商品是中药饮片过滤中药饮片
                    if (next.getCategory().equals(MEDICINE_TYPE)) {
                        againListRespDtoListIterator.remove();
                        continue;
                    }
                }
                if (CollectionUtils.isNotEmpty(categoryAreaNos)) {
                    next.setCategory(categoryAreaNos.get(0).getItemHealthCategoryName());
                } else {
                    next.setCategory("未配置");
                }
            }
        }
        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    @Override
    public void againConfirm(AgainConfirmReqDto req) throws Exception {
        ContainerLocationVo containerLocationVo = routeFeignService.findLocationByContainerList(Arrays.asList(req.getSourceContainerNo())).stream().findFirst().get();
        ContainerLocationVo targetContainerLocation = routeFeignService.findLocationByContainerList(Arrays.asList(req.getTargetContainerNo())).stream().findFirst().get();
        Criteria criteria = new Criteria(LocationCfg.class);
        criteria.restrictionBuilder().in(LocationCfg::getType, Arrays.asList(3, 4)).build();
        List<String> areaNoList = locationCfgService.findByCriteria(criteria).stream().map(LocationCfg::getAreaNo).collect(Collectors.toList());
        if (!areaNoList.contains(targetContainerLocation.getCurrentArea())) {
            throw new PrologException("目标容器正在任务中，请重新选择");
        }
        //原容器回库
        shelfReturnPda(ShelvesReturnDto.builder().containerNo(req.getSourceContainerNo()).build(), false);
        String containerSubNo = req.getTargetContainerNo();
        PalletInfo palletInfo = palletInfoMapper.findByMap(MapUtils.put("palletNo", req.getTargetContainerNo()).getMap(), PalletInfo.class).stream().findFirst().orElse(null);
        if (Objects.nonNull(palletInfo)) {
            AssertUtils.isNotTrue(palletInfo.getStatus() == BaseConstant.YES, "货架任务进行中，请重新选择！");
            //新货架搬运到站台
            updateContainerInfo(req.getTargetContainerNo(), ContainerTaskTypeConstants.INBOUND);
            StationCfg stationCfg = stationCfgMapper.findByMap(MapUtils.put("areaNo", containerLocationVo.getCurrentArea()).getMap(), StationCfg.class).stream().findFirst().orElseThrow(() -> new PrologException(String.format("未查询到站台%s", containerLocationVo.getCurrentArea())));
            BizInboundTaskDetail taskDetail = bizInboundTaskDetailMapper.findById(req.getDetailId(), BizInboundTaskDetail.class);
//            ItemSyncVO itemInfoVo = itemService.queryItemMst(Arrays.asList(taskDetail.getItemId())).stream().findFirst().orElseThrow(() -> new PrologException("未查询到商品信息"));
//            if (!StrUtil.equals(palletInfo.getPalletType(), "0") && !StrUtil.equals(palletInfo.getPalletType(), itemInfoVo.getItemCategoryCode())) {
//                throw new PrologException("此货架不支持存储此大类商品");
//            }
            //校验同货架同品必须同批
            List<ContainerInfoDetail> containerInfoDetailList = containerInfoDetailService.findByMap(MapUtils.put("containerNo", palletInfo.getPalletNo()).put("itemId", taskDetail.getItemId()).getMap());
            if (CollectionUtils.isNotEmpty(containerInfoDetailList)) {
                long count = containerInfoDetailList.stream().filter(item -> !StrUtil.equals(item.getLotId(), taskDetail.getLotId())).count();
                AssertUtils.isNotTrue(count > 0, String.format("货架%s已存在此商品,批次与上架商品批次不同", palletInfo.getPalletNo()));
            }
            containerSubNo = getContainerSubNo(palletInfo.getPalletNo(), taskDetail);
            PalletLocation palletLocation = palletLocationMapper.findByMap(MapUtils.put("palletLocation", containerSubNo).getMap(), PalletLocation.class).stream().findFirst().orElseThrow(() -> new PrologException("未查询到货格信息"));
            palletMoveExecuteService.palletArriveIng(req.getTargetContainerNo(), targetContainerLocation.getCurrentArea(), containerLocationVo.getCurrentArea(), palletLocation.getPlanes(), stationCfg.getAngle(), BaseTaskTypeConstants.HJ_TYPE);
        } else {
            //新容器搬运到站台
            CarryTask carryTask = new CarryTask();
            carryTask.setId(StrUtil.uuid());
            carryTask.setPalletNo(req.getTargetContainerNo());
            carryTask.setContainerNo(req.getTargetContainerNo());
            carryTask.setTaskType(LocationConstants.PATH_TASK_TYPE_CARRY);
            carryTask.setEndRegion(containerLocationVo.getCurrentArea());
            carryTask.setCreateTime(new Date());
            carryTask.setBusinessType(String.valueOf(BaseTaskTypeConstants.AGVL_TYPE)); //todo 类型确认
            carryTask.setExtend2(WmsLocationCodeConstants.SX01);
            carryTask.setTaskRemark("拆零入库容器出库");
            carryTask.setPriority(99);
            routeFeignService.createBatchCarry(Arrays.asList(carryTask));
        }
        Criteria criteriaDismantling = Criteria.forClass(DismantlingLocationHitRecord.class);
        criteriaDismantling.setRestriction(Restrictions.and(Restrictions.eq(DismantlingLocationHitRecord::getPalletNo, req.getSourceContainerNo()), Restrictions.eq(DismantlingLocationHitRecord::getTaskDetailId, req.getDetailId())));
        dismantlingLocationHitRecordService.updateMapByCriteria(MapUtils.put("locationNo", containerSubNo).put("palletNo", req.getTargetContainerNo()).getMap(), criteriaDismantling);

        dismantlingLocationHitRecordService.deleteByMap(MapUtils.put("taskDetailId", req.getDetailId()).put("palletNo", req.getSourceContainerNo()).put("status", 0).getMap());
    }

    private String getContainerSubNo(String palletNo, BizInboundTaskDetail taskDetail) {
        List<PalletLocation> palletLocations = palletLocationMapper.findByMap(MapUtils.put("palletNo", palletNo).put("isLock", 0).getMap(), PalletLocation.class);
        Map<String, BigDecimal> collect2 = palletLocations.stream().collect(Collectors.toMap(PalletLocation::getPalletLocation, PalletLocation::getVolume));
        List<ContainerInfoDetail> containerInfoDetailList = containerInfoDetailService.findByMap(MapUtils.put("containerNo", palletNo).getMap());
        List<String> collect = containerInfoDetailList.stream().map(ContainerInfoDetail::getContainerSubNo).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            palletLocations = palletLocations.stream().filter(item -> !collect.contains(item.getPalletLocation())).collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(palletLocations)) {
            return palletLocations.stream().sorted(Comparator.comparing(PalletLocation::getPalletLocation)).findFirst().get().getPalletLocation();
        }
        List<ContainerInfoDetail> collect1 = containerInfoDetailList.stream().filter(item -> StrUtil.equals(item.getItemId(), taskDetail.getItemId()) && StrUtil.equals(item.getLotId(), taskDetail.getLotId()) && StrUtil.equals(item.getPackId(), taskDetail.getPackId()) && StrUtil.equals(item.getOwnerId(), taskDetail.getOwnerId()) && collect2.get(item.getContainerSubNo()).compareTo(item.getVolume()) > 0).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect1)) {
            throw new PrologException("没有符合分配的货格");
        }
        return collect1.stream().sorted(Comparator.comparing(ContainerInfoDetail::getVolume)).findFirst().get().getContainerSubNo();
    }

    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(rollbackFor = Exception.class)
    @Override
    public void locationChange(LocationChangeReqDto req) throws Exception {
        if (StrUtil.equals(req.getContainerSubNo(), req.getToContainerSubNo())) {
            return;
        }
        PalletLocation palletLocation = palletLocationMapper.findByMap(MapUtils.put("palletLocation", req.getToContainerSubNo()).getMap(), PalletLocation.class).stream().findFirst().orElseThrow(() -> new PrologException(String.format("未查询到%s货格信息", req.getToContainerSubNo())));
        AssertUtils.isNotTrue(!StrUtil.equals(req.getContainerNo(), palletLocation.getPalletNo()), "不能更换成其他货架货格");
        Criteria criteria = Criteria.forClass(DismantlingLocationHitRecord.class);
        criteria.setRestriction(Restrictions.and(Restrictions.eq(DismantlingLocationHitRecord::getLocationNo, req.getToContainerSubNo()), Restrictions.eq(DismantlingLocationHitRecord::getTaskDetailId, req.getDetailId())));
        List<DismantlingLocationHitRecord> hitRecords = dismantlingLocationHitRecordService.findByCriteria(criteria);
        if (CollectionUtils.isNotEmpty(hitRecords)) {
            throw new PrologException("此货格已存在待上架任务，无法更换");
        }
        //校验同品同批
        ContainerInfoDetail containerInfoDetail = containerInfoDetailService.findOneByMap(MapUtils.put("containerSubNo", req.getToContainerSubNo()).getMap());
        if (Objects.nonNull(containerInfoDetail)) {
            BizInboundTaskDetail taskDetail = bizInboundTaskDetailMapper.findById(req.getDetailId(), BizInboundTaskDetail.class);
            AssertUtils.isNotTrue(!StrUtil.equals(containerInfoDetail.getItemId(), taskDetail.getItemId()) || !StrUtil.equals(containerInfoDetail.getLotId(), taskDetail.getLotId()) || !StrUtil.equals(containerInfoDetail.getOwnerId(), taskDetail.getOwnerId()) || !StrUtil.equals(containerInfoDetail.getPackId(), taskDetail.getPackId()), "更换货格失败，同货格必须同品同批");
        }
//        PalletInfo palletInfo = palletInfoMapper.findByMap(MapUtils.put("palletNo", req.getContainerNo()).getMap(), PalletInfo.class).stream().findFirst().get();
//        ContainerLocationVo containerLocationVo = routeFeignService.findLocationByContainerList(Arrays.asList(req.getContainerNo())).stream().findFirst().get();
//        StationCfg stationCfg = stationCfgMapper.findByMap(MapUtils.put("areaNo", containerLocationVo.getCurrentArea()).getMap(), StationCfg.class).stream().findFirst().orElseThrow(() -> new PrologException(String.format("未查询到站台%s", containerLocationVo.getCurrentArea())));
//       //判断是否要换面
//        String directionStr = AngleConversionAB.getDirectionStr(palletInfo.getAngle(), stationCfg.getAngle());
//        if (!directionStr.equals(palletLocation.getPlanes())) {
//            palletMoveExecuteService.palletRotate(req.getContainerNo(), stationCfg.getAreaNo(), palletLocation.getPlanes(), stationCfg.getAngle());
//        }
        //更换货格
        Criteria criteriaDismantling = Criteria.forClass(DismantlingLocationHitRecord.class);
        criteriaDismantling.setRestriction(Restrictions.and(Restrictions.eq(DismantlingLocationHitRecord::getPalletNo, req.getContainerNo()), Restrictions.eq(DismantlingLocationHitRecord::getTaskDetailId, req.getDetailId())));
        dismantlingLocationHitRecordService.updateMapByCriteria(MapUtils.put("locationNo", req.getToContainerSubNo()).getMap(), criteriaDismantling);
    }
}
