package com.prolog.cs.biz.outbound.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.codingapi.tx.annotation.TxTransaction;
import com.fasterxml.jackson.core.type.TypeReference;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import com.prolog.common.RestMsgHelper;
import com.prolog.cs.basic.chain.model.carrier.BaseCarrierMst;
import com.prolog.cs.basic.chain.model.customer.BaseCustomerMst;
import com.prolog.cs.basic.chain.model.customer.vo.BaseCustomerMstRequestVO;
import com.prolog.cs.basic.chain.model.supplier.BaseSupplierMst;
import com.prolog.cs.basic.chain.vo.carrier.BaseCarrierMstRequestVO;
import com.prolog.cs.basic.common.model.BaseCommonDict;
import com.prolog.cs.basic.common.model.print.PrintParam;
import com.prolog.cs.basic.item.model.BaseMtlItemMst;
import com.prolog.cs.basic.warehouse.model.BaseWmsWarehouseArea;
import com.prolog.cs.basic.warehouse.model.BaseWmsWarehouseMst;
import com.prolog.cs.basic.warehouse.model.BaseWmsWhWorkstation;
import com.prolog.cs.basic.warehouse.model.WmsWhSlideway;
import com.prolog.cs.basic.warehouse.model.dto.WmsWhSlidewayDTO;
import com.prolog.cs.basic.warehouse.model.vo.ContainerQueryVO;
import com.prolog.cs.basic.warehouse.model.vo.WarehouseAreaQueryVO;
import com.prolog.cs.basic.warehouse.model.vo.WarehouseLocatorBasicInfo;
import com.prolog.cs.biz.inbound.dto.IsSuperviseDTO;
import com.prolog.cs.biz.inbound.model.OmsAsnBillD;
import com.prolog.cs.biz.inbound.model.SupervisionCode;
import com.prolog.cs.biz.inbound.vo.OutBoundUploadCircubParamVO;
import com.prolog.cs.biz.inbound.vo.UploadCircubParamVO;
import com.prolog.cs.biz.outbound.Application;
import com.prolog.cs.biz.outbound.convert.TmsConvert;
import com.prolog.cs.biz.outbound.core.SpringUtils;
import com.prolog.cs.biz.outbound.dao.*;
import com.prolog.cs.biz.outbound.enums.PickTaskDFLowStatus;
import com.prolog.cs.biz.outbound.model.*;
import com.prolog.cs.biz.outbound.model.dto.*;
import com.prolog.cs.biz.outbound.model.dto.check.OuterCheckBarcodeDetailDTO;
import com.prolog.cs.biz.outbound.model.dto.check.OuterLblPkgDTO;
import com.prolog.cs.biz.outbound.model.dto.check.OuterTaskV2DTO;
import com.prolog.cs.biz.outbound.model.entity.*;
import com.prolog.cs.biz.outbound.model.out.ContainerBindTaskDto;
import com.prolog.cs.biz.outbound.model.print.PrintDataWithMark;
import com.prolog.cs.biz.outbound.model.tms.TmsShipBillPackageItem;
import com.prolog.cs.biz.outbound.model.vo.*;
import com.prolog.cs.biz.outbound.model.vo.check.OutCheckSupervisionCodeVO;
import com.prolog.cs.biz.outbound.model.vo.check.OuterTaskVO;
import com.prolog.cs.biz.outbound.model.vo.faceorder.JdKyOrderAddVO;
import com.prolog.cs.biz.outbound.model.vo.faceorder.SfFaceOrderCdVO;
import com.prolog.cs.biz.outbound.resource.*;
import com.prolog.cs.biz.outbound.service.*;
import com.prolog.cs.biz.outbound.service.impl.faceorder.*;
import com.prolog.cs.biz.outbound.service.strategy.STRATEGY_CODE;
import com.prolog.cs.biz.outbound.service.strategy.StrategySelector;
import com.prolog.cs.biz.outbound.service.strategy.handles.IStrategyHandle;
import com.prolog.cs.biz.outbound.utils.BillUtils;
import com.prolog.cs.biz.outbound.utils.HttpClientUtils;
import com.prolog.cs.biz.outbound.utils.IntegrationUtil;
import com.prolog.cs.data.exchange.client.ExchangeSender;
import com.prolog.cs.platform.power.model.Employee;
import com.prolog.entity.vo.ApplyForPackageWeighVO;
import com.prolog.entity.vo.OperationCompleteItemVO;
import com.prolog.entity.vo.OperationCompleteVO;
import com.prolog.enums.OutBoundRequestEnum;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.authority.user.UserTemplate;
import com.prolog.framework.authority.util.HystrixVarUtil;
import com.prolog.framework.beans.BeanUtils;
import com.prolog.framework.bz.core.model.ModelUtils;
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.util.PageUtils;
import com.prolog.framework.lock.DistributedLock;
import com.prolog.framework.toolkit.MapToolKit;
import com.prolog.framework.utils.*;
import com.prolog.fx.inf.core.Exception.RetryException;
import com.prolog.fx.inf.core.InterfaceType;
import com.prolog.fx.inf.core.StandardInterface;
import com.prolog.fx.inf.core.annotation.InterfaceMethod;
import com.prolog.fx.inf.core.dto.SimpleLog;
import com.prolog.inte.EisHandler;
import com.prolog.upcloud.base.inventory.model.WmsInvStockPre;
import com.prolog.upcloud.base.inventory.vo.InvStockPartCheckOut;
import com.prolog.upcloud.base.inventory.vo.QuantityListVo;
import com.prolog.upcloud.base.inventory.vo.WmsInvStockQtyQueryVO;
import com.prolog.upcloud.base.inventory.vo.WmsInvStockQtyVO;
import com.prolog.upcloud.base.strategy.model.BusinessControl;
import com.prolog.upcloud.base.wh.operate.vo.MoveConfirmParamsVO;
import com.prolog.upcloud.base.wh.operate.vo.ReplenishDetailVO;
import com.prolog.upcloud.base.wh.operate.vo.ReplenishIncidentallyVO;
import com.prolog.upcloud.base.wh.operate.vo.ReplenishPassiveSaveDetailVO;
import org.apache.http.conn.ConnectTimeoutException;
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.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import springfox.documentation.spring.web.json.Json;
import sun.misc.FloatingDecimal;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * @author zzz
 * @desc 拣货、外复核（PDA）
 * @date 2021/6/4
 */
@Service
public class PickTaskAppServiceImpl implements PickTaskAppService, StandardInterface<InterfaceBill, Object> {

    private static Logger log = LoggerFactory.getLogger(PickTaskServiceImpl.class);

    @Autowired
    private WaveBillDMapper billDMapper;

    @Autowired
    private PickTaskHMapper pickTaskHMapper;

    @Autowired
    private UserTemplate userTemplate;

    @Autowired
    private BarcodeHMapper barcodeHMapper;

    @Autowired
    private CommonClient commonClient;

    @Autowired
    private BarcodeDMapper barcodeDMapper;

    @Autowired
    private PickTaskServiceImpl pickTaskService;

    @Autowired
    private PickTaskDMapper pickTaskDMapper;

    @Autowired
    private PickOrderMapper pickOrderMapper;

    @Autowired
    private InBoundClient inBoundClient;

    @Autowired
    private ExchangeSender exchangeSender;

    @Autowired
    private MoveTaskMapper moveTaskMapper;

    @Autowired
    private InventoryResource invClient;

    @Autowired
    private SaleRedRecordMapper saleRedRecordMapper;

    @Autowired
    private WaveBillMapper billMapper;

    @Autowired
    WorkStageService workStageService;

    @Autowired
    private OperateResource operateResource;

    @Autowired
    private ControlResource controlResource;

    @Autowired
    protected DistributedLock distributedLock;

    @Autowired
    private StrategyResource strategyResource;

    @Autowired
    private WarehouseResource warehouseResource;

    @Autowired
    private WaveStorageMapper storageMapper;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private WaveBillDMapper waveBillDMapper;

    @Autowired
    private WmsTaskOutBackMapper outBackMapper;

    @Autowired
    private WaveStorageMapper waveStorageMapper;

    @Autowired
    private OmsDoBillDMapper omsDoBillDMapper;

    @Autowired
    private WmsFaceOrderMapper wmsFaceOrderMapper;

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

//    @Autowired
//    private OrderOutboundStatusBackService orderOutboundStatusBackService;

    @Autowired
    EisAgvResource eisAgvResource;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${prolog.dao.keyGenerator.snowFlake.dataCenterId:15}")
    private long dataCenterId;

    @Value("${prolog.dao.keyGenerator.snowFlake.machineId:2}")
    private long machineId;

    // 业务参数配置内/外复核回传ERP by Huanglh 20220112
    @Autowired
    private StrategySelector strategySelector;

    @Autowired
    private PostBackErpService postBackErpService;

    @Autowired
    private WaveBillMapper waveBillMapper;

    @Autowired
    private OmsDoBillHMapper omsDoBillHMapper;

    @Autowired
    private OutcomingRecordHMapper outcomingRecordHMapper;

    @Autowired
    private OutcomingRecordDMapper outcomingRecordDMapper;

    @Autowired
    private IntegrationUtil integrationUtil;

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

    @Autowired
    private PickTaskServiceImpl pickTaskServiceImpl;

    @Autowired
    private ChainResource chainResource;

    @Autowired
    private PrintService printService;

    @Autowired
    private InvoicePdfDOMapper invoicePdfDOMapper;

    @Resource
    private MqOutBoundProducer producer;
    @Resource
    private TmsConvert convert;

    @Resource
    private EisHandler eisHandler;
    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private FaceOrderService faceOrderService;
    @Autowired
    private PrintLogService printLogService;

    @Autowired
    private PowerResource powerResource;

    /**
     * 外复核-待索取任务订单列表
     *
     * @return
     */
    @Override
    public Page<OuterTaskDDTO> outerCheckUnAsk(String barcode, String bldgId, String warehouseId, Integer pageNum, Integer pageSize) {
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        PageHelper.startPage(pageNum, pageSize);
        List<OuterTaskDDTO> list = pickTaskHMapper.getUnOuterCheckHApp(bldgId, warehouseId, enterpriseId, barcode);
        return PageUtils.getPage(list);
    }

    /**
     * 外复核-订单所有复核任务列表
     *
     * @return
     */
    @Override
    public Page<OuterTaskDDTO> outerCheckUnCheck(String bldgId, String srcCode, String warehouseId, Integer pageNum, Integer pageSize) {
        if (StringUtils.isBlank(srcCode))
            throw new ParameterException("订单编号不能为空");
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorId = userDTO.getId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        PageHelper.startPage(pageNum, pageSize);
        List<OuterTaskDDTO> dtoList = pickTaskHMapper.outerCheckUnCheckApp(bldgId, warehouseId, srcCode, enterpriseId);
        if (dtoList.size() == 0) {
            throw new BizException("未找到数据！订单编号" + srcCode);
        }
        Date now = new Date();
        int doPcs = 0, totalPcs = 0, doLcl = 0, totalLcl = 0;
        for (OuterTaskDDTO dto : dtoList) {
            String barcodeId = dto.getBarcodeId();
            if ("0".equals(dto.getCheckStatus()) || StringUtils.isEmpty(dto.getCheckStatus())) {
                barcodeDMapper.updateMapById(barcodeId, MapUtils.put("checkStatus", "1").getMap(), BarCodeDDO.class);
            }
            if (!dto.getType().equals("1")) {
                dto.setLcl(1);
                dto.setPcs(1);
                dto.setIsSupervise(0);//是否扫监管码
                totalLcl++;
                if ("5".equals(dto.getCheckStatus())) {
                    doLcl++;
                }
            } else {
                List<OuterTaskDDTO> items = pickTaskHMapper.getItemByBarcodeDId(warehouseId, dto.getBarcode());
                //整件任务
                Integer pcs = 0;
                for (OuterTaskDDTO item : items) {
                    List<BarCodeDDO> dList = barcodeDMapper.findByMap(MapUtils.put("wmsPickTaskDId", item.getPickTaskDId()).getMap(), BarCodeDDO.class);
                    dto.setItemId(item.getItemId());
                    dto.setItemName(item.getItemName());
                    dto.setItemCode(item.getItemCode());
                    dto.setItemSpecs(item.getItemSpecs());
                    dto.setConversionRate(item.getConversionRate());
                    dto.setUom(item.getUom());
                    dto.setManufacturerLotNum(item.getManufacturerLotNum());
                    dto.setManufacturer(item.getManufacturer());
                    pcs = new BigDecimal(item.getPcs()).divide(item.getConversionRate(), 0, BigDecimal.ROUND_DOWN).intValue();
                    dto.setBarcodePcs(new BigDecimal(pcs).divide(new BigDecimal(dList.size()), 0, BigDecimal.ROUND_DOWN).intValue());
                    dto.setPcs(pcs);
                    totalPcs = totalPcs + dto.getBarcodePcs();
                    if ("5".equals(dto.getCheckStatus())) {
                        doPcs = doPcs + dto.getBarcodePcs();
                    }
                    if (item.getSaleRedQty().compareTo(BigDecimal.ZERO) > 0) {
                        Integer salePcs = item.getSaleRedQty().divide(item.getConversionRate(), 0, BigDecimal.ROUND_DOWN).intValue();
                        Integer barcodePcs = dto.getBarcodePcs() - salePcs;
                        dto.setBarcodePcs(barcodePcs);
                    }
                }
            }
        }
        for (OuterTaskDDTO dto : dtoList) {
            dto.setDoLcl(doLcl);
            dto.setTotLcl(totalLcl);
            dto.setDoPcs(doPcs);
            dto.setTotPcs(totalPcs);
        }
        //请求仓库信息
        log.info("outerCheckUnCheck isSupervise,srcCode：{}，dtoList：{}", srcCode, JSON.toJSONString(dtoList));
        if (totalPcs > 0) {
            RestMessage<BaseWmsWarehouseMst> itemResultWarehouse = warehouseResource.warehouse(warehouseId);
            if (itemResultWarehouse.isSuccess() && itemResultWarehouse.getData() != null) {
                BaseWmsWarehouseMst wmsWarehouseMst = itemResultWarehouse.getData();
                //扫描监管码节点：0=整件拣货、零货拣货 1=整件外复核、零货拣货 2=整件拣货、零货内复核 3=整件外复核、零货内复核
                if (wmsWarehouseMst != null) {
                    Integer stage = wmsWarehouseMst.getScanSupervisionCodeStage();
                    if (stage != null && (stage == 1 || stage == 3)) {
                        isSupervise(dtoList, 7);
                    }
                }
            }
        }
        return PageUtils.getPage(dtoList);
    }

    /**
     * 外复核-确认
     *
     * @param barcode
     */
    @Override
    @Transactional
    @TxTransaction
    public Boolean outerCheckConfirm(String barcode, Integer pcs, String superviseCode, String warehouseId) {
        if (StringUtils.isBlank(barcode))
            throw new ParameterException("条码不能为空");
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();

        // 变更当前条码状态
        BarCodeDDO byId = barcodeDMapper.findById(barcode, BarCodeDDO.class);
        byId.setCheckStatus("5");
        barcodeDMapper.update(byId);
        // 查询barcodeH是否还有未复核条码
        List<BarCodeDDO> barcodeIds = barcodeDMapper.findByMap(MapUtils.put("barcodeId", byId.getBarcodeId()).getMap(), BarCodeDDO.class);
        long count1 = barcodeIds.stream().filter(x -> !x.getCheckStatus().equals("5")).count();
        if (count1 != 0) {
            return true;
        }
        //更新pick_task_d的flow_status=7
        pickTaskHMapper.updateFlowStatusApp("7", barcode, warehouseId);

        BarcodeHDO barcodeHDO = barcodeHMapper.findById(byId.getBarcodeId(), BarcodeHDO.class);
        barcodeHMapper.updateMapById(byId.getBarcodeId(), MapUtils.put("checkStatus", "5").put("checkerId", operatorId).put("checkerNo", operatorCode).put("checkerName", operatorName).put("checkTime2", new Date()).getMap(), BarcodeHDO.class);

        pickTaskHMapper.updateStatusEndByBarcode(barcode, warehouseId, enterpriseId);
        List<String> idList = new ArrayList<>();
        idList.add(barcodeHDO.getId());
        String point = "2";
        // 业务参数配置/出库回传ERP节点 1:内复核回传  2:外复核回传
        RestMessage<Map<String, BusinessControl>> restMessageCode = strategyResource.getControlByCodes(new String[]{"OUT_BACK_ERP_POINT"}, warehouseId, null, enterpriseId, null);
        if (restMessageCode.isSuccess() && restMessageCode.getData() != null) {
            Map<String, BusinessControl> result = restMessageCode.getData();
            if (result.containsKey("OUT_BACK_ERP_POINT")) {
                point = String.valueOf(result.get("OUT_BACK_ERP_POINT").getRegValue());
            } else {
                throw new BizException("出库回传ERP节点未配置");
            }
        }
        // 根据合单号srcCode 查询 未外复核确认数量，为 0 条则，根据合单号srcCode 查询 来源单号集合回传erp
        Criteria crt2 = Criteria.forClass(BarcodeHDO.class);
        Restriction r1 = Restrictions.eq("billGroupId", barcodeHDO.getBillGroupId());
        Restriction r2 = Restrictions.or(Restrictions.isnull("checkStatus"), Restrictions.in("checkStatus", new String[]{"0", "1"}));
        Restriction r3 = Restrictions.eq("warehouseId", warehouseId);
        Restriction r4 = Restrictions.eq("enterpriseId", enterpriseId);
        Restriction r5 = Restrictions.notIn("id", idList.toArray(new String[idList.size()]));
        crt2.setRestriction(Restrictions.and(r1, r2, r3, r4, r5));
        long count = barcodeHMapper.findCountByCriteria(crt2);
        if (count == 0) {
            List<String> omsBillIds = barcodeHMapper.getOmsBillIds(barcodeHDO.getBillGroupId(), enterpriseId);
            if (omsBillIds.size() > 0) {
                List<String> srcCodes = new ArrayList<>();
                srcCodes.add(barcodeHDO.getBillGroupId());
                if (point.equals("2")) {
                    postBackErpByTable(omsBillIds);
                } else {
                }
            }
        }
        return true;
    }

    public void postBackErpByTable(List<String> omsBillIds) {
        String[] ids = omsBillIds.toArray(new String[omsBillIds.size()]);
        Criteria crtH = Criteria.forClass(OutcomingRecordH.class);
        Criteria crtD = Criteria.forClass(OutcomingRecordD.class);
        crtH.setRestriction(Restrictions.in("billid", ids));
        crtD.setRestriction(Restrictions.in("billid", ids));
        outcomingRecordHMapper.deleteByCriteria(crtH);
        outcomingRecordDMapper.deleteByCriteria(crtD);
        for (String omsBillId : omsBillIds) {
            List<OutcomingRecordH> listH = outcomingRecordHMapper.getH(omsBillId);
            if (listH.size() > 0) {
                outcomingRecordHMapper.saveBatch(listH);
            }
            List<OutcomingRecordD> listD = outcomingRecordHMapper.getD(omsBillId);
            if (CollUtil.isNotEmpty(listD)) {
//                List<String> lineIds = listD.stream().map(OutcomingRecordD::getLineId).distinct().collect(Collectors.toList());
//                List<OutcomingRecordD> saveRecordDList = new ArrayList<>();
//                if (lineIds.size() > 0) {
//                    for (String lineId : lineIds) {
//                        // 先找批号不为空的
//                        OutcomingRecordD outcomingRecordD = listD.stream().filter(d -> d.getLineId().equals(lineId) && !StringUtils.isBlank(d.getLotNo())).findFirst().orElse(null);
//                        if (null == outcomingRecordD) {
//                            OutcomingRecordD recordD = listD.stream().filter(d -> d.getLineId().equals(lineId)).findFirst().orElse(null);
//                            saveRecordDList.add(recordD);
//                        } else {
//                            saveRecordDList.add(outcomingRecordD);
//                        }
//                    }
//                }
                if (CollUtil.isNotEmpty(listD)) {
                    outcomingRecordDMapper.saveBatch(listD);
                }
            }
        }
//        // 调用接口平台回传OMS
//        try {
//            if (StringUtils.isEmpty(outComingRecordBack)) {
//                throw new BizException("请求路径配置为空");
//            }
//            String url = outComingRecordBack;
//            log.info("调用OMS接口URL:{}", JSONUtil.toJsonStr(url));
//            List<OutcomingRecordHDto> backList = pickTaskServiceImpl.queryOutboundDataToOms(omsBillIds);
//            log.info("调用OMS接口入参:{}", JSONUtil.toJsonStr(backList));
//            String result = HttpUtil.post(url, JSONObject.toJSONString(backList));
//            JSONObject parse = JSONObject.parseObject(result);
//            log.info("调用OMS接口返回参数:{}", parse);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    /**
     * 查询待索取任务数
     *
     * @param warehouseId
     * @param pickTaskType 0:整件 1:零货 2:功能库房 3:整单
     * @return
     */
    @Override
    public long getPickTaskCount(String bldgId, String warehouseId, Integer pickTaskType, String operatorCode, Integer type) {
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");
        if (pickTaskType == null)
            throw new ParameterException("类型不能为空");
        if (StringUtils.isEmpty(operatorCode)) {
            UserDTO userDTO = userTemplate.getUserDTO();
            operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        }
        List<String> areaCodes = null;
        String workType = null;
        if (pickTaskType == 1) {
            //获取员工作业库区编码集合
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "BULK_PICKING");
        } else if (pickTaskType == 0) {
            //获取员工作业类型
            RestMessage<String> restMessage1 = controlResource.getWorkType(operatorCode, warehouseId, "2011");
            if (!restMessage1.isSuccess())
                throw new RuntimeException("获取员工作业类型失败！" + restMessage1.getMessage());
            workType = restMessage1.getData();
            if (StringUtils.isEmpty(workType))
                throw new BizException("该员工未配置，整件拣货/补货作业权限");
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", workType);
        } else if (pickTaskType == 2) {
            //获取员工作业库区编码集合
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "WHOLE_BULK_PICKING");
        } else if (pickTaskType == 3) {
            //零货
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "BULK_PICKING");
            //整件
            RestMessage<String> restMessage1 = controlResource.getWorkType(operatorCode, warehouseId, "2011");
            if (!restMessage1.isSuccess())
                throw new RuntimeException("获取员工作业类型失败！" + restMessage1.getMessage());
            workType = restMessage1.getData();
            if (StringUtils.isEmpty(workType))
                throw new BizException("该员工未配置，整件拣货/补货作业权限");
            List<String> areaCodes2 = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", workType);
            areaCodes.addAll(areaCodes2);
            pickTaskType = null;
        }
        return pickTaskHMapper.getUnAskPickCount(pickTaskType, warehouseId, bldgId, areaCodes, type);
    }

    /**
     * RF零货拣货-查询区域对应任务数
     *
     * @param warehouseId
     * @param bldgId
     */
    @Override
    public Map<String, Object> queryAreaTaskList(String bldgId, String warehouseId) {
        Map<String, Object> map = new HashMap<>();
        UserDTO userDTO = userTemplate.getUserDTO();
        // 周转框数量
        int pickBoxNum = 4; // 默认4
        RestMessage<Map<String, BusinessControl>> restMessage = strategyResource.getControlByCodes(new String[]{"PICK_BOX_NUM"}, warehouseId, null, userDTO.getEnterpriseId(), bldgId);
        if (restMessage.isSuccess() && restMessage.getData() != null) {
            Map<String, BusinessControl> result = restMessage.getData();
            if (result.containsKey("PICK_BOX_NUM")) {
                pickBoxNum = Integer.parseInt(result.get("PICK_BOX_NUM").getRegValue());
            }
        }
        List<Map<String, Object>> rsList = new ArrayList<>();
        BulkPickBoardVo bulkPickBoardVo = this.bulkPickBoard(bldgId, warehouseId);
        List<TaskCountVo> bulkPickTask = bulkPickBoardVo.getBulkPickTask();
        if (!CollUtil.isEmpty(bulkPickTask)) {
            for (TaskCountVo taskCountVo : bulkPickTask) {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put(taskCountVo.getAreaCode(), taskCountVo.getCount());
                rsList.add(resultMap);
            }
        }
        map.put("pickBoxNum", pickBoxNum);
        map.put("areaTaskList", rsList);
        return map;
    }

    /**
     * 索取
     *
     * @param warehouseId
     * @param pickTaskType 0:整件 1:零货 2:功能库房 3:整单
     */
    @Override
    @Transactional
    public Map<String, Object> createByOperatorCode(String bldgId, String warehouseId, Integer pickTaskType, Integer pickBoxNum) {
        log.info("开始执行索取方法+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();
        Map<String, Object> map = new HashMap<>();

        // 查询已索取的拣选单
        List<PickOrder> pickOrderList = pickOrderMapper.getPickOrderList(bldgId, pickTaskType, null, warehouseId, "0", operatorCode);
        List<PickOrder> pickOrderList2 = pickOrderMapper.getPickOrderList(bldgId, pickTaskType, null, warehouseId, "1", operatorCode);
        if (pickOrderList.size() > 0 || pickOrderList2.size() > 0) {
            List<String> h1 = new ArrayList<>();
            if (pickTaskType == 0) {
                // 整件拣货索取
                Set<String> orderIds = pickOrderList.stream().map(PickOrder::getPickOrderId).collect(Collectors.toSet());
                if (CollUtil.isNotEmpty(orderIds)) {
                    orderIds.addAll(pickOrderList2.stream().map(PickOrder::getPickOrderId).collect(Collectors.toSet()));
                } else {
                    orderIds = pickOrderList2.stream().map(PickOrder::getPickOrderId).collect(Collectors.toSet());
                }
                // 根据order查询pick_task_h，判断任务是否属于ZJK，若无整件库则直接跳过
                Criteria c1 = Criteria.forClass(PickTaskH.class);
                Restriction r1 = Restrictions.in("pickOrderId", orderIds.toArray());
                c1.setRestriction(r1);
                List<PickTaskH> pickTaskHS = pickTaskHMapper.findByCriteria(c1);
                if (CollUtil.isEmpty(pickTaskHS)) {
                    throw new BizException("已索取的任务包不存在拣货任务！");
                }
                RestMessage<List<BaseWmsWarehouseArea>> areas = warehouseResource.getByAreaCodes(warehouseId, pickTaskHS.stream().map(PickTaskH::getWarehouseAreaCode).distinct().toArray(String[]::new));
                for (BaseWmsWarehouseArea datum : areas.getData()) {
                    if (datum.getWarehouseAreaCategory().equals("ZJK")) {
                        for (PickTaskH pickTaskH : pickTaskHS) {
                            if (pickTaskH.getWarehouseAreaCode().equals(datum.getWarehouseAreaCode())) {
                                h1.add(pickTaskH.getPickOrderId());
                            }
                        }
                    }
                }
                List<PickOrder> p1 = new ArrayList<>();
                List<PickOrder> p2 = new ArrayList<>();
                if (CollUtil.isNotEmpty(h1)) {
                    for (PickOrder pickOrder : pickOrderList) {
                        if (h1.contains(pickOrder.getPickOrderId())) {
                            p1.add(pickOrder);
                        }
                    }
                    pickOrderList = p1;
                    for (PickOrder pickOrder : pickOrderList2) {
                        if (h1.contains(pickOrder.getPickOrderId())) {
                            p2.add(pickOrder);
                        }
                    }
                    pickOrderList2 = p2;
                }
            }
            // 如果整件索取时没有整件库的已索取任务，则走索取逻辑索取整件库任务
            if (pickTaskType != 0 || CollUtil.isNotEmpty(h1)) {
                PickOrder pickOrder = null;
                if (pickOrderList2.size() > 0) {
                    pickOrder = pickOrderList2.get(0);
                } else {
                    pickOrder = pickOrderList.get(0);
                }
                Criteria crt = Criteria.forClass(PickTaskH.class);
                crt.setRestriction(Restrictions.and(Restrictions.eq("pickOrderId", pickOrder.getPickOrderId()), Restrictions.isNotNull("containerCode")));
                long doCount = pickTaskHMapper.findCountByCriteria(crt);
                long taskCount = pickTaskHMapper.findCountByMap(MapUtils.put("pickOrderId", pickOrder.getPickOrderId()).getMap(), PickTaskH.class);
                map.put("total", taskCount); // 总任务数
                if (pickTaskType != 3) {
                    map.put("doCount", doCount); // 已绑定容器任务数
                } else {
                    if (pickOrder.getType() == 1) {
                        map.put("doCount", taskCount); // 补货任务，无需绑容器
                    } else {
                        map.put("doCount", taskCount > doCount ? taskCount - 1 : taskCount); // 整单拣货，只绑定一个容器
                    }
                }
                map.put("pickOrderId", pickOrder.getPickOrderId());
                map.put("printStatus", pickOrder.getPrintStatus());
                List<PickTaskH> pickTaskHList = pickTaskHMapper.getTaskHList(pickOrder.getPickOrderId());
                List<Map<String, String>> containerNos = new ArrayList<>();
                for (PickTaskH pickTaskH : pickTaskHList) {
                    Map<String, String> container = new HashMap<>();
                    container.put("pickTaskId", pickTaskH.getPickTaskId());
                    container.put("containerNo", pickTaskH.getContainerCode());
                    container.put("serialNumber", pickTaskH.getSerialNumber());
                    containerNos.add(container);
                }
                map.put("container", containerNos);
                return map;
            }
        }
        if (pickTaskType == 3) {
            // 查询未上架的拣货任务
            Integer notFinishCount = pickTaskHMapper.getNotFinishCount(warehouseId, operatorCode);
            if (notFinishCount > 0) {
                throw new BizException("请先上架确认补货任务");
            }
        }
        List<String> areaCodes = new ArrayList<>();
        String workType = null;
        if (pickTaskType == 1) {
            //零货拣货也需要校验权限
            //获取员工作业库区编码集合
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "BULK_PICKING");
            if (CollUtil.isEmpty(areaCodes)) {
                throw new BizException("工号没有散件拣货权限");
            }
            workType = "BULK_PICKING";
        } else if (pickTaskType == 0) {
            // WHOLE_PICKING_FIRST WHOLE_PICKING 两种拣货权限
            List<String> userAreas1 = new ArrayList<>();
            try {
                userAreas1 = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "WHOLE_PICKING");
            } catch (Exception ignored) {
            }
            List<String> userAreas2 = new ArrayList<>();
            try {
                userAreas2 = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "WHOLE_PICKING_FIRST");
            } catch (Exception ignored) {
            }
            try {
                userAreas1.addAll(userAreas2);
                areaCodes.addAll(userAreas1);
            } catch (Exception ignored) {
            }
            if (CollUtil.isEmpty(areaCodes)) {
                throw new BizException("工号没有整件拣货权限");
            }
            RestMessage<List<BaseWmsWarehouseArea>> areas = warehouseResource.getByAreaCodes(warehouseId, userAreas1.toArray(new String[]{}));
            for (BaseWmsWarehouseArea datum : areas.getData()) {
                if (datum.getWarehouseAreaCategory().equals("ZJK")) {
                    areaCodes.add(datum.getWarehouseAreaCode());
                }
            }
        } else if (pickTaskType == 2) {
            // 获取员工作业库区编码集合
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "WHOLE_BULK_PICKING");
        } else if (pickTaskType == 3) {
            //零货
            try {
                areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "BULK_PICKING");
            } catch (Exception e) {
            }
            // 整件
            RestMessage<String> restMessage1 = controlResource.getWorkType(operatorCode, warehouseId, "2011");
            if (!restMessage1.isSuccess()) {
                throw new RuntimeException("获取员工作业类型失败！" + restMessage1.getMessage());
            }
            workType = restMessage1.getData();
            if (StringUtils.isEmpty(workType)) {
                throw new BizException("该员工未配置，整件拣货/补货作业权限");
            }
            List<String> areaCodes2 = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", workType);
            areaCodes.addAll(areaCodes2);
        }
        List<PickTaskH> list = null;
        // 任务数
        Integer count = 4;
        // 最大拣货件数
        BigDecimal maxPcs = BigDecimal.TEN;
        RestMessage<Map<String, BusinessControl>> rest = strategyResource.getControlByCodes(new String[]{"PICK_TASK_NUM", "PICK_TASK_MAX_PCS"}, warehouseId, null, enterpriseId, bldgId);
        if (rest.isSuccess() && rest.getData() != null) {
            Map<String, BusinessControl> conMap = rest.getData();
            if (conMap.containsKey("PICK_TASK_NUM")) {
                if (pickTaskType == 1) {
                    count = pickBoxNum;
                } else {
                    count = Integer.valueOf(conMap.get("PICK_TASK_NUM").getRegValue());
                }
            }
            if (conMap.containsKey("PICK_TASK_MAX_PCS")) {
                maxPcs = new BigDecimal(conMap.get("PICK_TASK_MAX_PCS").getRegValue());
            }
        }
        if (pickTaskType == 1) {
            count = pickBoxNum;
        }
        List<Integer> pickTaskTypes = new ArrayList<>();
        pickTaskTypes.add(pickTaskType);
        if (pickTaskType == 0) {
            list = pickTaskHMapper.getPickTaskWholeList(bldgId, null, enterpriseId, warehouseId, count, pickTaskTypes, areaCodes, workType, null, null);
            if (list.size() > 1) {
                List<PickTaskH> list2 = new ArrayList<>();
                Integer type = 0;
                for (int i = 0; i < list.size(); i++) {
                    PickTaskH h = list.get(i);
                    if (i == 0) {
                        type = h.getType();
                    }
                    int pcs = pickTaskHMapper.getWholePcs(h.getPickTaskId(), enterpriseId);
                    BigDecimal js = new BigDecimal(pcs);
                    if (i == 0 || (js.compareTo(maxPcs) <= 0 && Objects.equals(h.getType(), type))) {
                        list2.add(h);
                        maxPcs = maxPcs.subtract(js);
                    } else {
                        break;
                    }
                }
                list = list2;
            }
        } else if (pickTaskType == 1) {
            list = pickTaskHMapper.getPickTaskHList(bldgId, null, enterpriseId, warehouseId, count, pickTaskTypes, areaCodes, null);
            if (list == null) {
                throw new BizException("当前没有拣货任务可索取");
            }
        } else if (pickTaskType == 2) {
            // 功能库房新增了整货，零货，所以需要先检查是否有补货单 - by Huanglh 2022-01-20
            // 查询当天最后的补货订单编号
            String billGroupId = pickTaskHMapper.getLastMoveBillId(warehouseId, operatorCode, 2);
            if (billGroupId != null) {
                // 查询该补货订单的拣货任务
                list = pickTaskHMapper.getPickTaskHListByBill3(bldgId, billGroupId, warehouseId, areaCodes, operatorCode, 2);
            }
            // 查询补货任务
            if (list == null || list.size() == 0) {
                list = pickTaskHMapper.getPickTaskHListByMove(bldgId, enterpriseId, warehouseId, count, areaCodes, workType, operatorCode, 2);
            }
            // 无补货任务,则索取整单任务
            if (list.size() == 0) {
                list = pickTaskHMapper.getPickTaskHListByBill(bldgId, enterpriseId, warehouseId, areaCodes, "1");
            }
        } else if (pickTaskType == 3) {
            // 查询当天最后的补货订单编号
            String billGroupId = pickTaskHMapper.getLastMoveBillId(warehouseId, operatorCode, null);
            if (billGroupId != null) {
                // 查询该补货订单的拣货任务
                list = pickTaskHMapper.getPickTaskHListByBill3(bldgId, billGroupId, warehouseId, areaCodes, operatorCode, null);
            }
            // 查询补货任务
            if (list == null || list.size() == 0) {
                list = pickTaskHMapper.getPickTaskHListByMove(bldgId, enterpriseId, warehouseId, count, areaCodes, workType, operatorCode, null);
            }
            // 无补货任务,则索取整单任务
            if (list.size() == 0) {
                list = pickTaskHMapper.getPickTaskHListByBill2(bldgId, enterpriseId, warehouseId, areaCodes, "0", operatorCode);
            }
        }
        List<String> pickTaskDIds1 = new ArrayList<>();
        List<String> pickTaskDIds2 = new ArrayList<>();
        String pickOrderId = String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId));
        if (list != null && list.size() > 0) {
            try {
                for (PickTaskH pickTaskH : list) {
                    pickTaskH.setPickOrderId(pickOrderId);
                    pickTaskH.setStatus("1");
                    pickTaskHMapper.updateFields(pickTaskH, FieldSelector.newInstance().include("status", "pickOrderId", "stationCode", "stationName", "stationId"));
                    // 如果是整件索取，生成条码
                    if (pickTaskH.getPickTaskType() == 0) {
                        List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("pickTaskId", pickTaskH.getPickTaskId()).getMap(), PickTaskD.class);
                        if (pickTaskDList.size() > 0) {
                            // 生成打印条码
                            for (PickTaskD pickTaskD : pickTaskDList) {
                                if ((pickTaskH.getType() == 0 && pickTaskType == 0) || pickTaskH.getType() == 1) {
                                    pickTaskService.saveBarcode(
                                            Collections.singletonList(pickTaskH),
                                            Collections.singletonList(pickTaskD.getPickTaskDId()),
                                            pickOrderId,
                                            bldgId,
                                            warehouseId,
                                            enterpriseId
                                    );
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                throw new PrologException("拣货索取失败！" + e.getMessage());
            }
            if (pickTaskType == 3) {
                pickTaskService.updatePickTaskD4WholeOrderPick(userDTO, enterpriseId, list);
            }
            PickOrder pickOrder = new PickOrder();
            pickOrder.setPickOrderId(pickOrderId);
            pickOrder.setStatus("0");
            pickOrder.setWarehouseId(warehouseId);
            pickOrder.setTaskCount(list.size());
            pickOrder.setOperatorId(operatorId);
            pickOrder.setOperatorName(operatorName);
            pickOrder.setOperatorCode(operatorCode);
            pickOrder.setPickTaskType(list.get(0).getPickTaskType());
            pickOrder.setPrintStatus("1");
            ModelUtils.generateBaseData(pickOrder, userTemplate::getUserDTO);
            pickOrderMapper.save(pickOrder);
            List<PrintDataWithMark> printDataList1 = new ArrayList<>();
            List<PrintDataWithMark> printDataList2;
            if (pickTaskType == 0) {
                // 调整件标签打印查询接口
                printDataList1 = pickTaskService.printWholeLabels(pickTaskDIds1, null, warehouseId, 0, operatorName);
                printDataList2 = pickTaskService.printWholeLabels(pickTaskDIds2, null, warehouseId, 1, operatorName);
                printDataList1.addAll(printDataList2);
            } else if (pickTaskType == 3) {
                printDataList2 = pickTaskService.printWholeLabels(pickTaskDIds2, null, warehouseId, 1, operatorName);
                printDataList1.addAll(printDataList2);
            }
            // 返回打印数据
            map.put("printDataList", printDataList1);
            map.put("total", list.size()); // 总任务数
            if (pickTaskType != 3) {
                map.put("doCount", 0); // 已绑定容器任务数
            } else {
                if (list.get(0).getType() == 1) {
                    map.put("doCount", list.size()); // 补货任务，无需绑容器
                } else {
                    map.put("doCount", list.size() - 1); // 整单拣货，只绑定一个容器
                }
            }
            map.put("pickOrderId", pickOrderId);
            map.put("printStatus", "0");
            log.info("结束执行索取方法+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
            return map;
        } else {
            throw new BizException("未索取到拣选任务");
        }
    }

    private BigDecimal replenishQty(
            String itemId,
            String batchNum,
            String locatorCode,
            String enterpriseId,
            String warehouseId
    ) {
        List<WmsInvStockQtyQueryVO> queryList = new ArrayList<>();
        WmsInvStockQtyQueryVO queryVO = new WmsInvStockQtyQueryVO();
        queryVO.setEnterpriseId(enterpriseId);
        queryVO.setWarehouseId(warehouseId);
        queryVO.setBatchNum(batchNum);
        queryVO.setLocatorCode(locatorCode);
        queryVO.setItemId(itemId);
        queryList.add(queryVO);
        RestMessage<List<WmsInvStockQtyVO>> msg = invClient.getAvailableQuantityList(queryList);
        if (msg.isSuccess() && CollUtil.isNotEmpty(msg.getData())) {
            WmsInvStockQtyVO vo = msg.getData().stream().filter(var -> var.getLocatorCode().equals(locatorCode) && var.getBatchNum().equals(batchNum) && var.getItemId().equals(itemId)).findFirst().orElse(null);
            if (null != vo) {
                // 查询顺带补货参数
                RestMessage<BusinessControl> restMessage = strategyResource.getControlByCode("AUTO_REPLENISH_LIMIT", warehouseId, null, enterpriseId, null);
                if (restMessage.isSuccess() && null != restMessage.getData() && StrUtil.isNotEmpty(restMessage.getData().getRegValue()) && NumberUtil.isNumber(restMessage.getData().getRegValue())) {
                    if (vo.getAvailableQuantity().doubleValue() <= new BigDecimal(restMessage.getData().getRegValue()).doubleValue() && null != vo.getLayerNum() && vo.getLayerNum() > 1) {
                        // 大于1层才补货
                        return vo.getAvailableQuantity();
                    }
                }
            }
        }
        return BigDecimal.ZERO;
    }

    /**
     * 零货/功能库房/整单-绑定容器
     *
     * @param pickOrderId
     * @param containerCodes
     */
    @Override
    @Transactional
    @TxTransaction
    public Integer bindContainer(String pickOrderId, String containerCodes, String warehouseId) {
        AssertUtils.isNotBlank(pickOrderId, "拣选单id不能为空");
        AssertUtils.isNotBlank(containerCodes, "容器号不能为空");
        AssertUtils.isNotBlank(warehouseId, "仓id不能为空");
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String[] containerCodeArray = containerCodes.split(",");
        // 校验容器是否已被其他任务使用
        if (containerCodeArray.length > 0) {
            for (int i = 0; i < containerCodeArray.length; i++) {
                Criteria crt2 = Criteria.forClass(PickTaskH.class);
                Restriction r4 = Restrictions.eq("enterpriseId", enterpriseId);
                Restriction r5 = Restrictions.eq("containerCode", containerCodeArray[i]);
                Restriction r6 = Restrictions.ne("status", "10");
                Restriction r7 = Restrictions.ne("pickTaskType", 2);
                crt2.setRestriction(Restrictions.and(r4, r5, r6,r7));
                List<PickTaskH> hList = pickTaskHMapper.findByCriteria(crt2);
                Integer count2 = hList.size();
                if (count2 > 0) {
                    throw new BizException("绑定的容器已被占用！");
                }
            }
        }

        Criteria crt = Criteria.forClass(PickTaskH.class);
        Restriction r1 = Restrictions.eq("pickOrderId", pickOrderId);
        Restriction r2 = Restrictions.eq("enterpriseId", enterpriseId);
        Restriction r4 = Restrictions.eq("warehouseId", warehouseId);
        crt.setRestriction(Restrictions.and(r1, r2, r4));
        crt.setOrder(Order.newInstance().asc("pickTaskId"));
        List<PickTaskH> pickTaskHList = pickTaskHMapper.findByCriteria(crt);
        if (CollUtil.isEmpty(pickTaskHList)) {
            return 0;
        }
        PickTaskH unBindH = pickTaskHList.stream().filter(var -> StrUtil.isEmpty(var.getContainerNo())).findFirst().orElse(null);
        if (null == unBindH) {
            return 0;
        }
        if (pickTaskHList.size() == 1)
            pickOrderMapper.updateMapById(pickTaskHList.get(0).getPickOrderId(), MapUtils.put("status", "1").getMap(), PickOrder.class);

        //新增逻辑-为容器添加编号 A/B/C/D，最多4个
        int bindedSize = 0;
        int usedNo = 0;
        BaseWmsWhWorkstation workstation = null;
        for (int i = 0; i < pickTaskHList.size(); i++) {
            //根据已绑定的条数设置容器编号
            bindedSize += 1;
            PickTaskH pickTaskH = pickTaskHList.get(i);
            if (StrUtil.isNotEmpty(pickTaskH.getContainerCode())) {
                continue;
            }
            if (usedNo >= containerCodeArray.length) {
                break;
            }
            String serialNumber;
            if (bindedSize == 1) {
                serialNumber = "A";
            } else if (bindedSize == 2) {
                serialNumber = "B";
            } else if (bindedSize == 3) {
                serialNumber = "C";
            } else {
                serialNumber = "D";
            }
            String containerCode = containerCodeArray[usedNo];
            Criteria crt2 = Criteria.forClass(PickTaskH.class);
            RestrictionBuilder builder = crt2.restrictionBuilder();
            builder.eq("enterpriseId", enterpriseId)
                    .eq("containerCode", containerCode)
                    .eq("warehouseId", warehouseId)
                    .in("status", new String[]{"1", "2"})
                    .ne("pickTaskType",2);
            crt2.buildRestriction();
            List<PickTaskH> list = pickTaskHMapper.findByCriteria(crt2);
            if (list.size() > 0)
                throw new BizException("该容器已绑定拣选任务！");
            pickTaskService.isEnableContainerCode(containerCode, warehouseId);
            if (i == 0 && pickTaskH.getPickTaskType() == 3) {
                workstation = pickTaskService.getBaseWmsWhWorkstation(null, warehouseId, enterpriseId, containerCode);
            }
            pickTaskH.setContainerCode(containerCode);
            MapToolKit containerCode1 = MapUtils.put("containerCode", containerCode).put("serialNumber", serialNumber);
            String pickTaskId = pickTaskH.getPickTaskId();
            if (workstation == null) {
                pickTaskHMapper.updateMapById(pickTaskId, containerCode1.getMap(), PickTaskH.class);
            } else {
                pickTaskHMapper.updateMapById(pickTaskId, containerCode1.put("stationId", workstation.getStationId())
                        .put("stationName", workstation.getStationName())
                        .put("stationCode", workstation.getStationCode()).getMap(), PickTaskH.class);
            }
            // 容器占用
//            pickTaskService.usedContainer(containerCode, warehouseId);
            usedNo++;
        }
        return containerCodeArray.length;
    }

    /**
     * 零货/功能库房/整单-查询任务列表
     *
     * @param warehouseId
     * @param pickOrderId
     */
    @Override
    public Page<PickTaskDDTO> getPickTaskDList(String bldgId, String warehouseId, String pickOrderId, Integer pageNum, Integer pageSize) {
        if (StringUtils.isBlank(pickOrderId))
            throw new ParameterException("任务包号不能为空");
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");
        PageHelper.startPage(pageNum, pageSize);
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        RestMessage<BusinessControl> restMessage = strategyResource.getControlByCode("PICK_TASK_ASK_WAY", warehouseId, null, enterpriseId, null);
        RestMessage<List<BaseCommonDict>> billTypeList = commonClient.getDictBasicListByCodes("DO_BILL_TYPE", null);
        Map<String, String> billTypes = new HashMap<>();
        billTypeList.getData().forEach(baseCommonDict -> billTypes.put(baseCommonDict.getDictCode(), baseCommonDict.getDictName()));
        if (restMessage.isSuccess() && restMessage.getData() != null && "1".equals(restMessage.getData().getRegValue())) {
            List<PickTaskDDTO> list = pickTaskHMapper.getPickTaskDList2("3", bldgId, pickOrderId, warehouseId);
            isSupervise(list, 51); // 51、52逻辑相同
            if (list.size() > 0) {
                for (PickTaskDDTO dto : list) {
                    dto.setPickTaskDId(String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId)));
                    dto.setBillTypeName(billTypes.get(dto.getBillType()));
                }
            }
            return PageUtils.getPage(list);
        } else {
            List<PickTaskDDTO> list = pickTaskHMapper.getPickTaskDList2(null, bldgId, pickOrderId, warehouseId);
            isSupervise(list, 51);//51、52逻辑相同
            if (list.size() > 0) {
                for (PickTaskDDTO dto : list) {
                    dto.setPickTaskDId(String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId)));
                    dto.setBillTypeName(billTypes.get(dto.getBillType()));
                }
            }
            return PageUtils.getPage(list);
        }
    }

    //扫码阶段：0=入库质检 10=PC整件拣货 11=PC零货拣货 12=PC功能库房拣货 2=PC内复核 3=PC外复核 4=补录
    // 50=PDA整件拣货 51=PDA零货拣货 52=PDA功能库房拣货 6=PDA内复核 7=PDA外复核
    private void isSupervise(List<? extends IsSuperviseDTO> list, Integer stage) {
        if (list == null || list.size() == 0) {
            return;
        }
        try {
            RestMessage<List<? extends IsSuperviseDTO>> rest = inBoundClient.isSupervise(list, stage);
            if (rest.isSuccess() && rest.getData() != null && rest.getData().size() == list.size()) {
                for (int i = 0; i < rest.getData().size(); i++) {
                    BeanUtils.copyProperties(rest.getData().get(i), list.get(i));
                }
            }
        } catch (Exception e) {
            log.error("调用监管码接口异常", e);
        }
    }


    //扫码阶段：0=入库质检 10=PC整件拣货 11=PC零货拣货 12=PC功能库房拣货 2=PC内复核 3=PC外复核 4=补录
    // 50=PDA整件拣货 51=PDA零货拣货 52=PDA功能库房拣货 6=PDA内复核 7=PDA外复核
    private void isSupervise(List<PickTaskDDTO> dtoList) {
        if (CollUtil.isEmpty(dtoList)) {
            return;
        }
        Map<Integer, List<PickTaskDDTO>> collect = dtoList.stream().collect(Collectors.groupingBy(PickTaskDDTO::getPickTaskType));
        List<PickTaskDDTO> resultList = new ArrayList<>();
        for (Integer integer : collect.keySet()) {
            List<PickTaskDDTO> list = collect.get(integer);
            if (CollUtil.isEmpty(list)) {
                continue;
            }
            Integer stage = 50;
            if (integer == 2) {
                stage = 52;
            }
            try {
                RestMessage<List<? extends IsSuperviseDTO>> rest = inBoundClient.isSupervise(list, stage);
                if (rest.isSuccess() && rest.getData() != null && rest.getData().size() == list.size()) {
                    for (int i = 0; i < rest.getData().size(); i++) {
                        BeanUtils.copyProperties(rest.getData().get(i), list.get(i));
                    }
                    resultList.addAll(list);
                }
            } catch (Exception e) {
                log.error("调用监管码接口异常", e);
            }
        }
        if (CollUtil.isNotEmpty(resultList)) {
            for (PickTaskDDTO pickTaskDDTO : dtoList) {
                for (PickTaskDDTO taskDDTO : resultList) {
                    if (pickTaskDDTO.getPickTaskDId().equals(taskDDTO.getPickTaskDId())) {
                        BeanUtils.copyProperties(taskDDTO, pickTaskDDTO);
                    }
                }
            }
        }
    }

    /**
     * 整件-查询任务列表
     *
     * @param bldgId
     * @param warehouseId
     * @param pickOrderId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Map<String, Object> getTaskHListByPickOrder(String bldgId, String warehouseId, String pickOrderId, Integer pageNum, Integer pageSize) {
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");

        List<String> userAreaCodes = this.getUserAreaCodes(userDTO.getUserBizModel().getEmployeeNo(), warehouseId, "2011", new String[]{"WHOLE_REPLENISH_FIRST", "WHOLE_PICKING_FIRST", "WHOLE_PICKING", "WHOLE_REPLENISH"});
        if (CollUtil.isEmpty(userAreaCodes)) {
            throw new BizException("工号没有菜单权限!");
        }
        RestMessage<List<BaseWmsWarehouseArea>> areas = warehouseResource.getByAreaCodes(warehouseId, userAreaCodes.toArray(new String[0]));
        if (areas == null || CollUtil.isEmpty(areas.getData())) {
            throw new BizException("工号没有菜单权限.");
        }
        List<String> zjAreaCodes = CollUtil.toList("ZJK","MJK","AGVZ","AGVQX","AGVSP");
        List<String> areaCodes = new ArrayList<>();
        for (BaseWmsWarehouseArea datum : areas.getData()) {
            if (zjAreaCodes.contains(datum.getWarehouseAreaCategory())) {
                areaCodes.add(datum.getWarehouseAreaCode());
            }
        }
        if (CollUtil.isEmpty(areaCodes)) {
            throw new BizException("工号没有整件拣货权限!");
        }
        Map<String, Object> result = new HashMap<>();
        List<PickTaskDDTO> list = pickTaskHMapper.getTaskHListByPickOrder(bldgId, pickOrderId, warehouseId, userDTO.getUserBizModel().getEmployeeNo());
        if (CollUtil.isEmpty(list)) {
            //任务数
            int count = 4;
            //最大拣货件数
            BigDecimal maxPcs = BigDecimal.TEN;
            RestMessage<Map<String, BusinessControl>> rest = strategyResource.getControlByCodes(new String[]{"PICK_TASK_NUM", "PICK_TASK_MAX_PCS"}, warehouseId, null, enterpriseId, bldgId);
            if (rest.isSuccess() && rest.getData() != null) {
                Map<String, BusinessControl> conMap = rest.getData();
                if (conMap.containsKey("PICK_TASK_NUM")) {
                    count = Integer.parseInt(conMap.get("PICK_TASK_NUM").getRegValue());
                }
                if (conMap.containsKey("PICK_TASK_MAX_PCS")) {
                    maxPcs = new BigDecimal(conMap.get("PICK_TASK_MAX_PCS").getRegValue());
                }
            }
            List<Integer> pickTaskTypes = new ArrayList<>();
            pickTaskTypes.add(0);

            List<PickTaskH> hList = pickTaskHMapper.listPickTaskWholeRF(bldgId, null, enterpriseId, warehouseId, count, pickTaskTypes, areaCodes, "WHOLE_PICKING", null, null);
            if (CollUtil.isEmpty(hList)) {
                throw new BizException("没有待拣货的任务!");
            } else {
                log.info("开始执行索取方法+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
                if (hList.size() > 1) {
                    List<PickTaskH> list2 = new ArrayList<>();
                    Integer type = 0;
                    for (int i = 0; i < hList.size(); i++) {
                        PickTaskH h = hList.get(i);
                        if (i == 0)
                            type = h.getType();
                        int pcs = pickTaskHMapper.getWholePcs(h.getPickTaskId(), enterpriseId);
                        BigDecimal js = new BigDecimal(pcs);
                        if (i == 0 || (js.compareTo(maxPcs) <= 0 && Objects.equals(h.getType(), type))) {
                            list2.add(h);
                            maxPcs = maxPcs.subtract(js);
                        } else {
                            break;
                        }
                    }
                    hList = list2;
                }
                pickOrderId = String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId));
                if (hList.size() > 0) {
                    try {
                        for (PickTaskH pickTaskH : hList) {
                            pickTaskH.setPickOrderId(pickOrderId);
                            pickTaskH.setStatus("1");
                            pickTaskHMapper.updateFields(pickTaskH, FieldSelector.newInstance().include("status", "pickOrderId", "stationCode", "stationName", "stationId"));
                            //如果是整件索取，生成条码
                            if (pickTaskH.getPickTaskType() == 0) {
                                List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("pickTaskId", pickTaskH.getPickTaskId()).getMap(), PickTaskD.class);
                                if (pickTaskDList.size() > 0) {
                                    //生成打印条码
                                    for (PickTaskD pickTaskD : pickTaskDList) {
                                        pickTaskService.saveBarcode(
                                                Collections.singletonList(pickTaskH),
                                                Collections.singletonList(pickTaskD.getPickTaskDId()),
                                                pickOrderId,
                                                bldgId,
                                                warehouseId,
                                                enterpriseId
                                        );
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        throw new PrologException("拣货索取失败！" + e.getMessage());
                    }
                    PickOrder pickOrder = new PickOrder();
                    pickOrder.setPickOrderId(pickOrderId);
                    pickOrder.setStatus("0");
                    pickOrder.setWarehouseId(warehouseId);
                    pickOrder.setTaskCount(hList.size());
                    pickOrder.setOperatorId(userDTO.getId());
                    pickOrder.setOperatorName(userDTO.getNickname());
                    pickOrder.setOperatorCode(userDTO.getUsername());
                    pickOrder.setPickTaskType(hList.get(0).getPickTaskType());
                    pickOrder.setPrintStatus("1");
                    ModelUtils.generateBaseData(pickOrder, userTemplate::getUserDTO);
                    pickOrderMapper.save(pickOrder);
                    log.info("结束执行索取方法+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
                }
            }
            list = pickTaskHMapper.getTaskHListByPickOrder(bldgId, pickOrderId, warehouseId, userDTO.getUserBizModel().getEmployeeNo());
        }
        isSupervise(list, 50);
        List<String> pickTaskDIds = new ArrayList<>();
        RestMessage<List<BaseCommonDict>> billTypeList = commonClient.getDictBasicListByCodes("DO_BILL_TYPE", null);
        Map<String, String> billTypes = new HashMap<>();
        billTypeList.getData().forEach(baseCommonDict -> billTypes.put(baseCommonDict.getDictCode(), baseCommonDict.getDictName()));
        for (PickTaskDDTO dto : list) {
            dto.setBillTypeName(billTypes.get(dto.getBillType()));
            pickTaskDIds.add(dto.getPickTaskDId());
            BigDecimal replenishQty = this.replenishQty(dto.getItemId(), dto.getBatchNum(), dto.getLocatorCode(), enterpriseId, warehouseId);
            if (replenishQty.doubleValue() > 0
                    && dto.getAreaCategory().equals("ZJK")
                    && dto.getWarehouseAreaCode().equals("GJK")
            ) {
                dto.setReplenishPcs(replenishQty.divide(dto.getConversionRate(), 0));
            } else {
                dto.setReplenishPcs(BigDecimal.ZERO);
            }
        }
        if (CollectionUtil.isNotEmpty(pickTaskDIds)) {
//            List<PrintDataWithMark> printDataList =  pickTaskService.printWholeLabels(pickTaskDIds,null,warehouseId,0, userDTO.getNickname());
//            Map<String, List<PrintDataWithMark>> collect = printDataList.stream().collect(Collectors.groupingBy(PrintDataWithMark::getDataMark));
//            List<Map<String, Object>> printDatas = new ArrayList<>();
//            for (String s : collect.keySet()) {
//                Map<String, Object> map = new HashMap<>();
//                map.put("dataMark", s);
//                map.put("printData", collect.get(s));
//                printDatas.add(map);
//            }
            result.put("bizData", list);
//            result.put("printData", printDatas);
            return result;
        }

        return result;
    }

    /**
     * 零货/功能库房/整单-查询任务容器列表
     *
     * @param warehouseId
     * @param pickOrderId
     * @param itemId
     * @param locatorCode
     * @param manufacturerLotNum
     * @return
     */
    @Override
    public List<ContainerListDTO> getContainerList(String warehouseId, String pickOrderId, String itemId, String locatorCode, String manufacturerLotNum) {
        if (StringUtils.isBlank(pickOrderId))
            throw new ParameterException("任务包号不能为空");
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");
        List<ContainerListDTO> list = pickTaskHMapper.getContainerList(warehouseId, pickOrderId, itemId, locatorCode, manufacturerLotNum);
        return list;
    }


    /**
     * 零货/功能库房/整单-拣货确认
     *
     * @param list
     */
    @Override
    @Transactional
    @TxTransaction
    public Map<String, Object> pickTaskConfirm(List<ContainerListDTO> list) {
        if (list == null || list.size() == 0)
            throw new ParameterException("参数不能为空！");
        Map<String, Object> result = new HashMap<>();
        boolean flag = false;
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();
        Date date = new Date();
        List<String> lineIds = new ArrayList<>();
        List<String> redOmsBillIds = new ArrayList<>();
        List<UpdateStockVO> stockVOList = new ArrayList<>();
        List<ReplenishDetailVO> replenishDetailVOList = new ArrayList<>();
        for (ContainerListDTO vo : list) {
            BigDecimal pickQty = vo.getPickQty();//输入拣货数量
            if (pickQty == null)
                throw new ParameterException("pickQty 实际拣货数量不能为空！");
            List<InvStockOutDTO> dtoList = pickTaskHMapper.getPickTaskDId(vo.getBldgId(), vo.getWarehouseId(), vo.getPickTaskId(), vo.getItemId(), vo.getLocatorCode(), vo.getManufacturerLotNum());
            if (dtoList.size() > 0) {
                for (InvStockOutDTO dto : dtoList) {
                    if (pickQty.compareTo(new BigDecimal("0")) <= 0 && StringUtils.isBlank(vo.getRedReason())) {
                        break;
                    }
                    if (dto != null && !StringUtils.isEmpty(dto.getPickTaskDId())) {
                        String pickTaskDId = dto.getPickTaskDId();
                        String pickTaskId = dto.getPickTaskId();
                        BigDecimal req = dto.getQty();//需求数量
                        BigDecimal qty = null;//实际保存拣货数量
                        //需求数量>输入拣货数量
                        if (req.compareTo(pickQty) > 0) {
                            qty = pickQty;
                            pickQty = new BigDecimal("0");
                            //需求数量<=输入拣货数量
                        } else {
                            qty = req;
                            pickQty = pickQty.subtract(req);
                        }
                        PickTaskD d = pickTaskDMapper.findById(pickTaskDId, PickTaskD.class);
                        Map<String, Object> map = MapUtils.put("pickQty", qty).put("pickerId", operatorId).put("pickerNo", operatorCode).put("pickerName", operatorName).put("pickTime", date).getMap();
                        d.setPickQty(qty);
                        if("WLK".equals(d.getWarehouseAreaCode())){
                            map.put("flowStatus", "7");
                        }else {
                            map.put("flowStatus", "3");
                        }

                        PickTaskH pickTaskH = pickTaskHMapper.findById(pickTaskId, PickTaskH.class);
                        //需求数量大于拣货数量，则冲红
                        List<WaveBillDDO> billDDOList = pickTaskHMapper.getBillDList(enterpriseId, pickTaskH.getWarehouseId(), dto.getWaveStorageId());
                        if (req.compareTo(qty) > 0 && !StringUtils.isBlank(vo.getRedReason())) {
                            if (billDDOList.size() > 0) {
                                BigDecimal redQty = req.subtract(qty);
                                if (d.getPickTaskType() != null && d.getPickTaskType() == 0) {
                                    BigDecimal[] results = redQty.divideAndRemainder(billDDOList.get(0).getConversionRate());
                                    if (results[1].compareTo(BigDecimal.ZERO) > 0)
                                        throw new PrologException("整件红冲数量不能为零散数!");
                                }
                                SaleRedRecord saleRedRecord = new SaleRedRecord();
                                saleRedRecord.setQty(redQty);
                                saleRedRecord.setReason(vo.getRedReason());
                                saleRedRecord.setBillDId(billDDOList.get(0).getId());
                                saleRedRecord.setBillId(billDDOList.get(0).getBillId());
                                saleRedRecord.setItemId(billDDOList.get(0).getItemId());
                                saleRedRecord.setSrcCode(billDDOList.get(0).getSrcCode());
                                saleRedRecord.setStatus(0);
                                saleRedRecord.setType(0);
                                saleRedRecord.setPickerId(operatorId);
                                saleRedRecord.setPickerName(operatorName);
                                saleRedRecord.setPickerNo(operatorCode);
                                saleRedRecord.setBldgId(pickTaskH.getBldgId());
                                saleRedRecord.setWarehouseId(pickTaskH.getWarehouseId());
                                saleRedRecord.setEnterpriseId(enterpriseId);
                                saleRedRecord.setCreator(operatorId);
                                saleRedRecord.setCreatorName(operatorName);
                                saleRedRecord.setGmtCreate(date);
                                saleRedRecord.setSrcId(billDDOList.get(0).getSrcId());
                                saleRedRecord.setSrcLineId(billDDOList.get(0).getSrcLineId());
                                saleRedRecordMapper.save(saleRedRecord);
                                //出库预占调整
                                UpdateStockVO updateStockVO = new UpdateStockVO();
                                updateStockVO.setBillId(billDDOList.get(0).getBillId());
                                updateStockVO.setBillDId(billDDOList.get(0).getId());
                                updateStockVO.setPickTaskDId(pickTaskDId);
                                updateStockVO.setRedQty(redQty);
                                stockVOList.add(updateStockVO);

                                map.put("saleRedQty", redQty.add(d.getSaleRedQty() == null ? BigDecimal.ZERO : d.getSaleRedQty()));
                                //转移到盘点库
                                RestMessage<String> rest = warehouseResource.getLocatorIdByCategory("PDK", dto.getWarehouseId());
                                if (!rest.isSuccess() || rest.getData() == null) {
                                    throw new PrologException("查询盘点库货位出错,或货位为空:" + rest.getMessage());
                                }
                                pickTaskService.updateStock(stockVOList, dto.getWarehouseId(), rest.getData());

//                                //查询barcoded
//                                Criteria crt = Criteria.forClass(BarCodeDDO.class);
//                                Restriction r11 = Restrictions.eq("wmsPickTaskDId", pickTaskDId);
//                                Restriction r12 = Restrictions.eq("warehouseId", pickTaskH.getWarehouseId());
//                                crt.setRestriction(Restrictions.and(r11, r12));
//                                List<BarCodeDDO> barCodeDDOS = barcodeDMapper.findByCriteria(crt);
//                                if (barCodeDDOS == null || barCodeDDOS.size() <= 0) {
//                                    throw new BizException("查询条码表明细失败!");
//                                }
//                                //查询barcodeh
//                                Criteria crth = Criteria.forClass(BarcodeHDO.class);
//                                List<String> barCodeIds = barCodeDDOS.stream().map(BarCodeDDO::getBarcodeId).collect(Collectors.toList());
//                                Restriction res11 = Restrictions.in("id", barCodeIds.toArray());
//                                Restriction res12 = Restrictions.eq("warehouseId", pickTaskH.getWarehouseId());
//                                crth.setRestriction(Restrictions.and(res11, res12));
//                                List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByCriteria(crt);
//                                if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
//                                    throw new BizException("查询条码表汇总失败!");
//                                }

                                //如果拣货明细全部红冲
                                if (redQty.add(d.getSaleRedQty() == null ? BigDecimal.ZERO : d.getSaleRedQty()).compareTo(d.getQty()) == 0) {
                                    List<Integer> countList = pickTaskHMapper.getRedCount(billDDOList.get(0).getSrcId(), billDDOList.get(0).getSrcLineId(), enterpriseId);
                                    //整单红冲则回传erp
                                    if (countList.size() > 1 && countList.get(0) == 0 && countList.get(1) == 0) {
                                        List<String> omsBillIds = barcodeHMapper.getOmsBillIds(pickTaskH.getBillGroupId(), enterpriseId);
                                        if (omsBillIds.size() > 0) {
                                            redOmsBillIds.addAll(omsBillIds);
                                        }

                                        String billGroupId = pickTaskH.getBillGroupId();
                                        Criteria crt1 = Criteria.forClass(PickTaskH.class);
                                        Restriction r1 = Restrictions.eq("billGroupId", billGroupId);
                                        Restriction r2 = Restrictions.eq("warehouseId", pickTaskH.getWarehouseId());
                                        Restriction r3 = Restrictions.ne("status", "10");
                                        crt1.setRestriction(Restrictions.and(r1, r2, r3));
                                        pickTaskHMapper.updateMapByCriteria(MapUtils.put("status", "10").getMap(), crt1);
                                    }

                                    if (!StringUtils.isBlank(pickTaskH.getContainerCode())) {
                                        //释放容器
                                        ContainerQueryVO containerQueryVO = new ContainerQueryVO();
                                        containerQueryVO.setContainerCode(pickTaskH.getContainerCode());
                                        containerQueryVO.setWarehouseId(pickTaskH.getWarehouseId());
                                        warehouseResource.release(containerQueryVO);
                                    }

//                                    barcodeDMapper.deleteByCriteria(crt);
//                                    //判断barcoded是否存在
//                                    Criteria ctrBarcodeD = Criteria.forClass(BarCodeDDO.class);
//                                    Restriction rBarcodeD = Restrictions.in("barcodeId", barCodeIds.toArray());
//                                    ctrBarcodeD.setRestriction(rBarcodeD);
//                                    long count = barcodeDMapper.findCountByCriteria(ctrBarcodeD);
//                                    if(count == 0){
//                                        barcodeHMapper.deleteByIds(barCodeIds.toArray(), BarcodeHDO.class);
//                                    }
                                } else {
//                                    if(!StringUtils.isEmpty(barcodeHDOS.get(0).getBarcode())){
//                                        barcodeHDOS = barcodeHDOS.stream().sorted(Comparator.comparing(BarcodeHDO::getBarcode)).collect(Collectors.toList());
//                                    }
//                                    //如果部分冲红，则将多余的barcode删除
//                                    BigDecimal[] n = d.getQty().divideAndRemainder(billDDOList.get(0).getConversionRate());
//                                    if (n[1].compareTo(BigDecimal.ZERO) > 0) {
//                                        //为零货
//                                        barcodeDMapper.deleteByCriteria(crt);
//                                        long count = barcodeDMapper.findCountByMap(MapUtils.put("barcodeId", barCodeIds.get(0)).getMap(), BarCodeDDO.class);
//                                        if (count == 0) {
//                                            barcodeHMapper.deleteByIds(barCodeIds.toArray(), BarcodeHDO.class);
//                                        }
//                                    } else {
//                                        List<String> delBarCodeIds = new ArrayList<>();
//                                        List<String> delBarCodeDIds = new ArrayList<>();
//                                        for (int i = 0; i < n[0].intValue(); i++) {
//                                            BarcodeHDO barcodeHDO = barcodeHDOS.get(i);
//                                            delBarCodeIds.add(barcodeHDO.getId());
//                                            BarCodeDDO barCodeDDO = barCodeDDOS.stream().filter(item -> item.getBarcodeId().equals(barcodeHDO.getId())).findFirst().orElse(null);
//                                            if (barCodeDDO == null) {
//                                                throw new BizException("匹配条码表明细失败！");
//                                            }
//                                            delBarCodeDIds.add(barCodeDDO.getId());
//                                        }
//                                        barcodeHMapper.deleteByIds(delBarCodeIds.toArray(), BarcodeHDO.class);
//                                        barcodeDMapper.deleteByIds(delBarCodeDIds.toArray(), BarCodeDDO.class);
//                                    }
                                    // 更新对应外复核数量
//                                    barcodeDMapper.updateMapByCriteria(MapUtils.put("qty", billDDOList.get(0).getConversionRate()).getMap(), crt);
                                }
                            }
                        }
//                        // 更新对应外复核数量
//                        Criteria c = Criteria.forClass(BarCodeDDO.class);
//                        Restriction r11 = Restrictions.eq("wmsPickTaskDId", pickTaskDId);
//                        Restriction r12 = Restrictions.eq("warehouseId", pickTaskH.getWarehouseId());
//                        c.setRestriction(Restrictions.and(r11, r12));
//                        barcodeDMapper.updateMapByCriteria(MapUtils.put("qty", billDDOList.get(0).getConversionRate()).getMap(), c);
                        pickTaskDMapper.updateMapById(pickTaskDId, map, PickTaskD.class);

                        //如果是补货任务，更新补货表状态
                        if (pickTaskH.getType() == 1) {
                            String moveId = pickTaskHMapper.getMoveTaskId(pickTaskDId, vo.getWarehouseId());
                            if (moveId != null) {
                                //2021-10-19 由库内服务确认补货任务状态并调用出库同步接口 wujunjie
//                                moveTaskMapper.updateMapById(moveId, MapUtils.put("status", "1").put("gmtModified", date).put("modifier", operatorId).put("modifierName", operatorName).put("outstoreWorkerName", operatorName).getMap(), MoveTaskDO.class);
                                MoveTaskDO move = moveTaskMapper.findById(moveId, MoveTaskDO.class);
                                lineIds.add(move.getDetailId());
                                ReplenishDetailVO replenishDetailVO = new ReplenishDetailVO();
                                replenishDetailVO.setLineId(move.getDetailId());
                                replenishDetailVO.setSrcLineId(pickTaskDId);
                                replenishDetailVOList.add(replenishDetailVO);
                            }
                        }
                        Criteria crt = Criteria.forClass(PickTaskD.class);
                        Restriction r1 = Restrictions.eq("pickTaskId", pickTaskId);
                        Restriction r2 = Restrictions.eq("enterpriseId", enterpriseId);
                        Restriction r3 = Restrictions.isnull("pickTime");
                        Restriction r4 = Restrictions.eq("warehouseId", vo.getWarehouseId());
                        Restriction r5 = Restrictions.ne("pickTaskDId", pickTaskDId);
                        crt.setRestriction(Restrictions.and(r1, r2, r3, r4, r5));
                        //查询 拣选任务主表下明细未确认条数
                        long count = pickTaskDMapper.findCountByCriteria(crt);
                        //如果明细都已确认，则任务主表状态更新为2：待复核
                        if (count == 0) {
                            //任务主表状态更新：2=待复核索取拣选任务 10=补货任务完成
                            if("WLK".equals(d.getWarehouseAreaCode())){
                                pickTaskHMapper.updateMapById(pickTaskId, MapUtils.put("status", "10").getMap(), PickTaskH.class);
                            }else {
                                pickTaskHMapper.updateMapById(pickTaskId, MapUtils.put("status", pickTaskH.getType() == 1 ? "5" : "2").getMap(), PickTaskH.class);
                            }
                            String pickOrderId = pickTaskH.getPickOrderId();
                            //查询未确认的拣选任务    
                            Integer count2 = pickTaskHMapper.getUnConfirmCountH(pickTaskId, pickOrderId, vo.getBldgId(), vo.getWarehouseId());
                            //拣选单状态更新为2：拣选完成
                            if (count2 == 0) {
                                flag = true;
                                result.put("billId",pickTaskH.getBillGroupId());
                                if("WLK".equals(d.getWarehouseAreaCode())){
                                    pickOrderMapper.updateMapById(pickOrderId, MapUtils.put("status", "10").getMap(), PickOrder.class);
                                }else {
                                    pickOrderMapper.updateMapById(pickOrderId, MapUtils.put("status", "2").getMap(), PickOrder.class);
                                }

                                // 整个订单完成,回传状态
                                if (pickTaskH.getType() == 0) {
//                                    orderOutboundStatusBackService.sendOutboundOrderStatusOms(pickTaskH.getBillGroupId(), "", "", "", "", "30", BigDecimal.ZERO);
                                }
                            }

//                            //如果是快递申请面单
//                            OmsDoBillHDO omsDoBillHDO = omsDoBillHMapper.findById(pickTaskH.getBillGroupId(), OmsDoBillHDO.class);
//                            if(omsDoBillHDO == null){
//                                throw new BizException("查询oms_do_bill_h失败!");
//                            }
                            gnkfGenerateBarcode(pickTaskH);
                            if("WLK".equals(d.getWarehouseAreaCode())){
                                //物料库更新barcodeh状态
                                List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("pickTaskId", pickTaskH.getPickTaskId()).getMap(), PickTaskD.class);
                                List<String> pickTaskDIds = pickTaskDList.stream().map(PickTaskD::getPickTaskDId).collect(Collectors.toList());
                                Criteria bdcrt = Criteria.forClass(BarCodeDDO.class);
                                Restriction bdres1 = Restrictions.in("wmsPickTaskDId", pickTaskDIds.toArray());
                                Restriction bdres2 = Restrictions.eq("warehouseId", pickTaskH.getWarehouseId());
                                bdcrt.setRestriction(Restrictions.and(bdres1, bdres2));

                                barcodeDMapper.updateMapByCriteria(MapUtils.put("checkStatus", "5").getMap(),bdcrt);

                                List<BarCodeDDO> dList = barcodeDMapper.findByCriteria(bdcrt);
                                Set<String> barcodeIds = dList.stream().map(BarCodeDDO::getBarcodeId).collect(Collectors.toSet());
                                Criteria barcodehcrt = Criteria.forClass(BarcodeHDO.class);
                                Restriction resth1 = Restrictions.in("id", barcodeIds.toArray());
                                barcodehcrt.setRestriction(resth1);
                                barcodeHMapper.updateMapByCriteria(MapUtils.put("checkStatus", "5")
                                        .put("checkerId",userDTO.getId())
                                        .put("checkerNo",userDTO.getUserBizModel().getEmployeeNo())
                                        .put("checkerName",userDTO.getNickname())
                                        .put("checkTime",new Date())
                                        .put("checkerId2",userDTO.getId())
                                        .put("checkerNo2",userDTO.getUserBizModel().getEmployeeNo())
                                        .put("checkerName2",userDTO.getNickname())
                                        .put("checkTime2",new Date()).getMap(),barcodehcrt);
                            }

//                            List<PrintParam> printData = getPrintData(pickTaskH, pickTaskDId, vo.getPickQty(), billDDOList);
//                            result.put("printData",printData);
//                            if("1".equals(omsDoBillHDO.getCarrierType())){
//                                getPrintData(pickTaskH, pickTaskDId, pickQty, billDDOList);
//
//                            }else {
//                                List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByMap(MapUtils.put("", omsDoBillHDO.getBillid()).getMap(), BarcodeHDO.class);
//                                List<String> barcodes = barcodeHDOS.stream().map(BarcodeHDO::getBarcode).collect(toList());
//                                printBarcodes(barcodes,omsDoBillHDO.getConsignorid(),omsDoBillHDO.getBranchid());
//                            }

                            //判断订单是否全部完成
                            if("WLK".equals(d.getWarehouseAreaCode())){
                                Criteria crth = Criteria.forClass(PickTaskH.class);
                                Restriction rh1 = Restrictions.eq("billGroupId", pickTaskH.getBillGroupId());
                                Restriction rh2 = Restrictions.ne("status", "10");
                                crth.setRestriction(Restrictions.and(rh1, rh2));
                                long umCompeleteCount = pickTaskHMapper.findCountByCriteria(crth);
                                if(umCompeleteCount <= 0){
                                    ServletRequestAttributes reqa = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
                                    new Thread(()-> {
                                        RequestContextHolder.setRequestAttributes(reqa, false);
                                        ServletRequestAttributes servletRequestAttributes =
                                                (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
                                        String userkey = servletRequestAttributes.getRequest().getHeader("UserKey");

                                        if (!HystrixRequestContext.isCurrentThreadInitialized()) {
                                            HystrixRequestContext.initializeContext();
                                        }
                                        HystrixVarUtil.setUserKey(userkey);
                                        try {
                                            postBackErpByTable(CollUtil.toList(pickTaskH.getBillGroupId()));
                                        }catch (Exception e) {
                                            log.error("RF复核完成回写回传中间表失败：{}", e.getMessage());
                                            omsDoBillHMapper.updateMapById(pickTaskH.getBillGroupId(),MapUtils.put("attrStr9","N").getMap(),OmsDoBillHDO.class);
                                        }finally {
                                            RequestContextHolder.resetRequestAttributes();
                                        }
                                    }).start();

                                    OmsDoBillHDO omsDoBillHDO = omsDoBillHMapper.findById(pickTaskH.getBillGroupId(), OmsDoBillHDO.class);
                                    String username = userDTO.getUsername();

                                    new Thread(()-> {
                                        RequestContextHolder.setRequestAttributes(reqa, false);
                                        ServletRequestAttributes servletRequestAttributes =
                                                (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
                                        String userkey = servletRequestAttributes.getRequest().getHeader("UserKey");

                                        if (!HystrixRequestContext.isCurrentThreadInitialized()) {
                                            HystrixRequestContext.initializeContext();
                                        }
                                        HystrixVarUtil.setUserKey(userkey);
                                        try {
                                            outBoundUploadCircubill(omsDoBillHDO,username);
                                        }catch (Exception e) {
                                            log.error("RF复核完成上传监管码失败：{}", e.getMessage());

                                        }finally {
                                            RequestContextHolder.resetRequestAttributes();
                                        }
                                    }).start();


                                    //释放容器号
                                    List<PickTaskH> pickTaskHList = pickTaskHMapper.findByMap(MapUtils.put("billGroupId", pickTaskH.getBillGroupId()).put("pickTaskType",2).getMap(), PickTaskH.class);
                                    if(pickTaskHList != null && pickTaskHList.size() > 0){
                                        List<String> containerCodes = pickTaskHList.stream().map(PickTaskH::getContainerCode).collect(toList());
                                        //释放容器
                                        ContainerQueryVO containerQueryVO = new ContainerQueryVO();
                                        containerQueryVO.setContainerCodeList(containerCodes);
                                        containerQueryVO.setWarehouseId(pickTaskHList.get(0).getWarehouseId());
                                        warehouseResource.release(containerQueryVO);
                                    }
                                }

                            }

                        }
                        //扣减库存
                        this.invStockConfirm(d, dto.getWarehouseId(),"2");

//                        //作业完成回告EIS
//                        if("MJZ".equals(d.getWarehouseAreaCode()) || "AGVZ".equals(d.getWarehouseAreaCode())){
//                            //调用作业完成确认回告
//                            List<OperationCompleteVO> operationCompleteVOS = pkgWorkCompeletToEisParams(pickTaskH.getPickOrderId(),d.getContainerCode());
//                            eisHandler.operationComplete(operationCompleteVOS);
//                        }
                    }
                }
                if (pickQty.compareTo(new BigDecimal("0")) > 0) {
                    throw new BizException("确认数量大于计划数量");
                }
            }
        }
        // 库内，下架确认
        if (lineIds.size() > 0) {
            MoveConfirmParamsVO vo = new MoveConfirmParamsVO();
            vo.setLineIds(lineIds.toArray(new String[lineIds.size()]));
            vo.setMoveFlag(0);
            vo.setReplenishDetailVOList(replenishDetailVOList);
            RestMessage restMessage = operateResource.confirmReplenish(vo);
            if (!restMessage.isSuccess()) {
                log.error("调用库存下架确认接口出错！" + restMessage.getMessage() + "，vo:" + JSON.toJSONString(vo));
                throw new PrologException("调用库存下架确认接口出错！" + restMessage.getMessage());
            }
        }
        // 整单红冲回传ERP
        // pickTaskService.saveOutcomingRecord(redOmsBillIds);
        // 业务参数配置内/外复核回传ERP，使用 PostBackErpHandle by Huanglh 20220112
        // 红冲只需要需要判断一个业务配置参数
        if (ObjectUtils.isNotNull(redOmsBillIds)) {
            IStrategyHandle strategyHandle = strategySelector.selectHandle(Arrays.asList(
                    STRATEGY_CODE.POST_BACK_ERP__MQ__ON), enterpriseId, list.get(0).getWarehouseId(), "do");
            strategyHandle.execute(redOmsBillIds);
        }
        result.put("flag",flag);
        return result;
    }

    /**
     * 组装作业完成回告EIS入参
     * @return
     */
    @Transactional
    public List<OperationCompleteVO> pkgWorkCompeletToEisParams(String pickOrderId,String containerNo) {
        List<OperationCompleteVO> vos = new ArrayList<>();
        List<PickTaskD> pickTaskDS = pickTaskDMapper.getPickTaskdByPickOrderIdAndContainerCode(containerNo, pickOrderId);
        if(pickTaskDS == null || pickTaskDS.size() <= 0){
            throw new BizException("查询出库任务失败!");
        }
        //判断容器下所有的任务是否全部完成
        long count = pickTaskDS.stream().filter(item -> Integer.valueOf(item.getFlowStatus()) < Integer.valueOf(PickTaskDFLowStatus.TASK_CONFIRMED.getCode())).count();
        if(count > 0){
            return null;
        }
        Set<String> srcIds = pickTaskDS.stream().map(PickTaskD::getSrcId).collect(Collectors.toSet());
        List<OmsDoBillHDO> omsDoBillHDOS = omsDoBillHMapper.findByIds(OmsDoBillHDO.class, srcIds.toArray(), null);
        if(omsDoBillHDOS == null || omsDoBillHDOS.size() <= 0){
            throw new BizException("作业完成回告EIS，查询订单失败!");
        }

        OperationCompleteVO operationCompleteVO = new OperationCompleteVO();
        operationCompleteVO.setMsgId(UUIDUtils.generateWithoutSeperator());
        operationCompleteVO.setContainerNo(containerNo);
        List<OperationCompleteItemVO> subList = new ArrayList<>();
        for (PickTaskD pickTaskD : pickTaskDS) {
            OmsDoBillHDO omsDoBillHDO = omsDoBillHDOS.stream().filter(item -> item.getBillid().equals(pickTaskD.getSrcId())).findFirst().orElse(null);
            if(omsDoBillHDO == null){
                throw new BizException("作业完成确认回告EIS，匹配订单失败!");
            }

            OperationCompleteItemVO itemVO = new OperationCompleteItemVO();
            itemVO.setWarehouseId(pickTaskD.getWarehouseId());
            itemVO.setEnterpriseId(pickTaskD.getEnterpriseId());

            OutBoundRequestEnum outBoundRequestEnum = OutBoundRequestEnum.get(omsDoBillHDO.getBilltype());
            itemVO.setWorkType(outBoundRequestEnum.getWorkType());
            itemVO.setBusinessType(outBoundRequestEnum.getBusinessType());

            itemVO.setTaskId(pickTaskD.getPickTaskId());
            itemVO.setBillNo(omsDoBillHDO.getBillno());
//            itemVO.setTaskLineId(pickTaskD.getPickTaskDId());
            if(StringUtils.isBlank(pickTaskD.getSplitSourceId())){
                itemVO.setTaskLineId(pickTaskD.getPickTaskDId());
            }else {
                itemVO.setTaskLineId(pickTaskD.getSplitSourceId());
            }
            itemVO.setItemId(pickTaskD.getItemId());
            if("MJK".equals(pickTaskD.getWarehouseAreaCode())){
                itemVO.setWmsLocationCode("MJZ");
            }else {
                itemVO.setWmsLocationCode(pickTaskD.getWarehouseAreaCode());
            }
            itemVO.setQty(String.valueOf(pickTaskD.getQty()));
            itemVO.setLotId(pickTaskD.getBatchId());
//            itemVO.setInventoryQty(Double.valueOf(getItemStock(pickTaskD)) - Double.valueOf(itemVO.getQty()));

            itemVO.setInventoryQty(getItemStock(pickTaskD));
            subList.add(itemVO);
        }
        operationCompleteVO.setSubList(subList);

        vos.add(operationCompleteVO);
        return vos;
    }

    /**
     * 整件-拣货确认
     *
     * @param pickOrderId
     * @param pickTaskDId
     * @param pickTaskId
     * @param pickQty
     * @param redType
     * @return
     */
    @Override
    @Transactional
    @TxTransaction
    public Map<String, Object> pickTaskHConfirm(
            String pickOrderId,
            String pickTaskDId,
            String pickTaskId,
            BigDecimal pickQty,
            String redReason,
            String redType
    ) {
        if (StringUtils.isBlank(pickOrderId))
            throw new ParameterException("pickOrderId不能为空");
        if (StringUtils.isBlank(pickTaskDId))
            throw new ParameterException("pickTaskDId不能为空");
        if (StringUtils.isBlank(pickTaskId))
            throw new ParameterException("pickTaskId不能为空");
        if (pickQty == null)
            throw new ParameterException("pickQty不能为空");
        Boolean flag = false;
        Map<String, Object> result = new HashMap<>();
        List<String> redOmsBillIds = new ArrayList<>();
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();
        /*String enterpriseId = "789478194809016320";
        String operatorCode = "yjtest001";
        String operatorName = "鹰江用户";
        String operatorId = "789478759186173952";*/
        PickTaskD d = pickTaskDMapper.findById(pickTaskDId, PickTaskD.class);
        if (Integer.valueOf(d.getFlowStatus()) >= 3) {
            throw new BizException("任务明细已确认！");
        }
        WaveStorageDO s = waveStorageMapper.findById(d.getWaveStorageId(), WaveStorageDO.class);
        Date date = new Date();
        Map<String, Object> map = MapUtils.put("pickQty", pickQty).put("pickerId", operatorId).put("pickerNo", operatorCode).put("pickerName", operatorName).put("pickTime", date).getMap();
        d.setPickQty(pickQty);
        if("WLK".equals(d.getWarehouseAreaCode())){
            map.put("flowStatus", "7");
        }else {
            map.put("flowStatus", "3");
        }

        PickTaskH h = pickTaskHMapper.findById(pickTaskId, PickTaskH.class);
        String warehouseId = h.getWarehouseId();
        List<WaveBillDDO> billDDOList = pickTaskHMapper.getBillDList(enterpriseId, h.getWarehouseId(), d.getWaveStorageId());
        boolean isWholeRed = false;
        // 需求数量大于拣货数量，则冲红
        if (d.getQty().compareTo(pickQty) > 0) {
            if (billDDOList.size() > 0) {
                BigDecimal redQty = d.getQty().subtract(pickQty);
                SaleRedRecord saleRedRecord = new SaleRedRecord();
                saleRedRecord.setQty(redQty);
                saleRedRecord.setPickTaskDId(pickTaskDId);
                if (StringUtils.isBlank(redType))
                    throw new ParameterException("红冲类型不能为空");
                ArrayList<String> redTypes = CollUtil.toList("1", "2");
                if (!redTypes.contains(redType)) {
                    throw new ParameterException("红冲类型不正确");
                }
                if (StringUtils.isBlank(redReason))
                    throw new ParameterException("红冲原因不能为空");
                saleRedRecord.setReason(redReason);
                saleRedRecord.setBillDId(billDDOList.get(0).getId());
                saleRedRecord.setBillId(billDDOList.get(0).getBillId());
                saleRedRecord.setItemId(billDDOList.get(0).getItemId());
                saleRedRecord.setSrcCode(billDDOList.get(0).getSrcCode());
                saleRedRecord.setStatus(0);
                saleRedRecord.setType(0);
                saleRedRecord.setPickerId(operatorId);
                saleRedRecord.setPickerName(operatorName);
                saleRedRecord.setPickerNo(operatorCode);
                saleRedRecord.setBldgId(h.getBldgId());
                saleRedRecord.setWarehouseId(h.getWarehouseId());
                saleRedRecord.setEnterpriseId(enterpriseId);
                saleRedRecord.setCreator(operatorId);
                saleRedRecord.setCreatorName(operatorName);
                saleRedRecord.setGmtCreate(new Date());
                saleRedRecord.setSrcId(billDDOList.get(0).getSrcId());
                saleRedRecord.setSrcLineId(billDDOList.get(0).getSrcLineId());
                saleRedRecordMapper.save(saleRedRecord);
                // 出库预占调整
                List<UpdateStockVO> stockVOList = new ArrayList<>();
                UpdateStockVO updateStockVO = new UpdateStockVO();
                updateStockVO.setBillId(billDDOList.get(0).getBillId());
                updateStockVO.setBillDId(billDDOList.get(0).getId());
                updateStockVO.setPickTaskDId(pickTaskDId);
                updateStockVO.setRedQty(redQty);
                updateStockVO.setBatchId(d.getBatchId());
                updateStockVO.setQty(d.getQty());
                stockVOList.add(updateStockVO);
                // 转移到盘点库
                RestMessage<String> rest = warehouseResource.getLocatorIdByCategory("PDK", warehouseId);
                if (!rest.isSuccess() || rest.getData() == null) {
                    throw new PrologException("查询盘点库货位出错,或货位为空:" + rest.getMessage());
                }
                if ("2".equals(redType)) {
                    pickTaskService.updateStock2(stockVOList, warehouseId, rest.getData(), redType);
                } else {
//                    pickTaskService.updateStock(stockVOList, warehouseId, rest.getData());
                }

                map.put("saleRedQty", redQty.add(d.getSaleRedQty() == null ? new BigDecimal(0) : d.getSaleRedQty()));

                //查询barcoded
                Criteria crt = Criteria.forClass(BarCodeDDO.class);
                Restriction r11 = Restrictions.eq("wmsPickTaskDId", pickTaskDId);
                Restriction r12 = Restrictions.eq("warehouseId", h.getWarehouseId());
                crt.setRestriction(Restrictions.and(r11, r12));
                List<BarCodeDDO> barCodeDDOS = barcodeDMapper.findByCriteria(crt);
                if (barCodeDDOS == null || barCodeDDOS.size() <= 0) {
                    throw new BizException("查询条码表明细失败!");
                }
                //查询barcodeh
                Criteria crth = Criteria.forClass(BarcodeHDO.class);
                List<String> barCodeIds = barCodeDDOS.stream().map(BarCodeDDO::getBarcodeId).collect(Collectors.toList());
                Restriction res11 = Restrictions.in("id", barCodeIds.toArray());
                Restriction res12 = Restrictions.eq("warehouseId", h.getWarehouseId());
                crth.setRestriction(Restrictions.and(res11, res12));
                List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByCriteria(crth);
                if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
                    throw new BizException("查询条码表汇总失败!");
                }
                // 如果明细全部红冲，则删除对应外复核数据
                if (redQty.add(d.getSaleRedQty() == null ? new BigDecimal(0) : d.getSaleRedQty()).compareTo(d.getQty()) == 0) {
                    pickTaskHMapper.updateMapById(pickTaskId, MapUtils.put("status", "10").getMap(), PickTaskH.class);
                    barcodeDMapper.deleteByCriteria(crt);
                    barcodeHMapper.deleteByIds(barCodeIds.toArray(), BarcodeHDO.class);

                    isWholeRed = true;
                } else {
                    if (!StringUtils.isBlank(barcodeHDOS.get(0).getBarcode())) {
                        barcodeHDOS = barcodeHDOS.stream().sorted(Comparator.comparing(BarcodeHDO::getBarcode)).collect(Collectors.toList());
                    }
                    //如果部分冲红，则将多余的barcode删除
                    BigDecimal js = redQty.divide(billDDOList.get(0).getConversionRate());
                    List<String> delBarCodeIds = new ArrayList<>();
                    List<String> delBarCodeDIds = new ArrayList<>();
                    for (int i = 0; i < js.intValue(); i++) {
                        BarcodeHDO barcodeHDO = barcodeHDOS.get(i);
                        delBarCodeIds.add(barcodeHDO.getId());
                        BarCodeDDO barCodeDDO = barCodeDDOS.stream().filter(item -> item.getBarcodeId().equals(barcodeHDO.getId())).findFirst().orElse(null);
                        if (barCodeDDO == null) {
                            throw new BizException("匹配条码表明细失败！");
                        }
                        delBarCodeDIds.add(barCodeDDO.getId());
                    }
                    barcodeHMapper.deleteByIds(delBarCodeIds.toArray(), BarcodeHDO.class);
                    barcodeDMapper.deleteByIds(delBarCodeDIds.toArray(), BarCodeDDO.class);
                    // 更新对应外复核数量
                    barcodeDMapper.updateMapByCriteria(MapUtils.put("qty", billDDOList.get(0).getCaseConversionRate()).getMap(), crt);
                }
                // 如果拣货明细全部红冲
                if (redQty.add(d.getSaleRedQty() == null ? new BigDecimal(0) : d.getSaleRedQty()).compareTo(d.getQty()) == 0) {
                    List<Integer> countList = pickTaskHMapper.getRedCount(billDDOList.get(0).getSrcId(), billDDOList.get(0).getSrcLineId(), enterpriseId);
                    // 整单红冲则回传erp
                    if (countList.size() > 1 && countList.get(0) == 0 && countList.get(1) == 0) {
                        List<String> omsBillIds = barcodeHMapper.getOmsBillIds(h.getBillGroupId(), enterpriseId);
                        if (omsBillIds.size() > 0) {
                            redOmsBillIds.addAll(omsBillIds);
                        }
                        String billGroupId = h.getBillGroupId();
                        Criteria crt1 = Criteria.forClass(PickTaskH.class);
                        Restriction r1 = Restrictions.eq("billGroupId", billGroupId);
                        Restriction r2 = Restrictions.eq("warehouseId", warehouseId);
                        Restriction r3 = Restrictions.ne("status", "10");
                        crt1.setRestriction(Restrictions.and(r1, r2, r3));
                        pickTaskHMapper.updateMapByCriteria(MapUtils.put("status", "10").getMap(), crt1);

                        Criteria crt2 = Criteria.forClass(BarcodeHDO.class);
                        Restriction r4 = Restrictions.eq("billGroupId", billGroupId);
                        Restriction r5 = Restrictions.eq("warehouseId", warehouseId);
                        Restriction r6 = Restrictions.ne("checkStatus", "5");
                        crt2.setRestriction(Restrictions.and(r4, r5, r6));
                        barcodeHMapper.updateMapByCriteria(MapUtils.put("checkStatus", "5").getMap(), crt2);
                    }
                }
            }
        }
        pickTaskDMapper.updateMapById(pickTaskDId, map, PickTaskD.class);
        // 如果是整件任务，则将对应条码表更新为0-待复核索取
        if (h.getPickTaskType() == 0) {
            List<BarCodeDDO> dList = barcodeDMapper.findByMap(MapUtils.put("wmsPickTaskDId", pickTaskDId).put("warehouseId", warehouseId).getMap(), BarCodeDDO.class);
            if (dList.size() > 0)
                barcodeHMapper.updateMapById(dList.get(0).getBarcodeId(), MapUtils.put("checkStatus", "0").getMap(), BarcodeHDO.class);

            //更新外复核数量
            Criteria c = Criteria.forClass(BarCodeDDO.class);
            Restriction r11 = Restrictions.eq("wmsPickTaskDId", pickTaskDId);
            Restriction r12 = Restrictions.eq("warehouseId", h.getWarehouseId());
            c.setRestriction(Restrictions.and(r11, r12));
            barcodeDMapper.updateMapByCriteria(MapUtils.put("qty", billDDOList.get(0).getConversionRate()).getMap(), c);
        }
        Criteria crt = Criteria.forClass(PickTaskD.class);
        Restriction r1 = Restrictions.eq("pickTaskId", pickTaskId);
        Restriction r2 = Restrictions.eq("enterpriseId", enterpriseId);
        Restriction r3 = Restrictions.isnull("pickTime");
        Restriction r4 = Restrictions.eq("warehouseId", warehouseId);
        Restriction r5 = Restrictions.ne("pickTaskDId", pickTaskDId);
        crt.setRestriction(Restrictions.and(r1, r2, r3, r4, r5));
        // 查询 拣选任务主表下明细未确认条数
        long count = pickTaskDMapper.findCountByCriteria(crt);
        // 如果明细都已确认，则任务主表状态更新为2：待复核
        if (count == 0) {
            // 任务主表状态更新
            if (h.getType() == 1) {
                pickTaskHMapper.updateMapById(pickTaskId, MapUtils.put("status", "5").getMap(), PickTaskH.class);
            } else {
                if("WLK".equals(d.getWarehouseAreaCode())){
                    pickTaskHMapper.updateMapById(pickTaskId, MapUtils.put("status", "10").getMap(), PickTaskH.class);
                }else {
                    pickTaskHMapper.updateMapById(pickTaskId, MapUtils.put("status", "2").getMap(), PickTaskH.class);
                }

                List<BarCodeDDO> dList = barcodeDMapper.findByMap(MapUtils.put("wmsPickTaskDId", pickTaskDId).put("warehouseId", warehouseId).getMap(), BarCodeDDO.class);
                if (dList.size() > 0){
                    if("WLK".equals(d.getWarehouseAreaCode())){
                        Set<String> ids = dList.stream().map(BarCodeDDO::getId).collect(Collectors.toSet());
                        Criteria barcodedcrt = Criteria.forClass(BarCodeDDO.class);
                        Restriction rest1 = Restrictions.in("id", ids.toArray());
                        barcodedcrt.setRestriction(rest1);
                        barcodeDMapper.updateMapByCriteria(MapUtils.put("checkStatus", "5").getMap(),barcodedcrt);

                        Set<String> barcodeIds = dList.stream().map(BarCodeDDO::getBarcodeId).collect(Collectors.toSet());
                        Criteria barcodedcrt2 = Criteria.forClass(BarCodeDDO.class);
                        Restriction rest2 = Restrictions.in("barcodeId", barcodeIds.toArray());
                        Restriction rest3 = Restrictions.ne("checkStatus", "5");
                        barcodedcrt2.setRestriction(Restrictions.and(rest2, rest3));
                        long count3 = barcodeDMapper.findCountByCriteria(barcodedcrt2);
                        if(count3 == 0){
                            Criteria barcodehcrt = Criteria.forClass(BarcodeHDO.class);
                            Restriction resth1 = Restrictions.in("id", barcodeIds.toArray());
                            barcodehcrt.setRestriction(resth1);
                            barcodeHMapper.updateMapByCriteria(MapUtils.put("checkStatus", "5").getMap(),barcodehcrt);
                        }

                    }
                }

            }
            // 查询未确认的拣选任务
            Integer count2 = pickTaskHMapper.getUnConfirmCountH(pickTaskId, pickOrderId, h.getBldgId(), warehouseId);
            // 拣选单状态更新为2：拣选完成
            if (count2 == 0) {
                flag = true;
                if("WLK".equals(d.getWarehouseAreaCode())){
                    pickOrderMapper.updateMapById(pickOrderId, MapUtils.put("status", "10").getMap(), PickOrder.class);
                }else {
                    pickOrderMapper.updateMapById(pickOrderId, MapUtils.put("status", "2").getMap(), PickOrder.class);
                }

                // 回传拣选完成状态
                if (h.getType() == 0) {
//                    orderOutboundStatusBackService.sendOutboundOrderStatusOms(h.getBillGroupId(), "", "", "", "", "30", BigDecimal.ZERO);
                }
            }
        }
        // 如果是补货任务，更新补货表状态
        if (h.getType() == 1) {
            String moveId = pickTaskHMapper.getMoveTaskId(pickTaskDId, warehouseId);
            if (moveId != null) {
                MoveTaskDO move = moveTaskMapper.findById(moveId, MoveTaskDO.class);
                MoveConfirmParamsVO vo = new MoveConfirmParamsVO();
                vo.setLineIds((new String[]{move.getDetailId()}));
                vo.setMoveFlag(0);
                List<ReplenishDetailVO> replenishDetailVOList = new ArrayList<>();
                ReplenishDetailVO replenishDetailVO = new ReplenishDetailVO();
                replenishDetailVO.setLineId(move.getDetailId());
                replenishDetailVO.setSrcLineId(pickTaskDId);
                replenishDetailVOList.add(replenishDetailVO);
                vo.setReplenishDetailVOList(replenishDetailVOList);

                // 库内，下架确认
                RestMessage restMessage = operateResource.confirmReplenish(vo);
                if (!restMessage.isSuccess()) {
                    log.error("调用库存下架确认接口出错！" + restMessage.getMessage() + "，vo:" + JSON.toJSONString(vo));
                    throw new PrologException("调用库存下架确认接口出错！" + restMessage.getMessage());
                }
            }
        } else {
            this.invStockConfirm(d, warehouseId,redType);
        }
        if (!isWholeRed) {
//            PrintDataWithMark printData = getPrintData(h, pickTaskDId, pickQty, billDDOList);
//            result.put("printData",printData);

            List<PrintParam> printData = getPrintData(h, pickTaskDId, pickQty, billDDOList);
            result.put("billNo",h.getBillGroupId());
            result.put("printData",printData);
        }
        // 根据库区判断是否回传EIS
//        if (!s.getAreaCategory().equals("ZJK")) {
//            // 回传EIS
//            ThreadUtil.execAsync(() -> pickTaskService.sendPickEndToEisByTaskDIds(new String[]{pickTaskDId}), false);
//        }
        //作业完成回告EIS
        if("Device".equals(d.getPickModel())){
            result.put("sendEis","1");
            result.put("containerCode",d.getContainerCode());
//            //调用作业完成确认回告
//            List<OperationCompleteVO> operationCompleteVOS = pkgWorkCompeletToEisParams(pickOrderId,d.getContainerCode());
//            log.info("整件拣货作业确认推送EIS入参：{}",JSON.toJSONString(operationCompleteVOS));
//            eisHandler.operationComplete(operationCompleteVOS);
        }
        result.put("flag", flag);

//        // 判断是否需要生成顺带补货任务 红冲不需要顺带补货
//        if (s.getAreaCategory().equals("ZJK") && s.getWarehouseAreaCode().equals("GJK")) {
//            BigDecimal replenishQty = this.replenishQty(s.getItemId(), s.getBatchNum(), s.getLocatorCode(),enterpriseId, warehouseId);
//            if (replenishQty.doubleValue() > 0) {
//                // 构造顺带补货VO;
//                String locatorId = getReplenishLocator(s);
//                ReplenishIncidentallyVO replenishVO = packReplenishIncidentallyVO(s.getWarehouseId(), s.getBldgId(), d, replenishQty,locatorId);
//                log.info("生成补货上架任务入参 {}", JSON.toJSONString(replenishVO));
//                // 顺带补货
//                RestMessage<List<ReplenishIncidentallyDTO>> restMessage = operateResource.replenishIncidentally(replenishVO);
//                if (null == restMessage || !restMessage.isSuccess() || CollUtil.isEmpty(restMessage.getData())) {
//                    log.info("拣货完成,调用库内顺带补货接口报错:{}", null == restMessage?"":restMessage.getMessage());
//                    result.put("flag", false);
//                    return result;
//                }
//                String detailIds = restMessage.getData().stream().map(ReplenishIncidentallyDTO::getDetailId).collect(Collectors.joining(","));
//                result.put("detailIds", detailIds);
//            }
//        }
        // 整单红冲回传ERP
        if (ObjectUtils.isNotNull(redOmsBillIds)) {
            IStrategyHandle strategyHandle = strategySelector.selectHandle(Arrays.asList(
                    STRATEGY_CODE.POST_BACK_ERP__MQ__ON), enterpriseId, warehouseId, "do");
            strategyHandle.execute(redOmsBillIds);
        }
        return result;
    }

    /**
     * 查询可补货高架库货位ID
     *
     * @return 可补货高架库货位ID
     */
    public String getReplenishLocator(WaveStorageDO s) {
        WaveBillDO billDO = billMapper.findById(s.getBillId(), WaveBillDO.class);
        // 需要补货的商品ID
        String[] arrItemId = new String[]{s.getItemId()};
        // 只查找符合货位限定规则的高架货位
        String[] locatorTypes = new String[]{"0"};
        // 楼层为1层的高架货位区域ID;
        RestMessage<List<BaseWmsWarehouseArea>> restMessage = warehouseResource.getByAreaCodes(s.getWarehouseId(), new String[]{s.getWarehouseAreaCode()});
        if (!restMessage.isSuccess() || CollUtil.isEmpty(restMessage.getData())) {
            throw new BizException("获取库区失败");
        }

        String[] areaIds = restMessage.getData().stream().map(BaseWmsWarehouseArea::getWarehouseAreaId).distinct().toArray(String[]::new);
        if (areaIds.length == 0) {
            throw new BizException("获取库区失败");
        }
        // 判断高架库是否存在可用的补货货位 空货位或同品同批货位 ，同时校验可用货位数量是否足够，不足则多余的不补货
        RestMessage<Map<String, String>> limitResult =
                controlResource.getItemArrayStLocatorList(arrItemId,
                        billDO.getConsignorId(),
                        s.getWarehouseId(),
                        null,
                        areaIds,
                        locatorTypes,
                        s.getEnterpriseId());
        log.info("limitResult为:{}", JSONUtil.toJsonStr(limitResult));
        Set<String> locatorIdList = new HashSet<>();
        if (limitResult.isSuccess() && MapUtil.isNotEmpty(limitResult.getData())) {
            for (String itemId : arrItemId) {
                locatorIdList.addAll(CollectionUtil.newHashSet(limitResult.getData().get(itemId).split(",")));
            }
        }
        if (CollUtil.isEmpty(locatorIdList)) {
            log.info("未找到货位限定库位,对应的商品ID为:{}", arrItemId);
            return null;
        }
        // 查询1层的高架货位ID
        RestMessage<List<WarehouseLocatorBasicInfo>> locatorMsgNew = warehouseResource.getLocationBasicInfos(locatorIdList.stream().distinct().toArray(String[]::new));
        if (null == locatorMsgNew || !locatorMsgNew.isSuccess() || CollUtil.isEmpty(locatorMsgNew.getData())) {
            return null;
        }
        // 1层高架货位ID
        List<String> firstLocatorId = locatorMsgNew.getData().stream().filter(datum -> null != datum.getLayerNum() && datum.getLayerNum().intValue() == 1).map(WarehouseLocatorBasicInfo::getWarehouseLocatorId).collect(Collectors.toList());
        // 查询库存及预占表,排除掉已有库存及存在补货预占的库存
        Set<String> existsLocatorLimitIds = invClient.queryExistsLocatorList(MapUtils.put("enterpriseId", s.getEnterpriseId()).put("warehouseId", s.getWarehouseId()).put("allLocatorIdList", firstLocatorId).getMap());
        // 1层高架库空货位
        Collection<String> emptyLocatorIds = CollectionUtil.disjunction(firstLocatorId, existsLocatorLimitIds);
        String locatorId = null;
        if (CollectionUtil.isNotEmpty(emptyLocatorIds)) {
            locatorId = emptyLocatorIds.iterator().next();
        } else {
            //空货位不存在, 则使用已有库存货位
            locatorId = existsLocatorLimitIds.iterator().next();
        }
        return locatorId;
    }

    /**
     * 组装补货上架任务入参
     *
     * @param blgId pickTaskD
     * @return vo
     */
    private ReplenishIncidentallyVO packReplenishIncidentallyVO(String warehouseId, String blgId, PickTaskD pickTaskD, BigDecimal replenishQty, String locatorId) {
        WaveStorageDO waveStorageDO = waveStorageMapper.findById(pickTaskD.getWaveStorageId(), WaveStorageDO.class);
        WaveBillDDO waveBillDDO = billDMapper.findById(waveStorageDO.getBillDId(), WaveBillDDO.class);
        WaveBillDO waveBillDO = billMapper.findById(waveStorageDO.getBillId(), WaveBillDO.class);
        String[] locatorIds = new String[]{waveStorageDO.getLocatorId(), locatorId};
        RestMessage<List<WarehouseLocatorBasicInfo>> restMessage = warehouseResource.getLocationBasicInfos(locatorIds);
        if (!restMessage.isSuccess()) {
            throw new PrologException("查询货位信息失败！");
        }
        List<WarehouseLocatorBasicInfo> basicInfoList = restMessage.getData();
        UserDTO user = userTemplate.getUserDTO();
        ReplenishIncidentallyVO result = new ReplenishIncidentallyVO();
        result.setOpUser(user.getNickname());
        result.setOpUserId(user.getId());
        result.setDetails(Lists.newArrayList());
        result.setWarehouseId(warehouseId);
        result.setEnterpriseId(user.getEnterpriseId());
        result.setDcId(blgId);

        List<ReplenishPassiveSaveDetailVO> list = new ArrayList<>();
        ReplenishPassiveSaveDetailVO vo = new ReplenishPassiveSaveDetailVO();
        WarehouseLocatorBasicInfo origin = basicInfoList.stream().filter(w -> w.getWarehouseLocatorId().equals(waveStorageDO.getLocatorId())).findFirst().orElse(null);
        WarehouseLocatorBasicInfo target = basicInfoList.stream().filter(w -> w.getWarehouseLocatorId().equals(locatorId)).findFirst().orElse(null);
        vo.setWhAreaId(null != origin ? origin.getWarehouseAreaId() : "");
        vo.setToWhAreaCategory(target.getWarehouseAreaCategory());
        vo.setToWhAreaId(target.getWarehouseAreaId());
        vo.setToWhAreaCode(target.getWarehouseAreaCode());
        vo.setToWhLocatorId(locatorId);
        vo.setToWhLocatorCode(target.getWarehouseLocatorCode());
        vo.setToWhWarehouseLocatorType(target.getWarehouseLocatorType());
        vo.setBatchId(waveStorageDO.getBatchId());
        vo.setCargoOwnerId(waveBillDO.getConsignorId());
        vo.setItemId(waveStorageDO.getItemId());
        vo.setItemCode(waveBillDDO.getItemCode());
        vo.setWhAreaCategory(waveStorageDO.getAreaCategory());
        vo.setWhLocatorId(waveStorageDO.getLocatorId());
        vo.setWhLocatorCode(null != origin ? origin.getWarehouseLocatorCode() : "");
        vo.setWhAreaCode(waveStorageDO.getWarehouseAreaCode());
        vo.setBatchNum(waveStorageDO.getBatchNum());
        vo.setManufacturerLotNum(waveStorageDO.getManufactureLotNum());
        vo.setBatchProductionDate(waveStorageDO.getProductionDate());
        vo.setBatchExpiredDate(waveStorageDO.getExpiredDate());
        vo.setUom(waveStorageDO.getUom());
        vo.setConversionRate(waveBillDDO.getCaseConversionRate());
        vo.setQuantity(replenishQty);
        vo.setPieceQuantity(waveBillDDO.getPieceQty());
        vo.setOmsBillNo(waveBillDO.getSrcCode());
        list.add(vo);
        result.setDetails(list);
        return result;
    }


    @Override
    @InterfaceMethod(key = "containerOffShelf", name = "EIS扫码，四向库下架", type = InterfaceType.Send)
    public ContainerBindTaskDto containerOffShelf(String containerNo) {
        log.info("containerOffShelf入参为：" + containerNo);
        ContainerBindTaskDto data = eisAgvResource.containerOffShelf(containerNo).getData();
        log.info("containerOffShelf返回为：" + JSON.toJSONString(data));
        return data;
    }

    /**
     * 拣货类型： 'WHOLE_REPLENISH_FIRST','WHOLE_PICKING','WHOLE_PICKING_FIRST','WHOLE_REPLENISH','BULK_PICKING','WHOLE_BULK_PICKING'
     */
    @Override
    public BulkPickBoardVo bulkPickBoard(String bldgId, String warehouseId) {
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();

        //获取员工作业库区编码集合
        List<String> userAreaCodes = new ArrayList<>();
        try {
            userAreaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "BULK_PICKING");
            if (CollUtil.isEmpty(userAreaCodes)) {
                throw new BizException("工号没有散件拣货权限");
            }
        } catch (Exception e) {
        }

        WarehouseAreaQueryVO queryVO = new WarehouseAreaQueryVO();
        queryVO.setEnterpriseId(enterpriseId);
        queryVO.setWarehouseId(warehouseId);
        queryVO.setWarehouseAreaCategoryList(Collections.singletonList("LHK"));
        RestMessage<List<Map<String, Object>>> restMessage = warehouseResource.listSimpleInfo(queryVO);
        if (!restMessage.isSuccess() || CollUtil.isEmpty(restMessage.getData())) {
            throw new BizException("获取库区失败");
        }
        List<String> areaCodes = restMessage.getData().stream().map(var -> (String) var.get("warehouseAreaCode")).distinct().collect(toList());
        if (CollUtil.isEmpty(areaCodes)) {
            throw new BizException("获取库区失败");
        }
        boolean hasLHK = false;
        for (String userAreaCode : userAreaCodes) {
            if (hasLHK) {
                break;
            }
            for (String areaCode : areaCodes) {
                if (userAreaCode.equals(areaCode)) {
                    hasLHK = true;
                }
            }
        }
        if (!hasLHK) {
            throw new BizException("工号没有零货库区散件拣货权限");
        }
        List<TaskCountVo> vos1 = pickTaskHMapper.getTaskCount(warehouseId, enterpriseId, bldgId, areaCodes);
        List<TaskCountVo> vos2 = pickTaskHMapper.getMoveCount(warehouseId, enterpriseId, bldgId, areaCodes);
        Set<String> sets = new HashSet<>();
        if (CollUtil.isNotEmpty(vos1)) {
            sets.addAll(vos1.stream().map(TaskCountVo::getAreaCode).collect(Collectors.toSet()));
        }
        if (CollUtil.isNotEmpty(vos2)) {
            sets.addAll(vos2.stream().map(TaskCountVo::getAreaCode).collect(Collectors.toSet()));
        }
        //翻译areaCode
        RestMessage<List<BaseWmsWarehouseArea>> areas = warehouseResource.getByAreaCodes(warehouseId, sets.toArray(new String[0]));
        BulkPickBoardVo bulkPickBoardVo = new BulkPickBoardVo();
        bulkPickBoardVo.setBulkPickTask(vos1);
        bulkPickBoardVo.setBulkReplenishmentTask(vos2);
        for (TaskCountVo vo : vos1) {
            areas.getData().stream().filter(t -> t.getWarehouseAreaCode().equals(vo.getAreaCode())).findFirst().ifPresent(area -> vo.setAreaName(area.getWarehouseAreaName()));
        }
        for (TaskCountVo vo : vos2) {
            areas.getData().stream().filter(t -> t.getWarehouseAreaCode().equals(vo.getAreaCode())).findFirst().ifPresent(area -> vo.setAreaName(area.getWarehouseAreaName()));
        }
        return bulkPickBoardVo;
    }

    @Override
    public Page<PickTaskDVo> getBulkPickTaskDList(
            String bldgId,
            String warehouseId,
            String pickOrderId,
            Integer pageNum,
            Integer pageSize
    ) {
        if (StringUtils.isBlank(pickOrderId))
            throw new ParameterException("任务包号不能为空");
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");
        PageHelper.startPage(pageNum, pageSize);
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        //查询当前任务包号下所有的拣货明细，以货位、批次、商品id分组统计数量
        //拣货明细关联预占，通过库存预占信息查询商品信息
        List<PickTaskDVo> list = pickTaskDMapper.getBulkPickTaskDList(warehouseId, enterpriseId, bldgId, pickOrderId, null);
        if (CollUtil.isEmpty(list)) {
            return PageUtils.getPage(list);
        }
        List<String> pks = list.stream().map(PickTaskDVo::getPk).collect(Collectors.toList());
        //查询对应的每箱拣货数量
        List<ContainerQtyVo> containerQtyVos = pickTaskDMapper.getContainerQty(warehouseId, enterpriseId, bldgId, pickOrderId, pks);
        for (PickTaskDVo pickTaskDVo : list) {
            pickTaskDVo.setWarehouseId(warehouseId);
            pickTaskDVo.setBldgId(bldgId);
            pickTaskDVo.setPickOrderId(pickOrderId);
            pickTaskDVo.setConfirmStatus(pickTaskDVo.getUnConfirmCount() == 0);
            List<ContainerQtyVo> tempList = new ArrayList<>();
            for (ContainerQtyVo containerQtyVo : containerQtyVos) {
                if (pickTaskDVo.getPk().equals(containerQtyVo.getPk())) {
                    tempList.add(containerQtyVo);
                }
            }
            pickTaskDVo.setContainerQtyList(tempList);
        }
        //查询库存信息
        try {
            Set<String> locatorIds = new HashSet<>();
            List<WmsInvStockQtyQueryVO> queryList = new ArrayList<>();
            for (PickTaskDVo pickTaskDVo : list) {
                locatorIds.add(pickTaskDVo.getLocateId());
                if (StringUtils.isBlank(pickTaskDVo.getManufacturerLotNum())) {
                    continue;
                }
                WmsInvStockQtyQueryVO queryVO = new WmsInvStockQtyQueryVO();
                queryVO.setEnterpriseId(enterpriseId);
                queryVO.setWarehouseId(warehouseId);
                queryVO.setManufacturerLotNum(pickTaskDVo.getManufacturerLotNum());
                queryVO.setItemId(pickTaskDVo.getItemId());
                queryVO.setIsAvailable("1");
                queryList.add(queryVO);
            }
            QuantityListVo quantityListVo = new QuantityListVo();
            quantityListVo.setQtyQueries(queryList);
            quantityListVo.setIsAvailable("1");
            // 请求库存批次信息
            RestMessage<List<WarehouseLocatorBasicInfo>> loMsg = warehouseResource.getLocationBasicInfos(locatorIds.toArray(new String[]{}));
            RestMessage<List<WmsInvStockQtyVO>> result = invClient.getAvailableQuantityList(queryList);
            for (PickTaskDVo pickTaskDVo : list) {
                for (WmsInvStockQtyVO datum : result.getData()) {
                    if (pickTaskDVo.getItemId().equals(datum.getItemId())
                            && pickTaskDVo.getLocateId().equals(datum.getLocatorId())
                            && pickTaskDVo.getManufacturerLotNum().equals(datum.getManufacturerLotNum())
                    ) {
                        pickTaskDVo.setItemCode(datum.getItemCode());
                        pickTaskDVo.setItemSpecs(datum.getSpecification());
                        pickTaskDVo.setExpiredDate(datum.getBatchExpiredDate());
                        pickTaskDVo.setItemName(datum.getItemName());
                        pickTaskDVo.setStockQty(datum.getQuantity());
                        pickTaskDVo.setUom(datum.getCaseUom());
                    }
                }
            }
            for (PickTaskDVo pickTaskDVo : list) {
                for (WarehouseLocatorBasicInfo datum : loMsg.getData()) {
                    if (pickTaskDVo.getLocateId().equals(datum.getWarehouseLocatorId())
                    ) {
                        pickTaskDVo.setLocateCode(datum.getWarehouseLocatorCode());
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取库存信息失败", e);
        }
        return PageUtils.getPage(list);
    }

    /**
     * 河南省以用-零货拣货确认
     *
     * @param pickTaskDVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @TxTransaction
    public Boolean pickTaskBulkConfirm(PickTaskDVo pickTaskDVo) {
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String warehouseId = pickTaskDVo.getWarehouseId();
        String bldgId = pickTaskDVo.getBldgId();
        String pickOrderId = pickTaskDVo.getPickOrderId();
        String pk = pickTaskDVo.getPk();
        if (StrUtil.isEmpty(pk)) {
            throw new ParameterException("唯一标识为空！");
        }
        //1、根据pk查询对应的拣货任务
        List<PickTaskDVo> list = pickTaskDMapper.getBulkPickTaskDList(warehouseId, enterpriseId, bldgId, pickOrderId, Collections.singletonList(pk));
        if (CollUtil.isEmpty(list)) {
            throw new ParameterException("待确认行不存在或者已经确认完成！");
        }
//        //查询待确认的拣货明细
//        List<PickTaskDPickVo> pickVoList = pickTaskDMapper.getByPickOrder(pickOrderId, pickTaskDVo.getLocateId(), pickTaskDVo.getItemId(), pickTaskDVo.getManufacturerLotNum());
//        if (CollUtil.isEmpty(pickVoList)){
//            throw new ParameterException("待确认行已经确认完成！");
//        }
        //2、对比每个容器的数量与应捡数量是否一致
        //查询对应的每箱拣货数量
        List<ContainerQtyVo> containerQtyVos = pickTaskDMapper.getContainerQty(warehouseId, enterpriseId, bldgId, pickOrderId, Collections.singletonList(pk));
        List<ContainerQtyVo> containerQtyReqs = pickTaskDVo.getContainerQtyList();
        Set<String> pickTaskDIds = new HashSet<>();
        for (ContainerQtyVo containerQtyVo : containerQtyVos) {
            for (ContainerQtyVo req : containerQtyReqs) {
                if (containerQtyVo.getPk().equals(req.getPk()) && containerQtyVo.getContainerCode().equals(req.getContainerCode())) {
                    //根据order_id、货位、商品、批号、容器查询匹配的拣货任务
                    List<ContainerListDTO> containerListDTOList = pickTaskHMapper.getContainerListById(
                            warehouseId,
                            pickOrderId,
                            pickTaskDVo.getLocateId(),
                            pickTaskDVo.getItemId(),
                            pickTaskDVo.getManufacturerLotNum(),
                            containerQtyVo.getContainerCode()
                    );

                    if (containerQtyVo.getQty().compareTo(req.getQty()) == 0) {
                        //确认数量与待确认数量一致，对该容器内的拣货明细进行确认(正常拣货)
                        for (ContainerListDTO containerListDTO : containerListDTOList) {
                            containerListDTO.setPickQty(containerListDTO.getQty());
                        }
                        this.pickTaskConfirm(containerListDTOList);
                    } else {
                        //确认数量与待确认数量不一致
                        if (containerQtyVo.getQty().doubleValue() >= req.getQty().doubleValue()) {
                            //对该容器内的拣货明细进行短拣处理，差异数量红冲，如果多个明细，优先满足可以足额拣货的进行确认
                            double totalPickQty = req.getQty().doubleValue();
                            for (ContainerListDTO dto : containerListDTOList) {
                                if (dto.getQty().doubleValue() <= totalPickQty) {
                                    dto.setPickQty(dto.getQty());
                                    totalPickQty = totalPickQty - dto.getQty().doubleValue();
                                } else {
                                    dto.setPickQty(new BigDecimal(FloatingDecimal.toJavaFormatString(totalPickQty)));
                                    dto.setRedReason("拣货冲红，数量不足");
                                    totalPickQty = 0D;
                                }
                            }
                            this.pickTaskConfirm(containerListDTOList);
                        } else {
                            throw new ParameterException("拣货数量大于待确认数量");
                        }
                    }
                }
            }
        }
        return true;
    }

    /**
     * 扣减库存,并回传ERP
     *
     * @param warehouseId
     */
    @Transactional
    public void invStockConfirm(PickTaskD pickTaskD, String warehouseId,String redType) {
        log.info("开始扣减库存");
        InvStockPartCheckOut invStockCheck = new InvStockPartCheckOut();
        if (pickTaskD == null) {
            return;
        }
        //查询预占信息
        WaveStorageDO waveStorageDO = waveStorageMapper.findById(pickTaskD.getWaveStorageId(), WaveStorageDO.class);
        if (null == waveStorageDO) {
            throw new BizException("未查询到预占信息！");
        }
        // 查询需要的参数 batchNum/locatorId/itemId/qty/containerCode
        invStockCheck.setContainerCode(waveStorageDO.getContainerCode());
        //青牛预占时，没有带上容器号，所以扣减库存时查库存预占也不需要带容器号
//        if (!StringUtils.isBlank(waveStorageDO.getAreaCategory()) && waveStorageDO.getAreaCategory().contains("AGVZ")) {
//            invStockCheck.setContainerCodeSelectPreFlag(true);
//        }
        //还原库位扣除拣货数量，入盘点库扣所有数量
        if("1".equals(redType)){
            invStockCheck.setQty(pickTaskD.getPickQty());
        }else {
            invStockCheck.setQty(pickTaskD.getQty());
        }
        invStockCheck.setLocatorId(waveStorageDO.getLocatorId());
        invStockCheck.setItemId(waveStorageDO.getItemId());
        invStockCheck.setLineBillIds(new String[]{waveStorageDO.getBillDId()});
        invStockCheck.setBatchNum(waveStorageDO.getBatchNum());
        RestMessage restMessage = invClient.outPartStockCheck(invStockCheck);
        log.info("请求参数：{}", JSONObject.toJSONString(invStockCheck));
        if (!restMessage.isSuccess()) {
            throw new BizException("扣减库存失败: " + restMessage.getMessage() +
                    String.format("，入参为：[仓库：%s][订单编号：%s]", warehouseId, JSONObject.toJSONString(invStockCheck)));
        }
        log.info("扣减库存成功");
    }

    @Override
    @InterfaceMethod(key = "getSlideway", name = "EIS回告->请求滑道号", type = InterfaceType.Send)
    public Map<String, String> getSlideway(String containerCode) {
        Map<String, String> result = new HashMap<>();
        //1、通过容器号查询拣货任务头
        //3、统计每个滑道的任务
        //4、根据规则为当前任务分配滑道
        //5、更新当前任务的滑道信息
        //6、返回滑道信息
        List<PickTaskH> hList = pickTaskHMapper.findByMap(MapUtils
                .put("containerCode", containerCode).put("status", "2").getMap(), PickTaskH.class);
        if (CollUtil.isEmpty(hList)) {
            //异常 分配14滑道
            result.put("targetlocation", "14");
            result.put("msgId", IdUtil.fastSimpleUUID());
            return result;
        }
        PickTaskH h = hList.get(0);
        //2、查询所有的滑道
        if (StrUtil.isNotEmpty(h.getSlidewayId())) {
            //已分配滑道，直接返回
            result.put("targetlocation", h.getSlidewayId());
            result.put("msgId", h.getPickTaskId());
            return result;
        }
        //2.01 校验容器内任务是否已经全完成
        List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("pickTaskId", h.getPickTaskId()).getMap(), PickTaskD.class);
        if (CollUtil.isEmpty(pickTaskDList)) {
            //异常 分配14滑道
            result.put("targetlocation", "14");
            result.put("msgId", h.getPickTaskId());
            return result;
        }
        for (PickTaskD pickTaskD : pickTaskDList) {
            if (pickTaskD.getPickQty() == null || (null != pickTaskD.getFlowStatus() && Integer.parseInt(pickTaskD.getFlowStatus()) < 3)) {
                //异常 分配14滑道
                result.put("targetlocation", "14");
                result.put("msgId", h.getPickTaskId());
                return result;
            }
        }
        //2.1 查询所有滑道
        WmsWhSlidewayDTO wmsWhSlidewayDTO = new WmsWhSlidewayDTO();
        wmsWhSlidewayDTO.setWarehouseId(h.getWarehouseId());
        wmsWhSlidewayDTO.setEnterpriseId(h.getEnterpriseId());
        RestMessage<List<WmsWhSlideway>> slidewayMsg = warehouseResource.findByParam(wmsWhSlidewayDTO);
        if (slidewayMsg == null || !slidewayMsg.isSuccess() || slidewayMsg.getData() == null || slidewayMsg.getData().size() <= 0) {
            throw new BizException("复核台滑道已满，请等待");
        }
        //2.2 获取当前拣货头所属订单下所有拣货头的滑道 -->优先同订单滑道
        List<PickTaskH> billSlideways = pickTaskHMapper.getBillSlideways(h.getPickTaskId());
        WmsWhSlideway retSlide;
        if (CollUtil.isEmpty(billSlideways)) {
            //当前订单还未分配过滑道，选择一个可用滑道
            retSlide = this.pickSlideWay(slidewayMsg.getData(), h.getPickTaskType());
        } else {
            //当前订单分配过滑道，优先分配同订单滑道
            retSlide = pickSameBillSlideWay(slidewayMsg.getData(), billSlideways, h.getPickTaskType());
        }
        result.put("targetlocation", retSlide.getSlidewayNum());
        result.put("msgId", h.getPickTaskId());
        this.updatePickTaskHSlideWayInfo(retSlide, h);
        return result;
    }

    private void updatePickTaskHSlideWayInfo(WmsWhSlideway slide, PickTaskH h) {
        //查询复核台信息
        RestMessage<BaseWmsWhWorkstation> msg = warehouseResource.getById(slide.getStationId());
        if (!msg.isSuccess() || msg.getData() == null) {
            throw new BizException("获取复核台信息失败！");
        }
        String stationCode = msg.getData().getStationCode();
        String stationName = msg.getData().getStationName();
        pickTaskHMapper.updatePickTaskHSlideWayInfo(slide.getSlidewayNum(), slide.getStationId(), stationCode, stationName, h.getPickTaskId());
    }

    /**
     * 已分配滑道订单选择滑道
     *
     * @param slidewayList  所有滑道信息
     * @param billSlideways 当前订单已经分配了滑道的拣货任务
     * @return 一个可用滑道
     */
    private WmsWhSlideway pickSameBillSlideWay(List<WmsWhSlideway> slidewayList, List<PickTaskH> billSlideways, int pickTaskType) {
        //优先选择相同订单的滑道，如果相同订单的滑道已满，则选择一个新的可用滑道
        Map<String, Long> map = billSlideways.stream().collect(Collectors.groupingBy(PickTaskH::getSlidewayId, Collectors.counting()));
        for (String s : map.keySet()) {
            for (WmsWhSlideway wmsWhSlideway : slidewayList) {
                if (s.equals(wmsWhSlideway.getSlidewayNum())) {
                    if ((!wmsWhSlideway.getIsEnable().equals("0")) && wmsWhSlideway.getCapacity() < map.get(s)) {
                        //校验对应的复核台状态
                        RestMessage<BaseWmsWhWorkstation> stationMsg = warehouseResource.getById(wmsWhSlideway.getStationId());
                        if (!stationMsg.isSuccess() || stationMsg.getData() == null) {
                            throw new BizException("获取复核台信息出错！");
                        }
                        if (pickTaskType == 2) {
                            //功能库房任务
                            if (stationMsg.getData().getIsEnable() == 1 && stationMsg.getData().getGroupCode().equals("90")) {
                                return wmsWhSlideway;
                            }
                        } else {
                            //非功能库房任务
                            if (stationMsg.getData().getIsEnable() == 1 && !stationMsg.getData().getGroupCode().equals("90")) {
                                return wmsWhSlideway;
                            }
                        }
                    }
                }
            }
        }
        //当前任务所有滑道已满，选择一个新滑道
        return this.pickSlideWay(slidewayList, pickTaskType);
    }


    /**
     * 选择一个新的可用滑道
     *
     * @param slidewayList 可用滑道
     * @return 滑道
     */
    private WmsWhSlideway pickSlideWay(List<WmsWhSlideway> slidewayList, int pickTaskType) {
        //3、统计每个滑道的任务数，选择一个任务数最少的滑道。如果滑道任务数大于0，则需判断该滑道是否允许不同订单
        List<String> slideIds = slidewayList.stream().map(WmsWhSlideway::getSlidewayNum).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(slideIds)) {
            throw new ParameterException("复核台滑道已满，请等待");
        }
        //3.1 统计任务数
        List<Map<String, Object>> pickTaskHCountList = pickTaskHMapper.countHBySlidWayId(slideIds);
        if (CollUtil.isEmpty(pickTaskHCountList)) {
            //如果为空，则表示滑道均未使用，直接return
            //校验对应的复核台状态
            for (WmsWhSlideway wmsWhSlideway : slidewayList) {
                RestMessage<BaseWmsWhWorkstation> stationMsg = warehouseResource.getById(wmsWhSlideway.getStationId());
                if (!stationMsg.isSuccess() || stationMsg.getData() == null) {
                    throw new BizException("获取复核台信息出错！");
                }
                if (pickTaskType == 2) {
                    //功能库房任务
                    if (stationMsg.getData().getIsEnable() == 1 && stationMsg.getData().getGroupCode().equals("90")) {
                        return wmsWhSlideway;
                    }
                } else {
                    //非功能库房任务
                    if (stationMsg.getData().getIsEnable() == 1 && !stationMsg.getData().getGroupCode().equals("90")) {
                        return wmsWhSlideway;
                    }
                }
            }
            throw new ParameterException("当前没有可用的复核台！");
        } else {
            WmsWhSlideway wmsWhSlideway = null;
            Set<String> usedSlidways = pickTaskHCountList.stream().map(var -> (String) var.get("slideWayId")).collect(Collectors.toSet());
            //优先选择无任务滑道
            for (WmsWhSlideway slideway : slidewayList) {
                if (usedSlidways.contains(slideway.getSlidewayNum())) {
                    continue;
                }
                if (wmsWhSlideway != null) {
                    return wmsWhSlideway;
                }
                RestMessage<BaseWmsWhWorkstation> stationMsg = warehouseResource.getById(slideway.getStationId());
                if (!stationMsg.isSuccess() || stationMsg.getData() == null) {
                    throw new BizException("获取复核台信息出错！");
                }
                if (pickTaskType == 2) {
                    //功能库房任务
                    if (stationMsg.getData().getIsEnable() == 1 && stationMsg.getData().getGroupCode().equals("90")) {
                        wmsWhSlideway = slideway;
                    }
                } else {
                    //非功能库房任务
                    if (stationMsg.getData().getIsEnable() == 1 && !stationMsg.getData().getGroupCode().equals("90")) {
                        wmsWhSlideway = slideway;
                    }
                }
            }
            for (Map<String, Object> map : pickTaskHCountList) {
                if (wmsWhSlideway != null) {
                    return wmsWhSlideway;
                }
                String tempSlideWayId = (String) map.get("slideWayId");
                Long taskCount = Convert.toLong(map.get("count"), 0L);
                if (taskCount == 0) {
                    wmsWhSlideway = slidewayList.stream().filter(var -> var.getSlidewayNum().equals(tempSlideWayId)).findFirst().orElse(null);
                } else {
                    //判断滑道的属性 1、是否允许混放；2、是否任务已满
                    wmsWhSlideway = slidewayList.stream().filter(var -> var.getSlidewayNum().equals(tempSlideWayId)).findFirst().orElse(null);
                    if (wmsWhSlideway != null) {
                        if (wmsWhSlideway.getIsEnable().equals("0") || (null != wmsWhSlideway.getIsMix() && !wmsWhSlideway.getIsMix()) || wmsWhSlideway.getCapacity() < taskCount) {
                            wmsWhSlideway = null;
                        }
                    }
                }
                if (wmsWhSlideway != null) {
                    //校验对应的复核台状态
                    RestMessage<BaseWmsWhWorkstation> stationMsg = warehouseResource.getById(wmsWhSlideway.getStationId());
                    if (!stationMsg.isSuccess() || stationMsg.getData() == null) {
                        throw new BizException("获取复核台信息出错！");
                    }
                    if (stationMsg.getData().getIsEnable() == 0) {
                        wmsWhSlideway = null;
                    } else {
                        if (pickTaskType == 2) {
                            if (!stationMsg.getData().getGroupCode().equals("90")) {
                                wmsWhSlideway = null;
                            }
                        } else {
                            if (stationMsg.getData().getGroupCode().equals("90")) {
                                wmsWhSlideway = null;
                            }
                        }
                    }
                }
            }
            if (wmsWhSlideway == null) {
                throw new ParameterException("复核台滑道已满，请等待");
            }
            return wmsWhSlideway;
        }
    }

    /*
        "dictCode": "WHOLE_PICKING",
        "dictName": "仅整件拣货",
        "dictCode": "BULK_PICKING",
        "dictName": "散件拣货",
        "dictCode": "WHOLE_BULK_PICKING",
        "dictName": "整散合一拣货",
        "dictCode": "WHOLE_REPLENISH",
        "dictName": "仅整件补货",
        "dictCode": "WHOLE_ORDER_PICKING",
        "dictName": "整单拣选",
        "dictCode": "WHOLE_PICKING_FIRST",
        "dictName": "整件拣货优先",
        "dictCode": "WHOLE_REPLENISH_FIRST",
        "dictName": "整件补货优先",
     */
    @Override
    public Page<PickTaskDDTO> getConfirmTaskList(String bldgId, String warehouseId, String containerCode, Integer pageNum, Integer pageSize) {
        if (StringUtils.isBlank(containerCode))
            throw new ParameterException("任务包号不能为空");
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");
        PageHelper.startPage(pageNum, pageSize);
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();
        //获取当前拣货人的权限 SPECIAL_PICK/WHOLE_PICKING/WHOLE_BULK_PICKING/WHOLE_PICKING_FIRST/WHOLE_REPLENISH_FIRST
        List<Integer> pickTaskTypes = new ArrayList<>();
        pickTaskTypes.add(0);
        pickTaskTypes.add(2);

        RestMessage<List<BaseCommonDict>> billTypeList = commonClient.getDictBasicListByCodes("DO_BILL_TYPE", null);
        Map<String, String> billTypes = new HashMap<>();
        billTypeList.getData().forEach(baseCommonDict -> billTypes.put(baseCommonDict.getDictCode(), baseCommonDict.getDictName()));
        List<PickTaskDDTO> list = pickTaskHMapper.getPickTaskDList3(pickTaskTypes, bldgId, containerCode, warehouseId, new ArrayList<>());
        for (PickTaskDDTO pickTaskDDTO : list) {
            pickTaskDDTO.setBillTypeName(billTypes.get(pickTaskDDTO.getBillType()));
            pickTaskDDTO.setBillType(billTypes.get(pickTaskDDTO.getBillType()));
        }
        isSupervise(list);
        replenishFlag(list);
        return PageUtils.getPage(list);
    }

    // 判断是否需要生成顺带补货
    private void replenishFlag(List<PickTaskDDTO> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        // 根据是否 GJK 和GJK层数 筛选出需要判断是否补货的任务
        String[] locatorIds = list.stream().map(PickTaskDDTO::getLocatorCode).distinct().toArray(String[]::new);
        if (ArrayUtil.isEmpty(locatorIds)) {
            return;
        }
        RestMessage<List<WarehouseLocatorBasicInfo>> locatorMsg = warehouseResource.getLocationBasicInfos(locatorIds);
        if (null == locatorMsg || !locatorMsg.isSuccess() || CollUtil.isEmpty(locatorMsg.getData())) {
            return;
        }
        // 可以补货的货位ID集合,GJK且大于1层的,canReplenishLocators
        List<String> canReplenishLocators = new ArrayList<>();
        for (WarehouseLocatorBasicInfo datum : locatorMsg.getData()) {
            if (datum.getWarehouseAreaCode().equals("GJK") && datum.getLayerNum() > 1) {
                canReplenishLocators.add(datum.getWarehouseLocatorId());
            }
        }
        if (CollUtil.isEmpty(canReplenishLocators)) {
            return;
        }
        // 需要补货的pickTaskId与数量
        List<Map<String, BigDecimal>> replenishPickTaskDIds = new ArrayList<>();
        Set<String> pickTaskDIds = new HashSet<>();
        // 已经校验过的预占
        List<String> billDIds = new ArrayList<>();
        for (PickTaskDDTO pickTaskDDTO : list) {
            if (canReplenishLocators.contains(pickTaskDDTO.getLocatorId())) {
                // 查询是否存在其他出库预占，存在则不需要顺带补货，需要排除已经校验过的预占
                // 通过itemId,locatorId,warehouseId查询wms_inv_stock_pre表预占,需要排除自己
                WmsInvStockPre wmsInvStockPre = new WmsInvStockPre();
                wmsInvStockPre.setWarehouseId(pickTaskDDTO.getWarehouseId());
                wmsInvStockPre.setItemId(pickTaskDDTO.getItemId());
                wmsInvStockPre.setLocatorId(pickTaskDDTO.getLocatorId());
                wmsInvStockPre.setBatchNum(pickTaskDDTO.getBatchNum());
                wmsInvStockPre.setLineBillId(pickTaskDDTO.getBillDId());
                List<WmsInvStockPre> preList = invClient.queryInvStockPreList(wmsInvStockPre);
                if (CollUtil.isEmpty(preList)) {
                    // 判断余量是否满足配置的补货阈值，如果是则记录补货数量
                    BigDecimal availableQuantity = this.replenishQty(pickTaskDDTO.getItemId(), pickTaskDDTO.getBatchNum(), pickTaskDDTO.getLocatorCode(), pickTaskDDTO.getEnterpriseId(), pickTaskDDTO.getWarehouseId());
                    BigDecimal surplusPcs = availableQuantity.subtract(pickTaskDDTO.getQty()).divide(pickTaskDDTO.getConversionRate(), 0, RoundingMode.UP);
                    if (availableQuantity.compareTo(BigDecimal.ZERO) > 0 && surplusPcs.compareTo(BigDecimal.ZERO) > 0) {
                        replenishPickTaskDIds.add(Collections.singletonMap(pickTaskDDTO.getPickTaskDId(), surplusPcs));
                        billDIds.add(pickTaskDDTO.getBillDId());
                        pickTaskDIds.add(pickTaskDDTO.getPickTaskDId());
                    }
                }
            }
        }

        if (CollUtil.isEmpty(replenishPickTaskDIds)) {
            return;
        }
        // 需要补货的商品ID
        String[] arrItemId = list.stream().map(d -> {
            if (pickTaskDIds.contains(d.getPickTaskDId())) {
                return d.getItemId();
            }
            return null;
        }).distinct().toArray(String[]::new);
        // 只查找符合货位限定规则的高架货位
        String[] locatorTypes = new String[]{"0"};
        // 楼层为1层的高架货位区域ID;
        RestMessage<List<BaseWmsWarehouseArea>> restMessage = warehouseResource.getByAreaCodes(list.get(0).getWarehouseId(), new String[]{"GJK"});
        if (!restMessage.isSuccess() || CollUtil.isEmpty(restMessage.getData())) {
            throw new BizException("获取库区失败");
        }

        String[] areaIds = restMessage.getData().stream().map(BaseWmsWarehouseArea::getWarehouseAreaId).distinct().toArray(String[]::new);
        if (areaIds.length == 0) {
            throw new BizException("获取库区失败");
        }
        // 判断高架库是否存在可用的补货货位 空货位或同品同批货位 ，同时校验可用货位数量是否足够，不足则多余的不补货
        RestMessage<Map<String, String>> limitResult =
                controlResource.getItemArrayStLocatorList(arrItemId,
                        list.get(0).getConsignorId(),
                        list.get(0).getWarehouseId(),
                        null,
                        areaIds,
                        locatorTypes,
                        list.get(0).getEnterpriseId());
        log.info("limitResult为:{}", JSONUtil.toJsonStr(limitResult));
        Set<String> locatorIdList = new HashSet<>();
        if (limitResult.isSuccess() && MapUtil.isNotEmpty(limitResult.getData())) {
            for (String itemId : arrItemId) {
                locatorIdList.addAll(CollectionUtil.newHashSet(limitResult.getData().get(itemId).split(",")));
            }
        }
        if (CollUtil.isEmpty(locatorIdList)) {
            log.info("未找到货位限定库位,对应的商品ID为:{}", arrItemId);
        }
        // 查询1层的高架货位ID
        RestMessage<List<WarehouseLocatorBasicInfo>> locatorMsgNew = warehouseResource.getLocationBasicInfos(locatorIdList.stream().distinct().toArray(String[]::new));
        if (null == locatorMsgNew || !locatorMsgNew.isSuccess() || CollUtil.isEmpty(locatorMsgNew.getData())) {
            return;
        }
        // 1层高架货位ID
        List<String> firstLocatorId = locatorMsgNew.getData().stream().filter(datum -> null != datum.getLayerNum() && datum.getLayerNum().intValue() == 1).map(WarehouseLocatorBasicInfo::getWarehouseLocatorId).collect(Collectors.toList());
        // 查询库存及预占表,排除掉已有库存及存在补货预占的库存
        Set<String> existsLocatorLimitIds = invClient.queryExistsLocatorList(MapUtils.put("enterpriseId", list.get(0).getEnterpriseId()).put("warehouseId", list.get(0).getWarehouseId()).put("allLocatorIdList", firstLocatorId).getMap());
        // 1层高架库空货位
        Collection<String> emptyLocatorIds = CollectionUtil.disjunction(firstLocatorId, existsLocatorLimitIds);
        if (CollUtil.isNotEmpty(emptyLocatorIds)) {
            // 存在则更新补货数量
            for (Map<String, BigDecimal> replenishPickTaskDId : replenishPickTaskDIds) {
                for (PickTaskDDTO pickTaskDDTO : list) {
                    if (replenishPickTaskDId.containsKey(pickTaskDDTO.getPickTaskDId())) {
                        pickTaskDDTO.setReplenishPcs(replenishPickTaskDId.get(pickTaskDDTO.getPickTaskDId()));
                    }
                }
            }
        }
    }

    /**
     * RF整件索取
     *
     * @param containerCode 托盘号，扫托盘索取
     * @param warehouseId   仓
     * @param bldgId        建筑
     * @return 任务明细
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> createWholePickOrder(
            String containerCode,
            String warehouseId,
            String bldgId
    ) {
        if (StringUtils.isBlank(containerCode))
            throw new ParameterException("托盘号不能为空");
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");

        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();

        //获取当前拣货人的权限 WHOLE_PICKING 仅整件拣货
        //区域是 密集库、AGV托盘库
        List<String> userAreaCodes = new ArrayList<>();
        try {
            userAreaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "WHOLE_PICKING");
        } catch (Exception ignored) {
        }

        if (CollUtil.isEmpty(userAreaCodes)) {
            throw new BizException("工号没有菜单权限!");
        }
        RestMessage<List<BaseWmsWarehouseArea>> areas = warehouseResource.getByAreaCodes(warehouseId, userAreaCodes.toArray(new String[0]));
        if (areas == null || CollUtil.isEmpty(areas.getData())) {
            throw new BizException("工号没有菜单权限.");
        }
        List<String> areaCodes = new ArrayList<>();
        for (BaseWmsWarehouseArea datum : areas.getData()) {
            if (datum.getWarehouseAreaCategory().equals("MJK") || datum.getWarehouseAreaCategory().equals("AGVZ")) {
                areaCodes.add(datum.getWarehouseAreaCode());
            }
        }
        if (CollUtil.isEmpty(areaCodes)) {
            throw new BizException("没有待拣货的任务");
        }
        Map<String, Object> result = new HashMap<>();
        // 查询已索取的任务
        List<PickTaskDDTO> taskDDTOList = pickTaskHMapper.getPickTaskDList4(bldgId, containerCode, warehouseId, areaCodes, "1");
        if (CollUtil.isNotEmpty(taskDDTOList)) {
            //判断当前任务是否已被他人索取
            PickTaskDDTO pickTaskDDTO = taskDDTOList.stream().filter(var -> StrUtil.isNotEmpty(var.getOperatorId()) && !var.getOperatorId().equals(userDTO.getId())).findFirst().orElse(null);
            if (null != pickTaskDDTO) {
                throw new BizException("当前任务已被" + pickTaskDDTO.getOperatorCode() + "索取");
            }
            List<String> pickTaskDIds = taskDDTOList.stream().map(PickTaskDDTO::getPickTaskDId).distinct().collect(toList());
            List<PrintDataWithMark> printDataList = pickTaskService.printWholeLabels(pickTaskDIds, null, warehouseId, 0, userDTO.getNickname());
            Map<String, List<PrintDataWithMark>> collect = printDataList.stream().collect(Collectors.groupingBy(PrintDataWithMark::getDataMark));
            List<Map<String, Object>> printDatas = new ArrayList<>();
            for (String s : collect.keySet()) {
                Map<String, Object> map = new HashMap<>();
                map.put("dataMark", s);
                map.put("printData", collect.get(s));
                printDatas.add(map);
            }
            result.put("bizData", taskDDTOList);
            result.put("printData", printDatas);
            return result;
        }

        RestMessage<BusinessControl> restMessage = strategyResource.getControlByCode("PICK_TASK_ASK_WAY", warehouseId, null, enterpriseId, null);
        List<PickTaskDDTO> list;
        if (restMessage.isSuccess() && restMessage.getData() != null && "1".equals(restMessage.getData().getRegValue())) {
            list = pickTaskHMapper.getPickTaskDList4(bldgId, containerCode, warehouseId, areaCodes, "0");
            if (CollUtil.isEmpty(list)) {
                throw new BizException("没有待拣货的任务1");
            } else {
                this.askPickTask(warehouseId, list, operatorId, operatorCode, operatorName, bldgId, enterpriseId);
            }
            isSupervise(list, 50);
        } else {
            list = pickTaskHMapper.getPickTaskDList4(bldgId, containerCode, warehouseId, areaCodes, "0");
            if (CollUtil.isEmpty(list)) {
                throw new BizException("没有待拣货的任务2");
            } else {
                this.askPickTask(warehouseId, list, operatorId, operatorCode, operatorName, bldgId, enterpriseId);
            }
            isSupervise(list, 50);
        }
        List<String> pickTaskDIds = list.stream().map(PickTaskDDTO::getPickTaskDId).distinct().collect(toList());
        List<PrintDataWithMark> printDataList = pickTaskService.printWholeLabels(pickTaskDIds, null, warehouseId, 0, userDTO.getNickname());
        Map<String, List<PrintDataWithMark>> collect = printDataList.stream().collect(Collectors.groupingBy(PrintDataWithMark::getDataMark));
        List<Map<String, Object>> printDatas = new ArrayList<>();
        for (String s : collect.keySet()) {
            Map<String, Object> map = new HashMap<>();
            map.put("dataMark", s);
            map.put("printData", collect.get(s));
            printDatas.add(map);
        }
        result.put("bizData", list);
        result.put("printData", printDatas);
        return result;
    }

    /**
     * 获取当前用户未完成任务列表
     * 1.如果有则返回任务信息；2.如果没有则获取各库区未完成任务数量
     *
     * @param warehouseId
     * @param bldgId
     * @return
     */
    @Override
    public Map<String, Object> getUserUnCompleteOrder(String warehouseId, String bldgId) {
        UserDTO userDTO = userTemplate.getUserDTO();
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");

        List<String> userAreaCodes = this.getUserAreaCodes(userDTO.getUserBizModel().getEmployeeNo(), warehouseId, "2011", new String[]{"WHOLE_REPLENISH_FIRST", "WHOLE_PICKING_FIRST", "WHOLE_PICKING", "WHOLE_REPLENISH"});
        if (CollUtil.isEmpty(userAreaCodes)) {
            throw new BizException("工号没有菜单权限!");
        }
        RestMessage<List<BaseWmsWarehouseArea>> areas = warehouseResource.getByAreaCodes(warehouseId, userAreaCodes.toArray(new String[0]));
        if (areas == null || CollUtil.isEmpty(areas.getData())) {
            throw new BizException("工号没有菜单权限.");
        }
        List<String> areaCodes = new ArrayList<>();
        for (BaseWmsWarehouseArea datum : areas.getData()) {
//            if (datum.getWarehouseAreaCategory().equals("ZJK") || datum.getWarehouseAreaCategory().equals("AGVZ")) {
//                areaCodes.add(datum.getWarehouseAreaCode());
//            }
            areaCodes.add(datum.getWarehouseAreaCode());
        }
        if (CollUtil.isEmpty(areaCodes)) {
            throw new BizException("工号没有菜单权限!");
        }
        Map<String, Object> result = new HashMap<>();
        List<PickTaskDDTO> list = pickTaskHMapper.getTaskHListByPickOrder(bldgId, null, warehouseId, userDTO.getUserBizModel().getEmployeeNo());
        if (CollUtil.isEmpty(list)) {
            List<TaskCountVo> areaUnAskPickCount = pickTaskHMapper.getAreaUnAskPickCount(0, warehouseId, bldgId, areaCodes, 0);
            result.put("areaTaskList", areaUnAskPickCount);
        } else {
            isSupervise(list, 50);
//            List<String> pickTaskDIds = new ArrayList<>();
            RestMessage<List<BaseCommonDict>> billTypeList = commonClient.getDictBasicListByCodes("DO_BILL_TYPE", null);
            Map<String, String> billTypes = new HashMap<>();
            billTypeList.getData().forEach(baseCommonDict -> billTypes.put(baseCommonDict.getDictCode(), baseCommonDict.getDictName()));
            for (PickTaskDDTO dto : list) {
                dto.setBillTypeName(billTypes.get(dto.getBillType()));
//                pickTaskDIds.add(dto.getPickTaskDId());
//                BigDecimal replenishQty = this.replenishQty(dto.getItemId(), dto.getBatchNum(), dto.getLocatorCode(), enterpriseId, warehouseId);
//                if (replenishQty.doubleValue() > 0
//                        && dto.getAreaCategory().equals("ZJK")
//                        && dto.getWarehouseAreaCode().equals("GJK")
//                        ){
//                    dto.setReplenishPcs(replenishQty.divide(dto.getConversionRate(),0));
//                } else {
//                    dto.setReplenishPcs(BigDecimal.ZERO);
//                }
            }
//            if(CollectionUtil.isNotEmpty(pickTaskDIds)){
//                List<PrintDataWithMark> printDataList =  pickTaskService.printWholeLabels(pickTaskDIds,null,warehouseId,0, userDTO.getNickname());
//                Map<String, List<PrintDataWithMark>> collect = printDataList.stream().collect(Collectors.groupingBy(PrintDataWithMark::getDataMark));
//                List<Map<String, Object>> printDatas = new ArrayList<>();
//                for (String s : collect.keySet()) {
//                    Map<String, Object> map = new HashMap<>();
//                    map.put("dataMark", s);
//                    map.put("printData", collect.get(s));
//                    printDatas.add(map);
//                }
//                result.put("bizData", list);
//                result.put("printData", printDatas);
//                return result;
//            }
            result.put("bizData", list);
        }
        return result;
    }

    @Override
    public List<TaskCountVo> queryWholeAreaTaskList(String bldgId, String warehouseId) {
//        UserDTO userDTO = userTemplate.getUserDTO();
        if (StringUtils.isBlank(warehouseId))
            throw new ParameterException("仓id不能为空");

//        List<String> userAreaCodes = this.getUserAreaCodes(userDTO.getUserBizModel().getEmployeeNo(), warehouseId, "2011", new String[]{"WHOLE_REPLENISH_FIRST","WHOLE_PICKING_FIRST","WHOLE_PICKING","WHOLE_REPLENISH"});
//        if (CollUtil.isEmpty(userAreaCodes)){
//            throw new BizException("工号没有菜单权限!");
//        }
//        RestMessage<List<BaseWmsWarehouseArea>> areas = warehouseResource.getByAreaCodes(warehouseId, userAreaCodes.toArray(new String[0]));
//        if (areas == null || CollUtil.isEmpty(areas.getData())){
//            throw new BizException("工号没有菜单权限.");
//        }
//        List<String> areaCodes = new ArrayList<>();
//        for (BaseWmsWarehouseArea datum : areas.getData()) {
//            if (datum.getWarehouseAreaCategory().equals("ZJK")){
//                areaCodes.add(datum.getWarehouseAreaCode());
//            }
//        }
//        if (CollUtil.isEmpty(areaCodes)){
//            throw new BizException("没有待拣货的任务");
//        }
        return pickTaskHMapper.getAreaUnAskPickCount(0, warehouseId, bldgId, null, 0);
    }

    /**
     * 索取
     *
     * @param params 入参
     */
    @Override
    @Transactional
    public Map<String, Object> createByOperatorCode2(Map<String, Object> params) {
        log.info("开始执行索取方法入參：{}", JSON.toJSONString(params));
        Integer pickTaskType = (Integer) params.get("pickTaskType");
        String warehouseId = (String) params.get("warehouseId");
        String bldgId = (String) params.get("bldgId");
        // 增加PDA立库托盘号入参，参数有值则为立库，无值则为普通库
        String containerCode = (String) params.get("containerCode");
        String mjkFlag = (String) params.get("mjkFlag"); // 是否密集库
        String billId = (String) params.get("billGroupId"); // 是否指定任务索取
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();
        Map<String, Object> map = new HashMap<>();
        if(StringUtils.isBlank(operatorCode)){
            throw new BizException("员工号不能为空!");
        }

        // 查询已索取的拣选单
        List<PickOrder> pickOrderList = pickOrderMapper.getPickOrderListV2(bldgId, pickTaskType, null, warehouseId, "0", operatorCode, mjkFlag, billId);
        List<PickOrder> pickOrderList2 = pickOrderMapper.getPickOrderListV2(bldgId, pickTaskType, null, warehouseId, "1", operatorCode, mjkFlag, billId);
        // 根据任务优先级判断
        if (pickOrderList.size() > 0 || pickOrderList2.size() > 0) {
            PickOrder pickOrder = null;
            if (pickOrderList2.size() > 0) {
                pickOrder = pickOrderList2.get(0);
            } else {
                pickOrder = pickOrderList.get(0);
            }
            Criteria crt = Criteria.forClass(PickTaskH.class);
            crt.setRestriction(Restrictions.and(Restrictions.eq("pickOrderId", pickOrder.getPickOrderId()), Restrictions.isNotNull("containerCode")));
            long doCount = pickTaskHMapper.findCountByCriteria(crt);
            Integer taskCount = pickOrder.getTaskCount();
            map.put("total", taskCount); // 总任务数
            if (pickTaskType != 3) {
                map.put("doCount", doCount); // 已绑定容器任务数
            } else {
                if (pickOrder.getType() == 1) {
                    map.put("doCount", taskCount); // 补货任务，无需绑容器
                } else {
                    map.put("doCount", taskCount > doCount ? taskCount - 1 : taskCount); // 整单拣货，只绑定一个容器
                }
            }
            map.put("pickOrderId", pickOrder.getPickOrderId());
            map.put("printStatus", pickOrder.getPrintStatus());
            return map;
        }
        /*if (pickTaskType==3) {
            // 查询未上架的拣货任务
            Integer notFinishCount = pickTaskHMapper.getNotFinishCount(warehouseId, operatorCode);
            if (notFinishCount > 0) {
                throw new BizException("请先上架确认补货任务");
            }
        }*/
        List<String> areaCodes = new ArrayList<>();
        String workType = null;
        if (pickTaskType == 1) {
            // 获取员工作业库区编码集合
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "BULK_PICKING");
        } else if (pickTaskType == 0) {
            // 获取员工作业类型
            RestMessage<String> restMessage1 = controlResource.getWorkType(operatorCode, warehouseId, "2011");
            if (!restMessage1.isSuccess()) {
                throw new RuntimeException("获取员工作业类型失败！" + restMessage1.getMessage());
            }
            workType = restMessage1.getData();
            if (StringUtils.isEmpty(workType)) {
                throw new BizException("该员工未配置，整件拣货/补货作业权限");
            }
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", workType);
        } else if (pickTaskType == 2) {
            // 获取员工作业库区编码集合
            areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "WHOLE_BULK_PICKING");
        } else if (pickTaskType == 3) {
            // 零货
            try {
                areaCodes = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", "BULK_PICKING");
            } catch (Exception e) {
            }
            // 整件
            RestMessage<String> restMessage1 = controlResource.getWorkType(operatorCode, warehouseId, "2011");
            if (!restMessage1.isSuccess()) {
                throw new RuntimeException("获取员工作业类型失败！" + restMessage1.getMessage());
            }
            workType = restMessage1.getData();
            if (StringUtils.isEmpty(workType)) {
                throw new BizException("该员工未配置，整件拣货/补货作业权限");
            }
            List<String> areaCodes2 = pickTaskService.getAreaCodes(operatorCode, warehouseId, "2011", workType);
            areaCodes.addAll(areaCodes2);
        }
        List<PickTaskH> list = null;
        // 任务数
        Integer count = 1; // 每次一条
        // 最大拣货件数
        BigDecimal maxPcs = BigDecimal.TEN;
        RestMessage<Map<String, BusinessControl>> rest = strategyResource.getControlByCodes(new String[]{"PICK_TASK_NUM", "PICK_TASK_MAX_PCS"}, warehouseId, null, enterpriseId, bldgId);
        if (rest.isSuccess() && rest.getData() != null) {
            Map<String, BusinessControl> conMap = rest.getData();
            if (conMap.containsKey("PICK_TASK_NUM")) {
                count = Integer.valueOf(conMap.get("PICK_TASK_NUM").getRegValue());
            }
            if (conMap.containsKey("PICK_TASK_MAX_PCS")) {
                maxPcs = new BigDecimal(conMap.get("PICK_TASK_MAX_PCS").getRegValue());
            }
        }
        List<Integer> pickTaskTypes = new ArrayList<>();
        pickTaskTypes.add(pickTaskType);
        if (pickTaskType == 0) {
            if (!StringUtils.isBlank(containerCode)) {
//                pickTaskTypes.add(2); // 立库增加拣货类型
                list = pickTaskHMapper.getPickTaskByContainerCode(bldgId, containerCode, enterpriseId, warehouseId, pickTaskTypes, areaCodes, workType, billId, mjkFlag);
            } else {
                list = pickTaskHMapper.getPickTaskWholeListV2(bldgId, null, enterpriseId, warehouseId, count, pickTaskTypes, areaCodes, workType, billId, mjkFlag);
            }
            if (StringUtils.isBlank(containerCode) && CollectionUtil.isNotEmpty(list)) {
                PickTaskH pickTaskH = list.get(0);
                list = list.stream().filter(x -> x.getBillGroupId().equals(pickTaskH.getBillGroupId())).collect(Collectors.toList());
                if (list.size() > count) {
                    list = list.subList(0, count);
                }
            }
            /*if (list.size() > 1) {
                List<PickTaskH> list2 = new ArrayList<PickTaskH>();
                Integer type =0;
                for (int i = 0; i < list.size(); i++) {
                    PickTaskH h = list.get(i);
                    if (i==0) {
                        type = h.getType();
                    }
                    int pcs = pickTaskHMapper.getWholePcs(h.getPickTaskId(), enterpriseId);
                    BigDecimal js = new BigDecimal(pcs);
                    if (i == 0 || (js.compareTo(maxPcs) <= 0 && h.getType()==type)) {
                        list2.add(h);
                        maxPcs = maxPcs.subtract(js);
                    } else {
                        break;
                    }
                }
                list = list2;
            }*/
        } else if (pickTaskType == 1) {
            list = pickTaskHMapper.getPickTaskHList(bldgId, null, enterpriseId, warehouseId, count, pickTaskTypes, areaCodes, null);
        } else if (pickTaskType == 2) {
            // 功能库房新增了整货，零货，所以需要先检查是否有补货单 - by Huanglh 2022-01-20
            // 查询当天最后的补货订单编号
//            String billGroupId = pickTaskHMapper.getLastMoveBillId(warehouseId, operatorCode, 2);
//            if (billGroupId != null) {
//                // 查询该补货订单的拣货任务
//                list = pickTaskHMapper.getPickTaskHListByBill3(bldgId, billGroupId, warehouseId, areaCodes, operatorCode, 2);
//            }
//            // 查询补货任务
//            if (list == null || list.size() == 0) {
//                list = pickTaskHMapper.getPickTaskHListByMove(bldgId, enterpriseId, warehouseId, count, areaCodes, workType, operatorCode, 2);
//            }
            // 无补货任务,则索取整单任务
            if (list == null || list.size() == 0) {
                list = pickTaskHMapper.getPickTaskHListByBill(bldgId, enterpriseId, warehouseId, areaCodes, "1");
            }
        } else if (pickTaskType == 3) {
            //查询当天最后的补货订单编号
            String billGroupId = pickTaskHMapper.getLastMoveBillId(warehouseId, operatorCode, null);
            if (billGroupId != null) {
                // 查询该补货订单的拣货任务
                list = pickTaskHMapper.getPickTaskHListByBill3(bldgId, billGroupId, warehouseId, areaCodes, operatorCode, null);
            }
            if (list == null || list.size() == 0) {
                // 查询补货任务
                list = pickTaskHMapper.getPickTaskHListByMove(bldgId, enterpriseId, warehouseId, count, areaCodes, workType, operatorCode, null);
            }
            if (list.size() == 0) {
                // 无补货任务,则索取整单任务
                list = pickTaskHMapper.getPickTaskHListByBill2(bldgId, enterpriseId, warehouseId, areaCodes, "0", operatorCode);
            }
        }
//        List<String> pickTaskDIds1 = new ArrayList<>();
//        List<String> pickTaskDIds2 = new ArrayList<>();
        String pickOrderId = String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId));
//        Map<String,BaseWmsWhWorkstation> stationMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(list)) {
            try {
//                BaseWmsWhWorkstation workstation = null;
                for (PickTaskH pickTaskH : list) {
                    pickTaskH.setPickOrderId(pickOrderId);
                    pickTaskH.setStatus("1");
//                    String areaCode = pickTaskH.getWarehouseAreaCode();
//                    if (pickTaskType !=0 && pickTaskH.getType()==0) {
//                        List<String> stationIds = pickTaskService.getWorkstationIds(areaCode,warehouseId);
                    // 找同订单的复核台
//                        List<BaseWmsWhWorkstation> stationList = pickTaskHMapper.getStationByBillId(pickTaskH.getPickTaskId(),null,stationIds);
//                        if (stationList.size() > 0) {
//                            workstation= stationList.get(0);
//                            stationMap.put(areaCode,workstation);
//                        } else if (!stationMap.isEmpty() && stationMap.containsKey(areaCode)) {
//                            // 找同库区的复核台
//                            workstation = stationMap.get(areaCode);
//                        } else {
//                            workstation = pickTaskService.getBaseWmsWhWorkstation(areaCode, warehouseId, enterpriseId);
//                            stationMap.put(areaCode,workstation);
//                        }
//                        pickTaskH.setStationId(workstation.getStationId());
//                        pickTaskH.setStationName(workstation.getStationName());
//                        pickTaskH.setStationCode(workstation.getStationCode());
//                    }
                    pickTaskHMapper.updateFields(pickTaskH, FieldSelector.newInstance().include(new String[]{"status", "pickOrderId", "stationCode", "stationName", "stationId"}));

                    // 如果是整件生成条码
                    if (pickTaskH.getPickTaskType() == 0) {
                        generateBarcode(pickTaskH);
                    }
                }
            } catch (Exception e) {
                throw new PrologException("拣货索取失败！" + e.getMessage());
            }
            if (pickTaskType == 3) {
                pickTaskService.updatePickTaskD4WholeOrderPick(userDTO, enterpriseId, list);
            }
            PickOrder pickOrder = new PickOrder();
            pickOrder.setPickOrderId(pickOrderId);
            pickOrder.setStatus("0");
            pickOrder.setWarehouseId(warehouseId);
            pickOrder.setTaskCount(list.size());
            pickOrder.setOperatorId(operatorId);
            pickOrder.setOperatorName(operatorName);
            pickOrder.setOperatorCode(operatorCode);
            pickOrder.setPickTaskType(list.get(0).getPickTaskType());
            pickOrder.setPrintStatus("1");
            ModelUtils.generateBaseData(pickOrder, userTemplate::getUserDTO);
            pickOrderMapper.save(pickOrder);
//            List<PrintData> printDataList1 = new ArrayList<>();
//            List<PrintData> printDataList2 = new ArrayList<>();
            if (pickTaskType == 0) {
                // 调整件标签打印查询接口
//                if (pickTaskDIds1!=null && pickTaskDIds1.size()>0) {
//                    printDataList1 = pickTaskService.printWholeLabels(pickTaskDIds1,null,warehouseId,0,operatorName);
//                }
//                if (pickTaskDIds2!=null && pickTaskDIds2.size()>0) {
//                    printDataList2 = pickTaskService.printWholeLabels(pickTaskDIds2,null,warehouseId,1,operatorName);
//                }
//                printDataList1.addAll(printDataList2);
            }
//            else if (pickTaskType==3 && pickTaskDIds2!=null && pickTaskDIds2.size()>0) {
//                printDataList2 = pickTaskService.printWholeLabels(pickTaskDIds2,null,warehouseId,1,operatorName);
//                printDataList1.addAll(printDataList2);
//            }
            // 返回打印数据
//            map.put("printDataList", printDataList1);
            map.put("total", list.size()); // 总任务数
            if (pickTaskType != 3) {
                map.put("doCount", 0); // 已绑定容器任务数
            } else {
                if (list.get(0).getType() == 1) {
                    map.put("doCount", list.size()); // 补货任务，无需绑容器
                } else {
                    map.put("doCount", list.size() - 1); // 整单拣货，只绑定一个容器
                }
            }
            map.put("pickOrderId", pickOrderId);
            map.put("printStatus", "0");
            log.info("结束执行索取方法+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
            return map;
        } else {
            if (StringUtils.isEmpty(containerCode)) {
                throw new BizException("未索取到拣选任务");
            } else {
                throw new BizException("该容器无拣货任务");
            }

        }
    }


    @Override
    public OuterTaskV2DTO outerCheckUnAskV2(String barcode, String bldgId, String warehouseId) {
        //通过barcode查询订单信息
        List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByMap(MapUtils.put("barcode", barcode).put("warehouseId", warehouseId).put("bldgId", bldgId).getMap(), BarcodeHDO.class);
        if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
            throw new BizException("查询无该包裹号，请确认！");
        }
        BarcodeHDO barcodeHDO = barcodeHDOS.get(0);
        if(barcodeHDO.getIsMerged() != null && 1 == barcodeHDO.getIsMerged()){
            if (!StringUtils.isBlank(barcodeHDO.getCheckStatus()) && Integer.valueOf(barcodeHDO.getCheckStatus()) >= 5){
                throw new BizException("该包裹号已复核！");
            }
            if(!"4".equals(barcodeHDO.getCheckStatus())){
                throw new BizException("该包裹号未做EIS复核！");
            }
        }
        if (barcodeHDO.getCancelFlag() != null) {
            if ("1".equals(barcodeHDO.getCancelFlag())) {
                throw new BizException("该面单已消单！");
            }
        }
//        barcodeHDOS = barcodeHDOS.stream().filter(item -> item.getIsMerged() == null || item.getIsMerged() != 1).collect(Collectors.toList());
//        if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
//            throw new BizException("该包裹号不需要复核！");
//        }
        String billGroupId = barcodeHDOS.get(0).getBillGroupId();
//        Criteria crt = Criteria.forClass(PickTaskH.class);
//        Restriction r1 = Restrictions.eq("billGroupId", billGroupId);
//        Restriction r2 = Restrictions.eq("warehouseId", warehouseId);
//        Restriction r3 = Restrictions.eq("bldgId", bldgId);
//        Restriction r4 = Restrictions.ne("pickTaskType", 1);
//        crt.setRestriction(Restrictions.and(r1, r2, r3, r4));
//        List<PickTaskH> pickTaskHS = pickTaskHMapper.findByCriteria(crt);
//        if (pickTaskHS == null || pickTaskHS.size() <= 0) {
//            throw new BizException("查询出库单失败!");
//        }
//        PickTaskH pickTaskH = pickTaskHS.get(0);
        List<PickTaskH> pickTaskHS = pickTaskHMapper.getByBarcode(barcode,billGroupId,bldgId,warehouseId);
        if(pickTaskHS == null || pickTaskHS.size() <= 0){
            throw new BizException("查询拣货任务汇总失败!");
        }
//        for (PickTaskH pickTaskH : pickTaskHS) {
//            if ("10".equals(pickTaskH.getStatus())) {
//                throw new BizException("订单已复核，不能重复复核！");
//            }
//        }
        boolean anyMatch = pickTaskHS.stream().anyMatch(item -> !"10".equals(item.getStatus()) || item.getPickTaskType() == 1);
        if(!anyMatch){
            throw new BizException("拣货任务已复核，不能重复复核！");
        }

        List<String> pickTaskIds = pickTaskHS.stream().filter(item -> !"10".equals(item.getStatus()) || item.getPickTaskType() == 1).map(PickTaskH::getPickTaskId).collect(Collectors.toList());

        //查询包裹明细
        List<OuterLblPkgDTO> lblPkgDTOS = barcodeHMapper.getlblPkgDTOS(billGroupId, bldgId, warehouseId);
        if (lblPkgDTOS == null || lblPkgDTOS.size() <= 0) {
            throw new BizException("查询包裹信息失败或包裹已复核！");
        }
        int zjCount = 0, lhCount = 0;
        for (OuterLblPkgDTO lblPkgDTO : lblPkgDTOS) {
            if ("0".equals(lblPkgDTO.getType())) {
                lblPkgDTO.setTypeName("拼箱");
                lhCount++;
            }
            if ("1".equals(lblPkgDTO.getType())) {
                lblPkgDTO.setTypeName("整件");
                zjCount++;
            }
            if (StringUtils.isEmpty(lblPkgDTO.getCheckStatus()) || "0".equals(lblPkgDTO.getCheckStatus())) {
                lblPkgDTO.setCheckStatus("0");
                lblPkgDTO.setSort(1);
            }
            if (barcode.equals(lblPkgDTO.getBarcode()) && !"5".equals(lblPkgDTO.getCheckStatus())) {
                lblPkgDTO.setCheckStatus("1");
                lblPkgDTO.setSort(0);
            }
            if (!barcode.equals(lblPkgDTO.getBarcode()) && "5".equals(lblPkgDTO.getCheckStatus())) {
                lblPkgDTO.setSort(2);
            }
            lblPkgDTO.setPickTaskId(String.join(",",pickTaskIds));
            lblPkgDTO.setBillGroupId(billGroupId);
            if(lblPkgDTO.getSort() == null){
                lblPkgDTO.setSort(1);
            }
        }
        //排序
        lblPkgDTOS = lblPkgDTOS.stream().sorted(Comparator.comparing(OuterLblPkgDTO::getSort)).collect(Collectors.toList());



        OuterTaskV2DTO result = new OuterTaskV2DTO();

        Criteria cr1 = Criteria.forClass(PickTaskD.class);
        Restriction res1 = Restrictions.in("pickTaskId", pickTaskIds.toArray());
        Restriction res2 = Restrictions.eq("warehouseId", warehouseId);
        Restriction res3 = Restrictions.lt("flowStatus", 3);
        cr1.setRestriction(Restrictions.and(res1, res2, res3));
        long count = pickTaskDMapper.findCountByCriteria(cr1);
        if (count == 0) {
            result.setStatus(0);
            result.setStatusName("拣货完成");
        } else {
            result.setStatus(1);
            result.setStatusName("拣货中");
        }

        result.setBillGroupId(billGroupId);
        result.setPickTaskId(String.join(",",pickTaskIds));
        result.setZjCount(zjCount);
        result.setLsCount(lhCount);
        result.setJsCount(lblPkgDTOS.size());
        result.setLblPkgDTOList(lblPkgDTOS);

        return result;
    }

    @Transactional
    @Override
    public Map<String, Object> outerCheckConfirmV2(OuterTaskVO vo) {
        TimeInterval timer = DateUtil.timer();
        log.info("outerCheckConfirmV2.updateDb.start:{}",timer.intervalRestart());
        if (StringUtils.isEmpty(vo.getBarcode())) {
            throw new BizException("条码不能为空!");
        }
        if (StringUtils.isEmpty(vo.getPickTaskId())) {
            throw new BizException("拣货任务id不能为空!");
        }
        if (StringUtils.isEmpty(vo.getBillGroupId())) {
            throw new BizException("billGroupId不能为空!");
        }

        Map<String, Object> result = new HashMap<>();

        UserDTO userDTO = userTemplate.getUserDTO();
        if(userDTO == null){
            throw new ParameterException("请登录!");
        }
        String operatorCode = userDTO.getUserBizModel().getEmployeeNo();
        String operatorName = userDTO.getUserBizModel().getEmployeeName();
        String operatorId = userDTO.getId();

        //根据条码查询barcodeh
        Criteria crth = Criteria.forClass(BarcodeHDO.class);
        Restriction res1 = Restrictions.eq("barcode", vo.getBarcode());
        crth.setRestriction(Restrictions.and(res1));
        List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByCriteria(crth);
        if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
            throw new BizException("查询条码表汇总失败!");
        }
        List<BarcodeHDO> collect = barcodeHDOS.stream().filter(x -> !StringUtils.isEmpty(x.getCheckStatus()) && Integer.valueOf(x.getCheckStatus()) >= 5).collect(Collectors.toList());
        if (collect.size() > 0) {
            List<String> barcodes = collect.stream().map(BarcodeHDO::getBarcode).collect(toList());
            throw new BizException("条码【" + JSON.toJSONString(barcodes) + "】已复核！");
        }

        //更新扫描包裹为已复核
        Map<String, Object> map = MapUtils.put("checkStatus", "5").put("checkerId2", operatorId).put("checkerNo2", operatorCode).put("checkerName2", operatorName).put("checkTime2", new Date()).getMap();
        //如果是整件包裹或者是包裹重量为空，则更新包裹重量
        if("1".equals(barcodeHDOS.get(0).getType()) || barcodeHDOS.get(0).getWeight() == null || barcodeHDOS.get(0).getWeight().compareTo(0d) == 0){
            //查询waveBilld的重量
            List<WaveBillDDO> waveBillDDOList = waveBillDMapper.findbyBarcode(vo.getBarcode());
            BigDecimal totalWeight = waveBillDDOList.stream().map(item -> (item.getPickQty().multiply(item.getWeight())).divide(item.getConversionRate(),2,BigDecimal.ROUND_HALF_UP)).reduce(BigDecimal.ZERO, BigDecimal::add);
            map.put("weight",totalWeight);
        }
        barcodeHMapper.updateMapByCriteria(map, crth);

        //更新扫描包裹为已复核
        Criteria crtd = Criteria.forClass(BarCodeDDO.class);
        Restriction resd1 = Restrictions.eq("barcodeId", barcodeHDOS.get(0).getId());
        crtd.setRestriction(Restrictions.and(resd1));
        barcodeDMapper.updateMapByCriteria(MapUtils.put("checkStatus", "5").getMap(), crtd);
        //更新出库任务状态
        checkPickTask(barcodeHDOS, vo.getPickTaskId());


        //查询出库单是否全部拣货完成
        Criteria cr1 = Criteria.forClass(PickTaskD.class);
        Restriction r1 = Restrictions.eq("srcId", barcodeHDOS.get(0).getBillGroupId());
        Restriction r2 = Restrictions.lt("flowStatus", 3);
        Restriction r3 = Restrictions.ne("pickTaskType", "1");
        cr1.setRestriction(Restrictions.and(r1, r2,r3));
        long count = pickTaskDMapper.findCountByCriteria(cr1);
        //如果有未拣货完成的任务，则将包裹复核完成后，判断拣货任务对应的包裹是否全部复核
        if (count > 0) {
            return result;
        }
        //判断当前包裹是否为对应订单的最后一个复核完成的包裹
//        Criteria crth2 = Criteria.forClass(BarcodeHDO.class);
//        Restriction resh1 = Restrictions.eq("billGroupId", vo.getBillGroupId());
//        Restriction resh2 = Restrictions.ne("checkStatus", "5");
//        Restriction resh3 = Restrictions.isnull("checkStatus" );
//        Restriction resh4 = Restrictions.isnull("isMerged" );
//        crth2.setRestriction(Restrictions.and(resh1, Restrictions.or(resh2,resh3,resh4)));
//        long count3 = barcodeHMapper.findCountByCriteria(crth2);
//        if (count3 > 0) {
//            return result;
//        }
        Criteria cr2 = Criteria.forClass(PickTaskD.class);
        Restriction r4 = Restrictions.lt("flowStatus", 7);
        cr2.setRestriction(Restrictions.and(r1, r4,r3));
        long count3 = pickTaskDMapper.findCountByCriteria(cr2);
        if (count3 > 0) {
            return result;
        }
        log.info("outerCheckConfirmV2.updateDb.end:{}",timer.intervalRestart());

        OmsDoBillHDO omsDoBillHDO = omsDoBillHMapper.findById(vo.getBillGroupId(), OmsDoBillHDO.class);
        if (omsDoBillHDO == null) {
            throw new BizException("查询出口订单失败!");
        }

        //2.2判断当前订单下是否存在零货拣货任务(包含AGVL库区的拣货任务)
        List<PickTaskH> pickTaskHS = pickTaskHMapper.findByMap(MapUtils.put("billGroupId", vo.getBillGroupId()).getMap(), PickTaskH.class);
        if (pickTaskHS == null || pickTaskHS.size() <= 0) {
            throw new BizException("查询出库单失败!");
        }
        long count2 = pickTaskHS.stream().filter(item -> item.getPickTaskType() == 1 && "AGVL".equals(item.getWarehouseAreaCode())).count();
        if(count2 <= 0){
            if("1".equals(omsDoBillHDO.getAttrStr5())){
                //2.2.2.2，则根据拣货任务的实际拣货数量打印出库清单，发票(pdf，需要调上游系统接口，获取url)，以及该订单下所有明细的质检报告单；
                //获取发票
                List<String> invoices = getInvoice(omsDoBillHDO.getBillno());
                if(invoices == null){
                    result.put("msg","该订单无需打印发票！");
                }else {
                    //打印发票信息
                    List<PrintParam> printInvoiceData = getPrintInvoiceData(omsDoBillHDO.getBillno(), omsDoBillHDO.getConsignorid(), omsDoBillHDO.getBranchid());
                    result.put("printInvoiceData",printInvoiceData);
                    result.put("billNo",omsDoBillHDO.getBillno());
                }
//                    //保存发票信息
//                    saveInvoice(invoice, omsDoBillHDO, userDTO.getNickname());
//
//                    //打印发票信息
//                    List<PrintParam> printInvoiceData = getPrintInvoiceData(omsDoBillHDO.getBillno(), omsDoBillHDO.getConsignorid(), omsDoBillHDO.getBranchid());
//                    result.put("printInvoiceData",printInvoiceData);
            }
            try {
                ServletRequestAttributes reqa = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
                new Thread(()-> {
                    RequestContextHolder.setRequestAttributes(reqa, false);
                    ServletRequestAttributes servletRequestAttributes =
                            (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
                    String userkey = servletRequestAttributes.getRequest().getHeader("UserKey");

                    if (!HystrixRequestContext.isCurrentThreadInitialized()) {
                        HystrixRequestContext.initializeContext();
                    }
                    HystrixVarUtil.setUserKey(userkey);
                    try {
                        print(omsDoBillHDO,pickTaskHS);
                    }catch (Exception e) {
                        log.error("RF复核打印失败：{}", e.getMessage());
                    }finally {
                        RequestContextHolder.resetRequestAttributes();
                    }
                }).start();

            }catch (Exception e){
                e.printStackTrace();
                log.info("RF复核打印失败：{}",e.toString());
            }
        }

        result.put("billId", omsDoBillHDO.getBillid());
        result.put("billtype", omsDoBillHDO.getBilltype());
        String username = userDTO.getUsername();
        ServletRequestAttributes reqa = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        new Thread(()-> {
            RequestContextHolder.setRequestAttributes(reqa, false);
            ServletRequestAttributes servletRequestAttributes =
                    (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
            String userkey = servletRequestAttributes.getRequest().getHeader("UserKey");

            if (!HystrixRequestContext.isCurrentThreadInitialized()) {
                HystrixRequestContext.initializeContext();
            }
            HystrixVarUtil.setUserKey(userkey);
            try {
                outBoundUploadCircubill(omsDoBillHDO,username);
            }catch (Exception e) {
                log.error("RF复核完成上传监管码失败：{}", e.getMessage());

            }finally {
                RequestContextHolder.resetRequestAttributes();
            }
        }).start();

        log.info("outerCheckConfirmV2.print.end:{}",timer.intervalRestart());

        //释放容器号
        List<PickTaskH> pickTaskHList = pickTaskHMapper.findByMap(MapUtils.put("billGroupId", vo.getBillGroupId()).put("pickTaskType",2).getMap(), PickTaskH.class);
        if(pickTaskHList != null && pickTaskHList.size() > 0){
            List<String> containerCodes = pickTaskHList.stream().map(PickTaskH::getContainerCode).collect(toList());
            //释放容器
            ContainerQueryVO containerQueryVO = new ContainerQueryVO();
            containerQueryVO.setContainerCodeList(containerCodes);
            containerQueryVO.setWarehouseId(pickTaskHList.get(0).getWarehouseId());
            warehouseResource.release(containerQueryVO);
        }

        log.info("outerCheckConfirmV2.releaseContainerNo.start:{}",timer.intervalRestart());


        Criteria cr3 = Criteria.forClass(PickTaskD.class);
        cr3.setRestriction(Restrictions.and(r1, r4));
        long count4 = pickTaskDMapper.findCountByCriteria(cr3);
        if (count4 > 0) {
            return result;
        }

        new Thread(()-> {
            RequestContextHolder.setRequestAttributes(reqa, false);
            ServletRequestAttributes servletRequestAttributes =
                    (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
            String userkey = servletRequestAttributes.getRequest().getHeader("UserKey");

            if (!HystrixRequestContext.isCurrentThreadInitialized()) {
                HystrixRequestContext.initializeContext();
            }
            HystrixVarUtil.setUserKey(userkey);
            try {
                postBackErpByTable(CollUtil.toList(omsDoBillHDO.getBillid()));
            }catch (Exception e) {
                log.error("RF复核完成回写回传中间表失败：{}", e.getMessage());
                omsDoBillHMapper.updateMapById(omsDoBillHDO.getBillid(),MapUtils.put("attrStr9","N").getMap(),OmsDoBillHDO.class);
            }finally {
                RequestContextHolder.resetRequestAttributes();
            }
        }).start();

        log.info("outerCheckConfirmV2.callback.start:{}",timer.intervalRestart());
        return result;
    }


    @Override
    public void scanSupervisionCode(OutCheckSupervisionCodeVO vo) {
        if (vo == null) {
            throw new BizException("入参不能为空!");
        }
        if (StringUtils.isEmpty(vo.getBillId())) {
            throw new BizException("billId不能为空!");
        }
        if (StringUtils.isEmpty(vo.getBillType())) {
            throw new BizException("billType不能为空!");
        }
        if (vo.getSupervisionCodes() == null || vo.getSupervisionCodes().size() <= 0) {
            throw new BizException("监管码不能为空！");
        }
        boolean anyMatch = vo.getSupervisionCodes().stream().anyMatch(item -> StringUtils.isEmpty(item));
        if (anyMatch) {
            throw new BizException("监管码不能是空字符串！");
        }
        log.info("扫描监管码入参：{}", JSON.toJSONString(vo));
        UploadCircubParamVO uploadCircubParamVO = new UploadCircubParamVO();
        uploadCircubParamVO.setBillCode(vo.getBillId());
        uploadCircubParamVO.setOutType(vo.getBillType());
        List<SupervisionCode> supervisionCodes = new ArrayList<>();
        for (String s : vo.getSupervisionCodes()) {
            SupervisionCode supervisionCode = new SupervisionCode();
            supervisionCode.setSupervisionCode(s);
            supervisionCode.setId(UUIDUtils.generateWithoutSeperator());
            supervisionCode.setRefBillId(vo.getBillId());
            supervisionCode.setUploadFlag("0");
            supervisionCode.setDownFlag(0);
            supervisionCode.setSaveType(2);
            supervisionCode.setSupervisionType(Integer.valueOf(vo.getBillType()));

            supervisionCodes.add(supervisionCode);
        }

//        uploadCircubParamVO.setSupervisionCodes(supervisionCodes);
//        RestMessage<Object> restMessage = inBoundClient.uploadCircubill(uploadCircubParamVO);
//        log.info("保存监管码返回结果：{}",JSON.toJSONString(restMessage));
//        if(restMessage == null || !restMessage.isSuccess()){
//            throw new BizException("保存监管码失败！");
//        }

        RestMessage<Object> restMessage = inBoundClient.batchAddSupCode(supervisionCodes);
        log.info("保存监管码返回结果：{}", JSON.toJSONString(restMessage));
        if (restMessage == null || !restMessage.isSuccess()) {
            throw new BizException("保存监管码失败！");
        }

    }


    private void askPickTask(
            String warehouseId,
            List<PickTaskDDTO> list,
            String operatorId,
            String operatorName,
            String operatorCode,
            String bldgId,
            String enterpriseId
    ) {
        //查询任务头
        List<PickTaskH> pickTaskHList = pickTaskHMapper.findByIds(PickTaskH.class, list.stream().map(PickTaskDDTO::getPickTaskId).distinct().toArray(), null);
        //组包索取
        String pickOrderId = String.valueOf(SnowFlakeUtils.getId());
        PickOrder pickOrder = new PickOrder();
        pickOrder.setPickOrderId(pickOrderId);
        pickOrder.setStatus("0");
        pickOrder.setWarehouseId(warehouseId);
        pickOrder.setTaskCount(list.size());
        pickOrder.setOperatorId(operatorId);
        pickOrder.setOperatorName(operatorName);
        pickOrder.setOperatorCode(operatorCode);
        pickOrder.setPickTaskType(list.get(0).getPickTaskType());
        pickOrder.setPrintStatus("1");
        ModelUtils.generateBaseData(pickOrder, userTemplate::getUserDTO);
        pickOrderMapper.save(pickOrder);

        //设置pickOrderId
        for (PickTaskDDTO pickTaskDDTO : list) {
            pickTaskDDTO.setPickOrderId(pickOrderId);
        }
        try {
            for (PickTaskH pickTaskH : pickTaskHList) {
                pickTaskH.setPickOrderId(pickOrderId);
                pickTaskH.setStatus("1");
                pickTaskHMapper.updateFields(pickTaskH, FieldSelector.newInstance().include("status", "pickOrderId"));
                //如果是整件索取，生成条码
                if (pickTaskH.getPickTaskType() == 0) {
                    List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("pickTaskId", pickTaskH.getPickTaskId()).getMap(), PickTaskD.class);
                    if (pickTaskDList.size() > 0) {
                        //生成打印条码
                        for (PickTaskD pickTaskD : pickTaskDList) {
                            if ((pickTaskH.getType() == 0 && pickTaskD.getPickTaskType() == 0) || pickTaskH.getType() == 1) {
                                pickTaskService.saveBarcode(
                                        Collections.singletonList(pickTaskH),
                                        Collections.singletonList(pickTaskD.getPickTaskDId()),
                                        pickOrderId,
                                        bldgId,
                                        warehouseId,
                                        enterpriseId
                                );
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("拣货索取失败", e);
            throw new PrologException("拣货索取失败！" + e.getMessage());
        }
        Criteria criteria = Criteria.forClass(PickTaskD.class);
        Object[] pickTaskDIds = list.stream().map(PickTaskDDTO::getPickTaskId).distinct().toArray();
        Restriction r1 = Restrictions.in("pickTaskDId", pickTaskDIds);
        criteria.setRestriction(Restrictions.and(r1));
        pickTaskDMapper.updateMapByCriteria(MapUtils.put("flowStatus", "2").getMap(), criteria);
    }

    /*
        "dictCode": "WHOLE_PICKING",
        "dictName": "仅整件拣货",
        "dictCode": "BULK_PICKING",
        "dictName": "散件拣货",
        "dictCode": "WHOLE_BULK_PICKING",
        "dictName": "整散合一拣货",
        "dictCode": "WHOLE_REPLENISH",
        "dictName": "仅整件补货",
        "dictCode": "WHOLE_ORDER_PICKING",
        "dictName": "整单拣选",
        "dictCode": "WHOLE_PICKING_FIRST",
        "dictName": "整件拣货优先",
        "dictCode": "WHOLE_REPLENISH_FIRST",
        "dictName": "整件补货优先",
     */
    private List<String> getUserAreaCodes(String operatorCode, String warehouseId, String businessType, String[] workTypes) {
        if (ArrayUtil.isEmpty(workTypes)) {
            return new ArrayList<>();
        }
        List<String> areaCodes = new ArrayList<>();
        for (String workType : workTypes) {
            areaCodes.addAll(getAreaCodes(operatorCode, warehouseId, businessType, workType));
        }
        return areaCodes;
    }

    private List<String> getAreaCodes(String operatorCode, String warehouseId, String businesstype, String worktype) {
        RestMessage<List<String>> restMessage = controlResource.getWorkareaList(operatorCode, warehouseId, businesstype, worktype, null);
        if (!restMessage.isSuccess()) {
            throw new RuntimeException("获取员工作业库区编码集合失败！" + restMessage.getMessage());
        }
        if (CollUtil.isNotEmpty(restMessage.getData())) {
            return restMessage.getData();
        }
        return new ArrayList<>();
    }


    @Override
    public Object execute(InterfaceBill dataObject) throws Exception {
        if (dataObject.getNo().equals("retry")) {
            throw new RetryException("retry test");
        }
        log.info("there is your interface proces");
        return null;
    }

    /**
     * @param dataObject
     * @return com.prolog.fx.inf.core.dto.LogInfo
     * @Description 转换日志信息
     * @param: dataObject
     * @Author chenyc
     * @Date 2021/8/9 18:25
     */
    @Override
    public SimpleLog toLog(InterfaceBill dataObject) {
        SimpleLog simpleLog = new SimpleLog();
        try {
            simpleLog.setData(JsonUtils.toString(dataObject));
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        simpleLog.setBussinessKey1(dataObject.getId());
        simpleLog.setBussinessKey2(dataObject.getNo());
        simpleLog.setBussinessKey3(dataObject.getCustomer());
        return simpleLog;
    }

    /**
     * @param simpleLog
     * @return D
     * @Description 转换数据对象
     * @param: logInfo
     * @Author chenyc
     * @Date 2021/8/9 18:25
     */
    @Override
    public InterfaceBill toDataObject(SimpleLog simpleLog) {
        if (simpleLog != null) {
            try {
                InterfaceBill bill = JsonUtils.parseJsonString(simpleLog.getData(), new TypeReference<InterfaceBill>() {
                });
                return bill;
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
        return null;
    }

    @Transactional
    @Override
    public List<PrintParam> getPrintFaceOrder(String faceOrder, String consignorId, String warehouseId, String carrierCode) {
//        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
//        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);//新发起一个事务
//        TransactionStatus status = transactionManager.getTransaction(def);// 获得事务状态
//        try {
//            // 业务代码
//            barcodeHMapper.updateMapById("fc100e8fca54492f92b8411c2315bc2f",MapUtils.put("barcode",faceOrder).getMap(),BarcodeHDO.class);
//            List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByMap(MapUtils.put("barcode", faceOrder).getMap(), BarcodeHDO.class);
//            transactionManager.commit(status);// 手动提交事务
//            return printFaceOrder(barcodeHDOS,consignorId,warehouseId,carrierCode);
//
//        }catch (Exception e){
//            // 异常的时候回滚
//            transactionManager.rollback(status);
//        }
//        return null;

        barcodeHMapper.updateMapById("fc100e8fca54492f92b8411c2315bc2f",MapUtils.put("barcode",faceOrder).getMap(),BarcodeHDO.class);
        List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByMap(MapUtils.put("barcode", faceOrder).getMap(), BarcodeHDO.class);
//        transactionManager.commit(status);// 手动提交事务
        return printFaceOrder(barcodeHDOS,consignorId,warehouseId,carrierCode);
    }

    /**
     * 标签复核
     *
     * @param pickTaskIds
     * @param barcodeHDOS
     */
    private void checkPickTask(List<BarcodeHDO> barcodeHDOS, String pickTaskIds) {
        Criteria crtd = Criteria.forClass(BarCodeDDO.class);
        List<String> barCodeIds = barcodeHDOS.stream().map(BarcodeHDO::getId).collect(Collectors.toList());
        Restriction rt = Restrictions.in("barcodeId", barCodeIds.toArray());
        crtd.setRestriction(Restrictions.and(rt));
        //更新拣货任务明细
        List<BarCodeDDO> barCodeDDOList = barcodeDMapper.findByCriteria(crtd);
        Set<String> pickTaskDId = barCodeDDOList.stream().map(BarCodeDDO::getWmsPickTaskDId).collect(Collectors.toSet());
        //判断任务明细对应的包裹是否全部复核
        Criteria crtd2 = Criteria.forClass(BarCodeDDO.class);
        Restriction rtd1 = Restrictions.in("wmsPickTaskDId", pickTaskDId.toArray());
        Restriction rtd2 = Restrictions.ne("checkStatus", "5");
        Restriction rtd3 = Restrictions.isnull("checkStatus");
        crtd2.setRestriction(Restrictions.and(rtd1, Restrictions.or(rtd2,rtd3)));
        long count2 = barcodeDMapper.findCountByCriteria(crtd2);
        if (count2 == 0) {
            Criteria c = Criteria.forClass(PickTaskD.class);
            Restriction r = Restrictions.in("pickTaskDId", pickTaskDId.toArray());
            c.setRestriction(Restrictions.and(r));
            pickTaskDMapper.updateMapByCriteria(MapUtils.put("flowStatus", "7").getMap(), c);

            //判断任务对应的任务明细是否全部复核
            String[] pickTaskIdar = pickTaskIds.split(",");
            Criteria c2 = Criteria.forClass(PickTaskD.class);
            Restriction rt1 = Restrictions.in("pickTaskId", pickTaskIdar);
            Restriction rt2 = Restrictions.lt("flowStatus", "7");
            c2.setRestriction(Restrictions.and(rt1, rt2));
            long count3 = pickTaskDMapper.findCountByCriteria(c2);
            if (count3 == 0) {
//                for (String pickTaskId : pickTaskIdar) {
//                    pickTaskHMapper.updateMapById(pickTaskId, MapUtils.put("status", "10").getMap(), PickTaskH.class);
//                }
                Criteria c3 = Criteria.forClass(PickTaskH.class);
                c3.setRestriction(rt1);
                pickTaskHMapper.updateMapByCriteria(MapUtils.put("status", "10").getMap(),c3);
            }
        }
    }

    /**
     * 获取面单处理器
     *
     * @param carrier
     * @return
     */
    public BaseFaceOrderHandler getFaceOrderHandler(String carrier) {
        BaseFaceOrderHandler baseFaceOrderHandler = null;
        switch (carrier) {
            case "SF":
                baseFaceOrderHandler = SpringUtils.getBeansByType(SfFaceOrderHandler.class);
                break;
            case "YUNDA":
                baseFaceOrderHandler = SpringUtils.getBeansByType(YdFaceOrderHandler.class);
                break;
            case "YUNDAPROD":
                baseFaceOrderHandler = SpringUtils.getBeansByType(YdFaceOrderHandler.class);
                break;
            case "JD":
                baseFaceOrderHandler = SpringUtils.getBeansByType(JdFaceOrderHandler.class);
                break;
            case "DBL":
                baseFaceOrderHandler = SpringUtils.getBeansByType(DbFaceOrderHandler.class);
                break;
            case "EMS":
                baseFaceOrderHandler = SpringUtils.getBeansByType(EmsFaceOrderHandler.class);
                break;
            case "SFCD":
                baseFaceOrderHandler = SpringUtils.getBeansByType(SfFaceorderCdHandler.class);
                break;
            default:
                break;
        }
        return baseFaceOrderHandler;
    }

    /**
     * 获取面单处理器
     *
     * @param carrier
     * @return
     */
    public KyBaseFaceOrderHandler getKyFaceOrderHandler(String carrier) {
        KyBaseFaceOrderHandler kyBaseFaceOrderHandler = null;
        switch (carrier) {
            case "YUNDAKUAIYUN":
            case "YUNDA":
                kyBaseFaceOrderHandler = SpringUtils.getBeansByType(YdKyFaceOrderHandler.class);
                break;
            case "SHUNFENGKUAIYUN":
                kyBaseFaceOrderHandler = SpringUtils.getBeansByType(SfKyFaceOrderHandler.class);
                break;
            case "DEBANGWULIU":
                kyBaseFaceOrderHandler = SpringUtils.getBeansByType(DbKyFaceOrderHandler.class);
                break;
            case "YOUZHENGGUONEI":
                kyBaseFaceOrderHandler = SpringUtils.getBeansByType(EmsKyFaceOrderHandler.class);
                break;
            case "JINGDONGKUAIYUN":
            case "JD":
                kyBaseFaceOrderHandler = SpringUtils.getBeansByType(JdKyFaceOrderHandler.class);
                break;
            case "JDKD":
                kyBaseFaceOrderHandler = SpringUtils.getBeansByType(JdKdFaceOrderHandler.class);
                break;
            default:
                break;
        }
        return kyBaseFaceOrderHandler;
    }

    /**
     * 打印数据
     *
     * @return
     */
    public List<PrintParam> getPrintData(PickTaskH h, String pickTaskDId, BigDecimal pickQty, List<WaveBillDDO> billDDOList) {

        List<PrintParam> printParams = new ArrayList<>();
        //查询oms_do_bill_h
        OmsDoBillHDO omsDoBillHDO = omsDoBillHMapper.findById(h.getBillGroupId(), OmsDoBillHDO.class);
        //查询barcoded
        Criteria criteria = Criteria.forClass(BarCodeDDO.class);
        Restriction res11;
        //功能库房按任务获取，整件按明细获取
        if(h.getPickTaskType() == 2){
            List<PickTaskD> pickTaskDS = pickTaskDMapper.findByMap(MapUtils.put("pickTaskId", h.getPickTaskId()).getMap(), PickTaskD.class);
            if(pickTaskDS == null || pickTaskDS.size() <= 0){
                throw new BizException("获取面单，查询任务明细失败！");
            }
            List<String> pickTaskDIds = pickTaskDS.stream().map(PickTaskD::getPickTaskDId).collect(toList());
            res11 = Restrictions.in("wmsPickTaskDId", pickTaskDIds.toArray());
            List<String> waveStorageIds = pickTaskDS.stream().map(PickTaskD::getWaveStorageId).collect(toList());
            billDDOList = pickTaskHMapper.getBillDListV2(h.getEnterpriseId(),h.getWarehouseId(),waveStorageIds);

        }else {
            res11 = Restrictions.eq("wmsPickTaskDId", pickTaskDId);
        }
        Restriction res12 = Restrictions.eq("warehouseId", h.getWarehouseId());
        criteria.setRestriction(Restrictions.and(res11, res12));
        List<BarCodeDDO> barCodeDDOS = barcodeDMapper.findByCriteria(criteria);
        if (barCodeDDOS == null || barCodeDDOS.size() <= 0) {
            throw new BizException("查询条码表明细失败!");
        }
        //查询barcodeh
        Criteria crth = Criteria.forClass(BarcodeHDO.class);
        List<String> barCodeIds = barCodeDDOS.stream().map(BarCodeDDO::getBarcodeId).collect(Collectors.toList());
        Restriction rest11 = Restrictions.in("id", barCodeIds.toArray());
        Restriction rest12 = Restrictions.eq("warehouseId", h.getWarehouseId());
        Restriction rest13 = null;
        if("1".equals(omsDoBillHDO.getCarrierType()) || "3".equals(omsDoBillHDO.getCarrierType())){
            rest13 = Restrictions.isnull("barcode");
        }
        crth.setRestriction(Restrictions.and(rest11, rest12, rest13));
        List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByCriteria(crth);
        if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
            throw new BizException("查询条码表汇总失败!");
        }
        if ("1".equals(omsDoBillHDO.getCarrierType()) || "3".equals(omsDoBillHDO.getCarrierType())) {
            //获取面单
            List<String> faceOrderNos = getFaceOrder(omsDoBillHDO,barcodeHDOS,billDDOList,barCodeDDOS);
            //面单获取失败重新获取
            if(faceOrderNos == null || faceOrderNos.size() <= 0){
                throw new BizException("获取面单失败!");
//                List<String> alreadyObtainFailedCarrierCodes = new ArrayList<>();
//                alreadyObtainFailedCarrierCodes.add(omsDoBillHDO.getCarrierCode());
//                //获取承运商信息
//                BaseCarrierMstRequestVO baseCarrierMstRequestVO = new BaseCarrierMstRequestVO();
//                RestMessage<List<BaseCarrierMst>> carrierMstRest = chainResource.findAll(baseCarrierMstRequestVO);
//                if(carrierMstRest == null || !carrierMstRest.isSuccess() || carrierMstRest.getData() == null || carrierMstRest.getData().size() <= 0){
//                    throw new BizException("承运商信息查询失败！");
//                }
//                List<BaseCarrierMst> carrierMstList = carrierMstRest.getData();
//                log.info("查询承运商返回列表:{}",JSON.toJSONString(carrierMstList));
//                for (int i = 0; i < carrierMstList.size(); i++) {
//                    BaseCarrierMst baseCarrierMst = carrierMstList.get(i);
//                    //如果是最后一个承运商
//                    if(i == carrierMstList.size() - 1){
//                        omsDoBillHDO.setAttrNum1(BigDecimal.ONE);
//                    }
//                    //过滤已获取失败的承运商并按优先级倒序排序
//                    carrierMstList = carrierMstList.stream().filter(item -> "1".equals(item.getIsEnable()) && item.getSort() != null && !alreadyObtainFailedCarrierCodes.contains(item.getCarrierCode())).sorted(Comparator.comparing(BaseCarrierMst::getSort).reversed()).collect(toList());
//                    if(carrierMstList.size() <= 0){
//                        throw new BizException("获取承运商失败!");
//                    }
//                    faceOrderNos = retryObtainFaceOrder(omsDoBillHDO,baseCarrierMst);
//                    if(faceOrderNos != null && faceOrderNos.size() > 0){
//                        String billno = omsDoBillHDO.getBillno();
//                        if(billno.contains("_")){
//                            billno = billno.substring(0,billno.indexOf("_"));
//                        }
//                        barcodeHDOS = barcodeHMapper.getByBillPickComplete(billno);
//                        break;
//                    }
//                    alreadyObtainFailedCarrierCodes.add(baseCarrierMst.getCarrierCode());
//
//                }

            }
            for (int i = 0; i < barcodeHDOS.size(); i++) {
                BarcodeHDO barcodeHDO = barcodeHDOS.get(i);
                barcodeHDO.setBarcode(faceOrderNos.get(i));
                barcodeHDO.setCarrierType(omsDoBillHDO.getCarrierType());
                barcodeHMapper.update(barcodeHDO);
            }
            try {
                printParams = printFaceOrder(barcodeHDOS, omsDoBillHDO.getConsignorid(), omsDoBillHDO.getBranchid(), omsDoBillHDO.getCarrierCode());
            }catch (Exception e){
                e.printStackTrace();
                log.info("打印面单报错：",e.getMessage());
            }
        } else {
            crth.setRestriction(Restrictions.and(rest11, rest12));
            List<BarcodeHDO> barcodeHDOS1 = barcodeHMapper.findByCriteria(crth);
            if (barcodeHDOS1 == null || barcodeHDOS1.size() <= 0) {
                throw new BizException("查询条码表汇总失败!");
            }
            List<String> barcodes = barcodeHDOS1.stream().map(BarcodeHDO::getBarcode).collect(toList());
            printBarcodes(barcodes, omsDoBillHDO.getConsignorid(), omsDoBillHDO.getBranchid(),omsDoBillHDO.getBillno());
        }
        return printParams;
    }

    /**
     * 获取面单
     * @param omsDoBillHDO
     * @param barcodeHDOS
     * @param billDDOList
     * @param barCodeDDOS
     */
    private List<String> getFaceOrder(OmsDoBillHDO omsDoBillHDO,List<BarcodeHDO> barcodeHDOS,List<WaveBillDDO> billDDOList,List<BarCodeDDO> barCodeDDOS){
        List<String> faceOrderNos = new ArrayList<>();
        //如果是京东，需要判断是否拆单
        if("JD".equals(omsDoBillHDO.getCarrierCode())){
            omsDoBillHDO.setCarrierType("3");
            List<BarcodeHDO> hdoList = barcodeHMapper.findByMap(MapUtils.put("billGroupId", omsDoBillHDO.getBillid()).getMap(), BarcodeHDO.class);
            boolean anyMatch = hdoList.stream().anyMatch(item -> !StringUtils.isBlank(item.getBarcode()));
            if(anyMatch){
                omsDoBillHDO.setBillno(omsDoBillHDO.getBillno() + "_" + (hdoList.stream().filter(item -> !StringUtils.isBlank(item.getBarcode())).count() + 1));
            }
        }
        if ("1".equals(omsDoBillHDO.getCarrierType())) {

            if("YUNDA".equals(omsDoBillHDO.getCarrierCode()) && "1".equals(omsDoBillHDO.getCarrierType())){
                boolean changeCarrierType = false;
                List<BarcodeHDO> hdoList = barcodeHMapper.findByMap(MapUtils.put("billGroupId", omsDoBillHDO.getBillid()).getMap(), BarcodeHDO.class);

                //将之前韵达快递获取的面单取消
                List<String> cancelBarcodes = hdoList.stream().filter(item -> !StringUtils.isBlank(item.getBarcode()) && "1".equals(item.getCarrierType())).map(BarcodeHDO::getBarcode).collect(Collectors.toList());
                if(!cancelBarcodes.isEmpty()){
                    faceOrderService.faceCancel(cancelBarcodes,false);

                    Criteria crth = Criteria.forClass(BarcodeHDO.class);
                    Restriction rest14 = Restrictions.eq("billGroupId",omsDoBillHDO.getBillid());
                    crth.setRestriction(Restrictions.and(rest14));
                    barcodeHMapper.updateMapByCriteria(MapUtils.put("cancelFlag","0").put("barcode",null).getMap(),crth);
                    barcodeHDOS = barcodeHMapper.findByMap(MapUtils.put("billGroupId", omsDoBillHDO.getBillid()).getMap(), BarcodeHDO.class);
                    changeCarrierType = true;
                }

                if(hdoList.size() > 1){
                    changeCarrierType = true;
                }

                if(changeCarrierType){
                    omsDoBillHDO.setCarrierType("3");
                    omsDoBillHMapper.updateMapById(omsDoBillHDO.getBillid(),MapUtils.put("carrierType","3").getMap(),OmsDoBillHDO.class);
                }
            }

            if("SF".equals(omsDoBillHDO.getCarrierCode())){
                //判断顺丰是否已经获取面单
                List<BarcodeHDO> hdoList = barcodeHMapper.findByMap(MapUtils.put("billGroupId", omsDoBillHDO.getBillid()).getMap(), BarcodeHDO.class);
                boolean anyMatch = hdoList.stream().anyMatch(item -> !StringUtils.isBlank(item.getBarcode()));
                if(anyMatch){
                    faceOrderNos = getFaceOrderHandler("SFCD").getFaceOrderNo(omsDoBillHDO, null, barcodeHDOS.size());
                    log.info("获取面单返回结果：{}",JSON.toJSONString(faceOrderNos));
                    return faceOrderNos;
                }
            }

            if("1".equals(omsDoBillHDO.getCarrierType())){
                try {
                    log.info("快递获取面单开始："+System.currentTimeMillis());
                    faceOrderNos = getFaceOrderHandler(omsDoBillHDO.getCarrierCode()).getFaceOrderNo(omsDoBillHDO, billDDOList, barcodeHDOS.size());
                }catch (Exception e){
                    log.info("快递获取面单失败: {}"+e.getMessage());
                    e.printStackTrace();
                }
            }
        }
        if ("3".equals(omsDoBillHDO.getCarrierType())) {
            Set<String> itemIds = barCodeDDOS.stream().map(BarCodeDDO::getItemId).collect(Collectors.toSet());
            RestMessage<List<BaseMtlItemMst>> itemClientListByIds = itemClient.getListByIds(itemIds);
            if(itemClientListByIds == null || !itemClientListByIds.isSuccess()){
                throw new BizException("查询物料信息失败!");
            }
            List<BaseMtlItemMst> data = itemClientListByIds.getData();
            if(data == null || data.size() <= 0){
                throw new BizException("根据物料ID列表："+JSON.toJSONString(itemIds)+"查询物料失败!");
            }
            List<FaceOrderPickTaskDDTO> list = new ArrayList<>();
            for (BarcodeHDO barcodeHDO : barcodeHDOS) {
                List<BarCodeDDO> barCodeDDOList = barCodeDDOS.stream().filter(item -> item.getBarcodeId().equals(barcodeHDO.getId())).collect(toList());
                if(barCodeDDOList == null || barCodeDDOList.size() <= 0){
                    throw new BizException("根据条码："+barcodeHDO.getBarcode()+"匹配条码明细失败!");
                }
                Set<String> itemIdList = barCodeDDOList.stream().map(BarCodeDDO::getItemId).collect(Collectors.toSet());
                List<String> itemNames = data.stream().filter(item -> itemIdList.contains(item.getItemId())).map(BaseMtlItemMst::getItemName).collect(Collectors.toList());

                FaceOrderPickTaskDDTO faceOrderPickTaskDDTO = new FaceOrderPickTaskDDTO();
                faceOrderPickTaskDDTO.setPcs(1);
                if(itemNames.size() > 0){
                    faceOrderPickTaskDDTO.setItemName(String.join(";",itemNames));
                }else {
                    faceOrderPickTaskDDTO.setItemName(itemNames.get(0));
                }
                list.add(faceOrderPickTaskDDTO);
            }
            List<FaceOrderPickTaskDDTO> faceOrderPickTaskDDTOS = new ArrayList<>();
            Map<String, List<FaceOrderPickTaskDDTO>> map = list.stream().collect(Collectors.groupingBy(FaceOrderPickTaskDDTO::getItemName));
            for (Map.Entry<String, List<FaceOrderPickTaskDDTO>> entry : map.entrySet()) {
                List<FaceOrderPickTaskDDTO> value = entry.getValue();

                FaceOrderPickTaskDDTO faceOrderPickTaskDDTO = new FaceOrderPickTaskDDTO();
                faceOrderPickTaskDDTO.setItemName(entry.getKey());
                faceOrderPickTaskDDTO.setPcs(value.size());

                faceOrderPickTaskDDTOS.add(faceOrderPickTaskDDTO);
            }
            try {
                log.info("快运获取面单开始："+System.currentTimeMillis());

                if ("JINGDONGKUAIYUN".equals(omsDoBillHDO.getCarrierCode()) || "JD".equals(omsDoBillHDO.getCarrierCode())) {
                    //如果是京东，需要先判断重量 获取面单处理方式
                    String flag = acquireFlag(omsDoBillHDO);
                    log.info("获取面单处理方式：{}",flag);
                    faceOrderNos = getKyFaceOrderHandler(flag).getFaceOrderNo(omsDoBillHDO, faceOrderPickTaskDDTOS, billDDOList, barcodeHDOS.size());
                } else {
                    faceOrderNos = getKyFaceOrderHandler(omsDoBillHDO.getCarrierCode()).getFaceOrderNo(omsDoBillHDO, faceOrderPickTaskDDTOS, billDDOList, barcodeHDOS.size());
                }

            }catch (Exception e){
                log.info("快运获取面单失败：{}",e.getMessage());
                e.printStackTrace();
            }
        }
        log.info("获取面单返回结果：{}",JSON.toJSONString(faceOrderNos));
        return faceOrderNos;
    }

    public String acquireFlag(OmsDoBillHDO omsDoBillHDO) {
        JdKyOrderAddVO faceOrderAddVO = new JdKyOrderAddVO();
//        String carrierCode = omsDoBillHDO.getCarrierCode();

        RestMessage<List<BaseCommonDict>> restMessage = commonClient.getDictBasicListByCodes("CarrierConfig", null);
        if(restMessage == null || !restMessage.isSuccess() || restMessage.getData() == null || restMessage.getData().size() <= 0){
            throw new BizException("获取面单配置失败!");
        }
        List<BaseCommonDict> data = restMessage.getData();
        List<BaseCommonDict> commonDicts = data.stream().filter(item -> omsDoBillHDO.getCarrierCode().equals(item.getAttr3())).collect(Collectors.toList());
        if(commonDicts.isEmpty()){
            throw new BizException("承运商："+ omsDoBillHDO.getCarrierCode()+"未配置面单参数!");
        }

        for (BaseCommonDict commonDict : commonDicts) {

            if(">=".equals(commonDict.getAttr1()) && omsDoBillHDO.getTotWeight().compareTo(new BigDecimal(commonDict.getAttr2())) >= 0){
                faceOrderAddVO.setCarrierCode(commonDict.getDictCode());
                return "JD";
            }

            if("<".equals(commonDict.getAttr1()) && omsDoBillHDO.getTotWeight().compareTo(new BigDecimal(commonDict.getAttr2())) < 0){
                faceOrderAddVO.setCarrierCode(commonDict.getDictCode());
               return "JDKD";
            }
        }
        if(StringUtils.isBlank(faceOrderAddVO.getCarrierCode())){
            throw new BizException("京东面单参数未配置!");
        }
        return "JD";
    }


    /**
     * 重新获取面单
     * @param omsDoBillHDO
     */
    private List<String> retryObtainFaceOrder(OmsDoBillHDO omsDoBillHDO,BaseCarrierMst baseCarrierMst) {
        //取消面单
        faceOrderService.cancelByBillno(omsDoBillHDO.getBillno());
        //清空barcode表面单号
        faceOrderService.clearByBillno(omsDoBillHDO.getBillno());

        String billno = omsDoBillHDO.getBillno();
        if(billno.contains("_")){
            billno = billno.substring(0,billno.indexOf("_"));
        }
        //查询订单已拣货完成条码明细
        List<BarcodeHDO> barcodeHDOList =  barcodeHMapper.getByBillPickComplete(billno);
        if(barcodeHDOList == null || barcodeHDOList.size() <= 0){
            throw new BizException("订单："+billno+"没有未拣货完成任务明细!");
        }
        Criteria crtd = Criteria.forClass(BarCodeDDO.class);
        List<String> barCodeIds = barcodeHDOList.stream().map(BarcodeHDO::getId).collect(Collectors.toList());
        Restriction rt = Restrictions.in("barcodeId", barCodeIds.toArray());
        crtd.setRestriction(Restrictions.and(rt));
        //查询barcode明细
        List<BarCodeDDO> barCodeDDOList = barcodeDMapper.findByCriteria(crtd);
        if(barCodeDDOList == null || barCodeDDOList.size() <= 0 ){
            throw new BizException("查询barcoded失败!");
        }
        //查询wavebilldd
        List<WaveBillDDO> billDDOList = waveBillDMapper.getByBillPickComplete(billno);
        if(billDDOList == null || billDDOList.size() <= 0 ){
            throw new BizException("查询wms_wave_bill_d失败!");
        }
        //更新承运商
        String carrierCode = baseCarrierMst.getCarrierCode();
        Map<String, Object> map = MapUtils.put("carrierCode", carrierCode).getMap();
        if("JD".equals(carrierCode)){
            omsDoBillHDO.setCarrierType("3");
        }else {
            omsDoBillHDO.setCarrierType("1");
        }
        map.put("carrierId",baseCarrierMst.getCarrierId());
        map.put("carrierName",baseCarrierMst.getCarrierName());
        map.put("carrierType",omsDoBillHDO.getCarrierType());
        omsDoBillHDO.setCarrierCode(carrierCode);
        omsDoBillHDO.setCarrierName(baseCarrierMst.getCarrierName());
        omsDoBillHDO.setCarrierId(baseCarrierMst.getCarrierId());
        omsDoBillHMapper.updateMapById(omsDoBillHDO.getBillid(), map,OmsDoBillHDO.class);
        return getFaceOrder(omsDoBillHDO, barcodeHDOList, billDDOList, barCodeDDOList);
    }




    /**
     * 获取发票
     *
     * @param billNo 上游订单号
     */
    public List<String> getInvoice(String billNo) {
//        try {
//            String url = getRequestUrl("GET_INVOICE_URL");
//            log.info("获取发票请求url：{}", url);
//            Map<String, Object> map = MapUtils.put("orderNos", billNo).getMap();
//            String param = JSON.toJSONString(map);
//            log.info("获取发票请求param：{}", param);
//            JSONObject jsonObject = HttpClientUtils.postByJson(url, param);
//            log.info("获取发票请求返回结果：{}", JSON.toJSONString(jsonObject));
//
//            int code = jsonObject.getIntValue("code");
//            if (code != 1) {
//                throw new BizException(jsonObject.getString("msg"));
//            }
//            JSONArray array = jsonObject.getJSONArray("data");
//            Object o = array.get(0);
//            JSONObject jsonObject1 = JSON.parseObject(JSON.toJSONString(o));
//            return jsonObject1.getString("Pdf");
//        }catch (Exception e){
//            return "http://121.41.99.69:8000/upload/55116335.pdf";
//        }
        List<InvoicePdfDO> invoicePdfDOS = invoicePdfDOMapper.findByMap(MapUtils.put("orderNo", billNo).getMap(), InvoicePdfDO.class);
        if(invoicePdfDOS == null || invoicePdfDOS.size() <= 0){
            throw new BizException("发票申请中，请等待！");
        }
        if(StringUtils.isBlank(invoicePdfDOS.get(0).getPdfUrl())){
            return null;
        }
        return invoicePdfDOS.stream().map(InvoicePdfDO :: getPdfUrl).collect(Collectors.toList());
    }

    /**
     * 获取请求地址
     *
     * @return
     */
    public String getRequestUrl(String code) {
        if (StringUtils.isBlank(code)) {
            return null;
        }
        RestMessage<List<BaseCommonDict>> restMessage = commonClient.getDictBasicListByCodes("ERP_URL", null);
        if (restMessage == null || !restMessage.isSuccess() || restMessage.getData() == null || restMessage.getData().size() <= 0) {
            throw new BizException("获取erp请求url列表失败!");
        }


        List<BaseCommonDict> data = restMessage.getData();
        BaseCommonDict baseCommonDict = data.stream().filter(item -> item.getDictCode().equals(code)).findFirst().orElse(null);
        if (baseCommonDict == null) {
            throw new BizException("未配置:" + code + "请求地址!");
        }
        return baseCommonDict.getDictName();
    }

    /**
     * 保存发票url
     *
     * @param invoice
     * @param omsDoBillHDO
     */
    public void saveInvoice(String invoice, OmsDoBillHDO omsDoBillHDO, String createBy) {

        invoicePdfDOMapper.deleteByMap(MapUtils.put("orderNo",omsDoBillHDO.getBillno()).getMap(),InvoicePdfDO.class);

        InvoicePdfDO pdfDO = new InvoicePdfDO();
        pdfDO.setConsignorId(omsDoBillHDO.getConsignorid());
        pdfDO.setCreateBy(createBy);
        pdfDO.setCreateDate(new Date());
        pdfDO.setOrderNo(omsDoBillHDO.getBillno());
        pdfDO.setEnterpriseId(omsDoBillHDO.getEnterpriseId());
        pdfDO.setPdfUrl(invoice);
        pdfDO.setWarehouseId(omsDoBillHDO.getBranchid());
        invoicePdfDOMapper.save(pdfDO);
    }

    /**
     * 打印面单
     *
     * @param barcodeHDOS
     * @param consignorId
     * @param warehouseId
     * @param carrierCode
     */
    public List<PrintParam> printFaceOrder(List<BarcodeHDO> barcodeHDOS, String consignorId, String warehouseId, String carrierCode) {
        List<String> carrierCodes = CollUtil.toList("SF","YUNDA","YUNDAPROD","JD","DBL","EMS","YUNDAKUAIYUN", "SHUNFENGKUAIYUN","DEBANGWULIU","YOUZHENGGUONEI","JINGDONGKUAIYUN");
        if(!carrierCodes.contains(carrierCode)){
            throw new BizException("承运商编码不正确！");
        }
        List<PrintParam> printParamList = new ArrayList<>();
        for (BarcodeHDO barcodeHDO : barcodeHDOS) {


            PrintParam printParam = new PrintParam();
            printParam.setConsignorId(consignorId);
            String printBillCode = null;
            if ("SHUNFENGKUAIYUN".equals(carrierCode)) {
                carrierCode = "SF";
            }
            if ("DEBANGWULIU".equals(carrierCode)) {
                carrierCode = "DBL";
            }
            if ("YOUZHENGGUONEI".equals(carrierCode)) {
                carrierCode = "EMS";
            }
            if ("JINGDONGKUAIYUN".equals(carrierCode)) {
                carrierCode = "JD";
            }
            switch (carrierCode) {
                case "SF":
                    printBillCode = "wmsFaceOrder-SF";
                    break;
                case "YUNDA":
                    printBillCode = "wmsFaceOrder-YD";
                    break;
                case "YUNDAPROD":
                    printBillCode = "wmsFaceOrder-YD";
                    break;
                case "YUNDAKUAIYUN":
                    printBillCode = "wmsFaceOrder-YD";
                    break;
                case "JD":
                    printBillCode = "wmsFaceOrder-JD";
                    break;
                case "DBL":
                    printBillCode = "wmsFaceOrder-DB";
                    break;
                case "EMS":
                    printBillCode = "wmsFaceOrder-EMS";
                    break;
                default:
                    break;
            }
            printParam.setPrintBillCode(printBillCode);
            printParam.setWarehouseId(warehouseId);
            printParam.setParams(MapUtils.put("waybillCode", barcodeHDO.getBarcode()).getMap());
            printParamList.add(printParam);
        }

//        log.info("打印面单入参：{}",JSON.toJSONString(printParamList));
//        RestMessage<?> restMessage = commonClient.executePrint(printParamList);
//        log.info("打印面单返回结果：{}", JSON.toJSONString(restMessage));
        return printParamList;
    }

    @Transactional
    @Override
    public RestMessage<?> print(List<PrintParam> printData) {
        if(printData == null || printData.size() <= 0){
            return null;
        }
        log.info("打印面单入参：{}",JSON.toJSONString(printData));
        RestMessage<?> restMessage = commonClient.executePrint(printData);
        log.info("打印面单返回结果：{}", JSON.toJSONString(restMessage));
        return restMessage;
    }

    /**
     * 打印标签
     *
     * @param barCodes
     * @param consignorId
     * @param warehouseId
     */
    public void printBarcodes(List<String> barCodes, String consignorId, String warehouseId,String billNo) {
        List<PrintParam> printParamList = new ArrayList<>();
        for (String barCode : barCodes) {
            PrintParam printParam = new PrintParam();
            printParam.setConsignorId(consignorId);
            printParam.setPrintBillCode("wmsBarcodeh");
            printParam.setWarehouseId(warehouseId);
            printParam.setParams(MapUtils.put("barcode", barCode).getMap());
            printParamList.add(printParam);
        }
        log.info("打印标签入参：{}",JSON.toJSONString(printParamList));
        RestMessage<?> restMessage = commonClient.executePrint(printParamList);
        log.info("打印标签返回结果：{}", JSON.toJSONString(restMessage));
        //记录打印日志
        printLogService.save(billNo,"wmsBarcodeh",restMessage.isSuccess());

    }

    /**
     * 获取打印打印发票数据
     *
     * @param orderNo
     */
    public List<PrintParam> getPrintInvoiceData(String orderNo, String consignorId, String warehouseId) {
        List<PrintParam> printParamList = new ArrayList<>();

        PrintParam printParam = new PrintParam();
//        printParam.setConsignorId(consignorId);
        printParam.setPrintBillCode("invoice-pdf");
//        printParam.setWarehouseId(warehouseId);
        printParam.setParams(MapUtils.put("orderNo", orderNo).getMap());

        printParamList.add(printParam);

//        log.info("打印发票入参：{}",JSON.toJSONString(printParamList));
//        RestMessage<?> restMessage = commonClient.executePrint(printParamList);
//        log.info("打印发票返回结果：{}", JSON.toJSONString(restMessage));
        return printParamList;
    }

    /**
     * 打印发票
     *
     * @param orderNo
     */
    public void printInvoice(String orderNo, String consignorId, String warehouseId) {
        List<PrintParam> printParamList = new ArrayList<>();

        PrintParam printParam = new PrintParam();
//        printParam.setConsignorId(consignorId);
        printParam.setPrintBillCode("invoice-pdf");
//        printParam.setWarehouseId(warehouseId);
        printParam.setParams(MapUtils.put("orderNo", orderNo).getMap());

        printParamList.add(printParam);

        try {
            log.info("打印发票入参：{}",JSON.toJSONString(printParamList));
            RestMessage<?> restMessage = commonClient.executePrint(printParamList);
            log.info("打印发票返回结果：{}", JSON.toJSONString(restMessage));
            //记录打印日志
            printLogService.save(orderNo,"invoice-pdf",restMessage.isSuccess());
        }catch (Exception e){
            e.printStackTrace();
            log.info("打印发票失败：{}",e.getMessage());
        }

    }

    /**
     * 打印出库清单
     *
     * @param billId
     */
    public void printOutDetailList(String billId, String consignorId, String warehouseId,String printDetailMode) {
        if ("2".equals(printDetailMode)){
            List<PrintParam> cgPrintParamList = new ArrayList<>();

            PrintParam printParamCg = new PrintParam();
            printParamCg.setConsignorId(consignorId);
            printParamCg.setPrintBillCode("OutBillQn-ZH");
            printParamCg.setWarehouseId(warehouseId);
            printParamCg.setParams(MapUtils.put("billId", billId).getMap());

            cgPrintParamList.add(printParamCg);

            try {
                log.info("打印出库清单-折后入参：{}",JSON.toJSONString(cgPrintParamList));
                RestMessage<?> restMessageCg = commonClient.executePrint(cgPrintParamList);
                log.info("打印出库清单-折后返回结果：{}", JSON.toJSONString(restMessageCg));
                //记录打印日志
                printLogService.save(billId,"OutBillQn-ZH",restMessageCg.isSuccess());
            }catch (Exception e){
                e.printStackTrace();
                log.info("打印出库清单-折后失败：{}",e.getMessage());
            }


        } else if ("3".equals(printDetailMode)) {
            List<PrintParam> ypPrintParamList = new ArrayList<>();
            PrintParam printParamYp = new PrintParam();
            printParamYp.setConsignorId(consignorId);
            printParamYp.setPrintBillCode("OutBillYM-YP");
            printParamYp.setWarehouseId(warehouseId);
            printParamYp.setParams(MapUtils.put("billId", billId).getMap());
            ypPrintParamList.add(printParamYp);
            log.info("打印出库清单-药品入参：{}",JSON.toJSONString(ypPrintParamList));
            try {
                RestMessage<?> restMessageYp = commonClient.executePrint(ypPrintParamList);
                log.info("打印出库清单-药品返回结果：{}", JSON.toJSONString(restMessageYp));
                //记录打印日志
                printLogService.save(billId,"OutBillYM-YP",restMessageYp.isSuccess());
            }catch (Exception e){
                e.printStackTrace();
                log.info("打印出库清单-药品失败：{}",e.getMessage());
            }



            List<PrintParam> qxPrintParamList = new ArrayList<>();
            PrintParam printParamQx = new PrintParam();
            printParamQx.setConsignorId(consignorId);
            printParamQx.setPrintBillCode("OutBillYM-QX");
            printParamQx.setWarehouseId(warehouseId);
            printParamQx.setParams(MapUtils.put("billId", billId).getMap());
            qxPrintParamList.add(printParamQx);
            log.info("打印出库清单-器械入参：{}",JSON.toJSONString(qxPrintParamList));

            try {
                RestMessage<?> restMessageQx = commonClient.executePrint(qxPrintParamList);
                log.info("打印出库清单-器械返回结果：{}", JSON.toJSONString(restMessageQx));
                //记录打印日志
                printLogService.save(billId,"OutBillYM-QX",restMessageQx.isSuccess());
            }catch (Exception e){
                e.printStackTrace();
                log.info("打印出库清单-器械失败：{}",e.getMessage());
            }



            List<PrintParam> spPrintParamList = new ArrayList<>();
            PrintParam printParamSp = new PrintParam();
            printParamSp.setConsignorId(consignorId);
            printParamSp.setPrintBillCode("OutBillYM-SP");
            printParamSp.setWarehouseId(warehouseId);
            printParamSp.setParams(MapUtils.put("billId", billId).getMap());
            spPrintParamList.add(printParamSp);
            log.info("打印出库清单-食品入参：{}",JSON.toJSONString(spPrintParamList));
            try {
                RestMessage<?> restMessageSp = commonClient.executePrint(spPrintParamList);
                log.info("打印出库清单-食品返回结果：{}", JSON.toJSONString(restMessageSp));
                //记录打印日志
                printLogService.save(billId,"OutBillYM-SP",restMessageSp.isSuccess());
            }catch (Exception e){
                e.printStackTrace();
                log.info("打印出库清单-食品失败：{}",e.getMessage());
            }

        } else if ("4".equals(printDetailMode)){
            List<PrintParam> cgPrintParamList = new ArrayList<>();

            PrintParam printParamCg = new PrintParam();
            printParamCg.setConsignorId(consignorId);
            printParamCg.setPrintBillCode("OutBillQn-NB");
            printParamCg.setWarehouseId(warehouseId);
            printParamCg.setParams(MapUtils.put("billId", billId).getMap());

            cgPrintParamList.add(printParamCg);

            log.info("打印出库清单-牛逼入参：{}",JSON.toJSONString(cgPrintParamList));
            try {
                RestMessage<?> restMessageCg = commonClient.executePrint(cgPrintParamList);
                log.info("打印出库清单-牛逼返回结果：{}", JSON.toJSONString(restMessageCg));
                //记录打印日志
                printLogService.save(billId,"OutBillQn-NB",restMessageCg.isSuccess());
            }catch (Exception e){
                e.printStackTrace();
                log.info("打印出库清单-牛逼失败：{}",e.getMessage());
            }

        } else {
            List<PrintParam> cgPrintParamList = new ArrayList<>();

            PrintParam printParamCg = new PrintParam();
            printParamCg.setConsignorId(consignorId);
            printParamCg.setPrintBillCode("OutBillQnCg");
            printParamCg.setWarehouseId(warehouseId);
            printParamCg.setParams(MapUtils.put("billId", billId).getMap());

            cgPrintParamList.add(printParamCg);

            log.info("打印出库清单-常规入参：{}",JSON.toJSONString(cgPrintParamList));
            try {
                RestMessage<?> restMessageCg = commonClient.executePrint(cgPrintParamList);
                log.info("打印出库清单返回结果：{}", JSON.toJSONString(restMessageCg));
                //记录打印日志
                printLogService.save(billId,"OutBillQnCg",restMessageCg.isSuccess());
            }catch (Exception e){
                e.printStackTrace();
                log.info("打印出库清单-常规失败：{}",e.getMessage());
            }

        }
    }

    /**
     * 打印质检报告单
     *
     * @param billId
     * @param consignorId
     * @param warehouseId
     */
    public void printQrReport(String billId, String consignorId, String warehouseId) {
        //查询任务明细
        List<PickTaskD> pickTaskDS = pickTaskDMapper.findByMap(MapUtils.put("srcId", billId).getMap(), PickTaskD.class);
        if (pickTaskDS == null || pickTaskDS.size() <= 0) {
            throw new BizException("查询任务明细失败！");
        }
//        Set<String> waveStorageIds = pickTaskDS.stream().map(PickTaskD::getWaveStorageId).collect(Collectors.toSet());
//        List<WaveStorageDO> storageDOList = waveStorageMapper.findByIds(WaveStorageDO.class, waveStorageIds.toArray(), null);
//        if (storageDOList == null || storageDOList.size() <= 0) {
//            throw new BizException("查询波次预占失败！");
//        }
        //查询商品、批次是否已经打印过质检报告单
        List<String> itemIds = pickTaskDS.stream().map(PickTaskD::getItemId).collect(Collectors.toList());
        List<PrintLog> printLogs = printLogService.findbyItemIds(itemIds,"imgManage-ZJBG-pdf");

        List<String> billdLineIds = new ArrayList<>();
        List<PrintParam> printParamList = new ArrayList<>();
        List<PrintLog> savePrintLogs = new ArrayList<>();
        for (PickTaskD pickTaskD : pickTaskDS) {
//            if(printLogs != null && printLogs.size() > 0){
//                //校验品批是否有打印记录
//                long count = printLogs.stream().filter(item -> item.getAttrStr1().equals(pickTaskD.getItemId()) && item.getAttrStr2().equals(pickTaskD.getBatchId())).count();
//                if(count > 0){
//                    log.info("该商品："+pickTaskD.getItemId()+",批次："+pickTaskD.getBatchId()+"已经打印过质检报告单!");
//                    continue;
//                }
//            }

            PrintParam printParam = new PrintParam();
//            printParam.setConsignorId(consignorId);
            printParam.setPrintBillCode("imgManage-ZJBG-pdf");
//            printParam.setWarehouseId(warehouseId);
//            WaveStorageDO waveStorageDO = storageDOList.stream().filter(item -> item.getId().equals(pickTaskD.getWaveStorageId())).findFirst().orElse(null);
//            if(waveStorageDO == null){
//                throw new BizException("匹配波次预占失败！");
//            }
            printParam.setParams(MapUtils.put("itemId", pickTaskD.getItemId()).put("batchId",pickTaskD.getBatchId()).put("barcode", billId).getMap());
            billdLineIds.add(pickTaskD.getSrcLineId());
            printParamList.add(printParam);

            PrintLog printLog = new PrintLog();
            printLog.setBillno(billId);
            printLog.setPrintCode("imgManage-ZJBG-pdf");
            printLog.setAttrStr1(pickTaskD.getItemId());
            printLog.setAttrStr2(pickTaskD.getBatchId());
            printLog.setStatus("200");
            savePrintLogs.add(printLog);
        }
        if(printParamList.size() <= 0){
            return;
        }
        log.info("打印质检报告单入参：{}",JSON.toJSONString(printParamList));
        RestMessage<?> restMessage = commonClient.executePrint(printParamList);
        //保存打印日志
        if(restMessage != null && restMessage.isSuccess()){
            printLogService.saveBatch(savePrintLogs);
        }
        //记录打印次数 attrstr4
        billdLineIds = new ArrayList<>(new HashSet<>(billdLineIds));
        omsDoBillDMapper.updateAttrstr4(billdLineIds);

        log.info("打印质检报告单返回结果：{}", JSON.toJSONString(restMessage));
    }


    /**
     * 打印首营资料
     *
     * @param billId
     * @param consignorId
     * @param warehouseId
     */
    public void printSyInfo(String billId, String consignorId, String warehouseId) {
        //查询任务明细
        List<PickTaskD> pickTaskDS = pickTaskDMapper.findByMap(MapUtils.put("srcId", billId).getMap(), PickTaskD.class);
        Set<String> uniqueItemIds = pickTaskDS.stream() .map(PickTaskD::getItemId) .collect(Collectors.toSet());
        List<BaseMtlItemMst> data = itemClient.getListByIds(uniqueItemIds).getData();
        Map<String, String> itemCodeMap = data.stream() .collect(Collectors.toMap(BaseMtlItemMst::getItemId, BaseMtlItemMst::getItemCode));
        pickTaskDS.forEach(pickTask -> { String itemCode = itemCodeMap.get(pickTask.getItemId()); pickTask.setItemCode(itemCode); });
        if (pickTaskDS == null || pickTaskDS.size() <= 0) {
            throw new BizException("查询任务明细失败！");
        }

        //查询商品是否已经打印过首营资料
        List<String> itemIds = pickTaskDS.stream().map(PickTaskD::getItemId).collect(Collectors.toList());
        List<PrintLog> printLogs = printLogService.findbyItemIds(itemIds,"imgManage-SYZL-pdf");

        List<String> billdLineIds = new ArrayList<>();
        List<PrintParam> printParamList = new ArrayList<>();
        List<PrintLog> savePrintLogs = new ArrayList<>();
        for (PickTaskD pickTaskD : pickTaskDS) {

//            if(printLogs != null && printLogs.size() > 0){
//                //校验品是否有打印记录
//                long count = printLogs.stream().filter(item -> item.getAttrStr1().equals(pickTaskD.getItemId())).count();
//                if(count > 0){
//                    log.info("改商品："+pickTaskD.getItemCode()+"已经打印过首营资料!");
//                    continue;
//                }
//            }

            PrintParam printParam = new PrintParam();
//            printParam.setConsignorId(consignorId);
            printParam.setPrintBillCode("imgManage-SYZL-pdf");
//            printParam.setWarehouseId(warehouseId);
            printParam.setParams(MapUtils.put("itemId", pickTaskD.getItemCode()).put("batchId",pickTaskD.getBatchId()).put("barcode", billId).getMap());
            billdLineIds.add(pickTaskD.getSrcLineId());
            printParamList.add(printParam);

            PrintLog printLog = new PrintLog();
            printLog.setBillno(billId);
            printLog.setPrintCode("imgManage-SYZL-pdf");
            printLog.setAttrStr1(pickTaskD.getItemId());
            printLog.setStatus("200");
            savePrintLogs.add(printLog);

        }
        log.info("打印首营资料入参：{}",JSON.toJSONString(printParamList));
        if(printParamList.size() <= 0){
            return;
        }
        RestMessage<?> restMessage = commonClient.executePrint(printParamList);
        //保存打印日志
        if(restMessage != null && restMessage.isSuccess()){
            printLogService.saveBatch(savePrintLogs);
        }
        //记录打印次数 attrstr3
        billdLineIds = new ArrayList<>(new HashSet<>(billdLineIds));
        omsDoBillDMapper.updateAttrstr3(billdLineIds);

        log.info("打印首营资料返回结果：{}", JSON.toJSONString(restMessage));
    }

//    /**
//     * 打印出库单号
//     * @param billid
//     */
    /*public void printOutBillNo(String billid) {
        List<PrintParam> printParamList = new ArrayList<>();
        PrintParam printParam = new PrintParam();
        printParam.setPrintBillCode("OutBillno");
        printParam.setParams(MapUtils.put("billid", billid).getMap());
        printParamList.add(printParam);
        log.info("打印出库单号入参：{}", JSON.toJSONString(printParamList));
        RestMessage<?> restMessage = commonClient.executePrint(printParamList);
        log.info("打印出库单号返回结果：{}", JSON.toJSONString(restMessage));
    }*/


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> applyForPackageWeigh(ApplyForPackageWeighVO vo) {

        Map<String, Object> result = new HashMap<>(1);
        result.put("target", 1);

        List<BarcodeHDO> list = barcodeHMapper.findByMap(MapUtils.put("barcode", vo.getMailNo()).getMap(), BarcodeHDO.class);
        if (CollUtil.isEmpty(list)) {
            return result;
        }

        FieldSelector fs = FieldSelector.newInstance().include("weight", "gmtModified");
        DateTime now = DateUtil.date();
        list.forEach(b -> {
            //转为千克
            b.setWeight(Double.valueOf(vo.getWeight())/1000);
            b.setGmtModified(now);
            barcodeHMapper.updateFields(b, fs);
        });
        result.put("target", 2);
        return result;
    }


    /**
     * 根据批次、物料、容器查询库存
     * @param pickTaskD
     * @return
     */
    private Double getItemStock(PickTaskD pickTaskD){
        WaveStorageDO waveStorageDO = waveStorageMapper.findById(pickTaskD.getWaveStorageId(), WaveStorageDO.class);
        if(waveStorageDO == null){
            throw new BizException("查询波次库存预占表失败!");
        }
        WmsInvStockQtyQueryVO queryVO = new WmsInvStockQtyQueryVO();
        queryVO.setEnterpriseId(pickTaskD.getEnterpriseId());
        queryVO.setWarehouseId(pickTaskD.getWarehouseId());
        queryVO.setItemId(pickTaskD.getItemId());
        queryVO.setContainerCode(pickTaskD.getContainerCode());
        queryVO.setBatchId(pickTaskD.getBatchId());
        queryVO.setManufacturerLotNum(waveStorageDO.getManufactureLotNum());
        queryVO.setStatus("1"); // 默认合格库存
        queryVO.setSubStatus("1");
        log.info("根据批次、物料、容器查询库存入参:{}", JSONObject.toJSONString(queryVO));
        RestMessage<List<WmsInvStockQtyVO>> restMessage = invClient.queryDeviceStockListV3(queryVO);
        if(restMessage == null || !restMessage.isSuccess()){
            throw new BizException("查询物料库存失败!");
        }
        log.info("根据批次、物料、容器查询库存返回结果:{}",JSON.toJSONString(restMessage));

        if(restMessage.getData() == null || restMessage.getData().size() <= 0){
            return 0d;
        }

        return restMessage.getData().stream().mapToDouble(itme -> itme.getQuantity().doubleValue()).sum();
    }

    /**
     * 生成barcode
     * @param pickTaskH
     */
    public void generateBarcode(PickTaskH pickTaskH){
        List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("pickTaskId", pickTaskH.getPickTaskId()).getMap(), PickTaskD.class);
        if (pickTaskDList.size() > 0) {
            //零货列表
            List<PickTaskD> lhList = new ArrayList<>();
            //整件列表
            List<PickTaskD> zjList = new ArrayList<>();

            // 生成打印条码
            for (PickTaskD pickTaskD : pickTaskDList) {
                if (pickTaskH.getPickTaskType() == 2) {
                    WaveStorageDO waveStorageDO = waveStorageMapper.findById(pickTaskD.getWaveStorageId(), WaveStorageDO.class);
                    WaveBillDDO waveBillDDO = billDMapper.findById(waveStorageDO.getBillDId(), WaveBillDDO.class);
                    BigDecimal[] n = pickTaskD.getQty().divideAndRemainder(waveBillDDO.getCaseConversionRate());
                    if (n[1].compareTo(BigDecimal.ZERO) > 0) {
                        // 说明是零货
                        lhList.add(pickTaskD);
                    } else {
                        zjList.add(pickTaskD);
                    }

                } else {
                    zjList.add(pickTaskD);
                }
            }

            if (lhList.size() > 0) {
                pickTaskService.saveBarcode2(pickTaskH, lhList, 1,"0");
            }
            if (zjList.size() > 0) {
                pickTaskService.saveBarcode2(pickTaskH, zjList, 0,"0");
            }
        }
    }

    /**
     * 重新生成barcode
     * @param pickTaskH
     */
    private void gnkfGenerateBarcode(PickTaskH pickTaskH){
        List<PickTaskD> pickTaskDList = pickTaskDMapper.findByMap(MapUtils.put("pickTaskId", pickTaskH.getPickTaskId()).getMap(), PickTaskD.class);
        pickTaskDList = pickTaskDList.stream().filter(item -> item.getPickQty().compareTo(BigDecimal.ZERO) > 0).collect(toList());
        if (pickTaskDList.size() > 0) {
            //零货列表
            List<PickTaskD> lhList = new ArrayList<>();
            //整件列表
            List<PickTaskD> zjList = new ArrayList<>();

            // 生成打印条码
            for (PickTaskD pickTaskD : pickTaskDList) {
//                if (pickTaskH.getPickTaskType() == 2) {
//                    WaveStorageDO waveStorageDO = waveStorageMapper.findById(pickTaskD.getWaveStorageId(), WaveStorageDO.class);
//                    WaveBillDDO waveBillDDO = billDMapper.findById(waveStorageDO.getBillDId(), WaveBillDDO.class);
//                    BigDecimal[] n = pickTaskD.getPickQty().divideAndRemainder(waveBillDDO.getCaseConversionRate());
//                    if (n[1].compareTo(BigDecimal.ZERO) > 0) {
//                        // 说明是零货
//                        lhList.add(pickTaskD);
//                    } else {
//                        zjList.add(pickTaskD);
//                    }
//
//                } else {
//                    zjList.add(pickTaskD);
//                }
                lhList.add(pickTaskD);
            }

            if (lhList.size() > 0) {
                pickTaskService.saveBarcode2(pickTaskH, lhList, 1,"1");
            }
            if (zjList.size() > 0) {
                pickTaskService.saveBarcode2(pickTaskH, zjList, 0,"1");
            }
        }
    }


    /**
     * 根据订单号获取面单打印数据
     * @param map
     * @return
     */
    @Override
    public List<String> getLHFaceOrder(Map<String,Object> map){
        String billno = map.get("billNo") == null ? null : (String) map.get("billNo");
        if(billno == null){
            throw new BizException("订单号不能为空!");
        }
        OmsDoBillHDO omsDoBillHDO = omsDoBillHMapper.findById(billno, OmsDoBillHDO.class);
        if(omsDoBillHDO == null){
            throw new BizException("根据订单号："+billno+"查询订单汇总失败!");
        }
        List<PickTaskD> pickTaskDS = pickTaskDMapper.findByMap(MapUtils.put("srcId", billno).getMap(), PickTaskD.class);
        if(pickTaskDS == null || pickTaskDS.size() <= 0){
            throw new BizException("获取面单，查询任务明细失败！");
        }
        //查询barcodeh
        List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByMap(MapUtils.put("billGroupId", billno).getMap(), BarcodeHDO.class);
        if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
            throw new BizException("查询条码表汇总失败!");
        }
        List<String> faceOrderNos = new ArrayList<>();
        //拆包标识
        Integer packFlag = map.get("packFlag") == null ? null : (Integer) map.get("packFlag");
        boolean isGet = false;
        //已生成barcode
        List<BarcodeHDO> barcodeHDOList = barcodeHDOS.stream().filter(item -> StringUtils.isBlank(item.getBarcode()) && "0".equals(item.getType())).collect(toList());
        if (barcodeHDOList == null || barcodeHDOList.size() <= 0) {

            if(packFlag == null || packFlag != 1){
                return null;
            }
            Integer labelCount = (Integer) map.get("labelCount");
            if(labelCount == null || labelCount <= 0){
                throw new ParameterException("拆包时，标签/面单数量必须大于等于1！");
            }
            BarcodeHDO barcodeHDO = barcodeHDOS.stream().filter(item -> "0".equals(item.getType())).findFirst().get();
            if(barcodeHDO == null){
                throw new BizException("请先获取面单，再拆单!");
            }
            for (Integer i = 0; i < labelCount; i++) {
                BarcodeHDO copy = new BarcodeHDO();
                BeanUtils.copyProperties(barcodeHDO,copy);
                copy.setId(UUIDUtils.generateWithoutSeperator());
                copy.setLclNo(barcodeHDO.getLclNo() == null ? 1 : barcodeHDO.getLclNo() + 1);
                copy.setGmtCreate(new Date());
                copy.setGmtModified(new Date());
                copy.setBarcode(null);
                barcodeHMapper.save(copy);
                barcodeHDOList.add(copy);

                List<BarCodeDDO> barCodeDDOS = barcodeDMapper.findByMap(MapUtils.put("barcodeId", barcodeHDO.getId()).getMap(), BarCodeDDO.class);
                if(barCodeDDOS == null || barCodeDDOS.size() <= 0){
                    throw new BizException("根据barcodeid："+barcodeHDO.getId() + "查询barcode明细失败!");
                }
                List<BarCodeDDO> saveDs = new ArrayList<>();
                for (BarCodeDDO barCodeDDO : barCodeDDOS) {
                    BarCodeDDO dCopy = new BarCodeDDO();
                    BeanUtils.copyProperties(barCodeDDO,dCopy);
                    dCopy.setId(UUIDUtils.generateWithoutSeperator());
                    dCopy.setBarcodeId(copy.getId());
                    dCopy.setGmtCreate(new Date());
                    dCopy.setGmtModified(new Date());
                    saveDs.add(dCopy);
                }

                barcodeDMapper.saveBatch(saveDs);
            }


            if("JD".equals(omsDoBillHDO.getCarrierCode())){
                omsDoBillHDO.setBillno(omsDoBillHDO.getBillno()+"_"+(barcodeHDOS.stream().filter(item -> !StringUtils.isBlank(item.getBarcode())).count() + 1));
            }
            //如果是拆单，韵达快递改为韵达快运
            if("YUNDA".equals(omsDoBillHDO.getCarrierCode()) && "1".equals(omsDoBillHDO.getCarrierType())){
                omsDoBillHDO.setCarrierType("3");
                omsDoBillHMapper.updateMapById(omsDoBillHDO.getBillid(),MapUtils.put("carrierType","3").getMap(),OmsDoBillHDO.class);
                //将之前韵达快递获取的面单取消
                List<String> cancelBarcodes = barcodeHDOS.stream().filter(item -> !StringUtils.isBlank(item.getBarcode()) && "1".equals(item.getCarrierType())).map(BarcodeHDO::getBarcode).collect(Collectors.toList());
                if(!cancelBarcodes.isEmpty()){
                    faceOrderService.faceCancel(cancelBarcodes,false);

                    Criteria crth = Criteria.forClass(BarcodeHDO.class);
                    Restriction rest14 = Restrictions.eq("billGroupId",omsDoBillHDO.getBillid());
                    crth.setRestriction(Restrictions.and(rest14));
                    barcodeHMapper.updateMapByCriteria(MapUtils.put("cancelFlag","0").put("barcode",null).getMap(),crth);
                    barcodeHDOList = barcodeHMapper.findByMap(MapUtils.put("billGroupId", omsDoBillHDO.getBillid()).getMap(), BarcodeHDO.class);
                }

            }
            if("SF".equals(omsDoBillHDO.getCarrierCode())){
                faceOrderNos = getFaceOrderHandler("SFCD").getFaceOrderNo(omsDoBillHDO, null, barcodeHDOList.size());
                isGet = true;
            }
        }else {
            boolean anyMatch = barcodeHDOS.stream().anyMatch(item -> !StringUtils.isBlank(item.getBarcode()));
            if(anyMatch){
                if("JD".equals(omsDoBillHDO.getCarrierCode())){
                    omsDoBillHDO.setBillno(omsDoBillHDO.getBillno()+"_"+(barcodeHDOS.stream().filter(item -> !StringUtils.isBlank(item.getBarcode())).count() + 1));
                }
                if("YUNDA".equals(omsDoBillHDO.getCarrierCode()) && "1".equals(omsDoBillHDO.getCarrierType())){
                    omsDoBillHDO.setCarrierType("3");
                    omsDoBillHMapper.updateMapById(omsDoBillHDO.getBillid(),MapUtils.put("carrierType","3").getMap(),OmsDoBillHDO.class);

                    //将之前韵达快递获取的面单取消
                    List<String> cancelBarcodes = barcodeHDOS.stream().filter(item -> !StringUtils.isBlank(item.getBarcode()) && "1".equals(item.getCarrierType())).map(BarcodeHDO::getBarcode).collect(Collectors.toList());
                    if(!cancelBarcodes.isEmpty()){
                        faceOrderService.faceCancel(cancelBarcodes,false);

                        Criteria crth = Criteria.forClass(BarcodeHDO.class);
                        Restriction rest14 = Restrictions.eq("billGroupId",omsDoBillHDO.getBillid());
                        crth.setRestriction(Restrictions.and(rest14));
                        barcodeHMapper.updateMapByCriteria(MapUtils.put("cancelFlag","0").put("barcode",null).getMap(),crth);
                        barcodeHDOList = barcodeHMapper.findByMap(MapUtils.put("billGroupId", omsDoBillHDO.getBillid()).getMap(), BarcodeHDO.class);
                    }
                }
                if("SF".equals(omsDoBillHDO.getCarrierCode())){
                    faceOrderNos = getFaceOrderHandler("SFCD").getFaceOrderNo(omsDoBillHDO, null, barcodeHDOList.size());
                    isGet = true;
                }
            }
        }

        List<String> waveStorageIds = pickTaskDS.stream().map(PickTaskD::getWaveStorageId).collect(toList());
        List<WaveBillDDO> billDDOList = pickTaskHMapper.getBillDListV2(omsDoBillHDO.getEnterpriseId(),omsDoBillHDO.getBranchid(),waveStorageIds);

        String carrierType = omsDoBillHDO.getCarrierType();
        if(!isGet){

            if ("1".equals(carrierType)) {

                faceOrderNos = getFaceOrderHandler(omsDoBillHDO.getCarrierCode()).getFaceOrderNo(omsDoBillHDO, billDDOList, barcodeHDOList.size());
            }
            if("3".equals(carrierType)){
                List<FaceOrderPickTaskDDTO> ddtos = new ArrayList<>();
                for (BarcodeHDO barcodeHDO : barcodeHDOList) {
                    FaceOrderPickTaskDDTO faceOrderPickTaskDDTO = new FaceOrderPickTaskDDTO();

                    String barCodeId = barcodeHDO.getId();
                    List<BarCodeDDO> barCodeDDOS = barcodeDMapper.findByMap(MapUtils.put("barcodeId", barCodeId).getMap(), BarCodeDDO.class);
                    if(barCodeDDOS == null || barCodeDDOS.size() <= 0){
                        throw new BizException("根据barcodeid："+barCodeId + "查询barcode明细失败!");
                    }
                    faceOrderPickTaskDDTO.setPcs(1);
                    faceOrderPickTaskDDTO.setItemName(String.join(";",billDDOList.stream().map(WaveBillDDO :: getItemName).collect(Collectors.toSet())));
                    ddtos.add(faceOrderPickTaskDDTO);
                }

                try {
                    if ("JINGDONGKUAIYUN".equals(omsDoBillHDO.getCarrierCode()) || "JD".equals(omsDoBillHDO.getCarrierCode())) {
                        //如果是京东，需要先判断重量 获取面单处理方式
                        String flag = acquireFlag(omsDoBillHDO);
                        log.info("获取面单处理方式：{}",flag);
                        faceOrderNos = getKyFaceOrderHandler(flag).getFaceOrderNo(omsDoBillHDO, ddtos, billDDOList, barcodeHDOList.size());
                    } else {
                        faceOrderNos = getKyFaceOrderHandler(omsDoBillHDO.getCarrierCode()).getFaceOrderNo(omsDoBillHDO, ddtos, billDDOList, barcodeHDOList.size());
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            if("2".equals(carrierType)){
                for (int i = 0; i < barcodeHDOList.size(); i++) {
                    String barcode = BillUtils.getBarcode(redisTemplate);
                    String maxBarcode = barcodeHMapper.getMaxBarcode();
                    if (!StringUtils.isEmpty(maxBarcode) && Long.valueOf(maxBarcode) > Long.valueOf(barcode)) {
                        throw new BizException("标签号生成失败，不能重复生成!");
                    }
                    faceOrderNos.add(barcode);
                }

            }
        }

        //面单获取失败重新获取
        if(faceOrderNos == null || faceOrderNos.size() <= 0){
            throw new BizException("获取面单失败!");
//            if("3".equals(carrierType) || "1".equals(carrierType)){
//                List<String> alreadyObtainFailedCarrierCodes = new ArrayList<>();
//                alreadyObtainFailedCarrierCodes.add(omsDoBillHDO.getCarrierCode());
//                //获取承运商信息
//                BaseCarrierMstRequestVO baseCarrierMstRequestVO = new BaseCarrierMstRequestVO();
//                RestMessage<List<BaseCarrierMst>> carrierMstRest = chainResource.findAll(baseCarrierMstRequestVO);
//                if(carrierMstRest == null || !carrierMstRest.isSuccess() || carrierMstRest.getData() == null || carrierMstRest.getData().size() <= 0){
//                    throw new BizException("承运商信息查询失败！");
//                }
//                List<BaseCarrierMst> carrierMstList = carrierMstRest.getData();
//                for (int i = 0; i < carrierMstList.size(); i++) {
//                    BaseCarrierMst baseCarrierMst = carrierMstList.get(i);
//                    //如果是最后一个承运商
//                    if(i == carrierMstList.size() - 1){
//                        omsDoBillHDO.setAttrNum1(BigDecimal.ONE);
//                    }
//                    //过滤已获取失败的承运商并按优先级倒序排序
//                    carrierMstList = carrierMstList.stream().filter(item -> "1".equals(item.getIsEnable()) && item.getSort() != null && !alreadyObtainFailedCarrierCodes.contains(item.getCarrierCode())).sorted(Comparator.comparing(BaseCarrierMst::getSort).reversed()).collect(toList());
//                    if(carrierMstList.size() <= 0){
//                        throw new BizException("获取面单失败!");
//                    }
//                    faceOrderNos = retryObtainFaceOrder(omsDoBillHDO,baseCarrierMst);
//                    if(faceOrderNos != null && faceOrderNos.size() > 0){
//                        String omsDoBillHDOBillno = omsDoBillHDO.getBillno();
//                        if(omsDoBillHDOBillno.contains("_")){
//                            omsDoBillHDOBillno = omsDoBillHDOBillno.substring(0,omsDoBillHDOBillno.indexOf("_"));
//                        }
//                        barcodeHDOList = barcodeHMapper.getByBillPickComplete(omsDoBillHDOBillno);
//                        break;
//                    }
//                    alreadyObtainFailedCarrierCodes.add(baseCarrierMst.getCarrierCode());
//
//                }
//            }

        }

        for (int i = 0; i < barcodeHDOList.size(); i++) {
            BarcodeHDO barcodeHDO = barcodeHDOList.get(i);
            barcodeHDO.setBarcode(faceOrderNos.get(i));
            barcodeHDO.setIsMerged(1);
            barcodeHDO.setCarrierType(omsDoBillHDO.getCarrierType());
//            barcodeHDO.setCheckStatus("5");
//            barcodeHDO.setCheckerId("EIS");
//            barcodeHDO.setCheckerNo("EIS");
//            barcodeHDO.setCheckerName("EIS");
//            barcodeHDO.setCheckTime(new Date());
            barcodeHMapper.update(barcodeHDO);
        }
        return barcodeHDOList.stream().map(BarcodeHDO :: getBarcode).collect(Collectors.toList());
//        //更新扫描包裹为已复核
//        List<String> barCodeIds = barcodeHDOList.stream().map(BarcodeHDO::getId).collect(Collectors.toList());
//        Criteria crtd = Criteria.forClass(BarCodeDDO.class);
//        Restriction resd1 = Restrictions.in("barcodeId", barCodeIds.toArray());
//        crtd.setRestriction(Restrictions.and(resd1));
//        barcodeDMapper.updateMapByCriteria(MapUtils.put("checkStatus", "5").getMap(), crtd);
//        //更新出库任务状态
//        List<String> pickTaskIds = pickTaskDS.stream().map(PickTaskD::getPickTaskId).distinct().collect(Collectors.toList());
//        checkPickTask(barcodeHDOS, String.join(",",pickTaskIds));
    }

    @Override
    public List<OuterCheckBarcodeDetailDTO> getBarcodeDetail(String barCode, String warehouseId) {
        UserDTO userDTO = userTemplate.getUserDTO();
        if(userDTO == null){
            throw new BizException("请登录!");
        }
        List<OuterCheckBarcodeDetailDTO> list = barcodeDMapper.getBarcodeDetail(barCode,warehouseId);
        return list;
    }

    @Override
    public void retryCallbackToERPByTable() {
        List<OmsDoBillHDO> omsDoBillHDOS = omsDoBillHMapper.findByMap(MapUtils.put("attrStr9", "N").getMap(), OmsDoBillHDO.class);
        List<String> billIds = omsDoBillHDOS.stream().map(OmsDoBillHDO::getBillid).collect(Collectors.toList());
        postBackErpByTable(billIds);
    }

    @Override
    public Map<String, Object> gnkfGenerateBarcodes(String billId, Integer barcodeNum) {
        if(StringUtils.isBlank(billId)){
            throw new BizException("订单号不能为空!");
        }
        if(barcodeNum == null || barcodeNum <= 0){
            throw new BizException("面单/标签数量必须大于0！");
        }

        Map<String, Object> result = new HashMap<>();
        List<PickTaskH> pickTaskHS = pickTaskHMapper.findByMap(MapUtils.put("billGroupId", billId).getMap(), PickTaskH.class);
        if(pickTaskHS == null || pickTaskHS.size() <= 0){
            throw new BizException("根据订单id:"+billId+"查询拣货任务汇总失败!");
        }
//        gnkfGenerateBarcode(pickTaskH);
        //查询barcode个数与界面输入个数，如果大于就新生成barcode
        List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByMap(MapUtils.put("billGroupId", billId).put("type","0").getMap(), BarcodeHDO.class);
        if(barcodeHDOS.size() < barcodeNum){
            //拆分出来的面单，默认零货才允许拆分
            int cf = barcodeNum - barcodeHDOS.size();
            BarcodeHDO barcodeHDO = barcodeHDOS.stream().filter(item -> "0".equals(item.getType())).findFirst().orElse(null);
            if(barcodeHDO != null){
                List<BarCodeDDO> barCodeDDOS = barcodeDMapper.findByMap(MapUtils.put("barcodeId", barcodeHDO.getId()).getMap(), BarCodeDDO.class);

                List<BarcodeHDO> saveHList = new ArrayList<>();
                List<BarCodeDDO> saveDList = new ArrayList<>();

                for (int i = 0; i < cf; i++) {
                    BarcodeHDO hdo = new BarcodeHDO();
                    BeanUtils.copyProperties(barcodeHDO,hdo);
                    hdo.setId(UUIDUtils.generateWithoutSeperator());
                    if(!StringUtils.isBlank(hdo.getBarcode())){
                        if("0".equals(hdo.getBarcodeType())){
                            String barcode = BillUtils.getBarcode(redisTemplate);
                            String maxBarcode = barcodeHMapper.getMaxBarcode();
                            if (!StringUtils.isEmpty(maxBarcode) && Long.valueOf(maxBarcode) > Long.valueOf(barcode)) {
                                throw new BizException("标签号生成失败，不能重复生成!");
                            }
                            hdo.setBarcode(barcode);
                        }else {
                            hdo.setBarcode(null);
                        }

                    }
                    saveHList.add(hdo);

                    for (BarCodeDDO barCodeDDO : barCodeDDOS) {
                        BarCodeDDO ddo = new BarCodeDDO();
                        BeanUtils.copyProperties(barCodeDDO,ddo);
                        ddo.setId(UUIDUtils.generateWithoutSeperator());
                        ddo.setBarcodeId(hdo.getId());

                        saveDList.add(ddo);
                    }
                }
                if(saveHList.size() > 0){
                    barcodeHMapper.saveBatch(saveHList);
                }
                if(saveDList.size() > 0){
                    barcodeDMapper.saveBatch(saveDList);
                }

            }
        }

        List<WaveBillDDO> billDDOList = new ArrayList<>();
        PickTaskH pickTaskH = pickTaskHS.stream().filter(item -> 2 == item.getPickTaskType()).findFirst().get();
        if(pickTaskH == null){
            throw new BizException("未查询到功能库房拣货任务汇总!");
        }
        List<PrintParam> printData = getPrintData(pickTaskH, null, null, billDDOList);
        result.put("printData",printData);

        return result;
    }


    @Override
    public Object saveFaceOrder(Map<String, Object> map) {
        String billno = map.get("billNo") == null ? null : (String) map.get("billNo");
        if(billno == null){
            throw new BizException("订单号不能为空!");
        }

        String carrierCode = map.get("carrierCode") == null ? null : (String) map.get("carrierCode");
        if(carrierCode == null){
            throw new BizException("承运商编码不能为空!");
        }

        List<String> faceOrders = map.get("faceOrders") == null ? null : (List<String>) map.get("faceOrders");
        if(faceOrders == null || faceOrders.size() <= 0){
            throw new BizException("面单号不能为空!");
        }

        OmsDoBillHDO omsDoBillHDO = omsDoBillHMapper.findById(billno, OmsDoBillHDO.class);
        if(omsDoBillHDO == null){
            throw new BizException("根据订单号："+billno+"查询订单汇总失败!");
        }
        List<PickTaskD> pickTaskDS = pickTaskDMapper.findByMap(MapUtils.put("srcId", billno).getMap(), PickTaskD.class);
        if(pickTaskDS == null || pickTaskDS.size() <= 0){
            throw new BizException("获取面单，查询任务明细失败！");
        }
        //查询barcodeh
        List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByMap(MapUtils.put("billGroupId", billno).getMap(), BarcodeHDO.class);
        if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
            throw new BizException("查询条码表汇总失败!");
        }

        if(!carrierCode.equals(omsDoBillHDO.getCarrierCode())){
            BaseCarrierMstRequestVO baseCarrierMstRequestVO = new BaseCarrierMstRequestVO();
            baseCarrierMstRequestVO.setCarrierCode(carrierCode);
            RestMessage<List<BaseCarrierMst>> carrierMstRest = chainResource.findAll(baseCarrierMstRequestVO);
            if(carrierMstRest == null || !carrierMstRest.isSuccess() || carrierMstRest.getData() == null || carrierMstRest.getData().size() <= 0){
                throw new BizException("承运商信息查询失败！");
            }
            List<BaseCarrierMst> baseCarrierMsts = carrierMstRest.getData();
            BaseCarrierMst baseCarrierMst = baseCarrierMsts.get(0);

            //判断barcode是否全为空或者全部取消
            boolean anyMatch = barcodeHDOS.stream().anyMatch(item -> !StringUtils.isBlank(item.getBarcode()) && (StringUtils.isBlank(item.getCancelFlag()) || !"1".equals(item.getCancelFlag())));
            if(anyMatch){
                throw new BizException("当前订单还有面单未取消，不能更新承运商!");
            }

            omsDoBillHMapper.updateMapById(omsDoBillHDO.getBillid(),MapUtils.put("carrierCode",carrierCode)
                    .put("carrierName",baseCarrierMst.getCarrierName()).put("carrierId",baseCarrierMst.getCarrierId())
                    .put("carrierType",baseCarrierMst.getCarrierType()).getMap(),OmsDoBillHDO.class);
        }

        //是否有零货面单
        long count = barcodeHDOS.stream().filter(item -> "0".equals(item.getType())).count();
        //未获取面单
        List<BarcodeHDO> emptys = barcodeHDOS.stream().filter(item -> StringUtils.isBlank(item.getBarcode())).collect(toList());
        if(emptys == null){
            emptys = new ArrayList<>();
        }
        if(count <= 0 && emptys.size() <= 0){
            throw new BizException("订单没有拆零面单，不允许拆单!");
        }

        //校验faceorder是否已经获取
        Criteria crt = Criteria.forClass(BarcodeHDO.class);
        Restriction r1 = Restrictions.in("barcode", faceOrders.toArray());
        Restriction r2 = Restrictions.isnull("cancelFlag");
        Restriction r3 = Restrictions.eq("cancelFlag", "0");
        crt.setRestriction(Restrictions.and(r1,Restrictions.or(r2,r3)));
        List<BarcodeHDO> extBarcodeHs = barcodeHMapper.findByCriteria(crt);
        if(extBarcodeHs != null && extBarcodeHs.size() > 0){
            BarcodeHDO barcodeHDO = extBarcodeHs.stream().filter(item -> faceOrders.contains(item.getBarcode())).findFirst().orElse(null);
            if(barcodeHDO != null){
                throw new BizException("面单："+barcodeHDO.getBarcode()+"已获取！");
            }
        }

        int labelCount = 0;

        //全部为拆单
        if(emptys == null || emptys.size() <= 0){
            labelCount = faceOrders.size();
        }else {
            labelCount = faceOrders.size() - emptys.size();
        }

        //拆单
        List<BarcodeHDO> saveHs = new ArrayList<>();
        List<BarCodeDDO> saveDs = new ArrayList<>();
        for (Integer i = 0; i < labelCount; i++) {

            BarcodeHDO barcodeHDO = barcodeHDOS.stream().filter(item -> "0".equals(item.getType())).findFirst().get();

            BarcodeHDO copy = new BarcodeHDO();
            BeanUtils.copyProperties(barcodeHDO,copy);
            copy.setId(UUIDUtils.generateWithoutSeperator());
            copy.setLclNo(barcodeHDO.getLclNo() == null ? 1 : barcodeHDO.getLclNo() + 1);
            copy.setGmtCreate(new Date());
            copy.setGmtModified(new Date());
            copy.setBarcode(null);
            copy.setCancelFlag(null);
            emptys.add(copy);
            saveHs.add(copy);

            List<BarCodeDDO> barCodeDDOS = barcodeDMapper.findByMap(MapUtils.put("barcodeId", barcodeHDO.getId()).getMap(), BarCodeDDO.class);
            if(barCodeDDOS == null || barCodeDDOS.size() <= 0){
                throw new BizException("根据barcodeid："+barcodeHDO.getId() + "查询barcode明细失败!");
            }

            for (BarCodeDDO barCodeDDO : barCodeDDOS) {
                BarCodeDDO dCopy = new BarCodeDDO();
                BeanUtils.copyProperties(barCodeDDO,dCopy);
                dCopy.setId(UUIDUtils.generateWithoutSeperator());
                dCopy.setBarcodeId(copy.getId());
                dCopy.setGmtCreate(new Date());
                dCopy.setGmtModified(new Date());
                saveDs.add(dCopy);
            }
        }

        if(saveHs.size() > 0){
            barcodeHMapper.saveBatch(saveHs);
        }
        if(saveDs.size() > 0){
            barcodeDMapper.saveBatch(saveDs);
        }

        List<WmsFaceOrder> wmsFaceOrders = new ArrayList<>();

        for (int i = 0; i < emptys.size(); i++) {
            BarcodeHDO barcodeHDO = emptys.get(i);
            barcodeHDO.setBarcode(faceOrders.get(i));
            barcodeHDO.setIsMerged(1);
            barcodeHDO.setCarrierType(omsDoBillHDO.getCarrierType());
            barcodeHMapper.update(barcodeHDO);

            WmsFaceOrder faceOrder = new WmsFaceOrder();
            faceOrder.setBillNo(billno);
            faceOrder.setWaybillCode(barcodeHDO.getBarcode());
            faceOrder.setId(UUIDUtils.generateWithoutSeperator());
            wmsFaceOrders.add(faceOrder);
        }
        if(wmsFaceOrders.size() > 0){
            wmsFaceOrderMapper.saveBatch(wmsFaceOrders);
        }

        return null;
    }

    @Override
    public void autoOuterCheckConfirm() {

        int times;
        RestMessage<List<BaseCommonDict>> retryTimes = commonClient.getDictBasicListByCodes("auto_out_check_times", null);
        if(retryTimes == null || !retryTimes.isSuccess() || retryTimes.getData() == null || retryTimes.getData().size() <= 0){
            times = 1;
        }else {
            times = Integer.parseInt(retryTimes.getData().get(0).getDictName());
        }
        //查询已拣货完成，未复核确认的订单（纯整件订单排除）
        List<String> billnos = pickTaskDMapper.getUnOutCheckBillNos(times);
        if(billnos == null || billnos.size() <= 0){
            return;
        }

        RestMessage<List<BaseCommonDict>> checkerName2sRestMsg = commonClient.getDictBasicListByCodes("checker_name2", null);
        if(checkerName2sRestMsg == null || !checkerName2sRestMsg.isSuccess() || checkerName2sRestMsg.getData() == null || checkerName2sRestMsg.getData().size() <= 0){
            log.info("请配置外复核人！");
            return;
        }
        List<BaseCommonDict> checkerName2s = checkerName2sRestMsg.getData();
        int randomNum = new Random().nextInt(checkerName2s.size());
        BaseCommonDict checkName2Common = checkerName2s.get(randomNum);

        for (String billno : billnos) {
            //查询barcodeh
            Criteria crth = Criteria.forClass(BarcodeHDO.class);
            Restriction res1 = Restrictions.eq("billGroupId", billno);
            Restriction res2 = Restrictions.eq("type", "0");
            crth.setRestriction(Restrictions.and(res1,res2));
            List<BarcodeHDO> barcodeHDOS = barcodeHMapper.findByCriteria(crth);
            if (barcodeHDOS == null || barcodeHDOS.size() <= 0) {
                throw new BizException("查询条码表汇总失败!");
            }

            //更新扫描包裹为已复核
            Map<String, Object> map = MapUtils.put("checkStatus", "5").put("checkerId2", checkName2Common.getAttr1()).put("checkerNo2", checkName2Common.getDictCode()).put("checkerName2", checkName2Common.getDictName()).put("checkTime2", new Date()).getMap();
            for (BarcodeHDO barcodeHDO : barcodeHDOS) {
                //如果是整件包裹，则更新包裹重量
                if("1".equals(barcodeHDO.getType())){
                    //查询waveBilld的重量
                    List<WaveBillDDO> waveBillDDOList = waveBillDMapper.findbyBarcode(barcodeHDO.getBarcode());
//                    BigDecimal totalWeight = waveBillDDOList.stream().map(item -> (item.getPickQty().multiply(item.getWeight())).divide(item.getConversionRate(),2,BigDecimal.ROUND_HALF_UP)).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal totalWeight = waveBillDDOList.get(0).getWeight();
                    map.put("weight",totalWeight);
                }
                barcodeHMapper.updateMapByCriteria(map, crth);

                //更新扫描包裹为已复核
                Criteria crtd = Criteria.forClass(BarCodeDDO.class);
                Restriction resd1 = Restrictions.eq("barcodeId", barcodeHDO.getId());
                crtd.setRestriction(Restrictions.and(resd1));
                barcodeDMapper.updateMapByCriteria(MapUtils.put("checkStatus", "5").getMap(), crtd);
            }

            //更新拣货任务状态
            Criteria c = Criteria.forClass(PickTaskD.class);
            Restriction r = Restrictions.eq("srcCode", billno);
            Restriction r2 = Restrictions.eq("pickTaskType", 1);
            c.setRestriction(Restrictions.and(r,r2));
            pickTaskDMapper.updateMapByCriteria(MapUtils.put("flowStatus", "7").getMap(), c);

            Criteria c3 = Criteria.forClass(PickTaskH.class);
            Restriction rt1 = Restrictions.eq("billGroupId", billno);
            Restriction rt2 = Restrictions.eq("pickTaskType", 1);
            c3.setRestriction(Restrictions.and(rt1,rt2));
            pickTaskHMapper.updateMapByCriteria(MapUtils.put("status", "10").getMap(),c3);

            //判断订单对应的出库任务是否全部复核完成
            Criteria ctrh = Criteria.forClass(PickTaskH.class);
            Restriction rt3 = Restrictions.lt("status", "10");
            ctrh.setRestriction(Restrictions.and(rt1,rt3));
            long count = pickTaskHMapper.findCountByCriteria(ctrh);
            if(count > 0){
                return;
            }

            //查询订单汇总
            OmsDoBillHDO omsDoBillHDO = omsDoBillHMapper.findById(billno, OmsDoBillHDO.class);
            if(omsDoBillHDO == null ){
                throw new BizException("根据订单编号："+billno+"查询订单汇总失败!");
            }

            Employee employee = RestMsgHelper.getData(powerResource.getByNum(checkName2Common.getDictCode(), omsDoBillHDO.getBranchid(), omsDoBillHDO.getEnterpriseId()));
            cn.hutool.core.lang.Assert.notNull(employee, "根据工号【{}】获取员工信息失败", checkName2Common.getDictCode());
            pickTaskServiceImpl.getUserDtoKeyAndSetCache(employee.getUsername());
            ServletRequestAttributes reqa = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            new Thread(()-> {
                RequestContextHolder.setRequestAttributes(reqa, false);
                ServletRequestAttributes servletRequestAttributes =
                        (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
                String userkey = servletRequestAttributes.getRequest().getHeader("UserKey");

                if (!HystrixRequestContext.isCurrentThreadInitialized()) {
                    HystrixRequestContext.initializeContext();
                }
                HystrixVarUtil.setUserKey(userkey);
                try {
                    outBoundUploadCircubill(omsDoBillHDO,checkName2Common.getDictName());
                }catch (Exception e) {
                    log.error("RF复核完成上传监管码失败：{}", e.getMessage());

                }finally {
                    RequestContextHolder.resetRequestAttributes();
                }
            }).start();

            //释放容器号
            List<PickTaskH> pickTaskHList = pickTaskHMapper.findByMap(MapUtils.put("billGroupId", billno).put("pickTaskType",2).getMap(), PickTaskH.class);
            if(pickTaskHList != null && pickTaskHList.size() > 0){
                List<String> containerCodes = pickTaskHList.stream().map(PickTaskH::getContainerCode).collect(toList());
                //释放容器
                ContainerQueryVO containerQueryVO = new ContainerQueryVO();
                containerQueryVO.setContainerCodeList(containerCodes);
                containerQueryVO.setWarehouseId(pickTaskHList.get(0).getWarehouseId());
                warehouseResource.release(containerQueryVO);
            }

            new Thread(()-> {
                RequestContextHolder.setRequestAttributes(reqa, false);
                ServletRequestAttributes servletRequestAttributes =
                        (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
                String userkey = servletRequestAttributes.getRequest().getHeader("UserKey");

                if (!HystrixRequestContext.isCurrentThreadInitialized()) {
                    HystrixRequestContext.initializeContext();
                }
                HystrixVarUtil.setUserKey(userkey);
                try {
                    postBackErpByTable(CollUtil.toList(omsDoBillHDO.getBillid()));
                }catch (Exception e) {
                    log.error("RF复核完成回写回传中间表失败：{}", e.getMessage());
                    omsDoBillHMapper.updateMapById(omsDoBillHDO.getBillid(),MapUtils.put("attrStr9","N").getMap(),OmsDoBillHDO.class);
                }finally {
                    RequestContextHolder.resetRequestAttributes();
                }
            }).start();

            //更新处理次数
            omsDoBillHMapper.updateMapById(billno,MapUtils.put("attrNum2",omsDoBillHDO.getAttrNum2() == null ? 1 : omsDoBillHDO.getAttrNum2().add(BigDecimal.ONE)).getMap(),OmsDoBillHDO.class);
        }
    }

    /**
     * 打印
     * @param omsDoBillHDO
     * @param pickTaskHS
     */
    private void print(OmsDoBillHDO omsDoBillHDO,List<PickTaskH> pickTaskHS){

//        if("1".equals(omsDoBillHDO.getAttrStr4())){
//            //打印质检报告单
//            printQrReport(omsDoBillHDO.getBillno(), omsDoBillHDO.getConsignorid(), omsDoBillHDO.getBranchid());
//        }
        long count2 = pickTaskHS.stream().filter(item -> item.getPickTaskType() == 1 && "AGVL".equals(item.getWarehouseAreaCode())).count();
        if (count2 <= 0) {
            //打印出库清单
            printOutDetailList(omsDoBillHDO.getBillno(), omsDoBillHDO.getConsignorid(), omsDoBillHDO.getBranchid(),omsDoBillHDO.getAttrStr7());
            if("1".equals(omsDoBillHDO.getAttrStr4())){
                //4.1若不包含，则在此处打印该订单下所有的首营资料、质检报告单；
                //打印质检报告单
                try {
                    printQrReport(omsDoBillHDO.getBillno(), omsDoBillHDO.getConsignorid(), omsDoBillHDO.getBranchid());
                }catch (Exception e){
                    e.printStackTrace();
                    log.info("外复核，打印质检报告单失败:{}",e.getMessage());
                }

            }
            if("1".equals(omsDoBillHDO.getAttrStr3())){
                //打印首营资料
                try {
                    printSyInfo(omsDoBillHDO.getBillno(), omsDoBillHDO.getConsignorid(), omsDoBillHDO.getBranchid());
                }catch (Exception e){
                    e.printStackTrace();
                    log.info("外复核，打印首营资料失败:{}",e.getMessage());
                }

            }
        }
    }


    /**
     * 上传监管码
     * @param omsDoBillHDO
     * @param username
     */
    private void outBoundUploadCircubill(OmsDoBillHDO omsDoBillHDO,String username){
        //当前订单下的所有包裹复核完成后，根据订单对应的客户的资料维护的是否上传监管码字段，来识别是否调用上传码上放心平台接口；若是，则上传，若否，则不上传；
        boolean isUpCode = false;
        String acceptEnterpriseId;

        String shipperid = omsDoBillHDO.getShipperid();
        List<BaseCustomerMst> customerMsts = new ArrayList<>();
        BaseCustomerMstRequestVO customerMstRequestVO = new BaseCustomerMstRequestVO();
        customerMstRequestVO.setEnterpriseid(omsDoBillHDO.getEnterpriseId());
        Set<String> customerIds = new HashSet<>();
        customerIds.add(shipperid);
        customerMstRequestVO.setIncludeSearchIds(customerIds);
        // 2 代表客户
        RestMessage<List<BaseCustomerMst>> restMessage = chainResource.findAll(customerMstRequestVO);
        log.info("RF外复核完成，上传监管码查询客户返回结果：{}",JSON.toJSONString(restMessage));
        if (restMessage.isSuccess() && CollUtil.isNotEmpty(restMessage.getData())) {
            customerMsts = restMessage.getData();
        }
        if (customerMsts.size() > 0) {
            if (customerMsts.get(0).getIsQrCodeSupervise() == 1) {
                isUpCode = true;
            }
            acceptEnterpriseId = customerMsts.get(0).getCustomerId();
        } else {
            // 查询供应商
            List<BaseSupplierMst> supplierMsts = new ArrayList<>();
            Set<String> supplierIds = new HashSet<>();
            supplierIds.add(shipperid);
            RestMessage<Map<String, BaseSupplierMst>> supplierMst = chainResource.getSupplierMstByIds(supplierIds);
            log.info("RF外复核完成，上传监管码查询供应商返回结果：{}",JSON.toJSONString(restMessage));
            if (supplierMst.isSuccess() && CollUtil.isNotEmpty(supplierMst.getData())) {
                for (String s : supplierMst.getData().keySet()) {
                    supplierMsts.add(supplierMst.getData().get(s));
                }
            }
            if (supplierMsts.size() > 0) {
                if ("1".equals(supplierMsts.get(0).getIsQrCodeSupervise())) {
                    isUpCode = true;
                }
                acceptEnterpriseId = supplierMsts.get(0).getSupplierId();
            } else {
                throw new BizException("查询订单客户失败!");
            }
        }
        //上传监管码
        if(isUpCode){
            List<PickTaskD> pickTaskDS = pickTaskDMapper.findByMap(MapUtils.put("srcId", omsDoBillHDO.getBillid()).getMap(), PickTaskD.class);
            if(pickTaskDS == null || pickTaskDS.size() <= 0){
                throw new BizException("RF复核，查询订单任务明细失败!");
            }
            List<String> pickTaskDIds = pickTaskDS.stream().map(PickTaskD::getPickTaskDId).collect(toList());
            OutBoundUploadCircubParamVO outBoundUploadCircubParamVO = new OutBoundUploadCircubParamVO();
            outBoundUploadCircubParamVO.setOutType(omsDoBillHDO.getBilltype());
            outBoundUploadCircubParamVO.setRefbilllineids(pickTaskDIds);
            outBoundUploadCircubParamVO.setUserName(username);
            outBoundUploadCircubParamVO.setAcceptEnterpriseId(acceptEnterpriseId);

            RestMessage<Object> restMessage1 = inBoundClient.outBoundUploadCircubill(outBoundUploadCircubParamVO);
            log.info("上传出码上放心平台返回结果：{}",JSON.toJSONString(restMessage1));
        }
    }

    /**
     * 零发整获取面单、标签
     *
     * @return
     */
    public List<String> getLfzBarcodes(OmsDoBillHDO omsDoBillHDO,List<BarcodeHDO> barcodeHDOS,List<BarCodeDDO> barCodeDDOS , List<WaveBillDDO> billDDOList) {
        if ("1".equals(omsDoBillHDO.getCarrierType()) || "3".equals(omsDoBillHDO.getCarrierType())) {
            //获取面单
            List<String> faceOrderNos = getFaceOrder(omsDoBillHDO,barcodeHDOS,billDDOList,barCodeDDOS);
            //面单获取失败重新获取
            if(faceOrderNos == null || faceOrderNos.size() <= 0){
                throw new BizException("获取面单失败!");
//                List<String> alreadyObtainFailedCarrierCodes = new ArrayList<>();
//                alreadyObtainFailedCarrierCodes.add(omsDoBillHDO.getCarrierCode());
//                //获取承运商信息
//                BaseCarrierMstRequestVO baseCarrierMstRequestVO = new BaseCarrierMstRequestVO();
//                RestMessage<List<BaseCarrierMst>> carrierMstRest = chainResource.findAll(baseCarrierMstRequestVO);
//                if(carrierMstRest == null || !carrierMstRest.isSuccess() || carrierMstRest.getData() == null || carrierMstRest.getData().size() <= 0){
//                    throw new BizException("承运商信息查询失败！");
//                }
//                List<BaseCarrierMst> carrierMstList = carrierMstRest.getData();
//                log.info("查询承运商返回列表:{}",JSON.toJSONString(carrierMstList));
//                for (int i = 0; i < carrierMstList.size(); i++) {
//                    BaseCarrierMst baseCarrierMst = carrierMstList.get(i);
//                    //如果是最后一个承运商
//                    if(i == carrierMstList.size() - 1){
//                        omsDoBillHDO.setAttrNum1(BigDecimal.ONE);
//                    }
//                    //过滤已获取失败的承运商并按优先级倒序排序
//                    carrierMstList = carrierMstList.stream().filter(item -> "1".equals(item.getIsEnable()) && item.getSort() != null && !alreadyObtainFailedCarrierCodes.contains(item.getCarrierCode())).sorted(Comparator.comparing(BaseCarrierMst::getSort).reversed()).collect(toList());
//                    if(carrierMstList.size() <= 0){
//                        throw new BizException("获取承运商失败!");
//                    }
//                    faceOrderNos = retryObtainFaceOrder(omsDoBillHDO,baseCarrierMst);
//                    if(faceOrderNos != null && faceOrderNos.size() > 0){
//                        String billno = omsDoBillHDO.getBillno();
//                        if(billno.contains("_")){
//                            billno = billno.substring(0,billno.indexOf("_"));
//                        }
//                        barcodeHDOS = barcodeHMapper.getByBillPickComplete(billno);
//                        break;
//                    }
//                    alreadyObtainFailedCarrierCodes.add(baseCarrierMst.getCarrierCode());
//
//                }

            }
            for (int i = 0; i < barcodeHDOS.size(); i++) {
                BarcodeHDO barcodeHDO = barcodeHDOS.get(i);
                barcodeHDO.setBarcode(faceOrderNos.get(i));
                barcodeHDO.setCarrierType(omsDoBillHDO.getCarrierType());
                barcodeHMapper.update(barcodeHDO);
            }
            return faceOrderNos;
        } else {
            return barcodeHDOS.stream().map(BarcodeHDO::getBarcode).collect(toList());
        }
    }

}
