package com.prolog.cs.biz.inbound.service.impl.rcv;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.codingapi.tx.annotation.TxTransaction;
import com.esotericsoftware.minlog.Log;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.prolog.common.util.ToolKits;
import com.prolog.cs.basic.chain.model.cargo.BaseCargoOwnerMst;
import com.prolog.cs.basic.common.model.BaseCommonDict;
import com.prolog.cs.basic.item.model.BaseMtlItemMst;
import com.prolog.cs.basic.item.model.vo.ItemBaseInfoVO;
import com.prolog.cs.basic.warehouse.model.BaseWmsWarehouseLocator;
import com.prolog.cs.basic.warehouse.model.vo.ContainerQueryVO;
import com.prolog.cs.basic.warehouse.model.vo.WarehouseLocatorBasicInfo;
import com.prolog.cs.biz.inbound.constant.BizConstant;
import com.prolog.cs.biz.inbound.constant.OperationConstant;
import com.prolog.cs.biz.inbound.dao.*;
import com.prolog.cs.biz.inbound.dao.rcv.*;
import com.prolog.cs.biz.inbound.dao.rqc.RqcHeadersMapper;
import com.prolog.cs.biz.inbound.dao.task.TaskInstockDetailMapper;
import com.prolog.cs.biz.inbound.dao.task.TaskQcDetailMapper;
import com.prolog.cs.biz.inbound.dto.PageParam;
import com.prolog.cs.biz.inbound.dto.rcv.*;
import com.prolog.cs.biz.inbound.dto.task.TaskInstockDetailDTO;
import com.prolog.cs.biz.inbound.model.*;
import com.prolog.cs.biz.inbound.model.rcv.*;
import com.prolog.cs.biz.inbound.model.rqc.RqcHeaders;
import com.prolog.cs.biz.inbound.model.task.TaskInstockDetail;
import com.prolog.cs.biz.inbound.remote.*;
import com.prolog.cs.biz.inbound.service.OrderInboundStatusBackService;
import com.prolog.cs.biz.inbound.service.impl.BaseServiceImpl;
import com.prolog.cs.biz.inbound.service.impl.processor.Helper.TaskHelper;
import com.prolog.cs.biz.inbound.service.rcv.RcvHeadersService;
import com.prolog.cs.biz.inbound.service.rcv.RcvInstockLinesService;
import com.prolog.cs.biz.inbound.service.task.TaskExceptionDetailService;
import com.prolog.cs.biz.inbound.service.task.TaskInstockDetailService;
import com.prolog.cs.biz.inbound.utils.ObjectUtils;
import com.prolog.cs.biz.inbound.utils.UserUtils;
import com.prolog.cs.biz.inbound.vo.*;
import com.prolog.cs.biz.inbound.vo.task.InstockTaskQueryVO;
import com.prolog.cs.biz.inbound.vo.task.TaskQueryVO;
import com.prolog.cs.data.exchange.client.ExchangeSender;
import com.prolog.cs.data.exchange.client.core.EtlMessage;
import com.prolog.cs.data.exchange.client.core.EtlTypeConstants;
import com.prolog.entity.vo.ContainerTailgatingRequestVO;
import com.prolog.entity.vo.InBoundRequestItemVO;
import com.prolog.entity.vo.InBoundRequestVO;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.beans.BeanUtils;
import com.prolog.framework.bz.common.integration.IntegrationApi;
import com.prolog.framework.bz.common.integration.IntegrationSearchData;
import com.prolog.framework.bz.common.integration.IntegrationSearchException;
import com.prolog.framework.bz.common.search.SearchApi;
import com.prolog.framework.bz.common.search.SearchException;
import com.prolog.framework.bz.core.collection.ValidList;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.exception.ParameterException;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.*;
import com.prolog.framework.dao.pagehelper.PageHelper;
import com.prolog.framework.dao.util.DaoUtils;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.framework.utils.*;
import com.prolog.inte.EisHandler;
import com.prolog.upcloud.base.inventory.enums.StockInTypeEnum;
import com.prolog.upcloud.base.inventory.vo.*;
import com.prolog.upcloud.base.wh.operate.vo.MoveConfirmParamsVO;
import com.prolog.wms.base.util.JsonMapper;
import com.prolog.wms.base.util.MD5Utils;
import com.prolog.wms.base.util.RestMsgUtils;
import com.prolog.wms.base.util.mapper.MapperCustom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.prolog.cs.biz.inbound.constant.InboundBizConstant.EIS_DEVICE_AREA_CODES;
import static com.prolog.cs.biz.inbound.constant.InboundBizConstant.EIS_PAPER_AREA_CODES;
import static com.prolog.cs.biz.inbound.utils.TransactionHelper.persistence;

@Service
public class RcvInstockLinesServiceImpl extends BaseServiceImpl<RcvInstockLines> implements RcvInstockLinesService {
    @Resource
    private RestTemplate restTemplate;

    @Resource
    private RcvInstockLinesMapper mapper;

    @Resource
    private UserUtils userUtils;

    @Resource
    private Validator validator;

    @Resource
    private TaskInstockDetailService taskInstockDetailService;

    @Resource
    private TaskInstockDetailMapper taskInstockDetailMapper;

    @Lazy
    @Resource
    private RcvHeadersService rcvHeadersService;

    @Resource
    private RcvHeadersMapper rcvHeadersMapper;

    @Resource
    private RcvLinesMapper rcvLineMapper;

    @Resource
    private RcvHeadersProfilesMapper rcvHeadersProfilesMapper;

    @Resource
    private RcvLinesProfilesMapper rcvLinesProfilesMapper;

    @Resource
    private BaseInventoryRemoteCaller baseInventoryRemoteCaller;

    @Resource
    private TaskExceptionDetailService taskExceptionDetailService;

    @Resource
    private BaseWmsWarehouseCaller baseWmsWarehouseCaller;

    @Resource
    private DataExchangeRemoteCaller dataExchangeRemoteCaller;

    @Resource
    private IncomingRecordBackHMapper incomingRecordBackHMapper;

    @Resource
    private IncomingRecordBackDMapper incomingRecordBackDMapper;

    @Resource
    private ReceivingRecordBackHMapper receivingRecordBackHMapper;

    @Resource
    private ReceivingRecordBackDMapper receivingRecordBackDMapper;

    @Resource
    private RqcHeadersMapper rqcHeadersMapper;

    @Resource
    private ExchangeSender exchangeSender;

    @Resource
    private OrderInboundStatusBackService orderStatusBackService;

    @Resource
    private WmsToEisTaskRecordMapper wmsToEisTaskRecordMapper;

    @Resource
    private OperateCaller operateCaller;

    @Resource
    private TaskHelper taskHelper;

    @Resource
    private EisHandler eisHandler;

    @Value("${prolog.dataExchange.dataExchangeUrl:http://data-exchange/data/callBack}")
    private String dataExchangeUrl;

    @Value("${prolog.test:false}")
    private boolean istest;

    @Value("${prolog.wms.instock.enablePadStoreTemperature:false}")
    private boolean enablePadStoreTemperature;
    @Value("${prolog.wms.instock.enablePadMatchLocatorType:false}")
    private boolean enablePadMatchLocatorType;

    @Value("${prolog.wms.instock.enablePadMatchLocatorLimit:false}")
    private boolean enablePadMatchLocatorLimit;

    @Value("${prolog.callSleepTimes:60000}") // 休眠1分钟
    private Long callSleepTimes;

    @Value("${prolog.callSleepTimes2:10}") // 休眠10ms
    private Long callSleepTimes2;

    @Value("${prolog.wms.instockTransforId:284}")
    private String instockTransforId;

    @Value("${prolog.wms.instockCallId:288}")
    private String instockCallId;

    @Value("${prolog.wms.instockCallStatusId:301}")
    private String instockCallStatusId;

    @Value("${prolog.wms.enablePush:false}")
    private Boolean enablePush;

    @Value("${prolog.instockTaskComplete.errorReturnTrue:true}")
    private Boolean errorReturnTrue;

//    @Value("${oms.incomingRecordBack}")
//    private String incomingRecordBack;

    private Executor executor = Executors.newFixedThreadPool(10);

    @Resource
    private SearchApi searchApi;

    @Resource
    private BaseItemRemoteCaller baseItemRemoteCaller;

    @Resource
    private IncomingRecordHMapper incomingRecordHMapper;

    @Resource
    private IncomingRecordDMapper incomingRecordDMapper;

    @Resource
    private OmsAsnBillHMapper omsAsnBillHMapper;

    @Resource
    private OmsAsnBillDMapper omsAsnBillDMapper;

    @Resource
    private OutboundCaller outboundCaller;

    private static Logger logger = LoggerFactory.getLogger(RcvInstockLinesServiceImpl.class);

    //	private final static String addMsg = "上架行保存操作";
    private final static String batchAddMsg = "上架行批量保存操作";
    private final static String batchEditMsg = "上架行批量编辑操作";

    @Value("${erp.inStockBack.erpUrl}")
    private String erpUrl;

    @Value("${eis.inboundTaskUrl}")
    private String inboundTaskUrl;

    @Resource
    EisToWmsMiddleMapper eisToWmsMiddleMapper;
    @Resource
    private ChainRemoteCaller chainRemoteCaller;

    private static Boolean AUTOFLAG = false;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private CommonCaller commonCaller;

    @Override
    @Transactional
    @TxTransaction
    public Object batchAdd(List<RcvInstockLinesDTO> rcvInstockLinesDTOList) {
        logger.info("执行上架逻辑-----------");
        // 前端需要从task中获取库存状态和上架标签传给上架行 TODO
        UserDTO userDTO = null;
        try {
            userDTO = userUtils.getUserDTO();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (userDTO == null) {
            userDTO = new UserDTO();
            userDTO.setEnterpriseId(rcvInstockLinesDTOList.get(0).getEnterpriseId());
            userDTO.setUsername("system");
            userDTO.setId("system");
        }
        this.batchAdd(rcvInstockLinesDTOList, userDTO, true);

        return true;
    }

    private void updateAsnStatus(Set<String> asnLineIdSet, String asnHeaderId) {
        // 更新asn相关状态
        //		if (!ObjectUtils.isNull(asnLineIdSet)) {
        //			for (String asnLineid : asnLineIdSet) {
        //				this.rcvLineMapper.updateAsnDetails(asnLineid);
        //			}
        //		}
        //		if (!ObjectUtils.isNull(asnHeaderId)) {
        //			this.rcvLineMapper.updateAsnHeader(asnHeaderId);
        //		}
    }

    private Object batchAdd(List<RcvInstockLinesDTO> rcvInstockLinesDTOList, UserDTO userDTO, Boolean call2erp) {
        return batchAdd(rcvInstockLinesDTOList, userDTO, call2erp, true);
    }

    private Object batchAdd(List<RcvInstockLinesDTO> rcvInstockLinesDTOList, UserDTO userDTO, Boolean call2erp, Boolean releaseContainer) {
        long start = System.currentTimeMillis();
        logger.info("上架开始时间: " + start + "(ms)");

        Date now = new Date();
        int row = 0;
        List<RcvInstockLines> list = new ArrayList<>();

        Map iqueryMap = new HashMap<>();
        List<Map> iqList = new ArrayList<>();

        List<String> locatorIds = rcvInstockLinesDTOList.stream().map(x -> x.getRealWhLocatorId()).collect(Collectors.toList());
        RestMessage<Map<String, Boolean>> locatorAreaPickMode = baseWmsWarehouseCaller.getLocatorAreaPickMode(locatorIds);
        if(!locatorAreaPickMode.isSuccess()){
            throw new BizException("远程调用查询货位库区拣货方式失败");
        }
        RestMessage<List<WarehouseLocatorBasicInfo>> locationBasicInfos = baseWmsWarehouseCaller.getLocationBasicInfos(locatorIds.toArray(new String[locatorIds.size()]));
        if(!locationBasicInfos.isSuccess()){
            throw new BizException("远程调用查询货位信息失败");
        }
        List<WarehouseLocatorBasicInfo> locatorInfos = locationBasicInfos.getData();
        Map<String, Boolean> data = locatorAreaPickMode.getData();
        for (RcvInstockLinesDTO rcvInstockLinesDTO : rcvInstockLinesDTOList) {
            row++;
            Boolean isBool = ArrayUtil.contains(EIS_DEVICE_AREA_CODES, rcvInstockLinesDTO.getWhAreaCategoryCode());
            //设备库的不能手动上架，非设备库的需要容器借道回告成功才能手动上架
            if(isBool){
                throw new BizException(String.format("第[%d]行实际货位[%s]库区拣货方式为设备，不能手动上架",row,rcvInstockLinesDTO.getRealWhLocatorCode()));
            }
            if (ArrayUtil.contains(EIS_PAPER_AREA_CODES, rcvInstockLinesDTO.getWhAreaCategoryCode()) && !"2".equals(rcvInstockLinesDTO.getEisPushStatus())) {
                throw new BizException(String.format("第[%d]行实际货位[%s]库区拣货方式为非设备，需要等待容器借道下发回告完成才能手动上架",row,rcvInstockLinesDTO.getRealWhLocatorCode()));
            }
            WarehouseLocatorBasicInfo locatorBasicInfo = locatorInfos.stream().filter(x -> x.getWarehouseLocatorId().equals(rcvInstockLinesDTO.getRealWhLocatorId())).findFirst().orElse(null);
            if(locatorBasicInfo!=null){
                if(!StringUtils.isEmpty(locatorBasicInfo.getMixType())&&locatorBasicInfo.getMixType().equals("1")){
                    WmsInvStockQtyQueryVO queryVO = new WmsInvStockQtyQueryVO();
                    queryVO.setEnterpriseId(rcvInstockLinesDTO.getEnterpriseId());
                    queryVO.setLocatorId(rcvInstockLinesDTO.getRealWhLocatorId());
                    queryVO.setWarehouseId(rcvInstockLinesDTO.getWarehouseId());
                    queryVO.setCargoOwnerId(rcvInstockLinesDTO.getMtlOwnerId());
                    RestMessage<List<WmsInvStockQtyVO>> availableQuantity = baseInventoryRemoteCaller.getAvailableQuantity(Collections.singletonList(queryVO));
                    if(!availableQuantity.isSuccess()){
                        throw new BizException("查询货位批次库存信息失败");
                    }
                    List<WmsInvStockQtyVO> stockLots = availableQuantity.getData();
                    List<WmsInvStockQtyVO> collect = stockLots.stream().filter(x -> !x.getBatchId().equals(rcvInstockLinesDTO.getBatchId())).collect(Collectors.toList());
                    if(collect.size()>0){
                        boolean flag = collect.stream().anyMatch(x -> x.getAvailableQuantity().compareTo(BigDecimal.ZERO) > 0);
                        if(flag){
                            throw new BizException(String.format("第%d行,货位%s为单品单批，已有其他商品批次库存",row,rcvInstockLinesDTO.getRealWhLocatorCode()));
                        }
                    }
                }
                rcvInstockLinesDTO.setWhAreaCategoryName(locatorBasicInfo.getWarehouseAreaCategoryName());
            }
            // 增加商品校验
            Map qmap = new HashMap<>();
            qmap.put("itemId", rcvInstockLinesDTO.getItemId());
            qmap.put("itemCategoryCode", rcvInstockLinesDTO.getCategoryId());
            qmap.put("refId", row);
            qmap.put("flag", false);
            qmap.put("message", "");
            iqList.add(qmap);

            rcvInstockLinesDTO.setLineNum(new BigDecimal(row));
            // 数据准确性计算
            BigDecimal pieceQty = rcvInstockLinesDTO.getPieceQty();
            BigDecimal conversionRate = rcvInstockLinesDTO.getConversionRate();
            if (conversionRate == null) {
                conversionRate = BigDecimal.ONE;
                rcvInstockLinesDTO.setConversionRate(conversionRate);
            }
            if (pieceQty == null) {
                pieceQty = BigDecimal.ZERO;
                rcvInstockLinesDTO.setPieceQty(pieceQty);
            }
            BigDecimal caseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
            BigDecimal multiply = caseQty.multiply(conversionRate);
            BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
            BigDecimal qty = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN); // 包装总量
            // 保证数据正确性再次进行计算
            rcvInstockLinesDTO.setOddCaseQty(caseQty);
            rcvInstockLinesDTO.setOddPieceQty(oddPieceQty);

            String realWhLocatorId = rcvInstockLinesDTO.getRealWhLocatorId();
            AssertUtils.isNotBlank(realWhLocatorId, String.format("第[%d]行,实际货位id不可为空!", row));
            Date autoTime = rcvInstockLinesDTO.getAutoTime() == null ? now : rcvInstockLinesDTO.getAutoTime();
            RcvInstockLines excuteSavePre = excuteSavePre(row, rcvInstockLinesDTO, autoTime, list);

            // 判断上架不能上超,超出关联的收货行,判断是
            String rcvLineId = rcvInstockLinesDTO.getRcvLineId();
            RcvLines findById = this.rcvLineMapper.findById(rcvLineId, RcvLines.class);
            if (findById != null && pieceQty.compareTo(findById.getPieceQty()) == 1) {
                throw new BizException(String.format("第[%d]行,上架数量超出收货数量!请检查重试!", row));
            }

            if (errorReturnTrue && ObjectUtils.isNull(excuteSavePre)) {
                continue;
            }
        }
        iqueryMap.put("queryMap", iqList);
        iqueryMap.put("type", "in");
        iqueryMap.put("cargoOwnerId", rcvInstockLinesDTOList.get(0).getMtlOwnerId());
//        excuteVaildteItem(iqueryMap, rcvInstockLinesDTOList, userDTO, now); //暂时注释，查询货主失败

        if (ObjectUtils.isNull(list) && errorReturnTrue) {
            logger.error("上架行保存失敗上架数据为空!");
            return true;
        }
        // 需要回传erp/oms 判断是否收货完成 TODO job 或手动 回传
        if (list.size() > 500) {
            try {
                DaoUtils.saveBatch(this.mapper, list, 500);
            } catch (Exception e) {
                logger.error("上架行保存失敗，错误详情:", e);
                throw new BizException("批量保存上架行失败!");
            }
        } else {
            this.mapper.saveBatch(list);
        }
        // 执行入库操作
        excuteInStock(list, releaseContainer);

        // 通知oms/erp收货上架成功
        if (call2erp) {
            excuteCallBackErp(list);
        }

        //asn没有状态需要更新
        // 更新asn明细表状态以及asn单状态
//        String asnHeaderId = rcvInstockLinesDTOList.get(0).getAsnHeaderId();
//        Set<String> asnLineIdSet = rcvInstockLinesDTOList.stream().filter(p -> StringUtils.isBlank(p.getAsnLineId())).map(p -> p.getAsnLineId()).collect(Collectors.toSet());
//        updateAsnStatus(asnLineIdSet, asnHeaderId);

        long end = System.currentTimeMillis();
        logger.info("上架结束时间: " + end + "(ms)");
        long eb = end - start;
        logger.info("耗时: " + eb + "(ms)");
        return null;
    }

    private void excuteVaildteItem(Map iqueryMap, List<RcvInstockLinesDTO> rcvInstockLinesDTOList, UserDTO userDTO, Date now) {
        RcvInstockLinesDTO linesDTO = rcvInstockLinesDTOList.get(0);
        String mtlOwnerId = linesDTO.getMtlOwnerId();
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("cargoOwnerId", mtlOwnerId);
        List<Map> searchForMap = null;
        try {
            searchForMap = searchApi.searchForMap("getCargoOwnerProp", queryMap);
        } catch (Exception e) {
            logger.info("获取货主属性失败,原因{}", e);
        }
        if (!ObjectUtils.isNull(searchForMap)) {
            Map map = searchForMap.get(0);
            String flag1 = (String) map.get("vaildateItemLicense");
            String flag2 = (String) map.get("vaildateItemVol");
            String flag3 = (String) map.get("vaildateItemCategory");
            String flag4 = (String) map.get("vaildateItemInbound");
            String flag5 = (String) map.get("vaildateCargoOwnerScop");
            String flag6 = (String) map.get("vaildateContainer");
            // 校验商品证照
            //			vaildateItemLicense(flag1, iqueryMap, rcvInstockLinesDTOList, userDTO, now);
            // 校验商品体积信息
            //			vaildateItemVol(flag2, iqueryMap, rcvInstockLinesDTOList, userDTO, now);
            // 校验商品大类是否维护
            //			vaildateItemCategory(flag3, iqueryMap, rcvInstockLinesDTOList, userDTO, now);
            // 校验商品是否停售召回
            vaildateItemInbound(flag4, iqueryMap, rcvInstockLinesDTOList, userDTO, now);
            // 校验货主-商品大类关系(即货主的经营范围)
            //			vaildateCargoOwnerScop(flag5, iqueryMap, rcvInstockLinesDTOList, userDTO, now);
            // 校验入库商品绑定容器是否正确
            //			vaildateItemContainer(flag6, iqueryMap, rcvInstockLinesDTOList, userDTO, now);

        }
    }

    private void vaildateItemInbound(String flag4, Map iqueryMap, List<RcvInstockLinesDTO> rcvInstockLinesDTOList, UserDTO userDTO, Date now) {
        // 校验商品是否停售召回
        if (!StringUtils.isBlank(flag4) && "1".equals(flag4)) {
            RestMessage<Object> vaildatePurchaseAndSales = null;
            try {
                vaildatePurchaseAndSales = baseItemRemoteCaller.vaildatePurchaseAndSales(iqueryMap);
            } catch (Exception e) {
                logger.error("调用远程商品服务校验商品是否召回停售失败,原因{}", e.getMessage());
            }
            if (vaildatePurchaseAndSales != null) {
                if (!vaildatePurchaseAndSales.isSuccess()) {
                    throw new BizException("校验商品是否停售召回失败,原因->" + vaildatePurchaseAndSales.getMessage());
                } else {
                    Map rMap = (Map) vaildatePurchaseAndSales.getData();
                    List<Map> queryList = (List) rMap.get("queryMap");
                    for (Map map2 : queryList) {
                        Integer row = (Integer) map2.get("refId");
                        Boolean flag = (Boolean) map2.get("flag");
                        String itemId = (String) map2.get("itemId");
                        String message = (String) map2.get("message");
                        if (!flag) {
                            throw new BizException(String.format("第[%d]行,商品id[%s],商品停售,召回校验失败.原因->[%s]", row, itemId, message));
                        }
                    }
                }
            }
        }
    }

    private RcvInstockLines excuteSavePre(int row, RcvInstockLinesDTO dto, Date now, List<RcvInstockLines> list) {
        String taskId = dto.getTaskId();
        // 并发校验
        // 加锁(数据库锁)
        boolean canCommit = canCommit(dto, row);
        if (!canCommit) {
            if (errorReturnTrue) {
                Log.error(String.format("第[%d行]保存上架行失败!taskId为[%s]的上架任务已处理中,请刷新重试!", row, taskId));
                return null;
            } else {
                throw new BizException(String.format("第[%d行]保存上架行失败!taskId为[%s]的上架任务已处理中,请刷新重试!", row, taskId));
            }
        }
        UserDTO userDTO = userUtils.getUserDTO();
        boolean editFlag = Boolean.FALSE;
        this.vaildateModel(dto, editFlag, userDTO, row, validator, batchAddMsg);
        RcvInstockLines rcvInstockLines = new RcvInstockLines();
        BeanUtils.copyProperties(dto, rcvInstockLines);
        this.buildField(rcvInstockLines, editFlag, userDTO, now);

        String rcvType = rcvInstockLines.getRcvType();
        if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.STRAIGHT_IN)) {
            // 直调入
            rcvInstockLines.setInventoryStatus("1");
            rcvInstockLines.setSubStatus("4");
        }
        if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.HOSTED_IN)) {
            // 代管
            rcvInstockLines.setInventoryStatus("5");
            rcvInstockLines.setSubStatus("1");
        }

        if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.WAIT_CHECK_IN)) {
            // 待检
            rcvInstockLines.setInventoryStatus("3");
            rcvInstockLines.setSubStatus("1");
        }
        // 代管转待检
        String inventoryOpType = rcvInstockLines.getInventoryOpType();
        if (!StringUtils.isBlank(inventoryOpType) && "1".equals(inventoryOpType)) {
            rcvInstockLines.setInventoryStatus("1");
            rcvInstockLines.setSubStatus("6");
        }
        // 代管转正常
        if (!StringUtils.isBlank(inventoryOpType) && "0".equals(inventoryOpType)) {
            rcvInstockLines.setInventoryStatus("1");
            rcvInstockLines.setSubStatus("5");
        }

        //		taskIds.add(taskId);
        // TODO 上架标签,这里先用雪花代替,以后使用其他逻辑获取,虚拟
        //		rcvInstockLines.setInstockLabel(String.valueOf(SnowFlakeUtils.getId()));
        //		Integer random = new Random().nextInt(2) + 1; // 随机1和2 库存状态
        String inventoryStatus = rcvInstockLines.getInventoryStatus();
        if (StringUtils.isBlank(inventoryStatus)) {
            rcvInstockLines.setInventoryStatus("1"); // 默认合格
        }
        rcvInstockLines.setLineNum(BigDecimal.valueOf(row));
        //河南省医药需要上架员的姓名
        rcvInstockLines.setCreatorName(userDTO.getNickname());
        rcvInstockLines.setModifierName(userDTO.getNickname());
        // 判断此taskId是否已经操作过
        list.add(rcvInstockLines);
        return rcvInstockLines;
    }

    private boolean canCommit(RcvInstockLinesDTO dto, int row) {
        String taskId = dto.getTaskId();
        // 数据库乐观锁
        //		TaskInstockDetail taskInstockDetail = this.taskInstockDetailMapper.findById(taskId, TaskInstockDetail.class);
        TaskInstockDetailDTO taskInstockDetail = this.taskInstockDetailMapper.findByPkId(taskId);
        AssertUtils.notNull(taskInstockDetail, String.format("第[%d]行,上架任务id:[%s]查询的任务为空!", row, taskId));
        String status = taskInstockDetail.getStatus();
        String rqcHeaderId = taskInstockDetail.getRqcHeaderId();
        String rqcLineId = taskInstockDetail.getRqcLineId();
        dto.setRefBillId(rqcHeaderId);
        dto.setRefLineId(rqcLineId);
        dto.setRefType(1);
        String inventoryOpType = dto.getInventoryOpType();
        if (StringUtils.isBlank(inventoryOpType)) {
            dto.setInventoryOpType(taskInstockDetail.getInventoryOpType());
        }
        String hostLocatorId = dto.getHostLocatorId();
        if (StringUtils.isBlank(hostLocatorId)) {
            dto.setHostLocatorId(taskInstockDetail.getHostLocatorId());
        }
        String whAreaCategoryCode = dto.getWhAreaCategoryCode();
        if (StringUtils.isBlank(whAreaCategoryCode)) {
            dto.setWhAreaCategoryCode(taskInstockDetail.getWhAreaCategoryCode());
        }

        if ("0".equals(status.trim()))
            throw new BizException(String.format("第[%d]行,上架任务id:[%s]查询的任务已经执行完毕,请刷新重试!", row, taskId));

        Criteria criteria = new Criteria(TaskInstockDetail.class);
        Integer dataVersion = taskInstockDetail.getDataVersion();

        criteria.setRestriction(Restrictions.and(Restrictions.eq("taskInboundId", taskId), Restrictions.eq("dataVersion", dataVersion)));
        //		criteria.setRestriction(
        //				Restrictions.and(Restrictions.eq("taskInboundId", taskId), Restrictions.eq("dataVersion", dataVersion),
        //						Restrictions.eq("status", status), Restrictions.eq("isLock", 0)));
        long count = taskInstockDetailMapper.updateMapByCriteria(MapUtils.put("dataVersion", dataVersion + 1).put("status", "0").getMap(), criteria);
        if (0 >= count)
            return false;
        //			throw new BizException(String.format("第%d行,[任务id:%s]数据正在进行处理,请刷新重试!", row, taskId));

        return true;
    }

    /**
     * 调用远程库存服务执行上架
     */
    private void excuteInStock(List<RcvInstockLines> list, Boolean releaseContainer) {

        // 已经预占过的进行入库确认
        // 注: 一个task对应一个上架行
        // (目前无法分辨哪个任务预占过库存,哪个是直接入库存.建议库存服务这里关联taskId进行处理,或者预占同步调用,task表中存储是否占用的标识)
        //		excuteInstockAffirm(list);
        UserDTO userDTO = userUtils.getUserDTO();
        // 直接入库上架,不走预占
        excuteInstock2(list);
        String warehouseId = list.get(0).getWarehouseId();
        if (releaseContainer) {
            // Step6: 容器释放 非立库的在上架完成释放容器，立库的不释放容器，在出库完成的时候释放
            List<String> containerCodeList = list.stream().filter(p -> !StringUtils.isBlank(p.getWhAreaCategoryCode())
                    && !ArrayUtil.contains(EIS_DEVICE_AREA_CODES, p.getWhAreaCategoryCode())
                    &&!StringUtils.isBlank(p.getContainerCode())
                    && !Objects.equals(p.getContainerCode(), "N/A")).map(RcvInstockLines::getContainerCode).collect(Collectors.toList());
            //检查容器上是否还存在其他的收货单没有完成，没有就可以释放
            List<String> canContainerList = new ArrayList<>();
            if(ToolKits.isNotEmpty(containerCodeList)){
                for (String containerCode : containerCodeList) {
                    Integer qty = mapper.checkContainerTask(containerCode);
                    if(qty == 0 ){//容器对应的asn明细单的数量全部上架完成，可以释放
                        canContainerList.add(containerCode);
                    }
                }
            }


            ContainerQueryVO cVO = new ContainerQueryVO();
            cVO.setWarehouseId(warehouseId);
            cVO.setEnterpriseId(userDTO.getEnterpriseId());
            cVO.setContainerCodeList(canContainerList);
            try {
                // 容器释放
                if(ToolKits.isNotEmpty(canContainerList)){
                    baseWmsWarehouseCaller.release(cVO);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void excuteInstock2(List<RcvInstockLines> list) {
        ValidList<InvStockIn> invStock = new ValidList<>();
        if (ObjectUtils.isNull(list)) {
            throw new BizException("上架的明细数据为空!请联系管理员重试!");
        }
        List<RcvInstockLines> list2 = list.stream().filter(p -> p.getCargoChangeIn() == null).collect(Collectors.toList());
        if (ObjectUtils.isNull(list2)) {
            return;
        }
        for (RcvInstockLines rcvInstockLines : list2) {
            Map<String, Object> extParams = new HashMap<>();
            //			for (RcvInstockLines rcvInstockLines : list) {
            String hostLocatorId = rcvInstockLines.getHostLocatorId();
            String rcvType = rcvInstockLines.getRcvType();
            if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.HOSTED_IN)) {
                // 代管
                rcvInstockLines.setInventoryStatus("5");
                rcvInstockLines.setSubStatus("1");
            }

            if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.WAIT_CHECK_IN)) {
                // 待检
                rcvInstockLines.setInventoryStatus("3");
                rcvInstockLines.setSubStatus("1");
            }

            if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.STRAIGHT_IN)) {
                // 直调
                rcvInstockLines.setInventoryStatus("1");
                rcvInstockLines.setSubStatus("4");
            }

            if (!StringUtils.isBlank(hostLocatorId) && !StringUtils.isBlank(rcvType)) {
                // 转单子控制
                if (rcvType.equals(BizConstant.WAIT_CHECK_IN)) {
                    // 代管转待检
                    rcvInstockLines.setSubStatus(StockInTypeEnum.ESCROW_TO_NO_INSPECT.getCode());
                    rcvInstockLines.setRealWhLocatorId(hostLocatorId); // 还是原货位转
                    extParams.put("noInspectLocatorId", hostLocatorId);
                } else {
                    // 代管转正常
                    rcvInstockLines.setSubStatus(StockInTypeEnum.ESCROW_TO_QUALIFIED.getCode());
                    extParams.put("escrowLocatorId", hostLocatorId);

                }
            }
            //            if (Objects.equals(rcvInstockLines.getInventoryStatus(),"4")) {
            //                rcvInstockLines.setInventoryStatus("2");
            //            }
            String batchId = rcvInstockLines.getBatchId();
            InvStockIn invStockIn = new InvStockIn();
            InvStockInDetail detail = new InvStockInDetail();
            List<InvStockInDetail> details = new ArrayList<>();

            detail.setExtParams(extParams);

            BigDecimal pieceQty = rcvInstockLines.getPieceQty();
            String warehouseLocatorId = rcvInstockLines.getWhLocatorId();
            String realWhLocatorId = rcvInstockLines.getRealWhLocatorId();
            String comments = rcvInstockLines.getComments();
            String goodsCaseCode = rcvInstockLines.getGoodsCaseCode();
            String containerCode = rcvInstockLines.getContainerCode();
            detail.setQuantity(pieceQty);
            detail.setContainerCode(containerCode);
//            if(!StringUtils.isEmpty(rcvInstockLines.getWhAreaCategoryCode()) && rcvInstockLines.getWhAreaCategoryCode().equals("AGVK")){
            if(!StringUtils.isEmpty(rcvInstockLines.getWhAreaCategoryCode()) && (ArrayUtil.contains(EIS_DEVICE_AREA_CODES, rcvInstockLines.getWhAreaCategoryCode()))){
                detail.setContainerCode(rcvInstockLines.getContainerCode());
            }else{
                detail.setContainerCode("N/A");
            }
            detail.setGoodsCaseCode(goodsCaseCode);
            detail.setLocatorId(realWhLocatorId);
            detail.setComments(comments);
            detail.setStatus(rcvInstockLines.getInventoryStatus());
            String subStatus = rcvInstockLines.getSubStatus();
            if (StringUtils.isBlank(subStatus)) {
                subStatus = "1";
            }
            detail.setInType(subStatus);
            detail.setBatchId(batchId);
            //			Map<String, Object> extParams = new HashMap<>();
            //			extParams.put("escrowLocatorId", hostLocatorId);
            //			detail.setExtParams(extParams);

            // 需要加入二级库存状态
            String secondStatus = rcvInstockLines.getSecondStatus();
            if (!StringUtils.isBlank(secondStatus)) {
                detail.setStatus(secondStatus);
            }

            details.add(detail);

            Date batchExpiredDate = rcvInstockLines.getBatchExpiredDate();
            Date batchProductionDate = rcvInstockLines.getBatchProductionDate();
            String inBoundLineId = rcvInstockLines.getInBoundLineId();
            String mtlOwnerId = rcvInstockLines.getMtlOwnerId();
            String itemId = rcvInstockLines.getItemId();
            String manufacturerBatchNum = rcvInstockLines.getManufacturerLotNum();
            String warehouseId = rcvInstockLines.getWarehouseId();
            String vendorBatchNum = rcvInstockLines.getVendorBatchNum();
            String productionPlace = rcvInstockLines.getProductionPlace();
            String orgId = rcvInstockLines.getOrgId();
            String vendorId = rcvInstockLines.getVendorId();
            String erpBatchNum2 = rcvInstockLines.getErpBatchNum();
            BigDecimal piecePriceTe = rcvInstockLines.getPiecePriceTe();
            BigDecimal piecePriceTi = rcvInstockLines.getPiecePriceTi();
            BigDecimal taxRate = rcvInstockLines.getTaxRate();
            String enterpriseId = rcvInstockLines.getEnterpriseId();

            // =====生产批次id/批次num所用
            String taskId = rcvInstockLines.getTaskId();
            String rcvHeaderId = rcvInstockLines.getRcvHeaderId();
            String asnHeaderId = rcvInstockLines.getAsnHeaderId();
            String rcvLineId = rcvInstockLines.getRcvLineId();
            String asnLineId = rcvInstockLines.getAsnLineId();
            Date rcvDate = rcvInstockLines.getRcvDate();

            invStockIn.setDetails(details);

            invStockIn.setAsnLineId(asnLineId);
            invStockIn.setAsnId(asnHeaderId);
            invStockIn.setRcvId(rcvHeaderId);
            invStockIn.setTaskId(taskId);
            invStockIn.setWarehouseId(warehouseId);
            //			invStockIn.setBatchId(batchId);
            invStockIn.setRcvLineId(rcvLineId);

            invStock.add(invStockIn);
        }

        // 远程调用直接入库存的服务
        RestMessage inStockBatchCheck = null;
        try {
            inStockBatchCheck = baseInventoryRemoteCaller.inStockBatchCheck(invStock);
            logger.info("调用库存接口inStockBatchCheck，入参：" + JsonUtils.toString(invStock) + "，返回：" + JsonUtils.toString(inStockBatchCheck));
        } catch (Exception e) {
            logger.error("上架调用远程库存服务失败!原因->{}", e);
            throw new BizException("上架调用远程库存服务失败!");
        }
        if (inStockBatchCheck == null) {
            logger.error("上架调用远程库存服务失败!");
            throw new BizException("上架调用远程库存服务失败!");
        }
        if (!inStockBatchCheck.isSuccess()) {
            Object data = inStockBatchCheck.getData();
            String dataMsg = "";
            if (data != null) {
                dataMsg = data.toString();
            }
            throw new BizException(String.format("上架调用远程库存服务失败!原因->%s", inStockBatchCheck.getMessage()) + dataMsg);
        }

    }

    private void excuteInstockAffirm(List<RcvInstockLines> list) {
        // TODO 进行入库操作(报错,待处理,已经预占过的)
        InvStockCheck check = new InvStockCheck();
        List<String> taskIds = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().distinct().map(RcvInstockLines::getTaskId).collect(Collectors.toList());
        check.setLineBillIds(taskIds.toArray(new String[taskIds.size()]));
        RestMessage inStock = null;
        try {
            inStock = baseInventoryRemoteCaller.inStockCheck(check);
        } catch (BizException e) {
            logger.error("调用库存接口失败", e);
            throw new BizException(e.getMessage());
        } catch (Exception e) {
            logger.error("调用库存接口失败", e);
            throw new BizException("调用库存接口失败");
        }
        if (inStock == null || !inStock.isSuccess())
            throw new BizException("入库失败!请刷新重试!原因");

    }

    //	private boolean canCommit(RcvInstockLinesDTO rcvInstockLinesDTO) {
    //		// 判断是否可以保存
    //		String taskId = rcvInstockLinesDTO.getTaskId();
    //		// 一个Task对应一个上架行
    //		Criteria criteria = new Criteria(RcvInstockLines.class);
    //		criteria.setRestriction(Restrictions.eq("taskId", taskId));
    //		long l = this.mapper.findCountByCriteria(criteria);
    //		if (l > 0)
    //			return false;
    //		return true;
    //	}

    private void buildField(RcvInstockLines rcvInstockLines, boolean editFlag, UserDTO userDTO, Date now) {
        this.setBaseSysField(rcvInstockLines, editFlag, userDTO, now);
        String executorUser = rcvInstockLines.getExecutorUser();
        if (StringUtils.isBlank(executorUser)) {
            rcvInstockLines.setExecutorUser(userDTO.getUsername()); // 执行者
        }
        vaildateModelRepeated(rcvInstockLines, editFlag, userDTO);

    }

    @Override
    @Transactional
    public Object batchEdit(List<RcvInstockLinesDTO> rcvInstockLinesDTOList) {
        // TODO
        UserDTO userDTO = userUtils.getUserDTO();
        boolean editFlag = Boolean.TRUE;
        Date now = new Date();
        int row = 0;
        for (RcvInstockLinesDTO rcvInstockLinesDTO : rcvInstockLinesDTOList) {
            this.vaildateModel(rcvInstockLinesDTO, editFlag, userDTO, row, validator, batchEditMsg);
            RcvInstockLines rcvInstockLines = new RcvInstockLines();
            BeanUtils.copyProperties(rcvInstockLinesDTO, rcvInstockLines);
            this.buildField(rcvInstockLines, editFlag, userDTO, now);
            this.mapper.updateWithValidate(rcvInstockLines, p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
        }
        return true;
    }

    private Restriction buildCondition(RcvInstockLinesDTO rcvInstockLinesDTO) {
        // 构建查询的条件
        if (ObjectUtils.isNull(rcvInstockLinesDTO))
            return null;

        //		String enterpriseId = rcvLinesDTO.getEnterpriseId();
        String rcvHeaderId = rcvInstockLinesDTO.getRcvHeaderId();
        String rcvLineId = rcvInstockLinesDTO.getRcvLineId();
        String itemId = rcvInstockLinesDTO.getItemId();
        String batchNum = rcvInstockLinesDTO.getBatchNum();
        String taskId = rcvInstockLinesDTO.getTaskId();
        String mtlOwnerId = rcvInstockLinesDTO.getMtlOwnerId();
        String warehouseId = rcvInstockLinesDTO.getWarehouseId();
        String stockStatus = rcvInstockLinesDTO.getStockStatus();

        Restriction r0 = Restrictions.eq("enterpriseId", userUtils.getEnterpriseId());
        Restriction r1 = StringUtils.isBlank(rcvHeaderId) ? null : Restrictions.eq("rcvHeaderId", rcvHeaderId);
        Restriction r2 = StringUtils.isBlank(rcvLineId) ? null : Restrictions.eq("rcvLineId", rcvLineId);
        Restriction r3 = StringUtils.isBlank(itemId) ? null : Restrictions.eq("itemId", itemId);
        Restriction r4 = StringUtils.isBlank(batchNum) ? null : Restrictions.like("batchNum", "%" + batchNum + "%"); // 批号模糊
        Restriction r5 = StringUtils.isBlank(taskId) ? null : Restrictions.eq("taskId", taskId);
        Restriction r6 = StringUtils.isBlank(mtlOwnerId) ? null : Restrictions.eq("mtlOwnerId", mtlOwnerId);
        Restriction r7 = StringUtils.isBlank(warehouseId) ? null : Restrictions.eq("warehouseId", warehouseId);
        Restriction r8 = StringUtils.isBlank(stockStatus) ? null : Restrictions.eq("stockStatus", stockStatus);

        return Restrictions.and(r0, r1, r2, r3, r4, r5, r6, r7, r8);
    }

    @Override
    public Object add(RcvInstockLinesDTO rcvInstockLinesDTO) {
        // TODO vaildate
        UserDTO userDTO = userUtils.getUserDTO();
        RcvInstockLines rcvInstockLines = new RcvInstockLines();
        BeanUtils.copyProperties(rcvInstockLinesDTO, rcvInstockLines);
        //		this.vaildateModel(rcvInstockLines,false,userDTO);
        this.buildField(rcvInstockLines, false, userDTO);
        this.mapper.save(rcvInstockLines);

        // 根据上架的逻辑来进行最终入库
        return true;
    }

    @Override
    public Object edit(String pkId, RcvInstockLinesDTO rcvInstockLinesDTO) {
        // TODO
        UserDTO userDTO = userUtils.getUserDTO();
        RcvInstockLines rcvInstockLines = new RcvInstockLines();
        BeanUtils.copyProperties(rcvInstockLinesDTO, rcvInstockLines);
        //		this.vaildateModel(rcvInstockLines,true,userDTO);
        this.buildField(rcvInstockLines, true, userDTO);
        this.mapper.updateWithValidate(rcvInstockLines, p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
        return true;
    }

    @Override
    @Transactional
    public Object delIds(List<String> pkIdList) {
        // TODO
        pkIdList.stream().filter(p -> canEdit(p)).forEach(p -> this.mapper.deleteById(p, RcvInstockLines.class));
        return true;
    }

    @Override
    public Object deletePkId(String pkId) {
        // TODO
        if (canEdit(pkId))
            throw new BizException("can not del");
        this.mapper.deleteById(pkId, RcvInstockLines.class);
        return "";
    }

    @Override
    public List<RcvInstockLinesDTO> findAll(RcvInstockLinesDTO rcvInstockLinesDTO) {
        // TODO
        Criteria criteria = Criteria.forClass(RcvInstockLines.class);
        RcvInstockLinesDTO condition = rcvInstockLinesDTO;
        Restriction r = buildCondition(condition);
        criteria.setRestriction(r);
        Order order = Order.newInstance().desc("gmtModified");
        criteria.setOrder(order);
        List<RcvInstockLines> list = this.mapper.findByCriteria(criteria);
        List<RcvInstockLinesDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(p -> {
            RcvInstockLinesDTO target = new RcvInstockLinesDTO();
            BeanUtils.copyProperties(p, target);
            return target;
        }).collect(Collectors.toList());
        return collect;
    }

    private RcvInstockLines findById(String id) {
        return this.mapper.findById(id, RcvInstockLines.class);
    }
    //
    //	private void vaildateModel(RcvInstockLines rcvInstockLines, Boolean editFlag, UserDTO userDTO) {
    //		if (!editFlag) {
    //			// TODO add
    //		} else {
    //			// TODO
    //		}
    //	}

    private void buildField(RcvInstockLines rcvInstockLines, Boolean editFlag, UserDTO userDTO) {
        buildField(rcvInstockLines, editFlag, userDTO, new Date());
    }

    private void vaildateModelRepeated(RcvInstockLines rcvInstockLines, Boolean editFlag, UserDTO userDTO) {
        if (!editFlag) {
            // TODO add
        } else {
            // TODO
        }
    }

    private boolean canEdit(String pkId) {
        boolean flag = true;
        RcvInstockLines rcvInstockLines = this.findById(pkId);
        AssertUtils.notNull(rcvInstockLines, "model empty!");
        // TODO
        if (true)
            flag = false;
        return flag;
    }

    /**
     * 上架任务拆分保存操作
     */
    @Override
    public Object splitTask(List<TaskInstockDetailDTO> taskInstockDetailDTOList) {
        return taskInstockDetailService.splitTask(taskInstockDetailDTOList);
    }

    @Override
    public Object confirmSplitTask(TaskInstockDetailDTO taskInstockDetailDTO) {
        return taskInstockDetailService.confirmSplitTask(taskInstockDetailDTO);
    }

    @Override
    public Page<RcvHAndPDTO> extractRcvH(RcvQueryVO rcvQueryVO, PageParam pageParam) {
        // 提取收货头表信息
        // 首先获取所有质检池中待质检的任务
        List<TaskInstockDetailDTO> findAll = taskInstockDetailService.findAll(null);
        if (ObjectUtils.isNull(findAll))
            return null;
        // 获取头表id列表
        List<String> rcvHeaderId = findAll.stream().distinct().collect(Collectors.groupingBy(TaskInstockDetailDTO::getRcvHeaderId)).entrySet().stream().map(p -> p.getKey()).collect(Collectors.toList());
        rcvQueryVO.setIncludeHids(rcvHeaderId);

        return rcvHeadersService.findListWithPro(rcvQueryVO, pageParam);
    }

    @Override
    public Page<RcvHDTO> extractRcvHAndPro(InsockTaskRcvQueryVO rcvQueryVO, PageParam pageParam) {
        return taskInstockDetailService.extractRcvHWithNativeSql(rcvQueryVO, pageParam);
    }

    @Override
    public Page<TaskInstockDetailDTO> extractTask(TaskQueryVO queryVO, PageParam pageParam) {
        // 提取任务池中任务
        queryVO.setStatus("1"); // 能执行的任务
        return taskInstockDetailService.extractTaskWithNativeSql(queryVO, pageParam);
    }

    @Override
    public RcvInstockLinesDTO findByPkId(String pkId) {
        // TODO
        RcvInstockLinesDTO dto = this.mapper.findByPkId(pkId);
        AssertUtils.notNull(dto, "查询的上架数据为空!");
        return dto;
    }

    @Override
    public Page<RcvInstockLinesDTO> findList(RcvInstockLinesQueryVO queryVO, PageParam pageParam) {

        this.startPage(pageParam);
        queryVO.setEnterpriseId(userUtils.getEnterpriseId());
        List<RcvInstockLinesDTO> list = this.mapper.findList(queryVO);
        return PageUtils.getPage(list);

    }

    @Transactional
    @Override
    public Object doException(List<RcvInstockLinesDTO> rcvInstockLinesDTOList) {
        // 上架异常处理

        AssertUtils.isNotEmpty(rcvInstockLinesDTOList, OperationConstant.COLLECTION_NULL_MSG);
        //		// 把对应的质检池任务暂时加锁
        //		List<String> taskIdList = rcvInstockLinesDTOList.stream().distinct().map(RcvInstockLinesDTO::getTaskId)
        //				.collect(Collectors.toList());
        //		updateTaskPoolStatus(taskIdList);
        return taskExceptionDetailService.saveTaskListByInStock(rcvInstockLinesDTOList);
    }

    private void updateTaskPoolStatus(List<String> taskIds) {
        if (ObjectUtils.isNull(taskIds))
            return;
        // 更新池任务状态 为已执行(不可用状态)
        Criteria criteria = new Criteria(TaskInstockDetail.class);
        int row = 0;
        for (String taskId : taskIds) {
            row++;
            // 数据库乐观锁
            TaskInstockDetail task = this.taskInstockDetailMapper.findById(taskId, TaskInstockDetail.class);
            AssertUtils.notNull(task, String.format("第[%d]行,上架任务id:[%s]查询的任务为空!", row, taskId));
            String status = task.getStatus();
            if (!"1".equals(status))
                throw new BizException(String.format("第[%d]行,上架任务id:[%s]查询的任务已经执行完毕,请刷新重试!", row, taskId));

            Integer dataVersion = task.getDataVersion();

            // 这里只需要dataVersion其实就可以了
            criteria.setRestriction(Restrictions.and(Restrictions.eq("taskInboundId", taskId), Restrictions.eq("dataVersion", dataVersion)));
            // 置为不可用状态(异常)
            long count = this.taskInstockDetailMapper.updateMapByCriteria(MapUtils.put("dataVersion", dataVersion + 1).put("status", "0").getMap(), criteria);
            if (count <= 0)
                throw new BizException(String.format("第[%d]行,上架任务id:[%s]查询的任务执行中,请刷新重试!", row, taskId));
        }

    }

    @Override
    public Object conditionExtractTask(InstockTaskQueryVO queryVO, PageParam pageParam) {
        // pad 方式查询上架任务 3种维度 1.区域 2.容器 3.上架标签 再精确商品条码
        UserDTO user = userUtils.getUserDTO();
        String enterpriseId = queryVO.getEnterpriseId();
        queryVO.setUserId(user.getId());
        if (ObjectUtils.isNull(enterpriseId))
            queryVO.setEnterpriseId(user.getEnterpriseId());
        String status = queryVO.getStatus();
        if (StringUtils.isBlank(status))
            queryVO.setStatus("1"); // 没有就默认可用上架任务
        String condition = queryVO.getCondition();
        AssertUtils.isNotBlank(condition, "请填写查询条件!");
        if (pageParam == null)
            return this.taskInstockDetailMapper.findListPad(queryVO);
        Integer pageSize = pageParam.getPageSize();
        Integer pageNum = pageParam.getPageNum();
        if (null == pageSize)
            pageSize = PageParam.DEFAULT_PAGE_SIZE;
        if (null == pageNum)
            pageNum = PageParam.DEFAULT_PAGE_NUM;
        PageHelper.startPage(pageNum, pageSize, true, false, false);

        List<TaskInstockDetailDTO> list = this.taskInstockDetailMapper.findListPad(queryVO);
        Assert.notEmpty(list, "该容器不存在待上架且未被索取的任务 或 不存在待上架任务，请注意！");
        Page<TaskInstockDetailDTO> page = PageUtils.getPage(list);
//        String[] areaCategoryCode = list.stream().map(TaskInstockDetailDTO::getWhAreaCategoryCode).distinct().toArray(String[]::new);
//        Assert.notEmpty(areaCategoryCode, "获取库别信息失败");
//
//
//        BaseWmsWarehouseArea dto = new BaseWmsWarehouseArea();
//        dto.setWarehouseAreaCategoryCode(areaCategoryCode[0]);
//        List<BaseWmsWarehouseArea> areas = RestMsgUtils.retrieveResult(baseWmsWarehouseCaller.findAll(dto));
//        Assert.notEmpty(areas, "获取货位信息失败");
//
//        List<BaseWmsWarehouseArea> unDeviceList = areas.stream().filter(t -> !PICK_MODE_DEVICE.equals(t.getPickMode())).collect(Collectors.toList());
//        if (CollUtil.isEmpty(unDeviceList)) {
//            throw new PrologException("立体库的不能通过人工上架，请注意！");
//        }
//        List<TaskInstockDetailDTO> result = list.stream().filter(t -> unDeviceList.stream().map(d -> d.getWarehouseAreaCategoryCode()).distinct().collect(Collectors.toList()).contains(t.getWhAreaCategoryCode())).collect(Collectors.toList());
        Set<String> itemIds = list.stream().map(TaskInstockDetailDTO::getItemId).collect(Collectors.toSet());
        String[] batchIds = list.stream().map(TaskInstockDetailDTO::getBatchId).distinct().toArray(String[]::new);
        List<BaseMtlItemMst> items = RestMsgUtils.retrieveResult(baseItemRemoteCaller.getListByIds(itemIds));
        List<BatchNumberListVO> batchs = RestMsgUtils.retrieveResult(baseInventoryRemoteCaller.getBatchNumberBasicInfo(batchIds));
        for (TaskInstockDetailDTO dtl : list) {

            if (CollUtil.isNotEmpty(items)) {
                items.stream().filter(i -> i.getItemId().equals(dtl.getItemId())).findFirst().ifPresent(i -> {
                    dtl.setItemName(i.getItemName());
                    dtl.setItemCode(i.getItemCode());
                });
            }
            if (CollUtil.isNotEmpty(batchs)) {
                batchs.stream().filter(b -> b.getBatchId().equals(dtl.getBatchId())).findFirst().ifPresent(b -> {
                    dtl.setBatchProductionDate(b.getBatchProductionDate());
                    dtl.setShowProductionDate(b.getBatchProductionDateShow());
                    dtl.setBatchExpiredDate(b.getBatchExpiredDate());
                    dtl.setShowExpiredDate(b.getBatchExpiredDateShow());
                });
            }
        }
        Page<TaskInstockDetailDTO> newPage = new Page<>();
        BeanUtil.copyProperties(page, newPage);
        newPage.setList(list);
        newPage.setTotalCount(list.size());
        return newPage;
    }

    @Override
    public Object queryUpTaskDetail(InstockTaskQueryVO queryVO) {
        // pad 方式查询上架任务 3种维度 1.区域 2.容器 3.上架标签 再精确商品条码
        String enterpriseId = queryVO.getEnterpriseId();
        if (ObjectUtils.isNull(enterpriseId))
            queryVO.setEnterpriseId(userUtils.getEnterpriseId());
        String status = queryVO.getStatus();
        if (StringUtils.isBlank(status))
            queryVO.setStatus("1"); // 没有就默认可用上架任务
        List<TaskInstockDetailDTO> findListPad = this.taskInstockDetailMapper.findListPad(queryVO);
        if (findListPad.isEmpty()) {
            throw new BizException("该容器不存在待上架任务，请注意！");
        }
        return PageUtils.getPage(findListPad);
    }

    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(isStart = true)
    @Override
    public TaskInstockDetailDTO addByPad(RcvInstockLinesDTO dto) {

        checkParams(dto);

        calculateQty(dto);

        TaskInstockDetailDTO result = null;
        if (dto.getRealQty().compareTo(dto.getPieceQty()) != 0) {
            result = splitUpdateAndGetResult(dto);
        }

        int row = 0;
        List<RcvInstockLines> list = new ArrayList<>();
        RcvInstockLines rcvInstockLines = excuteSavePre(row, dto, DateUtil.date(), list);

        updateRcvInstockLines(dto, rcvInstockLines);

        updateMaxLineNum(rcvInstockLines);

        this.mapper.save(rcvInstockLines);

        // 执行入库操作
        excuteInStock(list, true);

        excuteCallBackErp(list);

        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @TxTransaction(isStart = true)
    @Override
    public Object addByPadV2(RcvInstockLinesDTO dto) {
        checkParamsV2(dto);
        Object batchAdd = this.batchAdd(CollUtil.toList(dto));
        return batchAdd;
    }

    private TaskInstockDetailDTO splitUpdateAndGetResult(RcvInstockLinesDTO dto) {
        TaskInstockDetailDTO result;
        result = new TaskInstockDetailDTO();
        BeanUtil.copyProperties(dto, result);
        result.setPieceQty(dto.getPieceQty().subtract(dto.getRealQty()));
        calculateQty(result);
        TaskInstockDetail dtl = taskInstockDetailMapper.findById(dto.getTaskId(), TaskInstockDetail.class);
        Assert.notNull(dtl, "获取任务失败");
        TaskInstockDetail newDtl = new TaskInstockDetail();
        BeanUtil.copyProperties(dtl, newDtl);
        UserDTO user = userUtils.getUserDTO();
        newDtl.setQty(result.getPieceQty().divide(newDtl.getConversionRate(), 2, RoundingMode.DOWN));
        newDtl.setPieceQty(result.getPieceQty());
        newDtl.setGmtCreate(DateUtil.date());
        newDtl.setCreator(user.getId());
        newDtl.setCreatorName(user.getNickname());
        newDtl.setEisPushStatus("0");
        taskInstockDetailMapper.save(newDtl);
        result.setTaskInboundId(newDtl.getTaskInboundId());

        dtl.setQty(dto.getRealQty().divide(dtl.getConversionRate(), 2, RoundingMode.DOWN));
        dtl.setPieceQty(dto.getRealQty());
        dtl.setModifierName(user.getNickname());
        dtl.setGmtModified(DateUtil.date());
        dto.setPieceQty(dtl.getPieceQty());
        calculateQty(dto);
        taskInstockDetailMapper.update(dtl);
        return result;
    }

    private void updateMaxLineNum(RcvInstockLines rcvInstockLines) {
        Long maxLineNum = this.mapper.getMaxLineNum(rcvInstockLines.getRcvHeaderId());
        if (maxLineNum == null) {
            maxLineNum = 1L;
        }
        rcvInstockLines.setLineNum(BigDecimal.valueOf(maxLineNum + 1));
    }


    private void updateRcvInstockLines(RcvInstockLinesDTO dto, RcvInstockLines rcvInstockLines) {
        String warehouseId = dto.getWarehouseId();
        String mtlOwnerId = dto.getMtlOwnerId();
        // 获取是否校验货位限定的业务参数
        String businessControlValue = taskHelper.getBusinessControlValue(warehouseId, mtlOwnerId, "0", BizConstant.ENABLE_PDA_MATCH_LOCATOR_LIMIT);

        String storeTemperature = null;
        if (enablePadStoreTemperature || businessControlValue.equals("1")) {
            // 求出商品的储存条件
            RcvLinesProfiles linePro = rcvLinesProfilesMapper.findById(dto.getRcvLineId(), RcvLinesProfiles.class);
            if (null != linePro) {
                storeTemperature = linePro.getStoreTemperature();
            }
        }
        if (StringUtils.isBlank(storeTemperature)) {
            storeTemperature = "常温";
        }

        // 没有实际货位id的处理
        String realWhLocatorId = rcvInstockLines.getRealWhLocatorId();
        if (StringUtils.isBlank(realWhLocatorId)) {
            // 实际货位id为空,远程调用仓库服务获取货位
            Map<String, Object> map = new HashMap<>();
            ArrayList<String> newArrayList = Lists.newArrayList();
            String upperCase = dto.getRealWhLocatorCode().toUpperCase();
            newArrayList.add(upperCase);
            map.put("warehouseId", rcvInstockLines.getWarehouseId());
            map.put("warehouseLocatorCodes", newArrayList);
            RestMessage<Map<String, BaseWmsWarehouseLocator>> locationsByCodes = null;
            try {
                // 是否需要判断在货位限定中 TODO
                locationsByCodes = baseWmsWarehouseCaller.getLocationsByCodes(map);
            } catch (Exception e) {
                logger.error("远程调用仓库服务错误,异常信息->{}", e);
            }
            if (ObjectUtils.isNotNull(locationsByCodes) && ObjectUtils.isNotNull(locationsByCodes.getData())) {
                Map<String, BaseWmsWarehouseLocator> data = locationsByCodes.getData();
                BaseWmsWarehouseLocator baseWmsWarehouseLocator = data.get(dto.getRealWhLocatorCode());
                if (ObjectUtils.isNotNull(baseWmsWarehouseLocator)) {

                    if (enablePadMatchLocatorLimit || businessControlValue.equals("1")) {
                        // 是否进行货位限定匹配
                        matchLimitLocator(baseWmsWarehouseLocator, dto);
                    }

                    if (enablePadStoreTemperature || businessControlValue.equals("1")) {
                        String attribute2 = baseWmsWarehouseLocator.getAttribute2();
                        if (StringUtils.isBlank(attribute2)) {
                            attribute2 = "常温";
                        }
                        String errMsg = "商品[%s]储存条件[%s]无法匹配到所选货位[%s]的储存条件[%s],请重新选择货位!";
                        String itemName = dto.getItemName();
                        String format = String.format(errMsg, itemName, storeTemperature, dto.getRealWhLocatorCode(), attribute2);
                        if (storeTemperature.equals("常温") && !attribute2.equals("阴凉") && !attribute2.equals("常温")) {
                            // 常温存储条件不匹配
                            throw new BizException(format);
                        }
                        if (storeTemperature.equals("阴凉") && !attribute2.equals("阴凉")) {
                            // 阴凉存储条件不匹配
                            throw new BizException(format);
                        }
                        if (storeTemperature.equals("冷藏") && !attribute2.equals("冷藏")) {
                            // 冷藏存储条件不匹配
                            throw new BizException(format);
                        }
                        if (storeTemperature.equals("冷冻") && !attribute2.equals("冷冻")) {
                            // 冷冻存储条件不匹配
                            throw new BizException(format);
                        }
                    }

                    // 是否进行货位的类型匹配判断
                    if (enablePadMatchLocatorType) {
                        matchLocatorType(baseWmsWarehouseLocator, dto);
                    }

                    String warehouseLocatorId = baseWmsWarehouseLocator.getWarehouseLocatorId();
                    String warehouseLocatorName = baseWmsWarehouseLocator.getWarehouseLocatorName();
                    rcvInstockLines.setWhAreaCategoryCode(baseWmsWarehouseLocator.getWarehouseAreaCategoryCode());
                    rcvInstockLines.setWhAreaCategoryId(baseWmsWarehouseLocator.getWarehouseAreaCategory());
                    rcvInstockLines.setWhAreaCode(baseWmsWarehouseLocator.getWarehouseAreaCode());
                    rcvInstockLines.setRealWhLocatorId(warehouseLocatorId);
                    rcvInstockLines.setRealWhLocatorName(warehouseLocatorName);
                }
            }
            // 没能找到货位数据抛错
            if (StringUtils.isBlank(rcvInstockLines.getRealWhLocatorId())) {
                throw new BizException(String.format("当前货位编码[%s]没能检索到对应的货位信息,请检查重试!", upperCase));
            }
        }
    }

    private void calculateQty(RcvInstockLinesDTO dto) {
        BigDecimal pieceQty = dto.getPieceQty() == null ? BigDecimal.ZERO : dto.getPieceQty();
        BigDecimal conversionRate = dto.getConversionRate() == null ? BigDecimal.ONE : dto.getConversionRate();
        dto.setConversionRate(conversionRate);
        dto.setPieceQty(pieceQty);

        BigDecimal caseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
        BigDecimal multiply = caseQty.multiply(conversionRate);
        BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
        //BigDecimal qty = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN); // 包装总量
        // 保证数据正确性再次进行计算
        dto.setOddCaseQty(caseQty);
        dto.setOddPieceQty(oddPieceQty);
    }

    private void calculateQty(TaskInstockDetailDTO dto) {
        BigDecimal pieceQty = dto.getPieceQty() == null ? BigDecimal.ZERO : dto.getPieceQty();
        BigDecimal conversionRate = dto.getConversionRate() == null ? BigDecimal.ONE : dto.getConversionRate();
        dto.setConversionRate(conversionRate);
        dto.setPieceQty(pieceQty);

        BigDecimal caseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
        BigDecimal multiply = caseQty.multiply(conversionRate);
        BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
        //BigDecimal qty = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN); // 包装总量
        // 保证数据正确性再次进行计算
        dto.setCaseQty(caseQty);
        dto.setOddPieceQty(oddPieceQty);
    }


    private void checkParams(RcvInstockLinesDTO dto) {

        Assert.notBlank(dto.getTaskId(), "任务ID不能为空");

        if (dto.getRealQty().compareTo(BigDecimal.ZERO) <= 0) {
            throw new PrologException("上架数量不能小或等于0");
        }

        String rcvHeaderId = dto.getRcvHeaderId();
        Assert.notBlank(rcvHeaderId, "收货单号不能为空");

        String realWhLocatorCode = dto.getRealWhLocatorCode();
        Assert.notBlank(realWhLocatorCode, "实际上架货位不能为空或为回车校验");

//        WarehouseLocatorBasicInfo realLocator = RestMsgUtils.retrieveResult(baseWmsWarehouseCaller.getLocationInfoByCode(dto.getWarehouseId(), dto.getRealWhLocatorCode()));
//        Assert.notNull(realLocator, "货位不可用，不可上架");
//        if (realLocator.getWarehouseAreaCategory().equals("AGVK")) {
//            throw new PrologException("实际上架货位必须为收货库别且非AGV库的货位");
//        }
//        if(!StringUtils.isEmpty(dto.getWhAreaCategoryCode())){
//            String[] split = dto.getWhAreaCategoryCode().split(",");
//            List<String> strings = ArrayUtils.toList(split);
//            if (!strings.contains(realLocator.getWarehouseAreaCategory())) {
//                throw new PrologException("货位必须为商品货位限定推荐的货位范围内");
//            }
//        }
        Map<String, Object> map = new HashMap<>();
        List<String> locatorCodes = new ArrayList<>();
        locatorCodes.add(dto.getRealWhLocatorCode());
        map.put("warehouseId", dto.getWarehouseId());
        map.put("warehouseLocatorCodes", locatorCodes);
        RestMessage<Map<String, BaseWmsWarehouseLocator>> locationsByCodes = baseWmsWarehouseCaller.getLocationsByCodes(map);
        if(!locationsByCodes.isSuccess()){
            throw new BizException("远程调用查询货位信息失败");
        }
        BaseWmsWarehouseLocator locatorInfos = locationsByCodes.getData().get(dto.getRealWhLocatorCode());
        dto.setRealWhLocatorId(locatorInfos.getWarehouseLocatorId());
        List<String> locatorIds = new ArrayList<>();
        locatorIds.add(locatorInfos.getWarehouseLocatorId());
        RestMessage<Map<String, Boolean>> locatorAreaPickMode = baseWmsWarehouseCaller.getLocatorAreaPickMode(locatorIds);
        if(!locatorAreaPickMode.isSuccess()){
            throw new BizException("远程调用查询货位库区拣货方式失败");
        }
        Map<String, Boolean> data = locatorAreaPickMode.getData();
        Boolean isBool = data.get(locatorInfos.getWarehouseLocatorId());
        if(isBool){
            throw new BizException(String.format("货位[%s]库区拣货方式为设备，不能手动上架",dto.getRealWhLocatorCode()));
        }
        if(locatorInfos!=null){
            if(!StringUtils.isEmpty(locatorInfos.getMixType())&&locatorInfos.getMixType().equals("1")){
                WmsInvStockQtyQueryVO queryVO = new WmsInvStockQtyQueryVO();
                queryVO.setEnterpriseId(dto.getEnterpriseId());
                queryVO.setLocatorId(dto.getRealWhLocatorId());
                queryVO.setWarehouseId(dto.getWarehouseId());
                queryVO.setCargoOwnerId(dto.getMtlOwnerId());
                RestMessage<List<WmsInvStockQtyVO>> availableQuantity = baseInventoryRemoteCaller.getAvailableQuantity(Collections.singletonList(queryVO));
                if(!availableQuantity.isSuccess()){
                    throw new BizException("查询货位批次库存信息失败");
                }
                List<WmsInvStockQtyVO> stockLots = availableQuantity.getData();
                List<WmsInvStockQtyVO> collect = stockLots.stream().filter(x -> !x.getBatchId().equals(dto.getBatchId())).collect(Collectors.toList());
                if(collect.size()>0){
                    boolean flag = collect.stream().anyMatch(x -> x.getAvailableQuantity().compareTo(BigDecimal.ZERO) > 0);
                    if(flag){
                        throw new BizException(String.format("货位%s为单品单批，已有其他商品批次库存",dto.getRealWhLocatorCode()));
                    }
                }
            }
        }
        RcvLines rcvLines = this.rcvLineMapper.findById(dto.getRcvLineId(), RcvLines.class);
        if (rcvLines != null && dto.getRealQty().compareTo(rcvLines.getPieceQty()) > 0) {
            throw new BizException(String.format("第[%d]行,上架数量超出收货数量!请检查重试!", 0));
        }
    }

    private void checkParamsV2(RcvInstockLinesDTO dto) {

        Assert.notBlank(dto.getTaskId(), "任务ID不能为空");

        if (dto.getRealQty().compareTo(BigDecimal.ZERO) <= 0) {
            throw new PrologException("上架数量不能小或等于0");
        }

        String rcvHeaderId = dto.getRcvHeaderId();
        Assert.notBlank(rcvHeaderId, "收货单号不能为空");

        String realWhLocatorCode = dto.getRealWhLocatorCode();
        Assert.notBlank(realWhLocatorCode, "实际上架货位不能为空或为回车校验");

//        WarehouseLocatorBasicInfo realLocator = RestMsgUtils.retrieveResult(baseWmsWarehouseCaller.getLocationInfoByCode(dto.getWarehouseId(), dto.getRealWhLocatorCode()));
//        Assert.notNull(realLocator, "货位不可用，不可上架");
//        if (realLocator.getWarehouseAreaCategory().equals("AGVK")) {
//            throw new PrologException("实际上架货位必须为收货库别且非AGV库的货位");
//        }
//        if(!StringUtils.isEmpty(dto.getWhAreaCategoryCode())){
//            String[] split = dto.getWhAreaCategoryCode().split(",");
//            List<String> strings = ArrayUtils.toList(split);
//            if (!strings.contains(realLocator.getWarehouseAreaCategory())) {
//                throw new PrologException("货位必须为商品货位限定推荐的货位范围内");
//            }
//        }
        Map<String, Object> map = new HashMap<>();
        List<String> locatorCodes = new ArrayList<>();
        locatorCodes.add(dto.getRealWhLocatorCode());
        map.put("warehouseId", dto.getWarehouseId());
        map.put("warehouseLocatorCodes", locatorCodes);
        RestMessage<Map<String, BaseWmsWarehouseLocator>> locationsByCodes = baseWmsWarehouseCaller.getLocationsByCodes(map);
        if(!locationsByCodes.isSuccess()){
            throw new BizException("远程调用查询货位信息失败");
        }
        BaseWmsWarehouseLocator locatorInfos = locationsByCodes.getData().get(dto.getRealWhLocatorCode());
        if(locatorInfos == null){
            throw new BizException("根据实际货位编码："+dto.getRealWhLocatorCode()+"查询货位失败!");
        }
        dto.setRealWhLocatorId(locatorInfos.getWarehouseLocatorId());
        dto.setRealWhLocatorName(locatorInfos.getWarehouseLocatorName());
    }

    private void excuteCallBackErp(List<RcvInstockLines> callList) {
        // 把需要入库回传erp的数据存储到中间表中
        excuteSaveCallBackErpData(callList, true);
    }

    public void excuteSaveCallBackErpData(List<RcvInstockLines> callList, boolean isExtCallBack) {
        if (ObjectUtils.isNull(callList)) {
            logger.info("上架保存回传数据为空!");
            return;
        }
        logger.info("上架保存回传数据开始-------------------------------");
        // 校验是否收货全部完成
        String rcvHeaderId = callList.get(0).getRcvHeaderId().trim();
        if (vaildateRcvComplete(rcvHeaderId)) {
            // 执行数据保存 WMS_INF_CGRK_BILL
//            excuteSaveCallBackData(callList, "2");
            excuteSaveCallBackDataV2(rcvHeaderId);
            //收货拒收记录回传OMS -- //青牛版本没有oms系统,注释掉 不生成receiving_record_back_h表记录
//            excuteRcvAndRejectBackOms(rcvHeaderId,null);
            //验收记录回传OMS --//青牛版本没有oms系统,注释掉
//            excuteRqcBackOms(rcvHeaderId,null);
            //上架完成回传OMS --//青牛版本没有oms系统,改成回传erp // 测试环境暂时没有对接erp,暂时注释
//            excuteCallBackOms(rcvHeaderId);
        } else {
            logger.info("整个收货单上架保存回传数据失败,数量不达标----------------------");
        }
        //		}
    }

    private void excuteRqcBackOms(String rcvHeaderId,UserDTO userDTO) {
        List<RqcHeaders> rqcHeadersList = rqcHeadersMapper.findByMap(MapUtils.put("rcvHeaderId", rcvHeaderId).getMap(), RqcHeaders.class);
        for (RqcHeaders rqcHeadersDTO : rqcHeadersList) {
            //查询验收记录保存记录表
            List<ReceivingRecordBackVO> backList = new ArrayList<>();
            List<ReceivingRecordBackH> rqcInsertDataListH = receivingRecordBackHMapper.getRqcInsertData(rqcHeadersDTO.getRqcHeaderId());
            if (rqcInsertDataListH.size() > 0) {
                List<ReceivingRecordBackD> rqcInsertDataListD = receivingRecordBackDMapper.getRqcInsertData(rqcHeadersDTO.getRqcHeaderId());
                //验收明细
                List<ReceivingRecordBackDVO> rqcBackDVOList = new ArrayList<>();
                if (rqcInsertDataListD.size() > 0) {
                    for (ReceivingRecordBackD receivingRecordBackD : rqcInsertDataListD) {
                        if (!receivingRecordBackD.getStockstatus().equals("3")) {
                            ReceivingRecordBackDVO backDVO = convertBackDVORqc(receivingRecordBackD);
                            rqcBackDVOList.add(backDVO);
                        }
                    }
                } else {
                    continue;
                }
                for (ReceivingRecordBackH receivingRecordBackH : rqcInsertDataListH) {
                    ReceivingRecordBackVO backVO = new ReceivingRecordBackVO();
                    ReceivingRecordBackHVO backHVO = new ReceivingRecordBackHVO();
                    BeanUtils.copyProperties(receivingRecordBackH, backHVO);
                    backHVO.setRefBillno(receivingRecordBackH.getRefbillno());
                    backHVO.setGlBillno(receivingRecordBackH.getGlBillno());
                    backHVO.setPurorgId(receivingRecordBackH.getBuyerId());
                    backHVO.setPurorgName(receivingRecordBackH.getBuyerName());
                    backHVO.setShipmentDate(DateUtils.format(receivingRecordBackH.getRcvdate(), "yyyy-MM-dd HH:mm:ss"));
                    //backHVO.setRcvoperator(userDTO.getNickname());
                    backHVO.setPenterpriseid(receivingRecordBackH.getPEnterpriseid());
                    backHVO.setType("20");
                    backVO.setContent(backHVO);
                    backVO.setDetailList(rqcBackDVOList);
                    backList.add(backVO);
                }
                if (rqcInsertDataListH.size() > 0) {
                    receivingRecordBackHMapper.saveBatch(rqcInsertDataListH);
                }
                if (rqcInsertDataListD.size() > 0) {
                    receivingRecordBackDMapper.saveBatch(rqcInsertDataListD);
                }
                if (backList.size() == 0) {
                    return;
                }
                System.out.println(JSON.toJSONString(backList));
                //TODO 调用接口平台推送验收记录数据到OMS
                //青牛版本没有oms系统
//                try {
//                    if (rqcBackDVOList.size() > 0) {
//                        AskIntegrationVo vo = new AskIntegrationVo();
//                        vo.setIntegrationCode("receivingRecordBack");
//                        vo.setParam(backList);
//                        RestMessage<?> msg = baseInventoryRemoteCaller.askIntegration(vo);
//                        if (msg.isSuccess()) {
//                            String[] billids = rqcInsertDataListH.stream().map(x -> x.getBillid()).toArray(String[]::new);
//                            Criteria crt = Criteria.forClass(ReceivingRecordBackH.class);
//                            crt.restrictionBuilder().in("billid", billids);
//                            crt.buildRestriction();
//                            receivingRecordBackHMapper.updateMapByCriteria(MapUtils.put("uploadStatus", "1").getMap(), crt);
//                        }
//                    }
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
            }
        }
    }

    private ReceivingRecordBackDVO convertBackDVORqc(ReceivingRecordBackD receivingRecordBackD){
        ReceivingRecordBackDVO backDVO = new ReceivingRecordBackDVO();
        BeanUtils.copyProperties(receivingRecordBackD,backDVO);
        backDVO.setSeqNo(receivingRecordBackD.getSeqno());
        backDVO.setRefSeqNo(receivingRecordBackD.getRefSeqno());
        backDVO.setBrandName(receivingRecordBackD.getItemname());
        backDVO.setCapacity(receivingRecordBackD.getCategoryId());
        backDVO.setFfactory(receivingRecordBackD.getManufacturer());
        backDVO.setPcs(receivingRecordBackD.getAffirmedPcs());
        backDVO.setOdd(receivingRecordBackD.getAffirmedOdd());
        backDVO.setQty(receivingRecordBackD.getAffirmedQty());
        backDVO.setAddress(receivingRecordBackD.getShipmentPlace());
        backDVO.setShipmentResult(receivingRecordBackD.getStockstatus());
        backDVO.setStartDate(receivingRecordBackD.getShipmentDate()!=null?DateUtils.format(receivingRecordBackD.getShipmentDate(),"yyyy-MM-dd HH:mm:ss"):"");
        backDVO.setTemperatureType(receivingRecordBackD.getTemperaturecType());
        backDVO.setAttainDate(receivingRecordBackD.getShipArriveTime()!=null?DateUtils.format(receivingRecordBackD.getShipArriveTime(),"yyyy-MM-dd HH:mm:ss"):"");
        backDVO.setAttainTemperature(receivingRecordBackD.getShipArriveTemPerature());
        backDVO.setTemperatureStatus(receivingRecordBackD.getTempcinfo());
        backDVO.setRegistrationNo(receivingRecordBackD.getItemHealthRegisterNbr());
        backDVO.setImportpaperno(receivingRecordBackD.getItemHealthRegisterNbrEn());
        backDVO.setFsymbol(receivingRecordBackD.getItemHealthApprovalNbr());
        backDVO.setOrign(receivingRecordBackD.getCountryOriginId());
        backDVO.setSterilizationLotNo(receivingRecordBackD.getSterilizesno());
        backDVO.setSterilizationDate(receivingRecordBackD.getSterilizeexpdate());
        backDVO.setCarrierType(receivingRecordBackD.getCarrierUnit());
        backDVO.setShipType(receivingRecordBackD.getShippingType());
        backDVO.setShipCompany(receivingRecordBackD.getCarriername());
        backDVO.setItemid(receivingRecordBackD.getItemid());
        backDVO.setPdateFrom(receivingRecordBackD.getPdateFrom()!=null?DateUtils.format(receivingRecordBackD.getPdateFrom(),"yyyy-MM-dd HH:mm:ss"):"");
        backDVO.setValidUntil(receivingRecordBackD.getValidUntil()!=null?DateUtils.format(receivingRecordBackD.getValidUntil(),"yyyy-MM-dd HH:mm:ss"):"");
        if(receivingRecordBackD.getStockstatus().equals("1")){
            backDVO.setResult("合格");
        }
        if(receivingRecordBackD.getStockstatus().equals("2")){
            backDVO.setResult("不合格");
        }
        if(receivingRecordBackD.getStockstatus().equals("3")){
            backDVO.setResult("待处理");
        }
        return backDVO;
    }

    private void excuteRcvAndRejectBackOms(String rcvHeaderId,UserDTO userDTO){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        //保存记录到收货-拒收-验收记录表
        List<ReceivingRecordBackVO> backList = new ArrayList<>();
        List<ReceivingRecordBackH> backHList = receivingRecordBackHMapper.getRcvInsertData(rcvHeaderId);
        if(backHList.size()>0){
            List<ReceivingRecordBackD> backDList = receivingRecordBackDMapper.getRcvInsertData(rcvHeaderId);
            //收货明细
            List<ReceivingRecordBackDVO> rcvBackDVOList = new ArrayList<>();
            //拒收明细
            List<ReceivingRecordBackDVO> rejectBackDVOList = new ArrayList<>();
            if(backDList.size()>0){
                for (ReceivingRecordBackD receivingRecordBackD : backDList) {
                    ReceivingRecordBackDVO backDVO = convertBackDVO(receivingRecordBackD);
                    if(receivingRecordBackD.getStockstatus().equals("2")){
                        rejectBackDVOList.add(backDVO);
                    }else{
                        rcvBackDVOList.add(backDVO);
                    }
                }
            }
            if(rcvBackDVOList.size()>0){
                for (ReceivingRecordBackH receivingRecordBackH : backHList) {
                    ReceivingRecordBackVO backVO = new ReceivingRecordBackVO();
                    ReceivingRecordBackHVO backHVO = new ReceivingRecordBackHVO();
                    BeanUtils.copyProperties(receivingRecordBackH,backHVO);
                    backHVO.setRefBillno(receivingRecordBackH.getRefbillno());
                    backHVO.setPurorgId(receivingRecordBackH.getBuyerId());
                    backHVO.setPurorgName(receivingRecordBackH.getBuyerName());
                    backHVO.setShipmentDate(DateUtils.format(receivingRecordBackH.getRcvdate(),"yyyy-MM-dd HH:mm:ss"));
                    //backHVO.setRcvoperator(userDTO.getNickname());
                    backHVO.setPenterpriseid(receivingRecordBackH.getPEnterpriseid());
                    backHVO.setType("10");
                    backVO.setContent(backHVO);
                    backVO.setDetailList(rcvBackDVOList);
                    backList.add(backVO);
                }
            }
            if(rejectBackDVOList.size()>0){
                for (ReceivingRecordBackH receivingRecordBackH : backHList) {
                    ReceivingRecordBackVO backVO = new ReceivingRecordBackVO();
                    ReceivingRecordBackHVO backHVO = new ReceivingRecordBackHVO();
                    BeanUtils.copyProperties(receivingRecordBackH,backHVO);
                    backHVO.setRefBillno(receivingRecordBackH.getRefbillno());
                    backHVO.setPurorgId(receivingRecordBackH.getBuyerId());
                    backHVO.setPurorgName(receivingRecordBackH.getBuyerName());
                    backHVO.setShipmentDate(DateUtils.format(receivingRecordBackH.getRcvdate(),"yyyy-MM-dd HH:mm:ss"));
                    //backHVO.setRcvoperator(userDTO.getNickname());
                    backHVO.setPenterpriseid(receivingRecordBackH.getPEnterpriseid());
                    backHVO.setType("30");
                    backVO.setContent(backHVO);
                    backVO.setDetailList(rejectBackDVOList);
                    backList.add(backVO);
                }
            }
            receivingRecordBackHMapper.saveBatch(backHList);
            receivingRecordBackDMapper.saveBatch(backDList);
            //TODO 调用接口平台回传OMS
            //青牛版本没有oms系统
//            try {
//                System.out.println(JSON.toJSONString(backList));
//                AskIntegrationVo vo = new AskIntegrationVo();
//                vo.setIntegrationCode("receivingRecordBack");
//                vo.setParam(backList);
//                RestMessage<?> msg = baseInventoryRemoteCaller.askIntegration(vo);
//                if(msg.isSuccess()){
//                    String[] billids = backHList.stream().map(x -> x.getBillid()).toArray(String[]::new);
//                    Criteria crt = Criteria.forClass(ReceivingRecordBackH.class);
//                    crt.restrictionBuilder().in("billid",billids);
//                    crt.buildRestriction();
//                    receivingRecordBackHMapper.updateMapByCriteria(MapUtils.put("uploadStatus","1").getMap(),crt);
//                }
//            }catch (Exception e){
//                e.printStackTrace();
//            }
        }
    }

    public void excuteInboundCallBackErp(String rcvHeaderId) {
        final String INBOUND_CALLBACK_KEY = "InboundCallBackErpSuccessList:";

        String successList = "";
        try {
            successList = stringRedisTemplate.opsForValue().get(INBOUND_CALLBACK_KEY);
        } catch (Exception e) {
            logger.error("从缓存获取成功推送列表失败", e);
        }
        if (StrUtil.isNotEmpty(successList) && successList.indexOf(rcvHeaderId) > 0) {
            logger.info("跳过已成功推送的收货单：{}", rcvHeaderId);
            return;
        }
        List<IncomingRecordBackDVO> subList = incomingRecordBackDMapper.getInsertData(rcvHeaderId);
        if (CollUtil.isEmpty(subList)) {
            logger.info("收货单：{}，查不到可回传数据{}", rcvHeaderId);
            return;
        }

        //根据商品和批次分组回传
        Map<String, List<IncomingRecordBackDVO>> maps = subList.stream().filter(x -> ToolKits.isNotEmpty(x.getItemid()) && ToolKits.isNotEmpty(x.getLotNo()) && ToolKits.isNotEmpty(x.getConsignorcode()))
                .collect(Collectors.groupingBy(x -> StrUtil.join("_", x.getItemid(), x.getLotNo(), x.getConsignorcode())));
        if (CollUtil.isEmpty(maps)) {
            return;
        }
        List<IncomingRecordBackErpVO> list = new ArrayList<>();
        for (Entry<String, List<IncomingRecordBackDVO>> entry : maps.entrySet()) {
            List<IncomingRecordBackDVO> value = entry.getValue();
            if (CollUtil.isEmpty(value)) {
                continue;
            }
            IncomingRecordBackDVO vo = value.get(0);
            Double sumQty = value.stream().mapToDouble(e -> e.getQty().doubleValue()).sum();
            IncomingRecordBackErpVO sub = new IncomingRecordBackErpVO();
            sub.setGoodSn(vo.getItemcode());
            sub.setGoodName(vo.getItemname());
            sub.setFLot(vo.getLotNo());
            sub.setStock(sumQty.toString());
            sub.setExpiryDate(vo.getValidUntil());
            sub.setProduceDate(vo.getPdateFrom());
            sub.setIndustryline(vo.getIndustryline());
            sub.setWmsBillId(vo.getRefBillId());
            sub.setK3POnum(vo.getRefBillNo());
            sub.setBillType(vo.getBillType());
            sub.setStockName(vo.getWhAreaCategoryName());
            sub.setStockNum(vo.getWhAreaCategoryCode());
            sub.setItemIsGift(vo.getItemIsGift());
            sub.setStockInTime(com.prolog.common.util.DateUtils.format(vo.getStockInTime(), com.prolog.common.util.DateUtils.PATTERN_NORMAL));
            list.add(sub);
        }

        Map map = new HashMap();
        map.put("stockInBills", list);
        AskIntegrationVo vo = new AskIntegrationVo();
        vo.setIntegrationCode("incomingRecordBack");
        vo.setParam(map);
        logger.info("excuteInboundCallBackErp:{}", JSONObject.toJSONString(vo));
        try {
            RestMessage<?> msg = baseInventoryRemoteCaller.askIntegration(vo);
            logger.info("excuteInboundCallBackErp.msg:{}", JSONObject.toJSONString(msg));
            if ("1".equals(msg.getCode())) {
                String finalSuccessList = successList;
                persistence(() -> {
                    MapperCustom.builder(incomingRecordHMapper, IncomingRecordH.class)
                            .addParameter(IncomingRecordH::getAttrStr1, "Y")
                            .andEq(IncomingRecordH::getBillid, rcvHeaderId)
                            .updateFieldsByCriteria();
                    stringRedisTemplate.opsForValue().set(INBOUND_CALLBACK_KEY, finalSuccessList + "_" + rcvHeaderId, 10, TimeUnit.MINUTES);
                    logger.info("收货单:{}，入库回传ERP成功", rcvHeaderId);
                });
                return;
            }
            handleFailErp(rcvHeaderId);
        } catch (Exception e) {
            logger.error("入库回传ERP失败", e);

            handleFailErp(rcvHeaderId);
            return;
        }
    }

    public void handleFailErp(String rcvHeaderId) {
        logger.info("收货单:{}，入库回传ERP失败", rcvHeaderId);
        FieldSelector fs = FieldSelector.newInstance().include(new String[]{"billid" ,"attrNum1", "lastmodifydate"});
        Criteria criteria = Criteria.forClass(IncomingRecordH.class);
        Restriction r1 = Restrictions.eq("billid", rcvHeaderId);
        criteria.setRestriction(r1);
        List<IncomingRecordH> records = incomingRecordHMapper.findFieldsByCriteria(fs, criteria);

        if (CollUtil.isEmpty(records)) {
            return;
        }

        DateTime now = DateUtil.date();
        persistence(() -> {
            records.forEach(r -> {
                r.setLastmodifydate(now);
                r.setAttrNum1(r.getAttrNum1() == null ? BigDecimal.ONE : r.getAttrNum1().add(BigDecimal.ONE));
                incomingRecordHMapper.updateFieldsByCriteria(r, fs, criteria);
            });
        });
    }


    private ReceivingRecordBackDVO convertBackDVO(ReceivingRecordBackD receivingRecordBackD){
        ReceivingRecordBackDVO backDVO = new ReceivingRecordBackDVO();
        BeanUtils.copyProperties(receivingRecordBackD,backDVO);
        backDVO.setSeqNo(receivingRecordBackD.getSeqno());
        backDVO.setRefSeqNo(receivingRecordBackD.getRefSeqno());
        backDVO.setBrandName(receivingRecordBackD.getItemname());
        backDVO.setCapacity(receivingRecordBackD.getCategoryId());
        backDVO.setFfactory(receivingRecordBackD.getManufacturer());
        backDVO.setPcs(receivingRecordBackD.getAffirmedPcs());
        backDVO.setOdd(receivingRecordBackD.getAffirmedOdd());
        backDVO.setQty(receivingRecordBackD.getAffirmedQty());
        backDVO.setAddress(receivingRecordBackD.getShipmentPlace());
        backDVO.setShipmentResult(receivingRecordBackD.getStockstatus());
        backDVO.setStartDate(receivingRecordBackD.getShipmentDate()!=null?DateUtils.format(receivingRecordBackD.getShipmentDate(),"yyyy-MM-dd HH:mm:ss"):"");
        backDVO.setTemperatureType(receivingRecordBackD.getTemperaturecType());
        backDVO.setAttainDate(receivingRecordBackD.getShipArriveTime()!=null?DateUtils.format(receivingRecordBackD.getShipArriveTime(),"yyyy-MM-dd HH:mm:ss"):"");
        backDVO.setAttainTemperature(receivingRecordBackD.getShipArriveTemPerature());
        backDVO.setTemperatureStatus(receivingRecordBackD.getTempcinfo());
        backDVO.setRegistrationNo(receivingRecordBackD.getItemHealthRegisterNbr());
        backDVO.setImportpaperno(receivingRecordBackD.getItemHealthRegisterNbrEn());
        backDVO.setFsymbol(receivingRecordBackD.getItemHealthApprovalNbr());
        backDVO.setOrign(receivingRecordBackD.getCountryOriginId());
        backDVO.setSterilizationLotNo(receivingRecordBackD.getSterilizesno());
        backDVO.setSterilizationDate(receivingRecordBackD.getSterilizeexpdate());
        backDVO.setCarrierType(receivingRecordBackD.getCarrierUnit());
        backDVO.setShipType(receivingRecordBackD.getShippingType());
        backDVO.setShipCompany(receivingRecordBackD.getCarriername());
        backDVO.setItemid(receivingRecordBackD.getItemid());
        backDVO.setPdateFrom(receivingRecordBackD.getPdateFrom()!=null?DateUtils.format(receivingRecordBackD.getPdateFrom(),"yyyy-MM-dd HH:mm:ss"):"");
        backDVO.setValidUntil(receivingRecordBackD.getValidUntil()!=null?DateUtils.format(receivingRecordBackD.getValidUntil(),"yyyy-MM-dd HH:mm:ss"):"");
        if(receivingRecordBackD.getStockstatus().equals("1")){
            backDVO.setResult("合格");
        }
        if(receivingRecordBackD.getStockstatus().equals("2")){
            backDVO.setResult("拒收");
        }
        if(receivingRecordBackD.getStockstatus().equals("3")){
            backDVO.setResult("待处理");
        }
        return backDVO;
    }

    private void excuteSaveExtCallBack(List<RcvInstockLines> callList) {
        if (ObjectUtils.isNull(callList)) {
            return;
        }
        RcvInstockLines rcvInstockLines2 = callList.get(0);
        String rcvHeaderId = rcvInstockLines2.getRcvHeaderId();
        List<RcvInstockLines> findByMap = this.mapper.findByMap((Map<String, Object>) MapUtils.put("rcvHeaderId", rcvHeaderId).getMap(), RcvInstockLines.class);
        if (ObjectUtils.isNull(findByMap)) {
            return;
        }
        List<RcvInstockLines> collect = findByMap.stream().filter(p -> !StringUtils.isBlank(p.getInventoryOpType())).collect(Collectors.toList());

        if (!ObjectUtils.isNull(collect)) {
            RcvHeaders rcvHeader = this.rcvHeadersMapper.findById(rcvHeaderId, RcvHeaders.class);
            RcvHeadersProfiles rcvHeadersProfiles = this.rcvHeadersProfilesMapper.findById(rcvHeaderId, RcvHeadersProfiles.class);
            rcvHeader.setRcvHeaderId("DG" + rcvHeaderId);
            rcvHeader.setAutoBillNum("DG" + rcvHeader.getAutoBillNum());
            rcvHeader.setRcvType(BizConstant.HOSTED_IN);
            this.rcvHeadersMapper.save(rcvHeader);
            rcvHeadersProfiles.setRcvHeaderId("DG" + rcvHeaderId);
            this.rcvHeadersProfilesMapper.save(rcvHeadersProfiles);
            List<RcvInstockLines> resultList = new ArrayList<>();
            for (RcvInstockLines rcvInstockLines : collect) {
                String inventoryOpType = rcvInstockLines.getInventoryOpType();
                RcvInstockLines result = new RcvInstockLines();
                BeanUtils.copyProperties(rcvInstockLines, result);
                String inBoundLineId = rcvInstockLines.getInBoundLineId();
                result.setInBoundLineId("DG" + inBoundLineId);
                BigDecimal pieceQty = result.getPieceQty();
                BigDecimal oddCaseQty = result.getOddCaseQty();
                BigDecimal oddPieceQty = result.getOddPieceQty();
                result.setPiecePriceTe(pieceQty.negate());
                result.setOddPieceQty(oddPieceQty.negate());
                result.setOddCaseQty(oddCaseQty.negate());
                result.setRealWhLocatorId(result.getHostLocatorId());
                result.setRcvHeaderId("DG" + rcvHeaderId);
                result.setInstockLabel("DG" + result.getInstockLabel());
                if (!StringUtils.isBlank(inventoryOpType) && "0".equals(inventoryOpType)) {
                    // 代管转正常
                    result.setInventoryStatus("5");
                }
                if (!StringUtils.isBlank(inventoryOpType) && "1".equals(inventoryOpType)) {
                    // 代管转待检
                    result.setInventoryStatus("3");
                }
                resultList.add(result);
            }
            this.mapper.saveBatch(resultList);

            IncomingRecordQueryVO vo = new IncomingRecordQueryVO();
            List<String> rcvHeaderIds = new ArrayList<>();
            rcvHeaderIds.add("DG" + rcvHeaderId);
            vo.setRcvHeaderIds(rcvHeaderIds);
            List<IncomingRecordH> insertData = this.incomingRecordHMapper.getInsertData(vo);
            if (ObjectUtils.isNotNull(insertData)) {
                this.incomingRecordHMapper.saveBatch(insertData);
            }
            List<IncomingRecordD> insertDataD = this.incomingRecordDMapper.getInsertData(vo);
            if (ObjectUtils.isNotNull(insertData)) {
                this.incomingRecordDMapper.saveBatch(insertDataD);
            }
        }
    }

    private void excuteSaveCallBackData(List<RcvInstockLines> callList, String callType) {
        IncomingRecordQueryVO vo = new IncomingRecordQueryVO();
        if (callType.equals("1")) {
            // 获取所有收货单头以及单头对应的上架明细
            String asnHeaderId = callList.get(0).getAsnHeaderId();
            AssertUtils.isNotBlank(asnHeaderId, "asn单id不可为空!");
            vo.setAsnHeaderId(asnHeaderId);

        } else if (callType.equals("2")) {
            String rcvHeaderId = callList.get(0).getRcvHeaderId();
            AssertUtils.isNotBlank(rcvHeaderId, "收货单单id不可为空!");
            List<String> rcvHeaderIds = new ArrayList<>();
            rcvHeaderIds.add(rcvHeaderId);
            vo.setRcvHeaderIds(rcvHeaderIds);
            //此处调整查询数据回写客户中间表
            //getSyncErpDataInfo(rcvHeaderId);
        }

        List<IncomingRecordH> insertData = this.incomingRecordHMapper.getInsertData(vo);
        if (ObjectUtils.isNotNull(insertData)) {
            this.incomingRecordHMapper.saveBatch(insertData);
        }
        List<IncomingRecordD> insertDataD = this.incomingRecordDMapper.getInsertData(vo);
        if (ObjectUtils.isNotNull(insertData)) {
            this.incomingRecordDMapper.saveBatch(insertDataD);
        }
    }

    private void excuteSaveCallBackDataV2(String rcvHeaderId) {
        AssertUtils.isNotBlank(rcvHeaderId, "收货单单id不可为空!");
        logger.info("rcvHeaderId = "+ rcvHeaderId);
        IncomingRecordQueryVO vo = new IncomingRecordQueryVO();
        List<String> rcvHeaderIds = new ArrayList<>();
        rcvHeaderIds.add(rcvHeaderId);
        vo.setRcvHeaderIds(rcvHeaderIds);

        List<IncomingRecordH> insertData = this.incomingRecordHMapper.getInsertData(vo);
        if (ObjectUtils.isNotNull(insertData)) {
            this.incomingRecordHMapper.saveBatch(insertData);
        }
        List<IncomingRecordD> insertDataD = this.incomingRecordDMapper.getInsertData(vo);
        if (ObjectUtils.isNotNull(insertData)) {
            this.incomingRecordDMapper.saveBatch(insertDataD);
        }
    }

    @Override
    public String getSyncErpDataInfo(String rcvHeaderId) {
        List<String> distCodes = Lists.newArrayList();
        distCodes.add("oms_asn_bill_type");
        List<Map<String, String>> distInfos = taskQcDetailMapper.queryDictInfo(distCodes);
        List<Map<String, Object>> syncErpDataInfo = this.incomingRecordDMapper.getSyncErpDataInfo(rcvHeaderId);
        Map<String, List<Map<String, Object>>> map = syncErpDataInfo.stream().collect(Collectors.groupingBy(d ->
                d.get("spid").toString() + d.get("dj_sort") + d.get("ph") + d.get("rq_sc")
                        + d.get("yxqz") + d.get("ry_shouhy") + d.get("ry_zjy") + d.get("ry_czy")+ d.get("rcv_line_id")));
        List<Map<String, Object>> mapList = Lists.newArrayList();
        for (Map.Entry<String, List<Map<String, Object>>> entry : map.entrySet()) {
            Map<String, Object> resultMap = Maps.newHashMap();
            Map<String, Object> firstMap = entry.getValue().get(0);
            resultMap.put("djbh", Convert.toStr(firstMap.get("djbh"), null));
            resultMap.put("dwid", Convert.toStr(firstMap.get("dwid"), null));
            resultMap.put("rq", Convert.toDate(firstMap.get("rq"), null));
            resultMap.put("ry_cgy", Convert.toStr(firstMap.get("ry_cgy"), null));
            resultMap.put("ry_shouhy", Convert.toStr(firstMap.get("ry_shouhy"), null));
            resultMap.put("ry_zjy", Convert.toStr(firstMap.get("ry_zjy"), null));
            resultMap.put("ry_czy", Convert.toStr(firstMap.get("ry_czy"), null));
            resultMap.put("djbh_sj", Convert.toStr(firstMap.get("djbh_sj"), null));
            resultMap.put("dj_sort", Convert.toStr(firstMap.get("dj_sort"), null));
            List<Map<String, String>> billTypeList = distInfos.stream().filter(dist -> Objects.equals(dist.get("type_code"), "oms_asn_bill_type")).collect(Collectors.toList());
            String rktype = Convert.toStr(firstMap.get("rktype"), null);
            for (Map<String, String> billType : billTypeList) {
                if (Objects.equals(billType.get("dict_code"), rktype)) {
                    rktype = Convert.toStr(billType.get("dict_name"), null);
                    break;
                }
            }
            resultMap.put("rktype", rktype);
            resultMap.put("spid", Convert.toStr(firstMap.get("spid"), null));
            BigDecimal slTotal = entry.getValue().stream().map(v -> Convert.toBigDecimal(v.get("sl"), BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal cr = Convert.toBigDecimal(firstMap.get("conversion_rate"), BigDecimal.ONE);
            BigDecimal jsTotal = slTotal.divide(cr, 0, RoundingMode.DOWN);
            BigDecimal lssTotal = slTotal.subtract(jsTotal.multiply(cr));
            resultMap.put("sl", slTotal.doubleValue());
            resultMap.put("js", jsTotal.doubleValue());
            resultMap.put("lss", lssTotal.doubleValue());
            resultMap.put("ph", Convert.toStr(firstMap.get("ph"), null));
            resultMap.put("rq_sc", Convert.toStr(firstMap.get("rq_sc"), null));
            resultMap.put("yxqz", Convert.toStr(firstMap.get("yxqz"), null));
            resultMap.put("yspd", Convert.toStr(firstMap.get("yspd"), null));
            resultMap.put("mjph", Convert.toStr(firstMap.get("mjph"), null));
            resultMap.put("mjxq", Convert.toStr(firstMap.get("mjxq"), null));
            resultMap.put("jkzczh", Convert.toStr(firstMap.get("jkzczh"), null));
            resultMap.put("enterpriseid", Convert.toStr(firstMap.get("enterpriseid"), null));
            resultMap.put("branchid", Convert.toStr(firstMap.get("branchid"), null));
            resultMap.put("yzid", Convert.toStr(firstMap.get("yzid"), null));
            resultMap.put("dmrq", Convert.toDate(firstMap.get("dmrq"), null));
            resultMap.put("wmflg", Convert.toStr(firstMap.get("wmflg"), null));
            resultMap.put("xgtime", Convert.toDate(firstMap.get("xgtime"), null));
            resultMap.put("cgdd_sort", Convert.toStr(firstMap.get("cgdd_sort"), null));
            resultMap.put("sh_sort", Convert.toStr(firstMap.get("rcv_line_id"), null));
            mapList.add(resultMap);
        }
        logger.info("执行回传ERP中间表开始,入参:{}-----------", JsonMapper.toJsonString(mapList));
        String result = HttpUtil.createPost(erpUrl).body(JsonMapper.toJsonString(mapList)).execute().body();
        logger.info("执行回传ERP中间表结束,返回:{}-----------", result);
        return result;
    }

    private void matchLimitLocator(BaseWmsWarehouseLocator baseWmsWarehouseLocator, RcvInstockLinesDTO rcvInstockLinesDTO) {
        // 匹配货位限定逻辑区
        String categoryId = rcvInstockLinesDTO.getCategoryId();
        String itemId = rcvInstockLinesDTO.getItemId();
        String warehouseLogicId = baseWmsWarehouseLocator.getWarehouseLogicId();
        String warehouseAreaCategoryCode = baseWmsWarehouseLocator.getWarehouseAreaCategoryCode();
        String warehouseId = rcvInstockLinesDTO.getWarehouseId();
        String mtlOwnerId = rcvInstockLinesDTO.getMtlOwnerId();
        List<Map> searchForMap = null;
        try {

            Map<String, Object> map = MapUtils.put("logicId", warehouseLogicId).put("categoryCode", warehouseAreaCategoryCode).put("itemCategoryCode", categoryId).put("itemId", itemId).put("warehouseId", warehouseId).put("cargoOwnerId", mtlOwnerId).getMap();
            logger.info("校验货位限定逻辑区是否存在,入参->", JsonUtils.toString(map));
            searchForMap = searchApi.searchForMap("vaildateLocatorLogicLimit", map);
        } catch (Exception e) {
            logger.info("校验货位限定逻辑区是否存在,查询服务查询报错,原因->", e.getMessage());
            e.printStackTrace();
        }

        if (!ObjectUtils.isNull(searchForMap)) {
            Map map = searchForMap.get(0);
            Integer count = (Integer) map.get("count");
            if (count != null && count == 1) {
                return;
            } else {
                logger.info("查询的货位限定逻辑区为空!");
                matchLogic(baseWmsWarehouseLocator, rcvInstockLinesDTO);
            }
        } else {
            logger.info("查询的货位限定逻辑区为空,走逻辑区匹配商品大类逻辑.");
            matchLogic(baseWmsWarehouseLocator, rcvInstockLinesDTO);
        }

    }

    private void matchLogic(BaseWmsWarehouseLocator baseWmsWarehouseLocator, RcvInstockLinesDTO rcvInstockLinesDTO) {
        // 匹配逻辑区
        String warehouseLogicCode = baseWmsWarehouseLocator.getWarehouseLogicCode();
        String categoryId = rcvInstockLinesDTO.getCategoryId();
        if (StringUtils.isBlank(categoryId)) {
            return;
        }
        if (StringUtils.isBlank(warehouseLogicCode)) {
            return;
        }
        if (!StringUtils.isBlank(categoryId) && warehouseLogicCode.equals(categoryId)) {
            return;
        }
        if (!StringUtils.isBlank(categoryId) && !warehouseLogicCode.equals(categoryId)) {
            throw new BizException("逻辑区不匹配该商品大类!请重试!");
        }

    }

    /**
     * 匹配货位类型
     *
     * @param baseWmsWarehouseLocator
     * @param rcvInstockLinesDTO
     */
    private void matchLocatorType(BaseWmsWarehouseLocator baseWmsWarehouseLocator, RcvInstockLinesDTO rcvInstockLinesDTO) {

        BigDecimal oddCaseQty = rcvInstockLinesDTO.getOddCaseQty();
        BigDecimal oddPieceQty = rcvInstockLinesDTO.getOddPieceQty();
        String warehouseLocatorType = baseWmsWarehouseLocator.getWarehouseLocatorType();
        if (null != oddCaseQty && null != oddPieceQty && oddPieceQty.compareTo(BigDecimal.ZERO) == 0 && oddCaseQty.compareTo(BigDecimal.ZERO) == 1) {
            // 为整数
            if (warehouseLocatorType.equals("1")) {
                // 货位类型为散件,报错
                throw new BizException(String.format("当前货位[%s]类型为散件位,商品数量为整件,匹配失败!", baseWmsWarehouseLocator.getWarehouseLocatorCode()));
            }
        }

        if (null != oddCaseQty && oddCaseQty.compareTo(BigDecimal.ZERO) == 0 && null != oddPieceQty && oddPieceQty.compareTo(BigDecimal.ZERO) == 1) {
            // 零散散
            if (warehouseLocatorType.equals("0")) {
                // 货位类型为整件,报错
                throw new BizException(String.format("当前货位[%s]类型为整件位,商品数量为散件,匹配失败!", baseWmsWarehouseLocator.getWarehouseLocatorCode()));
            }
        }

        if (null != oddCaseQty && oddCaseQty.compareTo(BigDecimal.ZERO) == 1 && null != oddPieceQty && oddPieceQty.compareTo(BigDecimal.ZERO) == 1) {
            // 整散
            if (warehouseLocatorType.equals("0") || warehouseLocatorType.equals("1")) {
                // 货位类型为整件,散件,报错
                throw new BizException(String.format("当前货位[%s]类型为整件/散件位,商品数量为整散,匹配失败!", baseWmsWarehouseLocator.getWarehouseLocatorCode()));
            }
        }

    }

    @Override
    public Object getInstockPrintData(RcvInstockLinesQueryVO queryVO) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * 获取待上架的区域
     */
    @Override
    public Object getInstockTaskArea(TaskQueryVO queryVO) {
        String enterpriseId = queryVO.getEnterpriseId();
        String warehouseId = queryVO.getWarehouseId();
        // 仓库id不能为空
        if (StringUtils.isBlank(warehouseId) || "null".equals(warehouseId))
            throw new ParameterException("仓库id不可为空!");
        if (StringUtils.isBlank(enterpriseId))
            enterpriseId = userUtils.getEnterpriseId();
        queryVO.setEnterpriseId(enterpriseId);
        List<TaskInstockDetailDTO> findList = taskInstockDetailMapper.findList(queryVO);
        if (ObjectUtils.isNull(findList))
            return null;

        // 根据建筑物分组
        Map<String, List<TaskInstockDetailDTO>> collect = findList.stream().filter(p -> !StringUtils.isBlank(p.getBldgName())).collect(Collectors.groupingBy(p -> p.getBldgName()));
        Set<Entry<String, List<TaskInstockDetailDTO>>> entrySet = collect.entrySet();
        Set<Map<String, Object>> mapList = new HashSet<>();
        for (Entry<String, List<TaskInstockDetailDTO>> entry : entrySet) {
            String key = entry.getKey(); // 建筑物名称
            List<TaskInstockDetailDTO> value = entry.getValue();
            for (TaskInstockDetailDTO task : value) {
                Map<String, Object> map = new HashMap<>();
                String warehouseAreaCode = task.getWhAreaCode();
                if (StringUtils.isBlank(warehouseAreaCode)) {
                    map.put(key, "其他");
                } else {
                    map.put(key, warehouseAreaCode);
                }
                mapList.add(map);
            }
        }
        Map<String, Object> map = MapUtils.put("其他", "其他").getMap();
        mapList.add(map);
        return mapList;
    }

    @Override
    public Object getInstockTaskDetailsByArea(TaskQueryVO queryVO, PageParam pageParam) {
        // TODO 按区域上架 待实现
        String bldgName = queryVO.getBldgName();
        String whAreaCode = queryVO.getWhAreaCode();
        String mtlOwnerId = queryVO.getMtlOwnerId();
        String warehouseId = queryVO.getWarehouseId();
        AssertUtils.isNotBlank(bldgName, "建筑物名称不可为空!");
        AssertUtils.isNotBlank(whAreaCode, "库区编码不可为空!");
        AssertUtils.isNotBlank(mtlOwnerId, "货主id不可为空!");
        AssertUtils.isNotBlank(warehouseId, "仓库id不可为空!");

        this.startPage(pageParam);
        // 二者都为其他,其他的处理,查询所有 上架任务
        if ("其他".equals(bldgName) && "其他".equals(whAreaCode)) {
            queryVO.setBldgName(null);
            queryVO.setWhAreaCode(null);
            List<TaskInstockDetailDTO> findList = this.taskInstockDetailMapper.findList(queryVO);
            return PageUtils.getPage(findList);
        }
        // 库区为其他的处理,当前建筑物下的所有上架任务
        if ("其他".equals(whAreaCode)) {
            queryVO.setWhAreaCode(null);
            List<TaskInstockDetailDTO> findList = this.taskInstockDetailMapper.findList(queryVO);
            return PageUtils.getPage(findList);
        }
        // 建筑物,库区编码 索取上架任务
        List<TaskInstockDetailDTO> findList = this.taskInstockDetailMapper.findList(queryVO);
        return PageUtils.getPage(findList);
    }

    // 异步回传
    @Override
    public void excuteCallBackErp(List<RcvInstockLines> callList, Long sleepTimes) {
        executor.execute(() -> {
            try {
                if (sleepTimes != null) {
                    Thread.sleep(callSleepTimes + sleepTimes);
                } else {
                    Thread.sleep(callSleepTimes);
                }
                this.excuteCallBackErp(callList, true);
            } catch (Exception e) {
                logger.error("上架回传失败,上架明细:" + callList.get(0).getRcvHeaderId());
            }
        });
        return;
    }

    /**
     * 执行回传erp TODO
     *
     * @param callList
     */
    @Override
    public void excuteCallBackErp(List<RcvInstockLines> callList, boolean isExtCallBack) {
        logger.info("上架回传开始-------------------------------");
        // 需要根据货主属性是否一次回传来决定是按照收货单,一单一单回传,还是按照采购订单单个订单回传 TODO
        String asnHeaderId = callList.get(0).getAsnHeaderId();
        // 首先需要判断该asn单是否是wms制单的
        OmsAsnBillH findById = this.omsAsnBillHMapper.findById(asnHeaderId, OmsAsnBillH.class);
        if (findById != null && !StringUtils.isBlank(findById.getAttrStr14())) {
            return;
        }

        //		String cargoOwnerId = callList.get(0).getMtlOwnerId();
        //		Map<String, Object> queryMap = new HashMap<>();
        //		queryMap.put("cargoOwnerId", cargoOwnerId);
        //		List<Map> searchForMap = null;
        //		Integer isOneReturnErp = 0;
        //		try {
        //			searchForMap = searchApi.searchForMap("getCargoOwnerProp", queryMap);
        //		} catch (Exception e1) {
        //			logger.info("找寻货主属性失败,原因{}", e1);
        //		}
        //		if (searchForMap != null) {
        //			Map map = searchForMap.get(0);
        //			if (map != null && map.containsKey("isOneReturnErp")) {
        //				Object isOneReturnErpObj = map.get("isOneReturnErp");
        //				if (isOneReturnErpObj instanceof String) {
        //					String isOneReturnErpStr = (String) isOneReturnErpObj;
        //					isOneReturnErp = Integer.parseInt(isOneReturnErpStr);
        //				} else if (isOneReturnErpObj instanceof Integer) {
        //					isOneReturnErp = (Integer) isOneReturnErpObj;
        //				}
        //			}
        //		}
        //		if (isOneReturnErp != null && isOneReturnErp == 1) {
        //			// 需要整个订单回传 //需要oms支持多收货单回传
        //			if (vaildateBillComplete(asnHeaderId)) {
        //				String rcvIdsByBillId = rcvHeadersMapper.getRcvIdsByBillId(asnHeaderId);
        //				String[] split = rcvIdsByBillId.split(",");
        //				for (String rcvId : split) {
        //					// 需要根据asnHeaderId获取所有收货单id
        //					EtlMessage em = new EtlMessage();
        //					em.setId(rcvId);
        //					em.setEtlType(EtlTypeConstants.in_asn_w2o);
        //					try {
        //						logger.info("整个订单上架回传给data-exchange数据:{}", JsonUtils.toString(em));
        //						exchangeSender.send(em);
        //						logger.info("整个订单上架回传给data-exchange成功!");
        //						// 更新入库单状态为已上传
        //						excuteUpdateRcvH(rcvId);
        //
        //					} catch (Exception e) {
        //						logger.error("整个订单上架回传失败,原因->{}", e);
        //					}
        //				}
        ////				excuteVaildateCallBack(rcvIdsByBillId, em);
        //
        //				// 判断上架操作的类型,若是代管转正常,代管转待检,重新生成入库单,入库拓展,入库明细,入库明细拓展,上架明细(数量传负数)
        //				if (isExtCallBack) {
        //					excuteExtCallBack(callList);
        //				}
        //
        //			} else {
        //				logger.info("整个订单上架回传失败,数量不达标----------------------");
        //			}
        //			return;
        //		} else {

        // 校验是否收货全部完成
        String rcvHeaderId = callList.get(0).getRcvHeaderId().trim();
        if (vaildateRcvComplete(rcvHeaderId)) {
            EtlMessage em = new EtlMessage();
            em.setId(rcvHeaderId);
            em.setEtlType(EtlTypeConstants.in_asn_w2o);
            try {
                logger.info("上架回传给data-exchange数据:{}", JsonUtils.toString(em));
                exchangeSender.send(em);
                logger.info("上架回传给data-exchange成功!");
                // 更新入库单状态为已上传
                excuteUpdateRcvH(rcvHeaderId);
            } catch (Exception e) {
                logger.error("上架回传失败,原因->{}", e);
            }

            //				excuteVaildateCallBack(rcvHeaderId, em);
            // 判断上架操作的类型,若是代管转正常,代管转待检,重新生成入库单,入库拓展,入库明细,入库明细拓展,上架明细(数量传负数)
            if (isExtCallBack) {
                // 额外回传
                excuteExtCallBack(callList);
            }
        } else {
            logger.info("上架回传失败,数量不达标----------------------");
        }
        //		}

        // 更新asn明细表状态以及asn单状态
        try {
            Set<String> asnLineIdSet = callList.stream().filter(p -> !StringUtils.isBlank(p.getAsnLineId())).map(p -> p.getAsnLineId()).collect(Collectors.toSet());
            updateAsnStatus(asnLineIdSet, asnHeaderId);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //		List<String> list = callList.stream().filter(p -> !StringUtils.isBlank(p.getInBoundLineId()))
        //				.map(RcvInstockLines::getInBoundLineId).collect(Collectors.toList());
        //
        ////		 String ids = list.stream().map(String::valueOf).collect(Collectors.joining(","));
        //		for (String string : list) {
        ////			exchangeSender.setConfirmCallback();
        //			EtlMessage em = new EtlMessage();
        //			em.setId(string);
        //			em.setEtlType(EtlTypeConstants.in_asn_w2o);
        //			try {
        //				exchangeSender.send(em);
        //			} catch (Exception e) {
        //				e.printStackTrace();
        //				// 打印错误日志
        //			}
        //		}
    }

    private void excuteUpdateRcvH(String rcvId) {
        // 更新入库单状态为已上传erp
        this.rcvHeadersMapper.updateMapById(rcvId, MapUtils.put("statusAs", "20").getMap(), RcvHeaders.class);
    }

    private void excuteVaildateCallBack(String rcvHeaderId, EtlMessage em) {

        try {
            Thread.sleep(10 * 1000);// 睡眠10s进行操作
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        // 检查是否回传oms成功,若否,重新调用data-exchange服务接口手动回传
        List<Map> searchForMap2 = null;
        try {
            searchForMap2 = searchApi.searchForMap("getOmsIncoming", MapUtils.put("rcvHeaderIds", rcvHeaderId.split(",")).getMap());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!ObjectUtils.isNull(searchForMap2)) {
            Integer count = (Integer) searchForMap2.get(0).get("count");
            if (count == null || 0 == count) {
                // 回传没成功,手动调用data-exchange服务回传
                if (this.restTemplate == null) {
                    throw new SearchException("查询失败,RestTemplate为null");
                }

                //				executor.execute(() -> {
                try {
                    //						Thread.sleep(callSleepTimes);
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                    HttpEntity<String> formEntity = new HttpEntity<String>(JsonUtils.toString(em), headers);
                    String data = restTemplate.postForObject(dataExchangeUrl, formEntity, String.class);
                } catch (JsonProcessingException | IllegalArgumentException e) {
                    logger.error("上架回传失败,收货单id:" + em.getId());
                }
                //				});

                //				try {
                //					RestMessage<String> callBack = dataExchangeRemoteCaller.callBack(em);
                //					if (callBack != null && !callBack.isSuccess()) {
                //						logger.error("手动回传oms失败!原因->" + callBack.getMessage());
                //					}
                //				} catch (Exception e) {
                //					logger.error("手动回传oms失败!原因->{}", e);
                //				}
            }
        }

    }

    /**
     * 进行额外的回传
     *
     * @param callList
     */
    @Override
    public void excuteExtCallBack(List<RcvInstockLines> callList) {
        if (ObjectUtils.isNull(callList)) {
            return;
        }
        RcvInstockLines rcvInstockLines2 = callList.get(0);
        String rcvHeaderId = rcvInstockLines2.getRcvHeaderId();
        List<RcvInstockLines> findByMap = this.mapper.findByMap((Map<String, Object>) MapUtils.put("rcvHeaderId", rcvHeaderId).getMap(), RcvInstockLines.class);
        if (ObjectUtils.isNull(findByMap)) {
            return;
        }
        List<RcvInstockLines> collect = findByMap.stream().filter(p -> !StringUtils.isBlank(p.getInventoryOpType())).collect(Collectors.toList());

        if (!ObjectUtils.isNull(collect)) {
            RcvHeaders rcvHeader = this.rcvHeadersMapper.findById(rcvHeaderId, RcvHeaders.class);
            RcvHeadersProfiles rcvHeadersProfiles = this.rcvHeadersProfilesMapper.findById(rcvHeaderId, RcvHeadersProfiles.class);
            rcvHeader.setRcvHeaderId("DG" + rcvHeaderId);
            rcvHeader.setAutoBillNum("DG" + rcvHeader.getAutoBillNum());
            rcvHeader.setRcvType(BizConstant.HOSTED_IN);
            this.rcvHeadersMapper.save(rcvHeader);
            rcvHeadersProfiles.setRcvHeaderId("DG" + rcvHeaderId);
            this.rcvHeadersProfilesMapper.save(rcvHeadersProfiles);
            List<RcvInstockLines> resultList = new ArrayList<>();
            for (RcvInstockLines rcvInstockLines : collect) {
                String inventoryOpType = rcvInstockLines.getInventoryOpType();
                RcvInstockLines result = new RcvInstockLines();
                BeanUtils.copyProperties(rcvInstockLines, result);
                String inBoundLineId = rcvInstockLines.getInBoundLineId();
                result.setInBoundLineId("DG" + inBoundLineId);
                BigDecimal pieceQty = result.getPieceQty();
                BigDecimal oddCaseQty = result.getOddCaseQty();
                BigDecimal oddPieceQty = result.getOddPieceQty();
                result.setPiecePriceTe(pieceQty.negate());
                result.setOddPieceQty(oddPieceQty.negate());
                result.setOddCaseQty(oddCaseQty.negate());
                result.setRealWhLocatorId(result.getHostLocatorId());
                result.setRcvHeaderId("DG" + rcvHeaderId);
                result.setInstockLabel("DG" + result.getInstockLabel());
                if (!StringUtils.isBlank(inventoryOpType) && "0".equals(inventoryOpType)) {
                    // 代管转正常
                    result.setInventoryStatus("5");
                }
                if (!StringUtils.isBlank(inventoryOpType) && "1".equals(inventoryOpType)) {
                    // 代管转待检
                    result.setInventoryStatus("3");
                }
                resultList.add(result);
            }
            this.mapper.saveBatch(resultList);

            EtlMessage em = new EtlMessage();
            em.setId("DG" + rcvHeaderId);
            em.setEtlType(EtlTypeConstants.in_asn_w2o);
            try {
                logger.info("代管抵扣,上架回传给data-exchange数据:{}", JsonUtils.toString(em));
                exchangeSender.send(em);
                logger.info("代管抵扣,上架回传给data-exchange成功!");
                excuteUpdateRcvH("DG" + rcvHeaderId);
            } catch (Exception e) {
                logger.error("代管抵扣,上架回传失败,原因->{}", e);
            }
            //			excuteVaildateCallBack("DG" + rcvHeaderId, em);
        }
    }

    private boolean vaildateBillComplete(String asnHeaderId) {
        // 校验整个采购单是否收货上架完毕
        BigDecimal qty = null;
        try {
            qty = rcvHeadersMapper.getRemainQtyByBillId(asnHeaderId);
            logger.info("剩余未上架数量" + JSON.toJSONString(qty));
        } catch (Exception e) {
            logger.info("调用sql错误原因{}", e);
        }
        if (qty == null) {
            throw new BizException(String.format("收货原订单id[%s]对应的收货明细总量查询为空!请检查!", asnHeaderId));
        }
        if (qty != null && qty.compareTo(BigDecimal.ZERO) == 0) {
            return true;
        }
        return false;
    }

    /**
     * 校验是否全部收货完成
     *
     * @param rcvHeaderId
     * @return
     */
    private boolean vaildateRcvComplete(String rcvHeaderId) {
        return rcvHeadersService.vaildateRcvComplete(rcvHeaderId);
    }

    /**
     * 获取待上架容器集合(带分页)
     */
/*    @Override
    public Object getInstockTaskContainer(String warehouseId, String mtlOwnerId, String enterpriseId, Integer pageNum, Integer pageSize) {
        AssertUtils.isNotBlank(warehouseId, "仓库id请求为空!");
        AssertUtils.isNotBlank(mtlOwnerId, "货主id请求为空!");
        if (StringUtils.isBlank(enterpriseId)) {
            enterpriseId = userUtils.getEnterpriseId();
        }
        if (pageNum == null)
            pageNum = PageParam.DEFAULT_PAGE_NUM;
        if (pageSize == null || pageSize == 0)
            pageSize = PageParam.DEFAULT_PAGE_SIZE;

        PageUtils.startPage(pageNum, pageSize);
        List<String> containerCodes = this.taskInstockDetailMapper.findContainer(warehouseId, mtlOwnerId, enterpriseId);
        return PageUtils.getPage(containerCodes);
    }*/

    @Override
    public Object getInstockTaskContainer(String warehouseId, String mtlOwnerId, String enterpriseId, Integer pageNum, Integer pageSize) {
        AssertUtils.isNotBlank(warehouseId, "仓库id请求为空!");
        AssertUtils.isNotBlank(mtlOwnerId, "货主id请求为空!");
        if (StringUtils.isBlank(enterpriseId)) {
            enterpriseId = userUtils.getEnterpriseId();
        }
        if (pageNum == null)
            pageNum = PageParam.DEFAULT_PAGE_NUM;
        if (pageSize == null || pageSize == 0)
            pageSize = PageParam.DEFAULT_PAGE_SIZE;

        PageUtils.startPage(pageNum, pageSize);
        List<String> containerCodes = this.taskInstockDetailMapper.findContainer(warehouseId, mtlOwnerId, enterpriseId);
        return PageUtils.getPage(containerCodes);
    }

    @Override
    public Object taskMerge(List<TaskInstockDetailDTO> taskInstockDetailDTOList) {
        return taskInstockDetailService.taskMerge(taskInstockDetailDTOList);
    }

    @Override
    @Transactional
    @TxTransaction(isStart = true)
    public Object batchAddAuto(List<RcvInstockLinesDTO> lineList, UserDTO userDTO) {
        return this.batchAdd(lineList, userDTO, true);
    }

    @Override
    public Object getInstockInstockIn(String ids) {
        List<RcvInstockLines> findByIds = this.mapper.findByIds(RcvInstockLines.class, ids.split(","), null);
        this.excuteInstock2(findByIds);

        return true;
    }
    //		@Override
    //		public Page<TaskInstockDetailDTO> extractTask(TaskQcDQueryVO queryVO, PageParam pageParam) {
    //			// 提取任务池中任务
    //		BeanUtils.copyProperties(taskQcDQueryVO, dto);
    //		Page<TaskInstockDetailDTO> findList = taskInstockDetailService.findList(dto, pageParam);
    //
    //		List<TaskInstockDetailDTO> list = findList.getList();
    //		List<String> rcvLineIdList = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().distinct()
    //				.map(p -> p.getRcvLineId()).collect(Collectors.toList());
    //
    //		// 加入item的一系列参数
    //		if (ObjectUtils.isNotNull(rcvLineIdList)) {
    //			List<RcvLinesProfilesDTO> rcvPList = rcvLinesProfilesService.searchByIdList(rcvLineIdList);
    //			List<RcvLinesDTO> rcvLList = rcvLinesService.searchByIdList(rcvLineIdList);
    //			// 1. 根据行id分组
    //			Map<String, List<TaskInstockDetailDTO>> collect = Optional.ofNullable(list).orElse(Collections.emptyList())
    //					.stream().distinct().collect(Collectors.groupingBy(TaskInstockDetailDTO::getRcvLineId));
    //			Map<String, List<RcvLinesProfilesDTO>> collect2 = Optional.ofNullable(rcvPList)
    //					.orElse(Collections.emptyList()).stream().distinct()
    //					.collect(Collectors.groupingBy(RcvLinesProfilesDTO::getRcvLineId));
    //			Map<String, List<RcvLinesDTO>> collect3 = Optional.ofNullable(rcvLList).orElse(Collections.emptyList())
    //					.stream().distinct().collect(Collectors.groupingBy(RcvLinesDTO::getRcvLineId));
    //			Set<Entry<String, List<TaskInstockDetailDTO>>> entrySet = collect.entrySet();
    //			// 2. set进对应的拓展信息
    //			for (Entry<String, List<TaskInstockDetailDTO>> entry : entrySet) {
    //				List<TaskInstockDetailDTO> value = entry.getValue();
    //				String key = entry.getKey();
    //				List<RcvLinesProfilesDTO> list2 = collect2.get(key);
    //				List<RcvLinesDTO> list3 = collect3.get(key);
    //				if (ObjectUtils.isNotNull(value) && ObjectUtils.isNotNull(list2)) {
    //
    //					// 组装数据
    //					// 加入物料其它字段
    //					// 加入item属性
    //					Random random = new Random();
    //					int nextInt = random.nextInt(100);
    //					// 调用远程item服务查询
    //					list2.get(0).setItemAssistantCode("00" + nextInt);
    //					list2.get(0).setItemHealthApprovalNbr("00" + nextInt);
    //					list2.get(0).setIsCaseOrPiece("0");
    //					list2.get(0).setQcMode("01");
    //					list2.get(0).setCaseConversionRate(BigDecimal.valueOf(nextInt));
    //
    //					value.get(0).setRcvLinesProfilesDTO(list2.get(0));
    //					value.get(0).setRcvLinesDTO(list3.get(0));
    //					String warehouseArea = list3.get(0).getWarehouseAreaName();
    //					String warehouseAreaCategory = list3.get(0).getWarehouseAreaCategory();
    //					String warehouseLocator = list3.get(0).getWarehouseLocator();
    //					String warehouseRoom = list3.get(0).getWarehouseRoom();
    //					value.get(0).setWhLocator(warehouseLocator);
    //					value.get(0).setWhArea(warehouseArea);
    //					value.get(0).setWhRoom(warehouseRoom);
    //					value.get(0).setWhAreaCatagory(warehouseAreaCategory);
    //
    //					// 计算零散数
    //					BigDecimal qty = value.get(0).getQty();
    //					BigDecimal pieceQty = value.get(0).getPieceQty();
    //					BigDecimal conversionRate = value.get(0).getConversionRate();
    //					BigDecimal subtract = pieceQty.subtract(conversionRate.multiply(qty));
    //					value.get(0).setOddPieceQty(subtract);
    //
    //				}
    //			}
    //		}
    //		return findList;
    //	}
    //	private void excuteInstock(List<RcvInstockLines> list) {
    //	ValidList<InvStockIn> invStock = new ValidList<InvStockIn>();
    //	Map<String, List<RcvInstockLines>> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream()
    //			.distinct().collect(Collectors.groupingBy(RcvInstockLines::getItemId));
    //	for (List<RcvInstockLines> rcvInstockLinesList : collect.values()) {
    //		if (ObjectUtils.isNull(rcvInstockLinesList))
    //			continue;
    //		InvStockIn invStockIn = new InvStockIn();
    //		List<InvStockInDetail> details = new ArrayList<InvStockInDetail>();
    //		for (RcvInstockLines rcvInstockLines : rcvInstockLinesList) {
    //			InvStockInDetail detail = new InvStockInDetail();
    //			BigDecimal pieceQty = rcvInstockLines.getPieceQty();
    //			String warehouseLocatorId = rcvInstockLines.getWhLocatorId();
    //			String realWhLocatorId = rcvInstockLines.getRealWhLocatorId();
    //			String comments = rcvInstockLines.getComments();
    //			String goodsCaseCode = rcvInstockLines.getGoodsCaseCode();
    //			String containerCode = rcvInstockLines.getContainerCode();
    //			detail.setQuantity(pieceQty);
    //			detail.setContainerCode(containerCode);
    //			detail.setGoodsCaseCode(goodsCaseCode);
    //			detail.setLocatorId(realWhLocatorId);
    //			detail.setComments(comments);
    //
    //			detail.setStatus(rcvInstockLines.getInventoryStatus());
    ////			// 处理库存状态 (前端需要转result为StockStatus)
    ////			String result = rcvInstockLines.getStockStatus();
    ////			// 库存状态
    ////			switch (result) {
    ////			case "0":
    ////				detail.setStatus(StockStatusEnum.QUALIFIED.getCode());
    ////				break;
    ////			case "1":
    ////				detail.setStatus(StockStatusEnum.UNQUALIFIED.getCode());
    ////				break;
    ////			case "2":
    ////				detail.setStatus(StockStatusEnum.WAITING_INSPECTION.getCode());
    ////				break;
    ////			case "3":
    ////				detail.setStatus(StockStatusEnum.REFUND.getCode());
    ////				break;
    ////			default:
    ////				break;
    ////			}
    //			details.add(detail);
    //		}
    //		RcvInstockLines rcvInstockLines = rcvInstockLinesList.get(0);
    //
    //		Date batchExpiredDate = rcvInstockLines.getBatchExpiredDate();
    //		Date batchProductionDate = rcvInstockLines.getBatchProductionDate();
    //		String inBoundLineId = rcvInstockLines.getInBoundLineId();
    //		String mtlOwnerId = rcvInstockLines.getMtlOwnerId();
    //		String itemId = rcvInstockLines.getItemId();
    //		String manufacturerBatchNum = rcvInstockLines.getManufacturerLotNum();
    //		String warehouseId = rcvInstockLines.getWarehouseId();
    //		String vendorBatchNum = rcvInstockLines.getVendorBatchNum();
    //		String productionPlace = rcvInstockLines.getProductionPlace();
    //		String orgId = rcvInstockLines.getOrgId();
    //		String vendorId = rcvInstockLines.getVendorId();
    //		String erpBatchNum2 = rcvInstockLines.getErpBatchNum();
    //		BigDecimal piecePriceTe = rcvInstockLines.getPiecePriceTe();
    //		BigDecimal piecePriceTi = rcvInstockLines.getPiecePriceTi();
    //		BigDecimal taxRate = rcvInstockLines.getTaxRate();
    //		String enterpriseId = rcvInstockLines.getEnterpriseId();
    //
    //		// =====生产批次id/批次num所用
    //		String taskId = rcvInstockLines.getTaskId();
    //		String rcvHeaderId = rcvInstockLines.getRcvHeaderId();
    //		String asnHeaderId = rcvInstockLines.getAsnHeaderId();
    //		String rcvLineId = rcvInstockLines.getRcvLineId();
    //		Date rcvDate = rcvInstockLines.getRcvDate();
    //		String batchId = rcvInstockLines.getBatchId();
    //
    //		invStockIn.setDetails(details);
    //		invStockIn.setAsnId(asnHeaderId);
    //		invStockIn.setRcvId(rcvHeaderId);
    //		invStockIn.setTaskId(taskId);
    //		invStockIn.setWarehouseId(warehouseId);
    //		invStockIn.setEnterpriseId(enterpriseId);
    //		invStockIn.setBatchId(batchId);
    //		invStockIn.setRcvLineId(rcvLineId);
    //
    ////		invStockIn.setBillId(inBoundLineId);
    ////		invStockIn.setBatchExpiredDate(batchExpiredDate);
    ////		invStockIn.setBatchProductionDate(batchProductionDate);
    ////		invStockIn.setCargoOwnerId(mtlOwnerId);
    ////		invStockIn.setErpBatchNum(erpBatchNum2); // 预留
    ////		invStockIn.setGradeId("1"); // 等级
    ////		invStockIn.setItemId(itemId);
    ////		invStockIn.setManufacturerLotNum(manufacturerBatchNum);
    ////		invStockIn.setOrgnId(orgId); // 预留
    ////		invStockIn.setProductionPlace(productionPlace);
    ////		invStockIn.setShelfLifeDays(
    ////				Math.abs(DateUtils.subtract(batchExpiredDate, batchProductionDate, ChronoUnit.DAYS)));
    ////		invStockIn.setPieceCostTe(piecePriceTe);
    ////		invStockIn.setPieceCostTi(piecePriceTi);
    ////		invStockIn.setTaxRate(taxRate);
    ////		invStockIn.setVendorBatchNum(vendorBatchNum);
    ////		invStockIn.setVendorId(vendorId);
    //
    //		invStock.add(invStockIn);
    //	}
    //
    //	// 远程调用直接入库存的服务
    //	RestMessage inStockBatchCheck = null;
    //	try {
    //		inStockBatchCheck = baseInventoryRemoteCaller.inStockBatchCheck(invStock);
    //	} catch (Exception e) {
    //		logger.error("上架调用远程库存服务失败!原因->{}", e);
    //		throw new BizException("上架调用远程库存服务失败!");
    //	}
    //	if (inStockBatchCheck == null || inStockBatchCheck.getData() == null || !inStockBatchCheck.isSuccess()) {
    //		logger.error("上架调用远程库存服务失败!");
    //		throw new BizException("上架调用远程库存服务失败!");
    //	}
    //	if (!inStockBatchCheck.isSuccess()) {
    //		throw new BizException(String.format("上架调用远程库存服务失败!原因->%s", inStockBatchCheck.getMessage()));
    //	}
    //
    //}

    @Override
    public Object pickInstockTask(InstockTaskQueryVO queryVO) {
        String warehouseId = queryVO.getWarehouseId();
        AssertUtils.isNotBlank(warehouseId, "仓库id不可为空!");
        String mtlOwnerId = queryVO.getMtlOwnerId();
        AssertUtils.isNotBlank(mtlOwnerId, "货主id不可为空!");
        String container = queryVO.getContainer();
        AssertUtils.isNotBlank(container, "请按照容器号索取任务!");

        //		String enterpriseId = queryVO.getEnterpriseId();
        //		if (ObjectUtils.isNull(enterpriseId))
        //			queryVO.setEnterpriseId(userUtils.getEnterpriseId());
        String status = queryVO.getStatus();
        if (StringUtils.isBlank(status))
            queryVO.setStatus("1"); // 没有就默认可用上架任务

        long currentTimeMillis = System.currentTimeMillis();
        String getMD5Code = MD5Utils.GetMD5Code(warehouseId + mtlOwnerId + container + currentTimeMillis); // 任务包id需要定义为唯一id

        List<TaskInstockDetailDTO> findListPad = this.taskInstockDetailMapper.findListPad(queryVO);
        if (ObjectUtils.isNull(findListPad)) {
            throw new BizException("没有需要上架的任务!");
        }

        Set<String> collect = findListPad.stream().map(TaskInstockDetailDTO::getTaskInboundId).collect(Collectors.toSet());
        Criteria crt0 = Criteria.forClass(TaskInstockDetail.class);
        crt0.setRestriction(Restrictions.in("taskInboundId", collect.toArray()));
        taskInstockDetailMapper.updateMapByCriteria(MapUtils.put("segment2", getMD5Code).getMap(), crt0);
        //		{
        //		  "businessProperty": "业务属性",
        //		  "containerNo": "容器No",
        //		  "containerType": 0,
        //		  "subList": [{
        //		    "containerSubNo": "子容器No1",
        //		    "itemId": "商品Id1",
        //		    "lotId": "批次Id1",
        //		    "qty": 1000.0
        //		  }, {
        //		    "containerSubNo": "子容器No2",
        //		    "itemId": "商品Id2",
        //		    "lotId": "批次Id2",
        //		    "qty": 500.0
        //		  }],
        //		  "upperSystemTaskId": "WMS任务Id"
        //	}
        List<Map<String, Object>> subList = new ArrayList<>();
        for (TaskInstockDetailDTO taskInstockDetailDTO : findListPad) {
            Map<String, Object> subMap = new HashMap<>();
            String taskInboundId = taskInstockDetailDTO.getTaskInboundId();
            String itemId = taskInstockDetailDTO.getItemId();
            String batchId = taskInstockDetailDTO.getBatchId();
            BigDecimal pieceQty = taskInstockDetailDTO.getPieceQty();
            subMap.put("containerSubNo", taskInboundId);
            subMap.put("itemId", itemId);
            subMap.put("lotId", batchId);
            subMap.put("qty", pieceQty);
            subList.add(subMap);
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("containerNo", container);
        resultMap.put("upperSystemTaskId", getMD5Code);
        resultMap.put("subList", subList);

        return resultMap;
    }

    @Override
    @Transactional
    @TxTransaction(isStart = true)
    public List<CallbackInstockTaskDTO> completeInstockTask(List<CompleteInstockTaskDTO> completeInstockTaskList) {
        //		boolean anyMatch = completeInstockTaskList.stream().anyMatch(p -> StringUtils.isBlank(p.getLocatorId()));
        //		if (anyMatch) {
        //			throw new BizException("请检查自己的任务明细!货位为空!");
        //		}
        //		Set<String> collect2 = completeInstockTaskList.stream().map(CompleteInstockTaskDTO::getLocatorId)
        //				.collect(Collectors.toSet());

        List<Map> searchForMap = null;
        Set<String> collect2 = new HashSet<>();
        collect2.add(BizConstant.SBK);
        try {
            searchForMap = searchApi.searchForMap("locator_info_list", MapUtils.put("includeAreaCategoryCodes", collect2).put("isEnable", 1).getMap());
            //			searchForMap = searchApi.searchForMap("locator_info_list", MapUtils.put("locatorIds", collect2).getMap());
        } catch (Exception e) {
            logger.error("调用查询服务失败,");
        }
        if (ObjectUtils.isNull(searchForMap)) {
            logger.error("货位数据查询为空!参数->" + collect2.toString());
            throw new BizException("货位数据查询为空!");
        }

        //		Map<String, List<Map>> locatorListMap = searchForMap.stream()
        //				.collect(Collectors.groupingBy(p -> (String) p.get("whLocatorId")));

        //		Map<String, List<CompleteInstockTaskDTO>> taskMap = completeInstockTaskList.stream()
        //				.collect(Collectors.groupingBy(CompleteInstockTaskDTO::getTaskId));

        // 调用远程服务获取
        List<RcvInstockLinesDTO> rcvInstockLinesList = new ArrayList<>();
        int row = 0;
        for (CompleteInstockTaskDTO completeInstockTaskDTO : completeInstockTaskList) {
            row++;
            String upperSystemTaskId = completeInstockTaskDTO.getUpperSystemTaskId();

            //			Criteria crt0 = Criteria.forClass(TaskInstockDetail.class);
            //			crt0.setRestriction(Restrictions.eq("segment2", upperSystemTaskId));
            TaskQueryVO vo = new TaskQueryVO();
            vo.setSegment2(upperSystemTaskId);
            vo.setStatus("1");
            List<TaskInstockDetailDTO> findByCriteria = this.taskInstockDetailMapper.findList(vo);
            if (ObjectUtils.isNull(findByCriteria)) {
                logger.info("任务包id->" + upperSystemTaskId + "搜寻的上架任务为空!");
                continue;
            }
            for (TaskInstockDetailDTO taskDTO : findByCriteria) {
                RcvInstockLinesDTO rcvInstockLines = new RcvInstockLinesDTO();
                BeanUtils.copyProperties(taskDTO, rcvInstockLines);
                rcvInstockLines.setTaskId(taskDTO.getTaskInboundId());
                rcvInstockLines.setLineNum(new BigDecimal(row));

                //				String locatorId = completeInstockTaskDTO.getLocatorId();
                //				List<Map> locatorList = locatorListMap.get(locatorId);
                //				Map locatorMap = locatorList.get(0);
                Map locatorMap = searchForMap.get(0);
                String whLocatorCode = (String) locatorMap.get("whLocatorCode");
                String whLocatorName = (String) locatorMap.get("whLocatorName");
                String whAreaCategoryCode = (String) locatorMap.get("whAreaCategoryCode");
                String locatorId = (String) locatorMap.get("whLocatorId");
                rcvInstockLines.setRealWhLocatorId(locatorId);
                rcvInstockLines.setRealWhLocatorCode(whLocatorCode);
                rcvInstockLines.setRealWhLocatorCode(whLocatorName);
                rcvInstockLines.setWhAreaCategoryCode(whAreaCategoryCode);

                String enterpriseId = taskDTO.getEnterpriseId();
                String creator = taskDTO.getCreator();
                String creatorName = taskDTO.getCreatorName();
                rcvInstockLines.setEnterpriseId(enterpriseId);
                rcvInstockLines.setCreator(creator);
                rcvInstockLines.setCreatorName(creatorName);

                rcvInstockLinesList.add(rcvInstockLines);
            }

        }
        if (ObjectUtils.isNull(rcvInstockLinesList)) {
            if (errorReturnTrue) {
                logger.error("操作的上架数据为空!");
                return null;
            } else {
                throw new BizException("操作的上架数据为空!");
            }
        }

        UserDTO userDTO = null;
        try {
            userDTO = userUtils.getUserDTO();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        if (ObjectUtils.isNull(userDTO)) {
            RcvInstockLinesDTO rcvInstockLinesDTO = rcvInstockLinesList.get(0);
            userDTO = new UserDTO();
            userDTO.setEnterpriseId(rcvInstockLinesDTO.getEnterpriseId());
            userDTO.setId(rcvInstockLinesDTO.getCreator());
            userDTO.setUsername(rcvInstockLinesDTO.getCreatorName());
        }

        try {
            this.batchAdd(rcvInstockLinesList, userDTO, true, false);
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new BizException(e.getMessage());
        }

        return null;
    }

    @Override
    public Object batchAddNoCall2Erp(List<RcvInstockLinesDTO> rcvInstockLinesDTOList) {
        return this.batchAdd(rcvInstockLinesDTOList, userUtils.getUserDTO(), false);
    }

    @Override
    public Object instockCall2Erp(String hids) {
        String[] split = hids.split(",");
        for (String rcvHeaderId : split) {
            if (vaildateRcvComplete(rcvHeaderId)) {
                EtlMessage em = new EtlMessage();
                em.setId(rcvHeaderId);
                em.setEtlType(EtlTypeConstants.in_asn_w2o);
                try {
                    logger.info("上架回传给data-exchange数据:{}", JsonUtils.toString(em));
                    exchangeSender.send(em);
                    logger.info("上架回传给data-exchange成功!");
                    excuteUpdateRcvH(rcvHeaderId);
                } catch (Exception e) {
                    logger.error("上架回传失败,原因->{}", e);
                }

            } else {
                logger.info("上架回传失败,数量不达标----------------------");
            }
        }
        return null;
    }

    @Resource
    private IntegrationApi integrationApi;

    @Override
    public Object tansfor2AGV(InstockTaskQueryVO queryVO) {
        String warehouseId = queryVO.getWarehouseId();
        AssertUtils.isNotBlank(warehouseId, "仓库id不可为空!");
        String mtlOwnerId = queryVO.getMtlOwnerId();
        AssertUtils.isNotBlank(mtlOwnerId, "货主id不可为空!");
        //		String container = queryVO.getContainer();
        //		AssertUtils.isNotBlank(container, "请按照容器号索取任务!");

        String enterpriseId = queryVO.getEnterpriseId();
        if (ObjectUtils.isNull(enterpriseId))
            queryVO.setEnterpriseId(userUtils.getEnterpriseId());
        String status = queryVO.getStatus();
        if (StringUtils.isBlank(status))
            queryVO.setStatus("1"); // 没有就默认可用上架任务

        List<TaskInstockDetailDTO> findListPad = this.taskInstockDetailMapper.findListPad(queryVO);

        Map<String, Object> resultData = new HashMap<>();
        Map<String, Object> headMap = new HashMap<>();
        if (!ObjectUtils.isNull(findListPad)) {
            TaskInstockDetailDTO taskInstockDetailDTO = findListPad.get(0);
            String rcvHeaderId = taskInstockDetailDTO.getRcvHeaderId();
            //			RcvHDTO findByPkId = this.rcvHeadersMapper.findByPkId(rcvHeaderId);

            String rcvUser = taskInstockDetailDTO.getRcvUser();
            String executor2 = taskInstockDetailDTO.getExecutor();
            String rqcUser = taskInstockDetailDTO.getRqcUser();
            String bizUser = taskInstockDetailDTO.getBizUser();
            String mtlOwnerId2 = taskInstockDetailDTO.getMtlOwnerId();
            String asnRemark = taskInstockDetailDTO.getAsnRemark();
            long id = SnowFlakeUtils.getId();
            String shippid = "";
            String customerId = taskInstockDetailDTO.getCustomerId();
            if (StringUtils.isBlank(shippid)) {
                shippid = customerId;
            }
            String vendorId = taskInstockDetailDTO.getVendorId();
            if (StringUtils.isBlank(shippid)) {
                shippid = vendorId;
            }
            String rcvType = taskInstockDetailDTO.getRcvType();
            rcvType = convertRcvType(rcvType);

            headMap.put("djbh", String.valueOf(id));
            headMap.put("rq", getStringDate());
            headMap.put("dwid", shippid);
            headMap.put("ry_cgy", bizUser);
            headMap.put("ry_czy", executor2);
            headMap.put("ry_shouhy", rcvUser);
            headMap.put("ry_zjy", rqcUser);
            headMap.put("shr", rcvUser);
            headMap.put("sf_wc", "0");
            headMap.put("sf_xc", "0");
            headMap.put("sf_zx", "0");
            headMap.put("djbh_sj", rcvHeaderId);
            headMap.put("rktype", "0"); // 正常传0
            headMap.put("yzid", mtlOwnerId2);
            headMap.put("bz", asnRemark);
            int row = 0;
            List<Map> data_itemlist = new ArrayList<>();
            for (TaskInstockDetailDTO taskInstockDetailDTO2 : findListPad) {
                row++;
                String djbh = String.valueOf(id);
                Integer dj_sort = row;
                String itemId = taskInstockDetailDTO2.getItemId();
                BigDecimal pieceQty = taskInstockDetailDTO2.getPieceQty();
                BigDecimal conversionRate = taskInstockDetailDTO2.getConversionRate();
                // 数据准确性计算
                if (conversionRate == null) {
                    conversionRate = BigDecimal.ONE;
                }
                if (pieceQty == null) {
                    pieceQty = BigDecimal.ZERO;
                }
                BigDecimal oddCaseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
                BigDecimal multiply = oddCaseQty.multiply(conversionRate);
                BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
                BigDecimal qty = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN); // 包装总量
                String manufacturerLotNum = taskInstockDetailDTO2.getManufacturerLotNum();
                Date batchProductionDate = taskInstockDetailDTO2.getBatchProductionDate();
                String convertStringDate1 = convertStringDate(batchProductionDate);
                Date batchExpiredDate = taskInstockDetailDTO2.getBatchExpiredDate();
                String convertStringDate2 = convertStringDate(batchExpiredDate);
                String sf_zx = "0";
                String batchId = taskInstockDetailDTO2.getBatchId();
                String result = taskInstockDetailDTO2.getResult();
                String yspd = convertRqcResult(result);
                String cgdd_sort = taskInstockDetailDTO2.getAsnLineId();
                Integer sl_ywc = 0;
                String yzid = taskInstockDetailDTO2.getMtlOwnerId();
                Integer dj_sort_sj = 1;
                String bz = taskInstockDetailDTO2.getAsnLineRemark();
                String task_id = taskInstockDetailDTO2.getTaskInboundId();

                Map<String, Object> table = new HashMap<>();
                table.put("djbh", djbh);
                table.put("dj_sort", dj_sort);
                table.put("spid", itemId);
                table.put("sl", pieceQty);
                table.put("js", oddCaseQty);
                table.put("lss", oddPieceQty);
                table.put("ph", manufacturerLotNum);
                table.put("rq_sc", convertStringDate1);
                table.put("yxqz", convertStringDate2);
                table.put("sf_zx", sf_zx);
                table.put("pch", batchId);
                table.put("yspd", yspd);
                table.put("cgdd_sort", cgdd_sort);
                table.put("sl_ywc", sl_ywc);
                table.put("yzid", yzid);
                table.put("dj_sort_sj", dj_sort_sj);
                table.put("bz", bz);
                table.put("djbh", djbh);
                table.put("task_id", task_id);

                data_itemlist.add(table);

            }
            headMap.put("data_itemlist", data_itemlist);
            resultData.put("resultData", headMap);
        }
        if (!ObjectUtils.isNull(resultData)) {
            IntegrationSearchData sd = new IntegrationSearchData();
            sd.setInterfaceId(instockTransforId);
            sd.setData(resultData);
            try {
                integrationApi.searchForJsonStr(sd);
            } catch (IntegrationSearchException e) {
                e.printStackTrace();
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

        } else {
            throw new BizException("发送数据为空");
        }

        return null;
    }

    private String convertRqcResult(String result) {

        return "合格";
    }

    private String convertRcvType(String rcvType) {
        String result = null;
        if (!StringUtils.isBlank(rcvType)) {
            if (BizConstant.PURCHASE_IN.equals(rcvType)) {
                result = "采购入库";
            }
            if (BizConstant.SALE_RETURN_IN.equals(rcvType)) {
                result = "销售退回";
            }
            if (BizConstant.ALLOT_IN.equals(rcvType)) {
                result = "调拨入库";
            }
            if (BizConstant.MOVE_IN.equals(rcvType)) {
                result = "移库入库";
            }
            if (BizConstant.ACCOUNT_REG_IN.equals(rcvType)) {
                result = "调账入库";
            }
            if (BizConstant.OVERSTEP_IN.equals(rcvType)) {
                result = "越库入库";
            }
            if (BizConstant.STRAIGHT_IN.equals(rcvType)) {
                result = "直调入库";
            }
            if (BizConstant.HOSTED_IN.equals(rcvType)) {
                result = "代管入库";
            }
            if (BizConstant.WAIT_CHECK_IN.equals(rcvType)) {
                result = "待检入库";
            }
            if (BizConstant.INSTRUMENT_IN.equals(rcvType)) {
                result = "器械入库";
            }
            if (BizConstant.FREE_IN.equals(rcvType)) {
                result = "赠品入库";
            }
            if (BizConstant.BLANK_ENTITY_IN.equals(rcvType)) {
                result = "空入入库(有实物)";
            }
            if (BizConstant.BLANK_IN.equals(rcvType)) {
                result = "空入入库(无实物)";
            }
            if (BizConstant.BLANK_RETURN_ENTITY_IN.equals(rcvType)) {
                result = "空退入库(有实物)";
            }
            if (BizConstant.BLANK_RETURN_IN.equals(rcvType)) {
                result = "空退入库(无实物)";
            }

            return result;
        }
        return result;
    }

    @Override
    @Transactional
    @TxTransaction
    public Object receiveAgv(Map<String, Object> map) {
        // 接收上架回传任务更新任务
        IntegrationSearchData sd = new IntegrationSearchData();
        sd.setInterfaceId(instockCallId);
        Map<String, Object> data2 = MapUtils.put("type", 0).getMap();
        sd.setData(data2);
        List<Map> mapList = null;
        try {
            mapList = integrationApi.searchForRestMessageMap(sd);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (!ObjectUtils.isNull(mapList)) {
            try {
                String string = JsonUtils.toString(mapList);
                logger.info("agv回传任务数据->" + string);
            } catch (JsonProcessingException e2) {
                e2.printStackTrace();
            }
            //			boolean anyMatch = mapList.stream().anyMatch(p -> StringUtils.isBlank((String) p.get("LOCATOR_ID")));
            //			if (anyMatch) {
            //				throw new BizException("请检查自己的任务明细!货位为空!");
            //			}

            //			Set<String> collect2 = mapList.stream().map(p -> (String) p.get("LOCATOR_ID")).collect(Collectors.toSet());
            Set<String> collect2 = new HashSet<>();
            collect2.add(BizConstant.SBK);
            List<Map> searchForMap = null;
            String enterpriseId = "";
            Set<String> locatorIds = new HashSet<>();
            for (Map map2 : mapList) {
                if (ObjectUtils.isNull(map2)) {
                    logger.info("返回内容为空!");
                    continue;
                }
                String taskId = (String) map2.get("TASK_ID");
                if (StringUtils.isEmpty(taskId)) {
                    logger.info("任务id为空!");
                    continue;
                }
                TaskInstockDetailDTO taskDTO = this.taskInstockDetailMapper.findByPkId(taskId);
                if (ObjectUtils.isNull(taskDTO)) {
                    throw new BizException("任务id->" + taskId + "搜寻任务为空.");
                }
                String whLocatorId = taskDTO.getWhLocatorId();
                if (!StringUtils.isBlank(whLocatorId)) {
                    locatorIds.add(whLocatorId);
                } else {
                    throw new BizException("货位数据为空!");
                }
                if (!ObjectUtils.isNull(taskDTO)) {
                    enterpriseId = taskDTO.getEnterpriseId();
                    break;
                }
            }
            if (ObjectUtils.isNull(locatorIds)) {
                throw new BizException("上架任务,推荐货位id数据为空!");
            }
            try {
                String url = searchApi.getUrl();
                logger.info("远程调用查询服务url->" + url);
                //				Map<String, Object> map2 = MapUtils.put("includeAreaCategoryCodes", collect2).put("isEnable", 1)
                //						.put("enterpriseId", enterpriseId).getMap();

                Map<String, Object> map2 = MapUtils.put("locatorIds", locatorIds).getMap();

                String string = JsonUtils.toString(map2);
                logger.info("远程调用查询服务入参->" + string);
                searchForMap = searchApi.searchForMap("locator_info_list", map2);

            } catch (Exception e) {
                logger.error("调用查询服务失败,");
            }
            if (ObjectUtils.isNull(searchForMap)) {
                logger.error("货位数据查询为空!参数->" + locatorIds.toString());
                throw new BizException("货位数据查询为空!");
            }

            //			Map<String, List<Map>> locatorListMap = searchForMap.stream()
            //					.collect(Collectors.groupingBy(p -> (String) p.get("whLocatorId")));

            // 调用远程服务获取
            List<RcvInstockLinesDTO> rcvInstockLinesList = new ArrayList<>();
            for (Map map2 : mapList) {
                if (ObjectUtils.isNull(map2)) {
                    logger.info("返回内容为空!");
                    continue;
                }
                String taskId = (String) map2.get("TASK_ID");
                if (StringUtils.isEmpty(taskId)) {
                    logger.info("任务id为空!");
                    continue;
                }
                RcvInstockLinesDTO rcvInstockLines = new RcvInstockLinesDTO();
                TaskInstockDetailDTO taskDTO = this.taskInstockDetailMapper.findByPkId(taskId);
                if (taskDTO == null) {
                    logger.info("任务id->" + taskId + "查询对应的数据为空!需要检查.");
                    continue;
                }
                String enterpriseId2 = taskDTO.getEnterpriseId();
                BeanUtils.copyProperties(taskDTO, rcvInstockLines);
                rcvInstockLines.setEnterpriseId(enterpriseId2);

                // 去设备库库别寻找货位,使用searchApi获取
                //				String locatorId = (String) map2.get("LOCATOR_ID"); // agv字段缺
                //				List<Map> locatorList = locatorListMap.get(locatorId);
                //				Map locatorMap = locatorList.get(0);
                String whLocatorId = taskDTO.getWhLocatorId();
                Map locatorMap = searchForMap.stream().filter(x -> x.get("whLocatorId").equals(whLocatorId)).findFirst().orElse(null);

                if (ObjectUtils.isNull(locatorMap)) {
                    logger.error("agv拣货货位数据为空!请检查重试!");
                    continue;
                    //					throw new BizException("agv拣货货位数据为空!请检查重试!");
                }
                String whLocatorCode = (String) locatorMap.get("whLocatorCode");
                String whLocatorName = (String) locatorMap.get("whLocatorName");
                String whAreaCode = (String) map.get("whAreaCode");
                String whAreaCategoryCode = (String) locatorMap.get("whAreaCategoryCode");
                String locatorId = (String) locatorMap.get("whLocatorId");

                rcvInstockLines.setTaskId(taskId);
                rcvInstockLines.setRealWhLocatorId(locatorId);
                rcvInstockLines.setRealWhLocatorCode(whLocatorCode);
                rcvInstockLines.setRealWhLocatorCode(whLocatorName);
                rcvInstockLines.setWhAreaCategoryCode(whAreaCategoryCode);
                rcvInstockLinesList.add(rcvInstockLines);
            }
            if (ObjectUtils.isNull(rcvInstockLinesList)) {
                logger.error("agv上架回传失败,上架明细数为空!");
                return null;
            }
            try {
                // 执行上架保存
                this.batchAdd(rcvInstockLinesList);
                excuteUpdateAgvStatus(rcvInstockLinesList, 1);

            } catch (Exception e) {
                logger.error("1. agv上架回传更新失败,原因->" + e.getMessage());
                logger.error("2. agv上架回传失败,上架明细:" + rcvInstockLinesList.get(0).getRcvHeaderId());
                try {
                    updateAgvStatus(rcvInstockLinesList, 0);
                } catch (Exception e1) {
                    logger.error("3. agv上架回传更新失败,原因->" + e.getMessage());
                    throw new BizException(e.getMessage());
                }
                throw new BizException(e.getMessage());
            }
        } else {
            logger.error("4. agv上架回传更新失败,回传数据为空!");
            throw new BizException("agv上架回传更新失败,回传任务数据为空!");
        }
        return null;
    }

    private void updateAgvStatus(List<RcvInstockLinesDTO> rcvInstockLinesList, Integer status) throws IntegrationSearchException, JsonProcessingException {
        logger.info("更新agv回传的状态-----------------------------------------------");
        // 更新agv任务状态 异步
        //		executor.execute(() -> {
        //			try {
        //				Thread.sleep(callSleepTimes2);
        excuteUpdateAgvStatus(rcvInstockLinesList, status);
        //			} catch (Exception e) {
        //				logger.error("agv上架回传更新失败,原因->" + e.getMessage());
        //				logger.error("agv上架回传失败,上架明细:" + rcvInstockLinesList.get(0).getRcvHeaderId());
        //			}
        //		});

    }

    private void excuteUpdateAgvStatus(List<RcvInstockLinesDTO> rcvInstockLinesList, Integer status) throws IntegrationSearchException, JsonProcessingException {
        Set<String> collect = rcvInstockLinesList.stream().map(RcvInstockLinesDTO::getTaskId).collect(Collectors.toSet());
        IntegrationSearchData sd2 = new IntegrationSearchData();
        if (status == null) {
            status = 1;
        }
        if (!ObjectUtils.isNull(collect)) {
            for (String string : collect) {
                sd2.setInterfaceId(instockCallStatusId);
                List<Map<String, Object>> paraListMap = new ArrayList<>();
                Map<String, Object> map2 = MapUtils.put("task_id", string).put("status", status).getMap();
                paraListMap.add(map2);
                Map<String, Object> params = MapUtils.put("param", paraListMap).getMap();
                sd2.setData(params);
                logger.info("任务id->" + string + "更新上架状态入参->" + JsonUtils.toString(sd2));
                String searchForJsonStr = integrationApi.searchForJsonStr(sd2);
                JsonNode parse = JsonUtils.parse(searchForJsonStr);
                boolean has = parse.has("success");
                if (has) {
                    boolean asBoolean = parse.get("success").asBoolean();
                    if (!asBoolean) {
                        logger.info("任务id->" + string + "更新上架状态入参失败->" + JsonUtils.toString(sd2));
                        throw new BizException("任务id->" + string + "更新上架状态入参失败->" + JsonUtils.toString(sd2));
                    }
                }
            }
        }

    }

    public static String getStringDate() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(currentTime);
        return dateString;
    }

    public static String convertStringDate(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(date);
        return dateString;
    }

    /**
     * 补货上架 逻辑: 生成上架任务->发送agv指令
     */
    @Override
    @Transactional
    @TxTransaction
    public Object replenisInstock(List<RcvInstockLinesDTO> rcvInstockLinesDTOList) {
        long start = System.currentTimeMillis();
        logger.info("补货上架开始时间: " + start + "(ms)");
        UserDTO userDTO = userUtils.getUserDTO();
        Date now = new Date();
        int row = 0;

        // 根据货位找到库别以及其他相关数据 TODO
        List<Map> searchForMap = null;
        Set<RcvInstockLinesDTO> collect = rcvInstockLinesDTOList.stream().filter(p -> !StringUtils.isBlank(p.getRealWhLocatorId())).collect(Collectors.toSet());
        try {
            String url = searchApi.getUrl();
            logger.info("远程调用查询服务url->" + url);
            Map<String, Object> map2 = MapUtils.put("locatorIds", collect).getMap();

            String string = JsonUtils.toString(map2);
            logger.info("远程调用查询服务入参->" + string);
            searchForMap = searchApi.searchForMap("locator_info_list", map2);

        } catch (Exception e) {
            logger.error("调用查询服务失败,");
        }
        if (ObjectUtils.isNull(searchForMap)) {
            logger.error("货位数据查询为空!参数->" + collect.toString());
            throw new BizException("货位数据查询为空!");
        }

        Map<String, List<Map>> locatorMap = searchForMap.stream().collect(Collectors.groupingBy((p -> (String) p.get("whLocatorId"))));
        List<TaskInstockDetail> collect33 = new ArrayList<>();
        for (RcvInstockLinesDTO rcvInstockLinesDTO : rcvInstockLinesDTOList) {
            row++;
            String realWhLocatorId = rcvInstockLinesDTO.getRealWhLocatorId();
            AssertUtils.isNotBlank(realWhLocatorId, "实际的货位id不可为空!");
            TaskInstockDetail detail = new TaskInstockDetail();
            BeanUtils.copyProperties(rcvInstockLinesDTO, detail);
            detail.setWhLocatorId(realWhLocatorId);
            // 质检的结论不可为空
            String stockStatus = rcvInstockLinesDTO.getStockStatus();
            if (StringUtils.isBlank(stockStatus)) {
                stockStatus = "0";
            }
            detail.setResult(stockStatus);
            if (!ObjectUtils.isNull(locatorMap)) {
                List<Map> lmaplist = locatorMap.get(realWhLocatorId);
                if (ObjectUtils.isNotNull(lmaplist)) {
                    Map map = lmaplist.get(0);
                    String whLocatorCode = (String) map.get("whLocatorCode");
                    String whLocatorName = (String) map.get("whLocatorName");
                    String whAreaCode = (String) map.get("whAreaCode");
                    String whAreaCategoryCode = (String) map.get("whAreaCategoryCode");
                    String locatorId = (String) map.get("whLocatorId");
                    detail.setWhLocatorCode(whLocatorCode);
                    detail.setWhAreaCode(whAreaCode);
                    detail.setWhAreaCategoryCode(whAreaCategoryCode);
                    detail.setWhLocatorName(whLocatorName);
                }
            }

            long id = SnowFlakeUtils.getId();
            rcvInstockLinesDTO.setTaskId("REP_" + id);
            rcvInstockLinesDTO.setRcvHeaderId("REP_RCV_" + id);
            rcvInstockLinesDTO.setRcvLineId("REP_RCVL_" + id);
            rcvInstockLinesDTO.setInBoundLineId("REP_" + id);
            rcvInstockLinesDTO.setAsnHeaderId("REP_ASN" + id);
            rcvInstockLinesDTO.setAsnLineId("REP_ASNL" + id);

            this.buildFieldTask(detail, false, userDTO, now);
            String mtlOwnerId = rcvInstockLinesDTO.getMtlOwnerId();
            String warehouseId = rcvInstockLinesDTO.getWarehouseId();
            detail.setWarehouseId(warehouseId);
            detail.setMtlOwnerId(mtlOwnerId);
            detail.setActiveFlag("0"); // 默认允许作业
            String whAreaCategory = rcvInstockLinesDTO.getWhAreaCategoryCode();
            if (!StringUtils.isBlank(whAreaCategory)) {
                detail.setWhAreaCategoryCode(whAreaCategory);
            }
            detail.setAsnHeaderId(rcvInstockLinesDTO.getAsnHeaderId());
            detail.setAsnLineId(rcvInstockLinesDTO.getAsnLineId());
            detail.setSrcHeaderId(rcvInstockLinesDTO.getSrcHeaderId());
            detail.setSrcLineId(rcvInstockLinesDTO.getSrcLineId());

            BigDecimal pieceQty = rcvInstockLinesDTO.getPieceQty();
            BigDecimal conversionRate = rcvInstockLinesDTO.getConversionRate();
            // 计算qty,保证准确性
            if (pieceQty == null)
                pieceQty = BigDecimal.ZERO;
            if (conversionRate == null || BigDecimal.ZERO.compareTo(conversionRate) == 0)
                conversionRate = BigDecimal.ONE;
            BigDecimal divide = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN);
            detail.setQty(divide);

            detail.setDataVersion(0);
            detail.setStatus("1");
            detail.setEisPushStatus("0");
            detail.setInstockLabel(String.valueOf(SnowFlakeUtils.getId()));
            detail.setRefType(4); // 补货上架类型
            BigDecimal oddCaseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN);
            BigDecimal oddPieceQty = pieceQty.subtract(oddCaseQty.multiply(conversionRate));

            this.taskInstockDetailMapper.save(detail);
            collect33.add(detail);
        }

        if (!ObjectUtils.isNull(collect33)) {
            tansfor2AGV(collect33);
            Set<String> collect44 = collect33.stream().map(TaskInstockDetail::getTaskInboundId).collect(Collectors.toSet());
            // 更新任务状态为设备处理状态
            Criteria crt = Criteria.forClass(TaskInstockDetail.class);
            crt.setRestriction(Restrictions.in("taskInboundId", collect44.toArray()));
            this.mapper.updateMapByCriteria(MapUtils.put("status", "2").getMap(), crt);
        }

        long end = System.currentTimeMillis();
        logger.info("补货上架结束时间: " + end + "(ms)");
        long eb = end - start;
        logger.info("耗时: " + eb + "(ms)");
        return true;
    }

    private void tansfor2AGV(List<TaskInstockDetail> collect33) {
        Set<String> collect2 = collect33.stream().map(TaskInstockDetail::getTaskInboundId).collect(Collectors.toSet());
        TaskQueryVO vo = new TaskQueryVO();
        vo.setIncloudIds(new ArrayList<>(collect2));
        List<TaskInstockDetailDTO> findListPad = this.taskInstockDetailMapper.findList(vo);

        Map<String, Object> resultData = new HashMap<>();
        Map<String, Object> headMap = new HashMap<>();
        if (!ObjectUtils.isNull(findListPad)) {
            TaskInstockDetailDTO taskInstockDetailDTO = findListPad.get(0);
            String rcvHeaderId = taskInstockDetailDTO.getRcvHeaderId();

            String rcvUser = taskInstockDetailDTO.getRcvUser();
            String executor2 = taskInstockDetailDTO.getExecutor();
            String rqcUser = taskInstockDetailDTO.getRqcUser();
            String bizUser = taskInstockDetailDTO.getBizUser();
            String mtlOwnerId2 = taskInstockDetailDTO.getMtlOwnerId();
            String asnRemark = taskInstockDetailDTO.getAsnRemark();
            long id = SnowFlakeUtils.getId();
            String shippid = "";
            String customerId = taskInstockDetailDTO.getCustomerId();
            if (StringUtils.isBlank(shippid)) {
                shippid = customerId;
            }
            String vendorId = taskInstockDetailDTO.getVendorId();
            if (StringUtils.isBlank(shippid)) {
                shippid = vendorId;
            }
            String rcvType = taskInstockDetailDTO.getRcvType();
            rcvType = convertRcvType(rcvType);

            headMap.put("djbh", String.valueOf(id));
            headMap.put("rq", getStringDate());
            headMap.put("dwid", shippid);
            headMap.put("ry_cgy", bizUser);
            headMap.put("ry_czy", executor2);
            headMap.put("ry_shouhy", rcvUser);
            headMap.put("ry_zjy", rqcUser);
            headMap.put("shr", rcvUser);
            headMap.put("sf_wc", "0");
            headMap.put("sf_xc", "0");
            headMap.put("sf_zx", "0");
            headMap.put("djbh_sj", rcvHeaderId);
            headMap.put("rktype", "5"); // 补货传5
            //			headMap.put("rktype", rcvType);
            headMap.put("yzid", mtlOwnerId2);
            headMap.put("bz", asnRemark);
            int row = 0;
            List<Map> data_itemlist = new ArrayList<>();
            for (TaskInstockDetailDTO taskInstockDetailDTO2 : findListPad) {
                row++;
                String djbh = String.valueOf(id);
                Integer dj_sort = row;
                String itemId = taskInstockDetailDTO2.getItemId();
                BigDecimal pieceQty = taskInstockDetailDTO2.getPieceQty();
                BigDecimal conversionRate = taskInstockDetailDTO2.getConversionRate();
                // 数据准确性计算
                if (conversionRate == null) {
                    conversionRate = BigDecimal.ONE;
                }
                if (pieceQty == null) {
                    pieceQty = BigDecimal.ZERO;
                }
                BigDecimal oddCaseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
                BigDecimal multiply = oddCaseQty.multiply(conversionRate);
                BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
                BigDecimal qty = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN); // 包装总量
                String manufacturerLotNum = taskInstockDetailDTO2.getManufacturerLotNum();
                Date batchProductionDate = taskInstockDetailDTO2.getBatchProductionDate();
                String convertStringDate1 = convertStringDate(batchProductionDate);
                Date batchExpiredDate = taskInstockDetailDTO2.getBatchExpiredDate();
                String convertStringDate2 = convertStringDate(batchExpiredDate);
                String sf_zx = "0";
                String batchId = taskInstockDetailDTO2.getBatchId();
                String result = taskInstockDetailDTO2.getResult();
                String yspd = convertRqcResult(result);
                String cgdd_sort = taskInstockDetailDTO2.getAsnLineId();
                Integer sl_ywc = 0;
                String yzid = taskInstockDetailDTO2.getMtlOwnerId();
                Integer dj_sort_sj = 1;
                String bz = taskInstockDetailDTO2.getAsnLineRemark();
                String task_id = taskInstockDetailDTO2.getTaskInboundId();
                String containerCode = taskInstockDetailDTO2.getContainerCode();

                Map<String, Object> table = new HashMap<>();
                table.put("djbh", djbh);
                table.put("tptm", containerCode);
                table.put("dj_sort", dj_sort);
                table.put("spid", itemId);
                table.put("sl", pieceQty);
                table.put("js", oddCaseQty);
                table.put("lss", oddPieceQty);
                table.put("ph", manufacturerLotNum);
                table.put("rq_sc", convertStringDate1);
                table.put("yxqz", convertStringDate2);
                table.put("sf_zx", sf_zx);
                table.put("pch", batchId);
                table.put("yspd", yspd);
                table.put("cgdd_sort", cgdd_sort);
                table.put("sl_ywc", sl_ywc);
                table.put("yzid", yzid);
                table.put("dj_sort_sj", dj_sort_sj);
                table.put("bz", bz);
                table.put("djbh", djbh);
                table.put("task_id", task_id);

                data_itemlist.add(table);

            }
            headMap.put("data_itemlist", data_itemlist);
            resultData.put("resultData", headMap);
        }
        if (!ObjectUtils.isNull(resultData)) {
            IntegrationSearchData sd = new IntegrationSearchData();
            sd.setInterfaceId(instockTransforId);
            sd.setData(resultData);
            try {
                integrationApi.searchForJsonStr(sd);
            } catch (IntegrationSearchException e) {
                e.printStackTrace();
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

        } else {
            throw new BizException("发送数据为空");
        }

    }

    private void buildFieldTask(TaskInstockDetail detail, boolean editFlag, UserDTO userDTO, Date now) {
        // 构建系统基础字段
        Date gmtCreate = detail.getGmtCreate();
        Date gmtModified = detail.getGmtModified();
        String creator = detail.getCreator();
        String creatorName = detail.getCreatorName();
        String modifier = detail.getModifier();
        String modifierName = detail.getModifierName();
        String id = userDTO.getId();
        String enterpriseId = userDTO.getEnterpriseId();
        String username = userDTO.getUsername();

        if (null == now)
            now = new Date();
        if (!editFlag) {
            if (ObjectUtils.isNull(creator))
                detail.setCreator(id);
            if (ObjectUtils.isNull(creatorName))
                detail.setCreatorName(username);
            if (ObjectUtils.isNull(gmtCreate))
                detail.setGmtCreate(now);
            detail.setEnterpriseId(enterpriseId);

            if (ObjectUtils.isNull(detail.getIsSpilt()))
                detail.setIsSpilt(0);
            detail.setStatus("1");
            detail.setDataVersion(0);
        }
        if (ObjectUtils.isNull(modifier))
            detail.setModifier(id);
        if (ObjectUtils.isNull(modifierName))
            detail.setModifierName(username);
        if (ObjectUtils.isNull(gmtModified))
            detail.setGmtModified(now);

    }
    //	/**
    //	 * 补货上架 逻辑: 1.无上架任务 2. 货位id,code
    //	 */
    //	@Override
    //	@Transactional
    //	@TxTransaction
    //	public Object replenisInstock(List<RcvInstockLinesDTO> rcvInstockLinesDTOList) {
    //		long start = System.currentTimeMillis();
    //		logger.info("补货上架开始时间: " + start + "(ms)");
    //		List<RcvInstockLines> list = new ArrayList<>();
    //		UserDTO userDTO = userUtils.getUserDTO();
    //		int row = 0;
    //		for (RcvInstockLinesDTO rcvInstockLinesDTO : rcvInstockLinesDTOList) {
    //			row ++;
    //			String realWhLocatorId = rcvInstockLinesDTO.getRealWhLocatorId();
    //			AssertUtils.isNotBlank(realWhLocatorId, "实际的货位id不可为空!");
    //			boolean editFlag = Boolean.FALSE;
    //			Date now = new Date();
    //
    //			BigDecimal pieceQty = rcvInstockLinesDTO.getPieceQty();
    //			BigDecimal conversionRate = rcvInstockLinesDTO.getConversionRate();
    //			if (conversionRate == null) {
    //				conversionRate = BigDecimal.ONE;
    //				rcvInstockLinesDTO.setConversionRate(conversionRate);
    //			}
    //			if (pieceQty == null) {
    //				pieceQty = BigDecimal.ZERO;
    //				rcvInstockLinesDTO.setPieceQty(pieceQty);
    //			}
    //			BigDecimal caseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
    //			BigDecimal multiply = caseQty.multiply(conversionRate);
    //			BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
    //			BigDecimal qty = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN); // 包装总量
    //			// 保证数据正确性再次进行计算
    //			rcvInstockLinesDTO.setOddCaseQty(caseQty);
    //			rcvInstockLinesDTO.setOddPieceQty(oddPieceQty);
    //
    //			RcvInstockLines rcvInstockLines = excuteSavePre2(row, rcvInstockLinesDTO, userDTO, now, list, editFlag);
    //			this.mapper.save(rcvInstockLines);
    //			list.add(rcvInstockLines);
    //		}
    ////		this.mapper.saveBatch(list);
    //		// 执行入库操作
    //		excuteInStock(list);
    //
    //		long end = System.currentTimeMillis();
    //		logger.info("上架结束时间: " + end + "(ms)");
    //		long eb = end - start;
    //		logger.info("耗时: " + eb + "(ms)");
    //		return true;
    //	}

    private RcvInstockLines excuteSavePre2(int row, RcvInstockLinesDTO rcvInstockLinesDTO, UserDTO userDTO, Date now, List<RcvInstockLines> list, boolean editFlag) {
        long id = SnowFlakeUtils.getId();
        rcvInstockLinesDTO.setTaskId("REP_" + id);
        rcvInstockLinesDTO.setRcvHeaderId("REP_RCV_" + id);
        rcvInstockLinesDTO.setRcvLineId("REP_RCVL_" + id);
        rcvInstockLinesDTO.setInBoundLineId("REP_" + id);
        rcvInstockLinesDTO.setAsnHeaderId("REP_ASN" + id);
        rcvInstockLinesDTO.setAsnLineId("REP_ASNL" + id);

        this.vaildateModel(rcvInstockLinesDTO, editFlag, userDTO, row, validator, batchAddMsg);
        RcvInstockLines rcvInstockLines = new RcvInstockLines();
        BeanUtils.copyProperties(rcvInstockLinesDTO, rcvInstockLines);
        this.buildField(rcvInstockLines, editFlag, userDTO, now);

        String inventoryStatus = rcvInstockLines.getInventoryStatus();
        if (StringUtils.isBlank(inventoryStatus)) {
            rcvInstockLines.setInventoryStatus("1"); // 默认合格
        }
        rcvInstockLines.setLineNum(BigDecimal.valueOf(row));
        list.add(rcvInstockLines);
        return rcvInstockLines;
    }

    @Override
    @Transactional
    public List<EisToWmsMiddle> acceptEisToWmsRequestMessage(EisWmsRequestParamVO vo) {
        //查询上架任务池对应的状态为已发送入库任务的数据
        List<TaskInstockDetail> taskLineResultList = MapperCustom.builder(taskInstockDetailMapper, TaskInstockDetail.class)
                .andEq(TaskInstockDetail::getContainerCode, vo.getContainerNo())
                .andEq(TaskInstockDetail::getTaskInboundId, vo.getTaskId()) // 新增按容器和taskid的维度去处理上架任务
                .andEq(TaskInstockDetail::getEisPushStatus, "1")
                .findByCriteria();

        if(ToolKits.isEmpty(taskLineResultList)){
            if(StringUtils.isBlank(vo.getTaskId()) || StringUtils.isBlank(vo.getWmsLocationCode())){
                throw new RuntimeException("容器不存在对应的上架任务池记录");
            }else {
                MoveConfirmParamsVO moveConfirmParamsVO = new MoveConfirmParamsVO();
                moveConfirmParamsVO.setMoveFlag(1);
                moveConfirmParamsVO.setLineId(vo.getTaskId());
                moveConfirmParamsVO.setToWarehouseAreaCode(vo.getWmsLocationCode());
                RestMessage restMessage = operateCaller.autoConfirmReplenish(moveConfirmParamsVO);
                return null;
            }
        }

        //保存上架任务回告中间表
        List<TaskInstockDetail> deviceList = taskLineResultList.stream().filter(t -> "Device".equals(t.getAttribute2())).collect(Collectors.toList());
        List<EisToWmsMiddle> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(deviceList)) {
            for (TaskInstockDetail detail : deviceList) {
                EisToWmsMiddle dto = new EisToWmsMiddle();
                BeanUtils.copyProperties(vo, dto);
                dto.setOwnerId(detail.getMtlOwnerId());
                dto.setSeqNo(detail.getTaskInboundId());
                dto.setItemId(detail.getItemId());
                dto.setLotId(detail.getBatchId());
                dto.setQty(detail.getPieceQty());
                dto.setProcessingStatus("0");
                dto.setWmslocationCode(detail.getWhLocatorCode());
                list.add(dto);
            }
            if (list.size() > 0) {
                eisToWmsMiddleMapper.saveBatch(list);
            }
        }

        //更新上架任务池状态为-2已回告完成
        MapperCustom.builder(taskInstockDetailMapper, TaskInstockDetail.class).addParameter(TaskInstockDetail::getEisPushStatus, "2")
                 .andEq(TaskInstockDetail::getContainerCode, vo.getContainerNo())
                 .andEq(TaskInstockDetail::getEisPushStatus,"1")
                 .updateFieldsByCriteria();
        return list;
    }


    @Override
    @Transactional
    public List<InBoundRequestVO> receiveInStockWms(String containerNo) {
        List<TaskInstockDetail> taskList = new ArrayList<>();
        if(StringUtils.isEmpty(containerNo)){
            taskList = taskInstockDetailMapper.findEisTask();
        }else{
            taskList = MapperCustom.builder(taskInstockDetailMapper, TaskInstockDetail.class).andEq(TaskInstockDetail::getStatus, "1").andEq(TaskInstockDetail::getContainerCode, containerNo).findByCriteria();
        }
        if(taskList.size()==0){
            throw new RuntimeException("容器不存在上架任务");
        }
        Set<String> itemSet = taskList.stream().map(TaskInstockDetail::getItemId).collect(Collectors.toSet());
        RestMessage<List<BaseMtlItemMst>> itemResult = baseItemRemoteCaller.getListByIds(itemSet);
        Assert.isFalse(itemResult == null, "商品信息不存在,请检查");
        if (!itemResult.isSuccess()) {
            throw BizException.newInstance("商品信息" + itemResult.getMessage());
        }
        List<BaseMtlItemMst> itemDetailList = itemResult.getData();
        List<InBoundRequestVO> resultList = new ArrayList<>();
        List<WmsToEisTaskRecord> recordList = new ArrayList<>();
        if(taskList.size()>0){
            Map<String, List<TaskInstockDetail>> collect = taskList.stream().filter(x->!StringUtils.isEmpty(x.getContainerCode())).collect(Collectors.groupingBy(TaskInstockDetail::getContainerCode));
            Set<Entry<String, List<TaskInstockDetail>>> entrySet = collect.entrySet();
            for (Entry<String, List<TaskInstockDetail>> entry : entrySet) {
                InBoundRequestVO result = new InBoundRequestVO();
                List<InBoundRequestItemVO> detailList = new ArrayList<>();
                containerNo = entry.getKey();
                List<TaskInstockDetail> list = entry.getValue();
                TaskInstockDetail detail = list.get(0);
                String msgId = String.valueOf(SnowFlakeUtils.getId());
                result.setMsgId(msgId);
                result.setTaskId(msgId);
                result.setContainerNo(containerNo);
                result.setWarehouseId(detail.getWarehouseId());
                result.setEnterpriseId(detail.getEnterpriseId());
                if(StringUtils.isEmpty(detail.getWhAreaCategoryCode())){
                    throw new BizException("库别信息为空");
                }
                if(!StringUtils.isEmpty(detail.getWhAreaCode())){
                    result.setOriginalArea(detail.getWhAreaCode());
                }else{
                    if(StringUtils.isEmpty(detail.getWhAreaCategoryCode())){
                        throw new BizException("库别信息为空");
                    }
                    if(detail.getWhAreaCategoryCode().equals("MJK")){
                        result.setOriginalArea("SX01-R01");
                    }
                    if(detail.getWhAreaCategoryCode().equals("AGVZ")){
                        result.setOriginalArea("AGVTP01-R01");
                    }
                    if(detail.getWhAreaCategoryCode().equals("AGVL")){
                        result.setOriginalArea("AGVHJ01-R01");
                    }
                }
                result.setOriginalLocation("");
                result.setTargetArea("");
                result.setTargetLocation("");
                RcvHeaders rcvHeaders = rcvHeadersMapper.findById(detail.getRcvHeaderId(), RcvHeaders.class);
                if(!StringUtils.isEmpty(detail.getWhLocatorCode())){
                    result.setWmsLocationCode(detail.getWhLocatorCode());
                }else{
                    if(StringUtils.isEmpty(detail.getWhAreaCategoryCode())){
                        throw new BizException("库别信息为空");
                    }
                    if(detail.getWhAreaCategoryCode().equals("MJK")){
                        result.setWmsLocationCode("MJZ");
                    }
                    if(detail.getWhAreaCategoryCode().equals("AGVZ")){
                        result.setWmsLocationCode("AGVZ");//todo AGVZ AGVSP  AGVQX 一个托盘多个商品如何根据商品大类来判断
                    }
                    if(detail.getWhAreaCategoryCode().equals("AGVL")){
                        result.setWmsLocationCode("AGVL");
                    }
                }
                result.setWorkType("10");
                if(rcvHeaders.getRcvType().equals("1")){//1采购订单，2销售退回单，6直通入库单
                    result.setBusinessType("PO_NORM");
                }else {
                    result.setBusinessType("PO_SORETURN");
                }
                for (TaskInstockDetail i : list) {
                    WmsToEisTaskRecord byId = wmsToEisTaskRecordMapper.findById(i.getTaskInboundId(), WmsToEisTaskRecord.class);
                    if(byId!=null){
                        if(byId.getStatus().equals("1")){
                            continue;
                        }
                        byId.setCount(byId.getCount()+1);
                        //修改标识
                        byId.setType("1");
                        recordList.add(byId);
                    }else{
                        WmsToEisTaskRecord wmsToEisTaskRecord = new WmsToEisTaskRecord();
                        wmsToEisTaskRecord.setTaskId(i.getTaskInboundId());
                        wmsToEisTaskRecord.setStatus("0");
                        wmsToEisTaskRecord.setCount(1);
                        wmsToEisTaskRecord.setContainerCode(containerNo);
                        wmsToEisTaskRecord.setItemId(i.getItemId());
                        wmsToEisTaskRecord.setQty(i.getPieceQty());
                        wmsToEisTaskRecord.setWhAreaCategoryCode(detail.getWhAreaCategoryCode());
                        wmsToEisTaskRecord.setWhAreaCode(StringUtils.isEmpty(detail.getWhAreaCode())?result.getOriginalArea():detail.getWhAreaCode());
                        wmsToEisTaskRecord.setLocationCode(StringUtils.isEmpty(detail.getWhLocatorCode())?result.getWmsLocationCode():detail.getWhLocatorCode());
                        //新增标识
                        wmsToEisTaskRecord.setType("0");
                        //任务类型为 0-入库任务推送
                        wmsToEisTaskRecord.setTaskType(0);
                        recordList.add(wmsToEisTaskRecord);
                    }

                }
                //根据物料id和批次分组，同物料和同批次的合并成一条明细推送
                Map<String, List<TaskInstockDetail>> groupedByItemAndBatch  = list.stream().filter(x-> ToolKits.isNotEmpty(x.getItemId()) && ToolKits.isNotEmpty(x.getBatchId())).collect(Collectors.groupingBy(x -> x.getItemId() + "_" + x.getBatchId() ));
                for (Entry<String, List<TaskInstockDetail>> listEntry : groupedByItemAndBatch.entrySet()) {
                    List<TaskInstockDetail> taskInstockDetails = listEntry.getValue();
                    if(ToolKits.isNotEmpty(taskInstockDetails)){
                        TaskInstockDetail taskInstockDetail = taskInstockDetails.get(0);
                        Double sumQty = taskInstockDetails.stream().mapToDouble(e -> e.getQty().doubleValue()).sum();
                        InBoundRequestItemVO sub = new InBoundRequestItemVO();
                        sub.setOwnerId(taskInstockDetail.getMtlOwnerId());
                        sub.setItemId(taskInstockDetail.getItemId());
                        sub.setLotId(taskInstockDetail.getBatchId());
                        BaseMtlItemMst itemMst = itemDetailList.stream().filter(x -> x.getItemId().equals(taskInstockDetail.getItemId())).findFirst().orElse(null);
                        sub.setPackId("");
                        if(itemMst!=null){
                            sub.setPackId(itemMst.getBaseMtlItemUomConversionsList().size()>0?itemMst.getBaseMtlItemUomConversionsList().get(0).getItemUomId():"");
                        }
                        sub.setQty(sumQty.toString());
                        detailList.add(sub);
                    }
                }

                if(list.size()>0){
                    Set<String> locSet = list.stream().map(TaskInstockDetail::getWhAreaCategoryCode).collect(Collectors.toSet());
                    if (locSet.size() > 1) {
                        throw new RuntimeException("容器上存在多货位任务，请整理！");
                    }
                    Set<String> itemIdSet = detailList.stream().map(InBoundRequestItemVO::getItemId).collect(Collectors.toSet());
                    if (itemIdSet.size() > 4) {
                        throw new RuntimeException("容器上存在混批或混品超过4种！");
                    }
                }
                result.setSubList(detailList);
                resultList.add(result);
            }
            if(resultList.size()>0){
                resultList = resultList.stream().filter(x -> x.getSubList().size() > 0).collect(Collectors.toList());
            }
            if (resultList.size() < 1) {
                throw new RuntimeException("暂不存在上架任务");
            }
        }
        if(recordList.size()>0){
            List<WmsToEisTaskRecord> collect = recordList.stream().filter(x -> x.getType().equals("0")).collect(Collectors.toList());
            if(collect.size()>0){
                wmsToEisTaskRecordMapper.saveBatch(collect);
            }
        }

        //调用推送任务接口
//        eisHandler.inBoundRequest(resultList);//推送后把上架任务池eisPushStatus状态改成1 已推送eis
        return resultList;

//        for (EisInStockWmsResponseDTO eisInStockWmsResponseDTO:resultList) {
//            AskIntegrationVo askIntegrationVo = new AskIntegrationVo("inboundTaskUrl",eisInStockWmsResponseDTO);
//            RestMessage<?> msg = baseInventoryRemoteCaller.askIntegration(askIntegrationVo);
//            String container = eisInStockWmsResponseDTO.getContainerNo();
//
//            Criteria crtTaskRecord = Criteria.forClass(WmsToEisTaskRecord.class);
//            Restriction r1 = Restrictions.eq("containerCode", container);
//            Restriction r2 =Restrictions.eq("status", "0");
//            Restriction r3 =Restrictions.eq("taskType", 0);
//            crtTaskRecord.setRestriction(Restrictions.and(r1,r2,r3));
//
//            Criteria crtInstockDetail = Criteria.forClass(TaskInstockDetail.class);
//            Restriction r4 = Restrictions.eq("containerCode", container);
//            Restriction r5 =Restrictions.eq("eisPushStatus", "0");
//            crtInstockDetail.setRestriction(Restrictions.and(r4,r5));
//            if(msg.isSuccess()){
//                logger.info("请求成功");
//                //更新入库任务推送记录表为已推送成功的数据
//                Map<String, Object> map = new HashMap<>();
//                map.put("status","1");
//                map.put("message",JSON.toJSONString(msg.getMessage()));
//                wmsToEisTaskRecordMapper.updateMapByCriteria(map,crtTaskRecord);
//
//                //更新上架任务池状态为已成功推送的数据
//                Map<String, Object> map2 = new HashMap<>();
//                map2.put("eisPushStatus","1");
//                taskInstockDetailMapper.updateMapByCriteria(map2,crtInstockDetail);
//
//            }else{
//                Map<String, Object> map = new HashMap<>();
//                map.put("message",JSON.toJSONString(msg.getMessage()));
//                wmsToEisTaskRecordMapper.updateMapByCriteria(map,crtTaskRecord);
//            }
//        }
//
//        return resultList;
    }

    @Override
    @Transactional
    @TxTransaction
    public void autoEisWmsMessageToUpTask() {
        if(AUTOFLAG){
            throw new BizException("当前有任务正在执行，请稍后再试！");
        }
        AUTOFLAG = true;
        List<String> msgIdList = new ArrayList<>();
        String message = "";
        try {
            // step: 根据中间表数据匹配对应的上架任务
            Set<TaskInstockDetail> taskLineList = new HashSet<>();
            //托盘转运任务ID集合
            //List<String> taskIds = new ArrayList<>();
            //上架单集合
            List<RcvInstockLines> instockLines = new ArrayList<>();

            //释放容器的集合（仓库分组）
            List<ContainerQueryVO> containerQueryVOList = new ArrayList<>();

            List<EisToWmsMiddle> list = eisToWmsMiddleMapper.findNofinshList();
            //获取上架任务池ID
            List<String> seqNos = list.stream().filter(x->!x.getBusinessType().equals("50")).map(EisToWmsMiddle::getSeqNo).collect(Collectors.toList());
            //获取货位编码
            List<String> locationCodes = list.stream().map(x -> x.getWmslocationCode()).collect(Collectors.toList());
            if(seqNos.size()>0){
                List<TaskInstockDetail> taskLineResultList1 = MapperCustom.builder(taskInstockDetailMapper,TaskInstockDetail.class)
                        .andIn(TaskInstockDetail::getTaskInboundId,seqNos).findByCriteria();
                // 实际货位id为空,远程调用仓库服务获取货位
                Map<String, List<TaskInstockDetail>> collect = taskLineResultList1.stream().collect(Collectors.groupingBy(TaskInstockDetail::getWarehouseId));
                for (List<TaskInstockDetail> taskLineResultList : collect.values()) {
                    Integer row = 0;
                    for (TaskInstockDetail taskInstockDetail : taskLineResultList) {
                        row++;
                        EisToWmsMiddle eisToWmsMiddle = list.stream().filter(x -> x.getSeqNo().equals(taskInstockDetail.getTaskInboundId())).findFirst().orElse(null);
                        RcvInstockLines rcvInstockLines = new RcvInstockLines();
                        BeanUtils.copyProperties(taskInstockDetail, rcvInstockLines);
                        rcvInstockLines.setTaskId(taskInstockDetail.getTaskInboundId());
                        rcvInstockLines.setExecutorUser(taskInstockDetail.getCreatorName());
                        RcvHeaders byId = rcvHeadersMapper.findById(taskInstockDetail.getRcvHeaderId(), RcvHeaders.class);
                        RcvLines rcvLines = rcvLineMapper.findById(taskInstockDetail.getRcvLineId(), RcvLines.class);
                        rcvInstockLines.setBatchProductionDate(rcvLines.getBatchProductionDate());
                        rcvInstockLines.setBatchExpiredDate(rcvLines.getBatchExpiredDate());
                        rcvInstockLines.setOddCaseQty(taskInstockDetail.getQty());
                        rcvInstockLines.setOddPieceQty(BigDecimal.ZERO);
                        rcvInstockLines.setPieceQty(taskInstockDetail.getPieceQty());
                        rcvInstockLines.setGmtCreate(new Date());
                        rcvInstockLines.setGmtModified(new Date());
                        String rcvType = byId.getRcvType();

                        if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.WAIT_CHECK_IN)) {
                            // 待检
                            rcvInstockLines.setInventoryStatus("3");
                            rcvInstockLines.setSubStatus("1");
                        }
                        // 代管转待检
                        String inventoryOpType = rcvInstockLines.getInventoryOpType();
                        if (!StringUtils.isBlank(inventoryOpType) && "1".equals(inventoryOpType)) {
                            rcvInstockLines.setInventoryStatus("1");
                            rcvInstockLines.setSubStatus("6");
                        }
                        // 代管转正常
                        if (!StringUtils.isBlank(inventoryOpType) && "0".equals(inventoryOpType)) {
                            rcvInstockLines.setInventoryStatus("1");
                            rcvInstockLines.setSubStatus("5");
                        }
                        String inventoryStatus = rcvInstockLines.getInventoryStatus();
                        if (StringUtils.isBlank(inventoryStatus)) {
                            rcvInstockLines.setInventoryStatus("1"); // 默认合格
                        }
                        rcvInstockLines.setLineNum(BigDecimal.valueOf(row));
                        // 判断此taskId是否已经操作过
                        instockLines.add(rcvInstockLines);
                    }
                    taskLineList.addAll(taskLineResultList);
                    //容器释放,只释放非设备库的容器
                    List<String> containerCodeList = taskLineResultList.stream().filter(p -> !StringUtils.isBlank(p.getWhAreaCategoryCode())
                            &&!ArrayUtil.contains(EIS_DEVICE_AREA_CODES, p.getWhAreaCategoryCode())&&!StringUtils.isBlank(p.getContainerCode()) && !Objects.equals(p.getContainerCode(), "N/A")).map(TaskInstockDetail::getContainerCode).collect(Collectors.toList());
                    if(containerCodeList.size()>0){
                        ContainerQueryVO cVO = new ContainerQueryVO();
                        cVO.setWarehouseId(taskLineResultList.get(0).getWarehouseId());
                        cVO.setEnterpriseId(taskLineResultList.get(0).getEnterpriseId());
                        cVO.setContainerCodeList(containerCodeList);
                        containerQueryVOList.add(cVO);
                    }
                }
            }
            msgIdList = taskLineList.stream().map(TaskInstockDetail::getTaskInboundId).distinct().collect(Collectors.toList());
            if (taskLineList.size() > 0) {
                // step3: 增加实际库存
                this.addRealInstock(taskLineList);
                // step4 :更新上架任务池 状态为 0已生成上架单
                MapperCustom.builder(taskInstockDetailMapper, TaskInstockDetail.class).addParameter(TaskInstockDetail::getStatus, "0")
                        .andIn(TaskInstockDetail::getTaskInboundId, msgIdList).updateFieldsByCriteria();

                if(instockLines.size()>0){
                    this.mapper.saveBatch(instockLines);
                }
                //容器释放
                try {
                    if(containerQueryVOList.size()>0){
                        containerQueryVOList.stream().forEach(cVO->{
                            baseWmsWarehouseCaller.release(cVO);
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //TODO step5:入库订单回传WMS-OMS
                Map<String, List<TaskInstockDetail>> collect1 = taskLineList.stream().collect(Collectors.groupingBy(TaskInstockDetail::getRcvHeaderId));
                Set<Entry<String, List<TaskInstockDetail>>> entries = collect1.entrySet();
                for (Entry<String, List<TaskInstockDetail>> entry : entries) {
                    String headerId = entry.getKey();
                    if (vaildateRcvComplete(headerId)) {
                        // 执行数据保存 IncomingRecordH 回传erp中间表
//                        excuteSaveCallBackData(instockLines, "2");
                        excuteSaveCallBackDataV2(headerId);
                        //收货拒收记录回传OMS -- //青牛版本没有oms系统,注释掉 不生成receiving_record_back_h表记录
//                        excuteRcvAndRejectBackOms(headerId,null);
                        //验收记录回传OMS --//青牛版本没有oms系统,注释掉
//                        excuteRqcBackOms(headerId,null);
                        //上架完成回传erp --//青牛版本没有oms系统,改成使用定时任务回传erp
//                        excuteCallBackOms(headerId);
                    } else {
                        logger.info("整个收货单上架保存回传数据失败,数量不达标----------------------");
                    }
                }
                MapperCustom.builder(eisToWmsMiddleMapper, EisToWmsMiddle.class).addParameter(EisToWmsMiddle::getProcessingStatus, "100")
                        .andIn(EisToWmsMiddle::getSeqNo, msgIdList).updateFieldsByCriteria();
            }
        } catch (Exception e) {
            logger.error("autoEisWmsMessageToUpTask===>{}",e.getMessage());
            if(msgIdList.size()>0){
                eisToWmsMiddleMapper.updateProcessingStatus(msgIdList);
            }
            throw e;
        }finally {
            AUTOFLAG = false;
        }

    }

    @Override
    public void autoOmsIncomingBackTask() {

        List<IncomingRecordH> records = MapperCustom.builder(incomingRecordHMapper, IncomingRecordH.class)
                .addParameter(IncomingRecordH::getBillid).addParameter(IncomingRecordH::getAttrNum1)
                .andEq(IncomingRecordH::getAttrStr1, "N")
                .findFieldsByCriteria();
        if (CollUtil.isEmpty(records)) {
            logger.info("暂无入库回告ERP数据");
            return;
        }

        List<BaseCommonDict> dicts = RestMsgUtils.retrieveResult(commonCaller.getDictBasicListByCodes("callback_erp_retry_time", null));
        Assert.notEmpty(dicts, "请配置通用参数【callback_erp_retry_time】");

        double limit = NumberUtil.parseDouble(dicts.get(0).getDictName());
        List<IncomingRecordH> list = records.stream().filter(i -> limit > getCount(i.getAttrNum1())).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(list)) {
            return;
        }
        list.forEach(i -> excuteInboundCallBackErp(i.getBillid()));
    }

    private double getCount(BigDecimal count) {
        return count == null ? 0 : count.doubleValue();
    }

    private void addRealInstock(Set<TaskInstockDetail> list) {
        String warehouseId = list.stream().findFirst().orElseThrow(()-> new BizException("增加实际库存参数为空")).getWarehouseId();
        ValidList<InvStockIn> invStock = new ValidList<InvStockIn>();
        for (TaskInstockDetail rcvInstockLines : list) {
            Map<String, Object> extParams = new HashMap<>();
            String hostLocatorId = rcvInstockLines.getHostLocatorId();
            String batchId = rcvInstockLines.getBatchId();
            InvStockIn invStockIn = new InvStockIn();
            InvStockInDetail detail = new InvStockInDetail();
            List<InvStockInDetail> details = new ArrayList<InvStockInDetail>();
            detail.setExtParams(extParams);

            BigDecimal pieceQty = rcvInstockLines.getPieceQty();
            String realWhLocatorId = rcvInstockLines.getWhLocatorId();
            String comments = rcvInstockLines.getComments();
            String goodsCaseCode = rcvInstockLines.getGoodsCaseCode();
            String containerCode = rcvInstockLines.getContainerCode();
            detail.setQuantity(pieceQty);
            detail.setContainerCode(containerCode);
            if(rcvInstockLines.getWhAreaCategoryCode().equals("AGVL")){
                detail.setContainerCode("N/A");
            }
            detail.setGoodsCaseCode(goodsCaseCode);
            detail.setLocatorId(realWhLocatorId);
            detail.setComments(comments);
            detail.setStatus(rcvInstockLines.getInventoryStatus());
            detail.setInType("1");
            detail.setBatchId(batchId);

            // 需要加入二级库存状态
            String secondStatus = rcvInstockLines.getSecondStatus();
            if (!StringUtils.isBlank(secondStatus)) {
                detail.setStatus(secondStatus);
            }

            details.add(detail);

            String enterpriseId = rcvInstockLines.getEnterpriseId();

            // =====生产批次id/批次num所用
            String taskId = rcvInstockLines.getTaskInboundId();
            String rcvHeaderId = rcvInstockLines.getRcvHeaderId();
            String asnHeaderId = rcvInstockLines.getAsnHeaderId();
            String rcvLineId = rcvInstockLines.getRcvLineId();
            String asnLineId = rcvInstockLines.getAsnLineId();

            invStockIn.setDetails(details);

            invStockIn.setEnterpriseId(enterpriseId);
            invStockIn.setAsnLineId(asnLineId);
            invStockIn.setAsnId(asnHeaderId);
            invStockIn.setRcvId(rcvHeaderId);
            invStockIn.setTaskId(taskId);
            invStockIn.setWarehouseId(warehouseId);
            invStockIn.setRcvLineId(rcvLineId);

            invStock.add(invStockIn);
        }

        // 远程调用直接入库存的服务
        RestMessage inStockBatchCheck = null;
        try {

            inStockBatchCheck = baseInventoryRemoteCaller.inStockBatchCheck(invStock);
            logger.info("调用库存接口inStockBatchCheck，入参：" + JsonUtils.toString(invStock) + "，返回：" + JsonUtils.toString(inStockBatchCheck));
        } catch (Exception e) {
            logger.error("上架调用远程库存服务失败!原因->{}", e);
            throw new BizException("上架调用远程库存服务失败!");
        }
        if (inStockBatchCheck == null) {
            logger.error("上架调用远程库存服务失败!");
            throw new BizException("上架调用远程库存服务失败!");
        }
        if (!inStockBatchCheck.isSuccess()) {
            Object data = inStockBatchCheck.getData();
            String dataMsg = "";
            if (data != null) {
                dataMsg = data.toString();
            }
            throw new BizException(String.format("上架调用远程库存服务失败!原因->%s", inStockBatchCheck.getMessage()) + dataMsg);
        }
    }

    public void erpCallBack(Set<TaskInstockDetail> taskList) {
        Set<String> rcvHeadSet = taskList.stream().map(TaskInstockDetail::getRcvHeaderId).collect(Collectors.toSet());
        for (String rcvHeaderId : rcvHeadSet) {
            // 校验是否收货全部完成
            if (vaildateRcvComplete(rcvHeaderId)) {
                EtlMessage em = new EtlMessage();
                em.setId(rcvHeaderId);
                em.setEtlType(EtlTypeConstants.in_asn_w2o);
                try {
                    logger.info("上架回传给data-exchange数据:{}", JsonUtils.toString(em));
                    exchangeSender.send(em);
                    logger.info("上架回传给data-exchange成功!");
                    // 更新入库单状态为已上传
                    excuteUpdateRcvH(rcvHeaderId);
                } catch (Exception e) {
                    logger.error("上架回传失败,原因->{}", e);
                    throw new RuntimeException("上架回传失败,原因->{}" + e);
                }
            }
        }
    }
    /*       添加eis-wms的任务获取的任务回告功能-----------on 2022-07-29 by 陈浩 ---结束-----                               */

    @Resource
    private TaskQcDetailMapper taskQcDetailMapper;

    @Override
    public Page<RcvInstockLinesDTO> findListNew(RcvInstockLinesQueryVO queryVO, PageParam pageParam) {
        this.startPage(pageParam);
        queryVO.setEnterpriseId(userUtils.getEnterpriseId());
        String warehouseId = queryVO.getWarehouseId();
        AssertUtils.isNotBlank(warehouseId, "仓id不可为空!");
        List<RcvInstockLinesDTO> list = this.mapper.findListNew(queryVO);
        if (list != null && list.size() > 0) {
            for (RcvInstockLinesDTO dto : list) {
                BigDecimal conversionRate = dto.getConversionRate();
                if (conversionRate == null) {
                    conversionRate = BigDecimal.ONE;
                }
                BigDecimal oddCaseQty = dto.getPieceQty().divide(conversionRate, 0, RoundingMode.DOWN);
                BigDecimal oddPieceQty = dto.getPieceQty().subtract(oddCaseQty.multiply(conversionRate));
                dto.setOddCaseQty(oddCaseQty);
                dto.setOddPieceQty(oddPieceQty);
                dto.setConversionRate(conversionRate);
                List<String> distCodes = Lists.newArrayList();
                distCodes.add("oms_asn_bill_type");
                List<Map<String, String>> distInfos = taskQcDetailMapper.queryDictInfo(distCodes);
                if (distInfos != null && distInfos.size() > 0) {
                    List<Map<String, String>> billTypeList = distInfos.stream().filter(dist -> Objects.equals(dist.get("type_code"), "oms_asn_bill_type")).collect(Collectors.toList());
                    for (Map<String, String> map : billTypeList) {
                        if (Objects.equals(map.get("dict_code"), dto.getRcvType())) {
                            dto.setRcvTypeName(map.get("dict_name"));
                            break;
                        }
                    }
                }
                List<Map<String, String>> warehouseInfos = this.mapper.queryRoomInfo(warehouseId);
                if (warehouseInfos != null && warehouseInfos.size() > 0) {
                    for (Map<String, String> map : warehouseInfos) {
                        if (Objects.equals(map.get("warehouse_room_code"), dto.getWhAreaCategoryCode())) {
                            dto.setWhAreaCategoryName(map.get("warehouse_room_name"));
                            break;
                        }
                    }
                }
                List<Map<String, String>> areaInfos = this.mapper.queryAreaInfo(warehouseId);
                if (areaInfos != null && areaInfos.size() > 0) {
                    for (Map<String, String> map : areaInfos) {
                        if (Objects.equals(map.get("warehouse_area_code"), dto.getWhAreaCode())) {
                            dto.setWhAreaName(map.get("warehouse_area_name"));
                            break;
                        }
                    }
                }
            }
        }
        return PageUtils.getPage(list);

    }

    @Override
    public List<Map<String, String>> queryRoomInfo(String warehouseId) {
        return this.mapper.queryRoomInfo(warehouseId);
    }

    @Override
    public List<Map<String, String>> queryAreaInfo(String warehouseId) {
        return this.mapper.queryAreaInfo(warehouseId);
    }

    @Override
    public Page<TaskInstockDetailDTO> getMyTask(TaskQueryVO queryVO, PageParam pageParam) {
        UserDTO user = userUtils.getUserDTO();
        queryVO.setUserId(user.getId());
        queryVO.setEnterpriseId(user.getEnterpriseId());
        int pageNum = pageParam.getPageNum() == null ? PageParam.DEFAULT_PAGE_NUM : pageParam.getPageNum();
        int pageSize = pageParam.getPageSize() == null ? PageParam.DEFAULT_PAGE_SIZE : pageParam.getPageSize();
        PageHelper.startPage(pageNum, pageSize, true, false, false);
        List<TaskInstockDetailDTO> list = taskInstockDetailMapper.getMyTask(queryVO);

        if (CollUtil.isNotEmpty(list)) {
            fillFields4GetMyTask(list);
        }

        return PageUtils.getPage(list);
    }

    private void fillFields4GetMyTask(List<TaskInstockDetailDTO> list) {
        Set<String> ownerIds = list.stream().map(TaskInstockDetailDTO::getMtlOwnerId).collect(Collectors.toSet());
        String[] itemIds = list.stream().map(TaskInstockDetailDTO::getItemId).toArray(String[]::new);
        String[] batchIds = list.stream().map(TaskInstockDetailDTO::getBatchId).distinct().toArray(String[]::new);
        Set<String> vendorIds = list.stream().map(TaskInstockDetailDTO::getVendorId).collect(Collectors.toSet());


        List<ItemBaseInfoVO> items = RestMsgUtils.retrieveResult(baseItemRemoteCaller.getItemBaseList(itemIds));
        Map<String, BaseCargoOwnerMst> owners = RestMsgUtils.retrieveResult(chainRemoteCaller.getByIds(ownerIds));
        List<BatchNumberListVO> batchs = RestMsgUtils.retrieveResult(baseInventoryRemoteCaller.getBatchNumberBasicInfo(batchIds));
        Map<String, Map<String, Object>> suppliers = (Map<String, Map<String, Object>>) RestMsgUtils.retrieveResult(chainRemoteCaller.getSupplierMstByIds(vendorIds));

        for (TaskInstockDetailDTO dto : list) {
            if (CollUtil.isNotEmpty(owners)) {
                Optional.ofNullable(owners.get(dto.getMtlOwnerId())).ifPresent(t -> dto.setMtlOwnerName(t.getCargoOwnerName()));
            }
            if (CollUtil.isNotEmpty(suppliers)) {
                Optional.ofNullable(suppliers.get(dto.getVendorId())).ifPresent(t -> dto.setShipperName(String.valueOf(t.get("supplierName"))));
            }
            if (CollUtil.isNotEmpty(items)) {
                items.stream().filter(i -> i.getItemId().equals(dto.getItemId())).findFirst().ifPresent(t -> {
                    dto.setItemCode(t.getItemCode());
                    dto.setItemName(t.getItemName());
                    dto.setSpecification(t.getSpecification());
                    dto.setManufacturerName(t.getManufacturerName());
                });
            }
            if (CollUtil.isNotEmpty(batchs)) {
                batchs.stream().filter(b -> b.getBatchId().equals(dto.getBatchId())).findFirst().ifPresent(t -> {
                    dto.setProductionPlace(t.getProductionPlace());
                    dto.setShowProductionDate(t.getBatchProductionDateShow());
                    dto.setShowExpiredDate(t.getBatchExpiredDateShow());
                    dto.setManufacturerLotNum(t.getManufacturerLotNum());
                });
            }
            BigDecimal conversionRate = dto.getConversionRate();
            BigDecimal pieceQty = dto.getPieceQty();
            if (conversionRate != null && (!conversionRate.equals(BigDecimal.ZERO))) {
                BigDecimal[] bigDecimals = pieceQty.divideAndRemainder(conversionRate);
                dto.setCaseQty(bigDecimals[0]);
                dto.setOddPieceQty(bigDecimals[1]);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<TaskInstockDetailDTO> claimPutawayTask(InstockTaskQueryVO vo) {
        Assert.notNull(vo, "参数不能为空");
        Assert.notNull(vo.getCondition(), "容器号不能为空");

        UserDTO user = userUtils.getUserDTO();
        vo.setUserId(user.getId());
        vo.setStatus("1");
        List<TaskInstockDetailDTO> list = this.taskInstockDetailMapper.findListPad(vo);
        Assert.notEmpty(list, "暂无上架任务");

        String[] ids = list.stream().map(TaskInstockDetailDTO::getTaskInboundId).distinct().toArray(String[]::new);
        List<TaskInstockDetail> dtls = taskInstockDetailMapper.findByIds(TaskInstockDetail.class, ids, null);
        Assert.notEmpty(dtls, "上架任务不存在");

        fillFields4GetMyTask(list);

        List<TaskInstockDetail> unClaimTask = dtls.stream().filter(t -> StrUtil.isBlank(t.getAssignUid())).collect(Collectors.toList());
        unClaimTask.forEach(t -> {
            t.setAssignUid(user.getId());
            t.setGmtModified(DateUtil.date());
            t.setModifierName(user.getNickname());
            taskInstockDetailMapper.update(t);
        });

        return list;
    }

    @Override
    public Object bindPalletNo(TaskInstockDetailDTO taskInstockDetailDTO) {
        taskInstockDetailMapper.updateMapById(taskInstockDetailDTO.getTaskInboundId(),MapUtils.put("segment1",taskInstockDetailDTO.getPalletNo()).getMap(),TaskInstockDetail.class);
        return null;
    }

    @Override
    public List<ContainerTailgatingRequestVO> containerTailgating() {
        List<TaskInstockDetail> taskList = taskInstockDetailMapper.findEisTaskPK();
        if(taskList.size()==0){
            throw new RuntimeException("容器不存在整件库,中药库,物料库,不合格库的上架任务");
        }
        List<ContainerTailgatingRequestVO> resultList = new ArrayList<>();
        List<WmsToEisTaskRecord> recordList = new ArrayList<>();
        if(taskList.size()>0){
            Map<String, List<TaskInstockDetail>> collect = taskList.stream().filter(x->!StringUtils.isEmpty(x.getContainerCode())).collect(Collectors.groupingBy(TaskInstockDetail::getContainerCode));
            for (Entry<String, List<TaskInstockDetail>> entry : collect.entrySet()) {
                ContainerTailgatingRequestVO result = new ContainerTailgatingRequestVO();
                String containerNo = entry.getKey();
                List<TaskInstockDetail> list = entry.getValue();
                TaskInstockDetail detail = list.get(0);
                if(StringUtils.isEmpty(detail.getWhAreaCategoryCode())){
                    throw new BizException("库别信息为空");
                }
                String msgId = String.valueOf(SnowFlakeUtils.getId());
                result.setMsgId(msgId);
                result.setTaskId(msgId);
                result.setContainerNo(containerNo);
                result.setWarehouseId("901884530611326976");
                result.setOriginalArea("");
                result.setOriginalLocation("");
                if(detail.getWhAreaCategoryCode().equals("ZJK")){
                    result.setTargetArea("ZJK01");
                }
                if(detail.getWhAreaCategoryCode().equals("ZYK")){
                    result.setTargetArea("ZYYP");
                }
                if(detail.getWhAreaCategoryCode().equals("WLK")){
                    result.setTargetArea("WL");
                }
                if(detail.getWhAreaCategoryCode().equals("NHK")){
                    result.setTargetArea("NG01");
                }
                result.setTargetLocation("");
//                result.setWmslocationCode("");
                RcvHeaders rcvHeaders = rcvHeadersMapper.findById(detail.getRcvHeaderId(), RcvHeaders.class);
                result.setWorkType("10");
                if(rcvHeaders.getRcvType().equals("1")){//1采购订单，2销售退回单，6直通入库单
                    result.setBusinessType("PO_NORM");
                }else {
                    result.setBusinessType("PO_SORETURN");
                }
                for (TaskInstockDetail i : list) {
                    WmsToEisTaskRecord byId = wmsToEisTaskRecordMapper.findById(i.getTaskInboundId(), WmsToEisTaskRecord.class);
                    if(byId!=null){
                        if(byId.getStatus().equals("1")){
                            continue;
                        }
                        byId.setCount(byId.getCount()+1);
                        //修改标识
                        byId.setType("1");
                        recordList.add(byId);
                    }else{
                        WmsToEisTaskRecord wmsToEisTaskRecord = new WmsToEisTaskRecord();
                        wmsToEisTaskRecord.setTaskId(i.getTaskInboundId());
                        wmsToEisTaskRecord.setStatus("0");
                        wmsToEisTaskRecord.setCount(1);
                        wmsToEisTaskRecord.setContainerCode(containerNo);
                        wmsToEisTaskRecord.setItemId(i.getItemId());
                        wmsToEisTaskRecord.setQty(i.getPieceQty());
                        wmsToEisTaskRecord.setWhAreaCategoryCode(detail.getWhAreaCategoryCode());
                        wmsToEisTaskRecord.setWhAreaCode(StringUtils.isEmpty(detail.getWhAreaCode())?result.getOriginalArea():detail.getWhAreaCode());
//                        wmsToEisTaskRecord.setLocationCode(StringUtils.isEmpty(detail.getWhLocatorCode())?result.getWmslocationCode():detail.getWhLocatorCode());
                        //新增标识
                        wmsToEisTaskRecord.setType("0");
                        //任务类型为 1-容器借道下发
                        wmsToEisTaskRecord.setTaskType(1);
                        recordList.add(wmsToEisTaskRecord);
                    }
                }
                if(list.size()>0){
                    Set<String> locSet = list.stream().map(TaskInstockDetail::getWhAreaCategoryCode).collect(Collectors.toSet());
                    if (locSet.size() > 1) {
                        throw new RuntimeException("容器上存在多货位任务，请整理！");
                    }
                }
                resultList.add(result);
            }
            if (resultList.size() < 1) {
                throw new RuntimeException("暂不存在上架任务");
            }
        }
        if(recordList.size()>0){
            List<WmsToEisTaskRecord> collect = recordList.stream().filter(x -> x.getType().equals("0")).collect(Collectors.toList());
            if(collect.size()>0){
                wmsToEisTaskRecordMapper.saveBatch(collect);
            }
        }

        //调用推送任务接口
//        eisHandler.containerTailgatingRequest(resultList);//推送后把上架任务池eisPushStatus状态改成1 已推送eis
        return resultList;
    }

    @Override
    @Transactional
    public  void    acceptEisContainerMessage(EisWmsRequestParamVO vo) {
        //查询上架任务池对应的状态为已发送容器借道下发 的数据
        List<TaskInstockDetail> taskLineResultList = MapperCustom.builder(taskInstockDetailMapper,TaskInstockDetail.class)
                .andEq(TaskInstockDetail::getContainerCode,vo.getContainerNo())
                .andEq(TaskInstockDetail::getEisPushStatus,"1")
                .findByCriteria();

        if(ToolKits.isEmpty(taskLineResultList)){
            throw new RuntimeException("容器不存在对应的上架任务池记录");
        }

        //更新上架任务池状态为-2已回告完成
        MapperCustom.builder(taskInstockDetailMapper, TaskInstockDetail.class).addParameter(TaskInstockDetail::getEisPushStatus, "2")
                .andEq(TaskInstockDetail::getContainerCode, vo.getContainerNo())
                .andEq(TaskInstockDetail::getEisPushStatus,"1")
                .updateFieldsByCriteria();
    }

    @Override
    public RestMessage<Map<String,String>> checkTokenExp() {
        Map<String,String>  map =  taskInstockDetailMapper.checkTokenExp();
        return  RestMessage.newInstance(true, "成功", map);
    }

}