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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.prolog.common.RestMsgHelper;
import com.prolog.cs.basic.item.model.BaseMtlItemMst;
import com.prolog.cs.basic.item.model.BaseMtlItemUomConversions;
import com.prolog.cs.basic.warehouse.model.BaseWmsWhWorkstation;
import com.prolog.cs.biz.outbound.dao.*;
import com.prolog.cs.biz.outbound.model.*;
import com.prolog.cs.biz.outbound.model.dto.WaveStorageDTO;
import com.prolog.cs.biz.outbound.model.entity.*;
import com.prolog.cs.biz.outbound.model.vo.TaskParamsVO;
import com.prolog.cs.biz.outbound.resource.*;
import com.prolog.cs.biz.outbound.service.PackService;
import com.prolog.cs.biz.outbound.service.PickTaskService;
import com.prolog.cs.biz.outbound.service.PrintLogService;
import com.prolog.cs.biz.outbound.service.WorkStageService;
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.StatusUtil;
import com.prolog.entity.vo.ContainerTailgatingRequestVO;
import com.prolog.entity.vo.OutBoundRequestItemVO;
import com.prolog.entity.vo.OutBoundRequestVO;
import com.prolog.enums.OutBoundRequestEnum;
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.restriction.Criteria;
import com.prolog.framework.core.restriction.FieldSelector;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.utils.DateUtils;
import com.prolog.framework.utils.MapUtils;
import com.prolog.framework.utils.SnowFlakeUtils;
import com.prolog.framework.utils.StringUtils;
import com.prolog.inte.EisHandler;
import com.prolog.upcloud.base.inventory.vo.InvStockCheckOut;
import com.prolog.upcloud.base.strategy.model.BusinessControl;
import org.apache.commons.compress.utils.Lists;
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.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

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

import static com.prolog.cs.biz.outbound.model.constant.CacheKeyConstant.OUT_BOUND_REPLENISHMENT_REQUEST_WAVE_ID;
import static com.prolog.cs.biz.outbound.model.constant.CacheKeyConstant.OUT_BOUND_REQUEST_WAVE_ID;
import static com.prolog.enums.OutBoundRequestEnum.INV_RTM;

/**
 * @author zzz
 * @desc 拣选组包
 * @date 2022/1/4
 */
@Service
public class PackServiceImpl implements PackService {

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

    @Autowired
    private PickTaskHMapper pickTaskHMapper;

    @Autowired
    private PickTaskDMapper pickTaskDMapper;

    @Autowired
    private WmsTaskOutMapper wmsTaskOutMapper;

    @Autowired
    private MoveTaskMapper moveTaskMapper;

    @Autowired
    private WaveStorageMapper waveStorageMapper;

    @Autowired
    private PickOrderMapper pickOrderMapper;

    @Autowired
    private BarcodeHMapper barcodeHMapper;

    @Autowired
    private BarcodeDMapper barcodeDMapper;

    @Autowired
    private StrategyResource strategyResource;

    @Autowired
    private WaveBillMapper billMapper;

    @Autowired
    private WaveBillDMapper billDMapper;

    @Autowired
    private InventoryResource invClient;

    @Autowired
    InBoundClient inBoundClient;

    @Autowired
    WorkStageService workStageService;

    @Autowired
    WorkStageRuntimeMapper workStageRuntimeMapper;

    @Autowired
    private WaveMapper waveMapper;

    @Autowired
    private WarehouseResource warehouseResource;

    @Autowired
    private PickTaskService pickTaskService;

    @Resource
    private CommonClient commonClient;

    @Autowired
    private ItemClient itemClient;

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

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

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

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

    @Resource
    private EisHandler eisHandler;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private MoveTaskRefMapper moveTaskRefMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private OmsDoBillHMapper omsDoBillHMapper;
    @Autowired
    private PrintLogService printLogService;

    /**
     * 组包，生成拣选任务（特殊订单）
     */
    @Transactional
    @Override
    public void createPickTaskSpecial(List<TaskParamsVO> waveList) {
        if (waveList == null || waveList.size() == 0) {
            throw new ParameterException("参数不能为空！");
        }
        BigDecimal maxVolume = new BigDecimal("48000");
        for (TaskParamsVO taskParamsVO : waveList) {
            String waveId = taskParamsVO.getWaveId();
            String warehouseId = taskParamsVO.getWarehouseId();
            String enterpriseId = taskParamsVO.getEnterpriseId();
            this.getPickTaskSpecial(waveId, warehouseId, enterpriseId, maxVolume);
            // 扣减库存，回传erp
            // 新增企业id参数 - by Huanglh 2022-02-21
            this.invStockConfirm(waveId, warehouseId, enterpriseId);
        }
    }

    @Override
    public void specialPickTaskConfirm(List<OmsDoBillHDO> list) {
        if (CollectionUtil.isEmpty(list)) {
            throw new ParameterException("参数不能为空！");
        }
        for (OmsDoBillHDO omsDoBillHDO : list) {
            List<WaveBillDO> waveBillDOList = billMapper.findByMap(MapUtils.put("srcId", omsDoBillHDO.getBillid()).getMap(), WaveBillDO.class);
            if (CollectionUtil.isEmpty(waveBillDOList)) {
                continue;
            }
            WaveBillDO waveBillDO = waveBillDOList.get(0);
            String waveId = waveBillDO.getWaveId();
            String warehouseId = waveBillDO.getWarehouseId();
            String enterpriseId = waveBillDO.getEnterpriseId();
            // 扣减库存，回传erp
            // 新增企业id参数 - by Huanglh 2022-02-21
            this.invStockConfirm(waveId, warehouseId, enterpriseId);
        }
    }

    @Transactional
    public void getPickTaskSpecial(String waveId, String warehouseId, String enterpriseId, BigDecimal maxVolume) {
        String pickWay = "0";
        RestMessage<Map<String, BusinessControl>> rest = strategyResource.getControlByCodes(new String[]{"CONTAINER_VOLUME", "PICK_TASK_ASK_WAY"}, warehouseId, null, enterpriseId, null);
        if (rest.isSuccess() && rest.getData() != null) {
            Map<String, BusinessControl> conMap = rest.getData();
            if (conMap.containsKey("PICK_TASK_ASK_WAY"))
                pickWay = conMap.get("PICK_TASK_ASK_WAY").getRegValue();
            if (conMap.containsKey("CONTAINER_VOLUME"))
                maxVolume = new BigDecimal(conMap.get("CONTAINER_VOLUME").getRegValue());
        }
        //查询平库待拣货任务
        List<WaveStorageDTO> waveStorageList = pickTaskHMapper.getWaveStorageList(waveId, null, enterpriseId, warehouseId, null, null, 0, "1", "0");
        this.doPickingSpecial("0", waveStorageList, pickWay);

        //查询立库待拣货任务
        List<WaveStorageDTO> waveStorageDeviceList = pickTaskHMapper.getWaveStorageDeviceList(waveId, enterpriseId, warehouseId, null, 0, "1");
        this.doPickingSpecial("1", waveStorageDeviceList, pickWay);
    }

    /**
     * 扣减库存，回传erp,新增企业id参数 - by Huanglh 2022-02-21
     *
     * @param waveId       波次ID
     * @param warehouseId  仓库ID
     * @param enterpriseId 企业ID
     */
    private void invStockConfirm(String waveId, String warehouseId, String enterpriseId) {
        WaveDO wave = waveMapper.findById(waveId, WaveDO.class);
        // 货主转换不用扣减库存
        if (!wave.getType().equals("7")) {
            // 扣减库存
            List<String> billdIdList = billMapper.getBillDIdList(null, waveId, warehouseId);
            if (billdIdList.size() > 0) {
                InvStockCheckOut invStockCheck = new InvStockCheckOut();
                invStockCheck.setLineBillIds(billdIdList.toArray(new String[billdIdList.size()]));
                WaveDO waveDo = waveMapper.findById(waveId, WaveDO.class);
                invStockCheck.setOutType("8".equals(waveDo.getType()) ? "1" : waveDo.getType());
                RestMessage restMessage = invClient.outStockCheck(invStockCheck);
                if (!restMessage.isSuccess()) {
                    throw new BizException("扣减库存失败: " + restMessage.getMessage());
                }
            }
        }
        List<String> omsBillIds = barcodeHMapper.getBillIdByWave(waveId, warehouseId);
        // 回传erp
        // ERP回传方式写中间表，通过mq立刻通知oms处理，使用 PostBackErpHandle by Huanglh 20220112
        /*for (String omsBillId : omsBillIds) {
            EtlMessage etlMessage = new EtlMessage();
            etlMessage.setId(omsBillId);
            etlMessage.setEtlType(EtlTypeConstants.out_do_w2o);
            try {
                exchangeSender.send(etlMessage);
            }catch (Exception e){
                throw new BizException("外复核确认，回传ERP，rabbitmq发送消息失败！");
            }
        }*/
        // 只需要需要判断一个业务配置参数
        IStrategyHandle strategyHandle = strategySelector.selectHandle(Arrays.asList(
                STRATEGY_CODE.POST_BACK_ERP__MQ__ON), enterpriseId, warehouseId, "do");
        strategyHandle.execute(omsBillIds);
    }

    /**
     * 保存拣选任务（特殊订单）
     *
     * @param list    库存预占组包集合
     * @param pickWay 拣货方式：0-整散分开 1-整单拣货
     */
    private void createPickTaskSpecial(List<List<WaveStorageDTO>> list, String pickWay) {
        if (list.size() > 0) {
            Date date = new Date();
            List<PickTaskH> pickTaskHList = new ArrayList<>();
            String pickOrderId = String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId));
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MINUTE, new Random().nextInt(15) + 15);
            String operatorCode = null;
            WaveStorageDTO storage = list.get(0).get(0);
            String enterpriseId = storage.getEnterpriseId();
            String warehouseId = storage.getWarehouseId();
            String bldgId = storage.getBldgId();
            String bldgName = storage.getBldgName();
            String locatorType = storage.getWarehouseLocatorType();
            // 查询拣货人员
            List<String> operatorList = new ArrayList<>();
            try {
                operatorList = pickTaskService.getOperatorList(storage.getWarehouseAreaCode(), "2011", locatorType, enterpriseId, warehouseId);
            } catch (Exception e) {
                operatorList = pickTaskService.getOperatorList(null, "2011", locatorType, enterpriseId, warehouseId);
            }
            if (operatorList.size() > 0) {
                int random = (int) (Math.random() * operatorList.size());
                operatorCode = operatorList.get(random);
            }
            String operatorCode1 = null;
            // 查询外复核人员
            List<String> operatorList1 = pickTaskService.getOperatorList(null, "2016", null, enterpriseId, warehouseId);
            if (operatorList1.size() > 0) {
                int random = (int) (Math.random() * operatorList1.size());
                operatorCode1 = operatorList1.get(random);
            }
            String containerCode = null;
            String stationId = null;
            String stationCode = null;
            String stationName = null;
            String barcodeId = null;
            String barcode = String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId));
            int i = 0;
            Set<String> omsBillIds = new HashSet<>();
            // 循环所有装好的容器，生成拣选任务
            for (List<WaveStorageDTO> waveStorageLists : list) {
                storage = waveStorageLists.stream().findFirst().get();
                Integer pickTaskType;
                if (waveStorageLists.get(0).getPickType() != null) {
                    pickTaskType = waveStorageLists.get(0).getPickType();
                } else {
                    pickTaskType = Integer.valueOf(waveStorageLists.get(0).getWarehouseLocatorType());
                }
                BigDecimal volumeTotal = BigDecimal.ZERO;
                String pickTaskId = String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId));
                String pickPieceGroup = null;
                BigDecimal pcs = BigDecimal.ZERO;
                BigDecimal pcsTotal = BigDecimal.ZERO;
                if (pickTaskType == 0) {
                    for (WaveStorageDTO waveStorage : waveStorageLists) {
                        pcsTotal = pcsTotal.add(waveStorage.getQty().divide(waveStorage.getCaseConversionRate(), 0, BigDecimal.ROUND_DOWN));
                    }
                } else if (pickTaskType != 0 || pickWay.equals("1")) {
                    if (pickWay.equals("1")) {
                        int random = (int) (Math.random() * 80100 + 80001);
                        containerCode = String.valueOf(random);
                    } else {
                        int random = (int) (Math.random() * 5591 + 503);
                        String str = String.format("%07d", random);
                        containerCode = String.format("%s%s", "3", str);
                    }
                    BaseWmsWhWorkstation workstation = pickTaskService.getBaseWmsWhWorkstation(storage.getWarehouseAreaCode(), warehouseId, enterpriseId);
                    if (workstation != null) {
                        stationId = workstation.getStationId();
                        stationCode = workstation.getStationCode();
                        stationName = workstation.getStationName();
                    }
                }
                // 循环库存预占
                for (WaveStorageDTO waveStorage : waveStorageLists) {
                    if (pickPieceGroup == null || pickPieceGroup.length() < waveStorage.getPickPieceGroup().length()) {
                        pickPieceGroup = waveStorage.getPickPieceGroup();
                    }
                    BigDecimal volume = waveStorage.getVolume();
                    volumeTotal = volumeTotal.add(volume);
                    // 更新库存预占状态
                    waveStorageMapper.updateMapById(waveStorage.getId(), MapUtils.put("status", "1").getMap(), WaveStorageDO.class);
                    PickTaskD d = new PickTaskD();
                    d.setPickTaskId(pickTaskId);
                    d.setWaveStorageId(waveStorage.getId());
                    d.setWarehouseId(warehouseId);
                    d.setQty(waveStorage.getQty());
                    d.setEnterpriseId(enterpriseId);
                    d.setGmtCreate(date);
                    d.setPickQty(waveStorage.getQty());
                    d.setPrintCount(1);
                    d.setPickTime(date);
                    d.setPickerId(operatorCode);
                    d.setPickerName(operatorCode);
                    d.setPickerNo(operatorCode);
                    d.setFlowStatus("7");

                    WaveBillDO waveBillDO = billMapper.findById(waveStorage.getBillId(), WaveBillDO.class);
                    WaveBillDDO waveBillDDO = billDMapper.findById(waveStorage.getBillDId(), WaveBillDDO.class);
                    d.setSrcId(waveBillDO.getSrcId());
                    d.setSrcLineId(waveBillDDO.getSrcLineId());
                    d.setSrcCode(waveBillDO.getSrcCode());
                    d.setBillId(waveStorage.getBillId());
                    d.setBillDId(waveStorage.getBillDId());
                    d.setItemId(waveStorage.getItemId());
                    d.setBatchId(waveStorage.getBatchId());
                    d.setLocatorId(waveStorage.getWarehouseLocatorId());
                    d.setWarehouseAreaCode(waveStorage.getWarehouseAreaCode());
                    d.setPickModel(waveStorage.getPickModel());

                    // 任务类型（0-整件/1-散件/2-整散合一）
                    d.setPickTaskType(pickTaskType);
                    if (pickTaskType == 0) {
                        pcs = pcs.add(d.getQty().divide(waveStorage.getCaseConversionRate(), 0, BigDecimal.ROUND_DOWN));
                        d.setWholeNum(String.format("%s/%s", pcs, pcsTotal));
                    }
                    pickTaskDMapper.save(d);
                    BarCodeDDO barCodeDDO = new BarCodeDDO();
                    if (pickTaskType == 0) {
                        BarcodeHDO barCodeHDO = new BarcodeHDO();
                        barCodeHDO.setId(String.valueOf(SnowFlakeUtils.getId()));
                        barCodeHDO.setType("1");//整件拣选码
                        barCodeHDO.setBarcode(d.getPickTaskDId());
                        barCodeHDO.setBillGroupId(waveStorage.getMergedBillId());
                        barCodeHDO.setStatus('1');
                        barCodeHDO.setEnterpriseId(enterpriseId);
                        barCodeHDO.setWarehouseId(warehouseId);
                        barCodeHDO.setBldgId(bldgId);
                        barCodeHDO.setBldgName(bldgName);
                        barCodeHDO.setGmtCreate(date);
                        barCodeHDO.setGmtModified(date);
                        barCodeHDO.setCheckStatus("5");
                        barCodeHDO.setCheckerId(operatorCode1);
                        barCodeHDO.setCheckerName(operatorCode1);
                        barCodeHDO.setCheckerNo(operatorCode1);

                        Calendar calendar1 = Calendar.getInstance();
                        calendar1.add(Calendar.MINUTE, new Random().nextInt(30) + 15);
                        barCodeHDO.setCheckTime(calendar1.getTime());
                        calendar1.add(Calendar.MINUTE, new Random().nextInt(5) + 15);
                        barCodeHDO.setCheckTime2(calendar1.getTime());
                        barcodeHMapper.save(barCodeHDO);
                        barCodeDDO.setBarcodeId(barCodeHDO.getId());
                        barCodeDDO.setIsPiece(0);
                    } else {
                        if (i == 0) {
                            BarcodeHDO barCodeHDO = new BarcodeHDO();
                            barCodeHDO.setId(String.valueOf(SnowFlakeUtils.getId()));
                            barCodeHDO.setType("0");
                            barCodeHDO.setBarcode(barcode);
                            barCodeHDO.setLclNo(1);
                            barCodeHDO.setBillGroupId(waveStorage.getMergedBillId());
                            barCodeHDO.setStatus('1');
                            barCodeHDO.setEnterpriseId(enterpriseId);
                            barCodeHDO.setWarehouseId(warehouseId);
                            barCodeHDO.setBldgId(bldgId);
                            barCodeHDO.setBldgName(bldgName);
                            barCodeHDO.setGmtCreate(date);
                            barCodeHDO.setGmtModified(date);
                            barCodeHDO.setCheckStatus("5");
                            barCodeHDO.setCheckerId(operatorCode1);
                            barCodeHDO.setCheckerName(operatorCode1);
                            barCodeHDO.setCheckerNo(operatorCode1);
                            barCodeHDO.setContainerCode(containerCode);
                            barCodeHDO.setStationCode(stationCode);
                            Calendar calendar1 = Calendar.getInstance();
                            calendar1.add(Calendar.MINUTE, new Random().nextInt(30) + 15);
                            barCodeHDO.setCheckTime(calendar1.getTime());
                            calendar1.add(Calendar.MINUTE, new Random().nextInt(5) + 15);
                            barCodeHDO.setCheckTime2(calendar1.getTime());
                            barcodeHMapper.save(barCodeHDO);
                            barcodeId = barCodeHDO.getId();
                            i++;
                        }
                        barCodeDDO.setIsPiece(1);
                    }
                    if (pickTaskType > 0) {
                        barCodeDDO.setBarcodeId(barcodeId);
                    }
                    barCodeDDO.setGmtCreate(date);
                    barCodeDDO.setGmtModified(date);
                    barCodeDDO.setWmsPickTaskDId(d.getPickTaskDId());
                    barCodeDDO.setEnterpriseId(enterpriseId);
                    barCodeDDO.setWarehouseId(warehouseId);
                    barCodeDDO.setQty(d.getQty());
                    barCodeDDO.setItemId(waveStorage.getItemId());
                    barcodeDMapper.save(barCodeDDO);
                }
                Integer type = storage.getType();
                PickTaskH h = new PickTaskH();
                h.setPickTaskId(pickTaskId);
                if (pickWay.equals("1") && pickTaskType < 2) {
                    // 整单
                    h.setPickTaskType(3);
                } else {
                    // 任务类型（0-整件/1-散件/2-整散合一）
                    h.setPickTaskType(pickTaskType);
                }
                h.setEnterpriseId(enterpriseId);
                h.setWarehouseId(warehouseId);
                h.setPriority(storage.getPriority());
                h.setIsMerged(storage.getIsMerged());
                h.setWaveId(storage.getWaveId());
                h.setGmtModified(date);
                h.setWarehouseAreaCode(storage.getWarehouseAreaCode());
                h.setPickPieceGroup(pickPieceGroup);
                h.setBldgId(bldgId);
                h.setBldgName(bldgName);
                h.setType(type);
                h.setBillGroupId(storage.getMergedBillId());
                h.setBillId(storage.getBillId());
                h.setGmtCreate(date);
                h.setStatus("10");
                if (pickTaskType > 0 || pickWay.equals("1")) {
                    h.setContainerCode(containerCode);
                    h.setStationId(stationId);
                    h.setStationCode(stationCode);
                    h.setStationName(stationName);
                }
                h.setPickOrderId(pickOrderId);
                pickTaskHList.add(h);
                omsBillIds.add(storage.getBillId());
            }
            PickOrder pickOrder = new PickOrder();
            pickOrder.setPickOrderId(pickOrderId);
            pickOrder.setStatus("2");
            pickOrder.setWarehouseId(warehouseId);
            pickOrder.setTaskCount(list.size());
            pickOrder.setOperatorId(operatorCode);
            pickOrder.setOperatorName(operatorCode);
            pickOrder.setOperatorCode(operatorCode);
            pickOrder.setPickTaskType(Integer.valueOf(locatorType));
            pickOrder.setPrintStatus("1");
            pickOrder.setEnterpriseId(enterpriseId);
            pickOrder.setGmtCreate(calendar.getTime());
            pickOrder.setGmtModified(calendar.getTime());
            pickOrderMapper.save(pickOrder);
            pickTaskHMapper.saveBatch(pickTaskHList);
        }
    }

    /**
     * 组包，生成拣选任务
     */
    @Override
    public void createPickTask(List<TaskParamsVO> waveList, String type) {
        if (CollectionUtil.isEmpty(waveList)) {
            throw new ParameterException("参数不能为空！");
        }
        BigDecimal maxVolume = new BigDecimal("48000");
        // 拣货方式：0-整散分开索取；1-整单索取
        String pickWay = "0";
        String warehouseId = waveList.get(0).getWarehouseId();
        String enterpriseId = waveList.get(0).getEnterpriseId();
        RestMessage<Map<String, BusinessControl>> rest = strategyResource.getControlByCodes(new String[]{"CONTAINER_VOLUME", "PICK_TASK_ASK_WAY"}, warehouseId, null, enterpriseId, null);
        if (rest.isSuccess() && rest.getData() != null) {
            Map<String, BusinessControl> conMap = rest.getData();
            if (conMap.containsKey("PICK_TASK_ASK_WAY")) {
                pickWay = conMap.get("PICK_TASK_ASK_WAY").getRegValue();
            }
            if (conMap.containsKey("CONTAINER_VOLUME")) {
                maxVolume = new BigDecimal(conMap.get("CONTAINER_VOLUME").getRegValue());
            }
        }

        /*if ("1".equals(type)) {*/
        for (TaskParamsVO taskParamsVO : waveList) {
            String waveId = taskParamsVO.getWaveId();
            // 查询补货任务
            List<WaveStorageDTO> moveStorageList = pickTaskHMapper.getAgvStorageList(waveId, null, enterpriseId, warehouseId, null, null, 1, null);
            this.doPicking("0", moveStorageList, enterpriseId, warehouseId, maxVolume, "0", pickWay);
            if (pickWay.equals("0")) {
                // 整散分开拣货
                // 查询待拣货任务(整件)
                List<WaveStorageDTO> waveStorageList = pickTaskHMapper.getWaveStorageList(waveId, null, enterpriseId, warehouseId, "0", null, 0, null, "0");
                this.doPicking("0", waveStorageList, enterpriseId, warehouseId, maxVolume, "0", pickWay);
                // 查询待拣货任务(零散)
                List<WaveStorageDTO> waveStorageList2 = pickTaskHMapper.getWaveStorageList(waveId, null, enterpriseId, warehouseId, "1", null, 0, null, "0");
                this.doPicking("1", waveStorageList2, enterpriseId, warehouseId, maxVolume, "0", pickWay);
            } else {
                // 整单拣货
                List<String> pickTaskTypes = new ArrayList<>();
                pickTaskTypes.add("0");
                pickTaskTypes.add("1");
                // 查询待拣货任务(零散+整件)
                List<WaveStorageDTO> waveStorageList = pickTaskHMapper.getWaveStorageList(waveId, null, enterpriseId, warehouseId, null, pickTaskTypes, 0, null, "0");
                this.doPicking("3", waveStorageList, enterpriseId, warehouseId, maxVolume, "0", pickWay);
            }
            // 查询待拣货任务(整散合一，零散+整件)-功能库房 - 修改,在整散合一的基础上，加上 零散+整件  by Huanglh 2022-01-20
            // 功能库房同订单所有任务只放一个容器中，可跨区
            List<WaveStorageDTO> waveStorageList3 = pickTaskHMapper.getWaveStorageList(waveId, null, enterpriseId, warehouseId, null, Arrays.asList("0", "1", "2"), 0, null, "1");
            this.doPicking("2", waveStorageList3, enterpriseId, warehouseId, maxVolume, "0", pickWay);

            // 查询设备库,整件待拣货任务
            generatePickTasksByDevice(waveId, enterpriseId, warehouseId);
        }
    }

    public void generatePickTasksByDevice(String waveId, String enterpriseId, String warehouseId) {
        List<WaveStorageDTO> waveStorageEisDeviceList = pickTaskHMapper.getWaveStorageDeviceList(waveId, enterpriseId, warehouseId, Arrays.asList("0", "1"), 0, null);
        if (CollUtil.isNotEmpty(waveStorageEisDeviceList)) {
            this.doPickingEisDevice(waveStorageEisDeviceList);
        }
    }

    @Transactional
    @Override
    public void addPickTask(List<String> waveIdList) {
        List<TaskParamsVO> waveList = new ArrayList<>();
        for (String waveId : waveIdList) {
            WaveDO waveDO = waveMapper.findById(waveId, WaveDO.class);
            if (waveDO.getStatus() == null || (!waveDO.getStatus().equals(WAVE_STATUS.getWaveStatusEnum("WORK_STAGE")) && !waveDO.getStatus().equals(WAVE_STATUS.getWaveStatusEnum("COUNT_CONTAINER")))) {
                throw new PrologException("计算集货区失败才可以强制下发!");
            }
            TaskParamsVO vo = new TaskParamsVO();
            vo.setWaveId(waveId);
            vo.setWarehouseId(waveDO.getWarehouseId());
            vo.setEnterpriseId(waveDO.getEnterpriseId());
            waveList.add(vo);
            waveMapper.updateMapById(waveId, MapUtils.put("status", WAVE_STATUS.COMPLETED).getMap(), WaveDO.class);
            StatusUtil.updateWaveStartStatus(waveId, WAVE_STATUS.COMPLETED, null);
            StatusUtil.updateWaveEndStatus(waveId, WAVE_STATUS.COUNT_CONTAINER, null);
        }
        this.createPickTask(waveList, "1");
    }

    /**
     * 组包逻辑
     *
     * @param type            拣货类型
     * @param waveStorageList 预占集合
     * @param enterpriseId    企业ID
     * @param warehouseId     仓库ID
     * @param maxVolume       容器最大体积
     * @param waveType        波次类型
     */
    private void doPicking(String type, List<WaveStorageDTO> waveStorageList, String enterpriseId, String warehouseId, BigDecimal maxVolume, String waveType, String pickWay) {
        if (waveStorageList.size() > 0) {
            List<List<WaveStorageDTO>> allList = new ArrayList<>();
            if (type.equals("1")) {
                // 零货
                String[] codes = waveStorageList.stream().map(WaveStorageDTO::getWarehouseAreaCode).distinct().toArray(String[]::new);
                RestMessage<Map<String, String>> rest = warehouseResource.getVolumePercentageByCodes(codes, warehouseId);
                if (!rest.isSuccess() || rest.getData() == null) {
                    throw new PrologException("根据库区编号查询容器体积百分比错误!" + rest.getMessage());
                }
                // 库区容器体积百分比
                Map<String, String> volumeMap = rest.getData();
                List<List<WaveStorageDTO>> list1 = new ArrayList<>();
                // 组包，将任务明细装入容器，并计算
                Iterator<WaveStorageDTO> it = waveStorageList.iterator();
                while (it.hasNext()) {
                    WaveStorageDTO waveStorage = it.next();
                    String whAreaCode = waveStorage.getWarehouseAreaCode();
                    BigDecimal mVolume = maxVolume;
                    if (volumeMap.containsKey(whAreaCode)) {
                        String p = volumeMap.get(whAreaCode);
                        if (!StringUtils.isBlank(p)) {
                            mVolume = maxVolume.multiply(new BigDecimal(p).divide(new BigDecimal("100")));
                        }
                    }
                    String billId = waveStorage.getBillId();
                    BigDecimal volume = waveStorage.getVolume();
                    String itemId = waveStorage.getItemId();
                    // 新建一个包
                    List<WaveStorageDTO> list = new ArrayList<>();
                    list.add(waveStorage);
                    it.remove();
                    if (volume.compareTo(mVolume) < 0) {
                        // 体积差值
                        BigDecimal value = mVolume.subtract(volume);
                        it = waveStorageList.iterator();
                        while (it.hasNext()) {
                            WaveStorageDTO waveStorage2 = it.next();
                            String whAreaCode2 = waveStorage2.getWarehouseAreaCode();
                            String billId2 = waveStorage2.getBillId();
                            String itemId2 = waveStorage2.getItemId();
                            if (!whAreaCode.equals(whAreaCode2) || !billId.equals(billId2)) {
                                break;
                            }
                            BigDecimal volume2 = waveStorage2.getVolume();
                            if (itemId.equals(itemId2) || volume2.compareTo(value) <= 0) {
                                list.add(waveStorage2);
                                it.remove();
                                value = value.subtract(volume2);
                            }
                        }
                    }
                    list1.add(list);
                    it = waveStorageList.iterator();
                }
                allList.addAll(list1);
            } else if (type.equals("0") && pickWay.equals("0")) {
                // 整件拣货
                List<List<WaveStorageDTO>> list2 = new ArrayList<>();
                BigDecimal count = new BigDecimal("5");
                RestMessage<BusinessControl> restMessage = strategyResource.getControlByCode("PICK_TASK_QUANTITY", warehouseId, null, enterpriseId, null);
                if (restMessage.isSuccess() && restMessage.getData() != null) {
                    count = new BigDecimal(restMessage.getData().getRegValue());
                }
                // 区分平库和立库
                // 整件拣货,平库：按同订单号同库区同拣货类型进行任务组包,立体库：不组包，每行任务单独1个任务包号
                List<WaveStorageDTO> pkList = new ArrayList<>();
                // 判断是平库还是立体库
                for (int i = 0; i < waveStorageList.size(); i++) {
                    WaveStorageDTO waveStorageDO = waveStorageList.get(i);
                    if (waveStorageDO.getWarehouseAreaCode().contains("AGV")) {
                        List<WaveStorageDTO> list = new ArrayList<>();
                        list.add(waveStorageDO);
                        allList.add(list);
                    } else {
                        pkList.add(waveStorageDO);
                    }
                }
                // 平库组包，一条库存预占，对应一条或多条拣选任务明细（业务控制参数配置，小于等于5件拆分，大于5件不拆分）
                Map<String, List<WaveStorageDTO>> listMap = pkList.stream().collect(Collectors.groupingBy(w -> String.format("%s#%s", w.getBillId(), w.getWarehouseAreaCode())));
                BigDecimal finalCount = count;
                listMap.forEach((key, value) -> {
                    // 根据拣货顺序号排序
                    value.sort(Comparator.comparing(WaveStorageDTO::getOutIndex, Comparator.nullsLast(BigDecimal::compareTo)));
                    // 新建一个包
                    List<WaveStorageDTO> temp = new ArrayList<>();
                    BigDecimal tempPcs = BigDecimal.ZERO;
                    for (int i = 0; i < value.size(); i++) {
                        WaveStorageDTO waveStorageDO = value.get(i);
                        // 件数
                        BigDecimal js = waveStorageDO.getQty().divide(waveStorageDO.getCaseConversionRate(), 0, BigDecimal.ROUND_HALF_UP);
                        if (js.compareTo(finalCount) > 0) {
                            // 如果件数>5，则自己为一个拣选任务
                            // 新建一个包
                            List<WaveStorageDTO> list = new ArrayList<>();
                            list.add(waveStorageDO);
                            list2.add(list);
                        } else {
                            // 如果件数<=5，则拆分为每件一个拣选任务
                            tempPcs = tempPcs.add(js);
                            if (tempPcs.compareTo(finalCount) > 0) {
                                list2.add(temp);
                                temp = new ArrayList<>();
                                tempPcs = js;
                            }
                            temp.add(waveStorageDO);
                        }
                    }
                    if (CollUtil.isNotEmpty(temp)) {
                        list2.add(temp);
                    }
                });
                allList.addAll(list2);
            } else if (type.equals("0") && pickWay.equals("1")) {
                // 整单补货(所有任务放一个容器)
                List<List<WaveStorageDTO>> list5 = new ArrayList<>();
                Iterator<WaveStorageDTO> it = waveStorageList.iterator();
                while (it.hasNext()) {
                    WaveStorageDTO waveStorage = it.next();
                    String billId = waveStorage.getBillId();
                    // 新建一个包
                    List<WaveStorageDTO> list = new ArrayList<>();
                    list.add(waveStorage);
                    it.remove();
                    it = waveStorageList.iterator();
                    while (it.hasNext()) {
                        WaveStorageDTO waveStorage2 = it.next();
                        String billId2 = waveStorage2.getBillId();
                        if (!billId.equals(billId2)) {
                            break;
                        }
                        list.add(waveStorage2);
                        it.remove();
                    }
                    list5.add(list);
                    it = waveStorageList.iterator();
                }
                allList.addAll(list5);
            } else if (type.equals("2")) {
                // 整散合一,讨论改为：功能库房同订单所有任务只放一个容器中，可跨区
                // 功能库房拣货(整件+零货) 放一个容器中,同一库区同一订单的整件和零货同时索取 - by Huanglh 2022-01-20
                List<List<WaveStorageDTO>> list3 = new ArrayList<>();
                Iterator<WaveStorageDTO> it = waveStorageList.iterator();
                while (it.hasNext()) {
                    WaveStorageDTO waveStorage = it.next();
                    String billId = waveStorage.getBillId();
                    // 新建一个包
                    List<WaveStorageDTO> list = new ArrayList<>();
                    // 因为现在整件，散件，零散合一都有，所以必须手动指定 - by Huanglh 2022-01-20
                    waveStorage.setPickType(2);
                    list.add(waveStorage);
                    it.remove();
                    it = waveStorageList.iterator();
                    while (it.hasNext()) {
                        WaveStorageDTO waveStorage2 = it.next();
                        String billId2 = waveStorage2.getBillId();
                        if (!(billId.equals(billId2))) {
                            break;
                        }
                        waveStorage2.setPickType(2);
                        list.add(waveStorage2);
                        it.remove();
                    }
                    list3.add(list);
                    it = waveStorageList.iterator();
                }
                allList.addAll(list3);
            } else if (type.equals("3")) {
                // 整单拣货，同订单（整件+零货）放一个容器中，可跨区
                List<List<WaveStorageDTO>> list4 = new ArrayList<>();
                Iterator<WaveStorageDTO> it = waveStorageList.iterator();
                while (it.hasNext()) {
                    WaveStorageDTO waveStorage = it.next();
                    String billId = waveStorage.getBillId();
                    // 新建一个包
                    List<WaveStorageDTO> list = new ArrayList<>();
                    waveStorage.setPickType(3);
                    list.add(waveStorage);
                    it.remove();
                    it = waveStorageList.iterator();
                    while (it.hasNext()) {
                        WaveStorageDTO waveStorage2 = it.next();
                        String illId2 = waveStorage2.getBillId();
                        if (!billId.equals(illId2)) {
                            break;
                        }
                        waveStorage2.setPickType(3);
                        list.add(waveStorage2);
                        it.remove();
                    }
                    list4.add(list);
                    it = waveStorageList.iterator();
                }
                allList.addAll(list4);
            }
            if (waveType.equals("0")) {
                this.createPickTask(allList);
            } else {
                this.createPickTaskSpecial(allList, pickWay);
            }
        }
    }

    private void doPickingSpecial(String type, List<WaveStorageDTO> waveStorageList, String pickWay) {
        if (waveStorageList.size() > 0) {
            List<List<WaveStorageDTO>> allList = new ArrayList<>();
            Map<String, List<WaveStorageDTO>> listMap;
            if ("0".equals(type)) {
                // 平库 订单,库区组包
                listMap = waveStorageList.stream().map(row -> {
                    row.setPickType(4);
                    return row;
                }).collect(Collectors.groupingBy(x -> StrUtil.join(",", x.getBillId(), x.getWarehouseAreaCode())));
                allList.addAll(listMap.values());
                this.createPickTask(allList);
            } else {
                // 立库 任务行组包
                listMap = waveStorageList.stream().map(row -> {
                    row.setPickType(4);
                    return row;
                }).collect(Collectors.groupingBy(WaveStorageDTO::getId));
                allList.addAll(listMap.values());
                this.createPickTaskAndSaveEisParams(allList);
            }
        }
    }

    /**
     * EIS设备库组包逻辑
     *
     * @param list 库存预占组包集合
     */
    private void doPickingEisDevice(List<WaveStorageDTO> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        // 同订单组一个包
        // eis密集库任务发送,密集库任务一条明细行一个包
        createPickTaskAndSaveEisParams(list.stream().map(Collections::singletonList).collect(Collectors.toList()));
    }


    /**
     * @param list
     * @Notice 改本方法时注意waveBillDOs和waveBillDDOs的查询字段
     */
    public void createPickTaskAndSaveEisParams(List<List<WaveStorageDTO>> list) {

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

        log.info("组包信息为:{}", JSONObject.toJSONString(list));

        List<WaveStorageDTO> storages = list.stream().flatMap(List::stream).collect(Collectors.toList());

        Set<String> itemIdSet = storages.stream().map(WaveStorageDTO::getItemId).collect(Collectors.toSet());
        Assert.notEmpty(itemIdSet, "物料信息不存在");

        String waveId = storages.stream().filter(s -> StrUtil.isNotEmpty(s.getWaveId())).map(WaveStorageDTO::getWaveId).findFirst().orElse(null);
        cn.hutool.core.lang.Assert.notEmpty(waveId, "获取波次ID失败");

        List<BaseMtlItemMst> items = RestMsgHelper.getData(itemClient.getListByIds(itemIdSet));
        Assert.notEmpty(items, "获取物料信息失败");

        String[] billIds = storages.stream().map(WaveStorageDTO::getBillId).distinct().toArray(String[]::new);
        String[] billDIds = storages.stream().map(WaveStorageDTO::getBillDId).distinct().toArray(String[]::new);

        List<WaveBillDO> waveBillDOs = billMapper.findByIds(WaveBillDO.class, billIds, FieldSelector.newInstance().include("id", "waveId", "shipperId", "shipperName", "consignorId", "srcId", "srcCode", "type"));
        List<WaveBillDDO> waveBillDDOs = billDMapper.findByIds(WaveBillDDO.class, billDIds, FieldSelector.newInstance().include("id", "srcLineId"));
        String[] srcIds = waveBillDOs.stream().map(WaveBillDO::getSrcId).distinct().toArray(String[]::new);
        List<OmsDoBillHDO> bills = omsDoBillHMapper.findByIds(OmsDoBillHDO.class, srcIds, FieldSelector.newInstance().include("priorityLevel", "billid","attrStr3","attrStr4","totVolume","billDate"));
        cn.hutool.core.lang.Assert.notEmpty(bills, "订单获取失败");

        Date now = new Date();
        //eis出库任务
        List<OutBoundRequestItemVO> eisOutParams = Lists.newArrayList();
        List<PickTaskH> pickTaskHList = new ArrayList<>();
        List<PickTaskD> pickTaskDList = new ArrayList<>();
        List<BarcodeHDO> barcodeHList = new ArrayList<>();
        List<BarCodeDDO> barcodeDList = new ArrayList<>();
        //查询大体积订单通用参照
        BigDecimal bigBillVolume = BigDecimal.ZERO; // 默认自动波次下发
        RestMessage<Map<String, BusinessControl>> rest = strategyResource.getControlByCodes(new String[]{"big_do_bill_volume"},bills.get(0).getBranchid() , null, bills.get(0).getEnterpriseId(), null);
        if (rest.isSuccess() && rest.getData() != null) {
            Map<String,BusinessControl> conMap = rest.getData();
            if (conMap.containsKey("big_do_bill_volume")) {
                bigBillVolume = new BigDecimal(conMap.get("big_do_bill_volume").getRegValue());
            }
        }

        String[] storageIds = storages.stream().map(WaveStorageDTO::getId).distinct().toArray(String[]::new);
        boolean hasAGVL = false;
        // 循环所有装好的容器，生成拣选任务
        for (List<WaveStorageDTO> waveStorageLists : list) {
            Integer pickTaskType = getPickTaskType(waveStorageLists);
            BigDecimal volumeTotal = BigDecimal.ZERO;
            BigDecimal pcs = BigDecimal.ZERO;
            BigDecimal pcsTotal = getPcsTotal(waveStorageLists);
            // 任务头
            PickTaskH pickTaskH = wrapPickTaskH(pickTaskType, waveStorageLists.get(0), now);
            pickTaskHList.add(pickTaskH);

            // 循环库存预占，任务行
            for (WaveStorageDTO waveStorage : waveStorageLists) {

                if ("AGVL".equals(waveStorage.getAreaCategory())) {
                    hasAGVL = true;
                }

                WaveBillDO waveBillDO = waveBillDOs.stream().filter(wb -> wb.getId().equals(waveStorage.getBillId())).findFirst().orElse(null);
                cn.hutool.core.lang.Assert.notNull(waveBillDO, "获取波次订单汇总失败");

                WaveBillDDO waveBillDDO = waveBillDDOs.stream().filter(wbd -> wbd.getId().equals(waveStorage.getBillDId())).findFirst().orElse(null);
                cn.hutool.core.lang.Assert.notNull(waveBillDDO, "获取波次订单明细失败");

                if (waveStorage.getVolume() != null) {
                    volumeTotal = volumeTotal.add(waveStorage.getVolume());
                }

                String wholeNum = "";
                if ("0".equals(waveStorage.getWarehouseLocatorType())) {
                    pcs = pcs.add(waveStorage.getQty().divide(waveStorage.getCaseConversionRate(), 0, BigDecimal.ROUND_DOWN));
                    wholeNum = String.format("%s/%s", pcs, pcsTotal);
                }

                PickTaskD pickTaskD = wrapPickTaskD(waveStorage, pickTaskH.getPickTaskId(), now, wholeNum, waveBillDO, waveBillDDO);
                pickTaskDList.add(pickTaskD);

                OmsDoBillHDO bill = bills.stream().filter(b -> b.getBillid().equals(pickTaskD.getSrcId())).findFirst().orElse(null);
                //封装EIS推送信息
                addEisParams(waveStorage, items, waveBillDO, pickTaskD, eisOutParams, bill,bigBillVolume);

                if (pickTaskType == 1) {
                    BarcodeHDO exist = barcodeHList.stream().filter(br -> br.getBillGroupId().equals(bill.getBillid())).findFirst().orElse(null);
                    if (exist == null) {
                        exist = wrapBarcodeHDO(waveStorage, now);
                        barcodeHList.add(exist);
                    }

                    BarCodeDDO barCodeDDO = wrapBarCodeDDO(waveStorage, exist, now, pickTaskD);
                    barcodeDList.add(barCodeDDO);
                }
            }
        }

        if (hasAGVL) {
            //如果存在零货拣货任务且有物料库任务增加物料库拣货任务到EIS推送中
            addEisParamsByWlk(waveId, eisOutParams);
        }

        //缓存EIS推送任务到
        saveEisRequestByCache(storages.get(0).getWarehouseId(), waveId, eisOutParams);

        //持久化
        persistence(pickTaskHList, pickTaskDList, barcodeHList, barcodeDList, storageIds);

        log.info("结束生成拣货数据,下发数据到EIS");
    }

    public void addEisParamsByWlk(String waveId, List<OutBoundRequestItemVO> eisOutParams) {
        log.info("addEisParamsByWlk before:{}", JSONObject.toJSONString(eisOutParams));
        List<OutBoundRequestItemVO> list = waveStorageMapper.getOutbound4EisByWaveId(waveId);
        if (CollUtil.isEmpty(list)) {
            return;
        }
        List<OutBoundRequestItemVO> wlkTasks = list.stream().filter(l -> "WLK".equals(l.getTargetLocation())).collect(Collectors.toList());
        if (CollUtil.isEmpty(wlkTasks)) {
            return;
        }
        eisOutParams.addAll(wlkTasks);
        log.info("addEisParamsByWlk after:{}", JSONObject.toJSONString(eisOutParams));
    }

    private OutBoundRequestItemVO warpOutBoundRequest(WaveStorageDTO waveStorage, WaveBillDO waveBillDO, PickTaskD d, BaseMtlItemUomConversions conversions, OmsDoBillHDO bill,BigDecimal bigBillVolume) {

        OutBoundRequestItemVO eisParam = new OutBoundRequestItemVO();
        //四向库：MJZ;AGV整件药品托盘库：AGVZ;AGV整件食品托盘库：AGVSP;AGV整件器械托盘库：AGVQX;拆零库:AGVL(包含食品、器械、药品);
        eisParam.setWmsLocationCode("MJK".equals(waveStorage.getAreaCategory()) ? "MJZ" : waveStorage.getAreaCategory());
        eisParam.setOriginalArea("");
        eisParam.setTargetArea("");
        eisParam.setTargetLocation(waveStorage.getWarehouseAreaCode());
        eisParam.setItemId(d.getItemId());
        eisParam.setLotId(d.getBatchId());
        eisParam.setQty(d.getQty().toString());
        eisParam.setTaskId(d.getPickTaskId());
        eisParam.setTaskLineId(d.getPickTaskDId());
        OutBoundRequestEnum outBoundRequestEnum = OutBoundRequestEnum.get(waveBillDO.getType());
        eisParam.setWorkType(outBoundRequestEnum.getWorkType());
        eisParam.setBusinessType(outBoundRequestEnum.getBusinessType());
        eisParam.setWaveNo(waveStorage.getWaveId());
        eisParam.setBillNo(d.getSrcCode());
//        eisParam.setOrderCreateTime(DateUtils.format(bill.getBillDate(),"yyyy-MM-dd hh:mm:ss"));
        //attr_str3、attr_str4有一个为1，str1为1,否则为0
        eisParam.setStr1("1".equals(bill.getAttrStr3()) || "1".equals(bill.getAttrStr4()) ? "1" : "0");
//        if("1".equals(eisParam.getStr1())){
//            //判断质检、首营是否打印
//            List<PrintLog> printLogs = printLogService.findbyItemIds(CollUtil.toList(d.getItemId()),null);
//            if(printLogs != null && printLogs.size() > 0){
//                //质检报告
//                long count = printLogs.stream().filter(item -> "imgManage-ZJBG-pdf".equals(item.getPrintCode()) &&  d.getItemId().equals(item.getAttrStr1()) && d.getBatchId().equals(item.getAttrStr2())).count();
//                //首营资料
//                long count2 = printLogs.stream().filter(item -> "imgManage-SYZL-pdf".equals(item.getPrintCode()) && d.getItemId().equals(item.getAttrStr1())).count();
//                if(count > 0 && count2 > 0){
//                    eisParam.setStr1("0");
//                }
//            }
//        }
        //str2默认为1
        eisParam.setStr2("1");
        eisParam.setCompanyId(waveBillDO.getShipperId());
        eisParam.setCompanyName(waveBillDO.getShipperName());
        eisParam.setContainerNo("N/A".equals(waveStorage.getContainerCode()) ? "" : waveStorage.getContainerCode());
        eisParam.setPriority(bill == null ? 10D : Double.valueOf(bill.getPriorityLevel()));
        eisParam.setEnterpriseId(waveStorage.getEnterpriseId());
        eisParam.setLocNo(waveStorage.getLocatorCode());
        eisParam.setOwnerId(waveBillDO.getConsignorId());
        eisParam.setPackId(conversions.getItemUomId());
        eisParam.setInventoryShortageType(2);
        eisParam.setIsOver("0");
        eisParam.setIsCheck("0");

        //订单大体积标记
        if(bigBillVolume.multiply(new BigDecimal(1000000)).compareTo(bill.getTotVolume()) <= 0 ){
            eisParam.setLargeOrder(1);
        }else {
            eisParam.setLargeOrder(0);
        }
        return eisParam;
    }

    private ContainerTailgatingRequestVO warpContainerTailgatingParams(MoveTaskDO mt, String containerCode) {
        ContainerTailgatingRequestVO vo = new ContainerTailgatingRequestVO();
        vo.setMsgId(IdUtil.fastSimpleUUID());
        vo.setWarehouseId(mt.getWarehouseId());
        vo.setEnterpriseId(mt.getEnterpriseId());
        vo.setTargetLocation(mt.getDestWarehouseAreaCategory());
        vo.setWmsLocationCode("MJK".equals(mt.getSrcWarehouseAreaCategory()) ? "MJZ" : mt.getSrcWarehouseAreaCategory());
        vo.setContainerNo(containerCode);
        vo.setTaskId(mt.getDetailId());
        vo.setWorkType(INV_RTM.getWorkType());
        vo.setBusinessType(INV_RTM.getBusinessType());
        vo.setOriginalArea(mt.getSrcWarehouseAreaNum());
        vo.setOriginalLocation(mt.getSrcWarehouseLocatorNum());
        vo.setTargetArea("AGVL");
        return vo;
    }

    private void saveEisRequestByCache(String warehouseId, String waveId, List<OutBoundRequestItemVO> eisParams) {

        List<OutBoundRequestItemVO> eisReplenishmentParams = Lists.newArrayList();
        List<OutBoundRequestItemVO> outParams = Lists.newArrayList();

        filterEisParamsByReplenishment(waveId, eisParams, outParams, eisReplenishmentParams);

        outParams.addAll(eisReplenishmentParams);

        if (CollUtil.isNotEmpty(outParams)) {
            final String outboundKey = OUT_BOUND_REQUEST_WAVE_ID + waveId;
            OutBoundRequestVO vo = new OutBoundRequestVO();
            vo.setMsgId(IdUtil.fastSimpleUUID());
            vo.setWarehouseId(warehouseId);
            vo.setGroupOrderPolicy("0");
            vo.setSubList(outParams);
            List<OutBoundRequestVO> list = Collections.singletonList(vo);
            String eisMsg = JSONObject.toJSONString(list, SerializerFeature.DisableCircularReferenceDetect);
            log.info("outboundKey:{},eisMsg:{}", outboundKey, eisMsg);
            stringRedisTemplate.opsForValue().set(outboundKey, eisMsg);
        }

//        //该列表为被动补货完成后再推送的出库任务
//        if (CollUtil.isEmpty(eisReplenishmentParams)) {
//            return;
//        }
//
//        final String replenishmentkey = OUT_BOUND_REPLENISHMENT_REQUEST_WAVE_ID + waveId;
//        OutBoundRequestVO vo = new OutBoundRequestVO();
//        vo.setMsgId(IdUtil.fastSimpleUUID());
//        vo.setWarehouseId(warehouseId);
//        vo.setGroupOrderPolicy("0");
//        vo.setSubList(eisReplenishmentParams);
//        List<OutBoundRequestVO> list = Collections.singletonList(vo);
//        String eisMsg = JSONObject.toJSONString(list, SerializerFeature.DisableCircularReferenceDetect);
//        log.info("replenishmentkey:{},eisMsg:{}", replenishmentkey, eisMsg);
//        stringRedisTemplate.opsForValue().set(replenishmentkey, eisMsg);
    }

    public void filterEisParamsByReplenishment(String waveId, List<OutBoundRequestItemVO> eisParams, List<OutBoundRequestItemVO> outParams, List<OutBoundRequestItemVO> eisReplenishmentParams) {
        //获取本次波次的补货任务
        List<WmsMoveTaskRef> moveTaskRefs = moveTaskRefMapper.findFieldsByMap(FieldSelector.newInstance().include("moveTaskId", "srcCode"), MapUtils.put("waveId", waveId).getMap(), WmsMoveTaskRef.class);
        if (CollUtil.isEmpty(moveTaskRefs)) {
            for (OutBoundRequestItemVO eisParam : eisParams) {
                if ("2".equals(eisParam.getIsMaterial())) {
                    eisParam.setWmsLocationCode("AGVL");
                }
                outParams.add(eisParam);
            }
            return;
        }

        String[] moveTaskIds = moveTaskRefs.stream().map(WmsMoveTaskRef::getMoveTaskId).distinct().toArray(String[]::new);
        if (ArrayUtil.isEmpty(moveTaskIds)) {
            return;
        }

        List<MoveTaskDO> moveTasks = moveTaskMapper.findByIds(MoveTaskDO.class, moveTaskIds, null);
        if (CollUtil.isEmpty(moveTasks)) {
            return;
        }

        Set<String> itemIdSet = moveTasks.stream().map(MoveTaskDO::getItemId).distinct().collect(Collectors.toSet());
        Assert.notEmpty(itemIdSet, "物料信息不存在");

        List<BaseMtlItemMst> items = RestMsgHelper.getData(itemClient.getListByIds(itemIdSet));
        Assert.notEmpty(items, "获取物料信息失败");

        filterEisParams(waveId, eisParams, outParams, eisReplenishmentParams, moveTasks, moveTaskRefs, items);
    }

    /**
     * @param waveId                 波次号
     * @param eisParams              待推送EIS集合
     * @param outParams              出库推送集合
     * @param eisReplenishmentParams 出库任务完成后待推送的补货集合
     * @param moveTasks              补货任务
     * @param moveTaskRefs           补货任务依赖
     * @param items                  物料集合
     */
    public void filterEisParams(String waveId, List<OutBoundRequestItemVO> eisParams, List<OutBoundRequestItemVO> outParams, List<OutBoundRequestItemVO> eisReplenishmentParams, List<MoveTaskDO> moveTasks, List<WmsMoveTaskRef> moveTaskRefs, List<BaseMtlItemMst> items) {

        log.info("saveEisRequestByCache.eisParams.filterBefore:{}", JSONObject.toJSONString(eisParams));

        Map<String, List<MoveTaskDO>> map = moveTasks.stream().collect(Collectors.groupingBy(this::groupBy));
        for (Map.Entry<String, List<MoveTaskDO>> entry : map.entrySet()) {
            List<MoveTaskDO> value = entry.getValue();
            BigDecimal sum = value.stream().map(MoveTaskDO::getQty).reduce(BigDecimal.ZERO, BigDecimal::add);
            String groupLineId = value.stream().map(MoveTaskDO::getDetailId).distinct().collect(Collectors.joining(","));

            MoveTaskDO mt = value.get(0);
            List<OutBoundRequestItemVO> curMoveTaskEisParams = eisParams.stream().filter(ep -> ep.getItemId().equals(mt.getItemId())
                    && ep.getLotId().equals(mt.getBatchId())
                    && mt.getDestWarehouseAreaNum().equals(ep.getTargetLocation())
            ).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(curMoveTaskEisParams)) {
                eisParams.removeAll(curMoveTaskEisParams);
                eisReplenishmentParams.addAll(curMoveTaskEisParams);
            } else {
                String packId = "";
                BaseMtlItemMst itemMst = items.stream().filter(i -> i.getItemId().equals(mt.getItemId())).findFirst().orElse(null);
                if (itemMst != null) {
                    List<BaseMtlItemUomConversions> uomList = itemMst.getBaseMtlItemUomConversionsList();
                    if (CollUtil.isNotEmpty(uomList)) {
                        BaseMtlItemUomConversions conversions = uomList.stream().max(Comparator.comparing(BaseMtlItemUomConversions::getConversionRate)).get();
                        if (conversions != null) {
                            packId = conversions.getItemUomId();
                        }
                    }
                }

                OutBoundRequestItemVO vo = new OutBoundRequestItemVO();
                vo.setPackId(packId);
                curMoveTaskEisParams = Collections.singletonList(vo);
            }

            mt.setDetailId(groupLineId);
            mt.setQty(sum);
            OutBoundRequestItemVO reqParam = warpMoveTaskEisParams(waveId, mt, curMoveTaskEisParams);
            outParams.add(reqParam);
        }

        outParams.addAll(eisParams);

        List<OutBoundRequestItemVO> agvlList = outParams.stream().filter(op -> !"INV_RTM".equals(op.getBusinessType()) && "AGVL".equals(op.getTargetLocation())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(agvlList)) {
            outParams.removeAll(agvlList);
            eisReplenishmentParams.addAll(agvlList);
        }

        List<OutBoundRequestItemVO> wlkList = outParams.stream().filter(op -> "2".equals(op.getIsMaterial())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(wlkList)) {
            outParams.removeAll(wlkList);
            //拆零区含物料的出库任务将物料拣货明细库区改为AGVL
            for (OutBoundRequestItemVO outParam : wlkList) {
                outParam.setWmsLocationCode("AGVL");
                eisReplenishmentParams.add(outParam);
            }
//            eisReplenishmentParams.addAll(wlkList);
        }
        log.info("saveEisRequestByCache.outParams:{}", JSONObject.toJSONString(outParams));
        log.info("saveEisRequestByCache.eisReplenishmentParams:{}", JSONObject.toJSONString(eisReplenishmentParams));
    }

    private String groupBy(MoveTaskDO t) {
        return StrUtil.join("###", t.getItemId(), t.getBatchId(), t.getDestWarehouseAreaNum());
    }

    private OutBoundRequestItemVO warpMoveTaskEisParams(String waveId, MoveTaskDO mt, List<OutBoundRequestItemVO> curMoveTaskEisParams) {
        OutBoundRequestItemVO vo = curMoveTaskEisParams.get(0);
        OutBoundRequestItemVO eisParam = new OutBoundRequestItemVO();
        //四向库：MJZ;AGV整件药品托盘库：AGVZ;AGV整件食品托盘库：AGVSP;AGV整件器械托盘库：AGVQX;拆零库:AGVL(包含食品、器械、药品);
        eisParam.setWmsLocationCode("MJK".equals(mt.getSrcWarehouseAreaNum()) ? "MJZ" : mt.getSrcWarehouseAreaNum());
        eisParam.setOriginalArea("");
        eisParam.setTargetArea("");
        eisParam.setTargetLocation(mt.getDestWarehouseAreaNum());
        eisParam.setItemId(mt.getItemId());
        eisParam.setLotId(mt.getBatchId());
        eisParam.setQty(mt.getQty().toString());
        eisParam.setTaskId(mt.getHeaderId());
        eisParam.setTaskLineId(mt.getDetailId());
        eisParam.setWorkType(INV_RTM.getWorkType());
        eisParam.setBusinessType(INV_RTM.getBusinessType());
        eisParam.setWaveNo(waveId);
        eisParam.setBillNo(mt.getBillId());
        eisParam.setStr1("0");
        eisParam.setStr2("0");
        eisParam.setCompanyId(vo.getCompanyId());
        eisParam.setCompanyName(vo.getCompanyName());
        eisParam.setPackId(vo.getPackId());
        eisParam.setContainerNo("");
        eisParam.setPriority(10.0D);
        eisParam.setEnterpriseId(mt.getEnterpriseId());
        eisParam.setLocNo(mt.getSrcWarehouseLocatorNum());
        eisParam.setOwnerId(mt.getCargoOwnerId());
        eisParam.setInventoryShortageType(2);
        eisParam.setIsOver("0");
        eisParam.setIsCheck("0");
        eisParam.setIsMaterial("1");
        return eisParam;
    }

    private void addEisParams(WaveStorageDTO waveStorage, List<BaseMtlItemMst> items, WaveBillDO waveBillDO, PickTaskD pickTaskD, List<OutBoundRequestItemVO> eisOutParams, OmsDoBillHDO bill,BigDecimal bigBillVolume) {
        BaseMtlItemMst itemMst = items.stream().filter(i -> i.getItemId().equals(waveStorage.getItemId())).findFirst().orElse(null);
        cn.hutool.core.lang.Assert.notNull(itemMst, "获取物料【{}】失败", waveStorage.getItemCode());

        List<BaseMtlItemUomConversions> uomList = itemMst.getBaseMtlItemUomConversionsList();
        cn.hutool.core.lang.Assert.notEmpty(uomList, "没有配置物料【{}】的包装", waveStorage.getItemCode());

        BaseMtlItemUomConversions conversions = uomList.stream().max(Comparator.comparing(BaseMtlItemUomConversions::getConversionRate)).get();
        cn.hutool.core.lang.Assert.notNull(conversions, "没有配置物料【{}】的包装", waveStorage.getItemCode());

        //存在补货任务需要与出库任务一起推给EIS
        eisOutParams.add(warpOutBoundRequest(waveStorage, waveBillDO, pickTaskD, conversions, bill,bigBillVolume));
    }

    private PickTaskD wrapPickTaskD(WaveStorageDTO waveStorage, String pickTaskId, Date date, String wholeNum, WaveBillDO wb, WaveBillDDO wbd) {
        PickTaskD d = new PickTaskD();
        d.setPickTaskDId(String.valueOf(SnowFlakeUtils.getId()));
        d.setPickTaskId(pickTaskId);
        d.setWaveStorageId(waveStorage.getId());
        d.setWarehouseId(waveStorage.getWarehouseId());
        d.setQty(waveStorage.getQty());
        d.setEnterpriseId(waveStorage.getEnterpriseId());
        d.setGmtCreate(date);
        d.setPrintCount(0);
        d.setFlowStatus("0");
        d.setPickTaskType(Integer.valueOf(waveStorage.getWarehouseLocatorType()));
        d.setWholeNum(wholeNum);
        // 通过billId查询波次订单表
        d.setSrcId(wb.getSrcId());
        d.setSrcCode(wb.getSrcCode());
        d.setSrcLineId(wbd.getSrcLineId());
        //增加冗余字段
        d.setBillId(waveStorage.getBillId());
        d.setBillDId(waveStorage.getBillDId());
        d.setItemId(waveStorage.getItemId());
        d.setBatchId(waveStorage.getBatchId());
        d.setLocatorId(waveStorage.getWarehouseLocatorId());
        d.setWarehouseAreaCode(waveStorage.getWarehouseAreaCode());
        d.setPickModel(waveStorage.getPickModel());
        return d;
    }

    private PickTaskH wrapPickTaskH(Integer pickTaskType, WaveStorageDTO waveStorageDTO, Date date) {
        PickTaskH h = new PickTaskH();
        h.setPickTaskId(String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId)));
        h.setPickTaskType(pickTaskType); // 任务类型（0-整件/1-散件/2-整散合一/3-整单）
        h.setEnterpriseId(waveStorageDTO.getEnterpriseId());
        h.setWarehouseId(waveStorageDTO.getWarehouseId());
        h.setPriority(waveStorageDTO.getPriority());
        h.setIsMerged(waveStorageDTO.getIsMerged());
        h.setWaveId(waveStorageDTO.getWaveId());
        h.setStatus("0");
        h.setWarehouseAreaCode(waveStorageDTO.getWarehouseAreaCode());
        h.setBldgId(waveStorageDTO.getBldgId());
        h.setBldgName(waveStorageDTO.getBldgName());
        h.setType(waveStorageDTO.getType());
        String billGroupId = waveStorageDTO.getMergedBillId();
        h.setBillGroupId(billGroupId);
        h.setBillId(waveStorageDTO.getBillId());
        h.setGmtCreate(date);
        h.setGmtModified(date);
        return h;
    }


    /**
     * 生成拣货数据,下发数据到EIS
     *
     * @param list 库存预占组包集合
     */
    public Map<String, String> queryContainerMap(List<List<WaveStorageDTO>> list) {
        Map<String, String> resultMap = new HashMap<>();
        List<WaveStorageDTO> tempList = new ArrayList<>();
        for (List<WaveStorageDTO> waveStorageLists : list) {
            for (WaveStorageDTO waveStorageDTO : waveStorageLists) {
                if (null != waveStorageDTO.getContainerCode() && !waveStorageDTO.getContainerCode().equals("N/A")) {
                    tempList.add(waveStorageDTO);
                }
            }
        }
        Map<String, List<WaveStorageDTO>> containerMap = tempList.stream().collect(Collectors.groupingBy(WaveStorageDTO::getContainerCode));
        for (String containerCode : containerMap.keySet()) {
            List<WaveStorageDTO> waveStorageDTOList = containerMap.get(containerCode);
            BigDecimal qty = BigDecimal.ZERO;
            BigDecimal containerCodeQty = waveStorageDTOList.get(0).getContainerCodeQty();
            for (WaveStorageDTO waveStorageDTO : waveStorageDTOList) {
                qty = qty.add(waveStorageDTO.getQty());
            }
            if (containerCodeQty.compareTo(qty) > 0) {
                // 非整托
                resultMap.put(containerCode, "AGVTP01-C02");
            } else if (containerCodeQty.compareTo(qty) == 0) {
                resultMap.put(containerCode, "AGVTP01-C01");
            } else {
                // 非整托
                resultMap.put(containerCode, "AGVTP01-C02");
            }
        }
        return resultMap;
    }

    /**
     * 保存拣选任务
     *
     * @param list 组包集合
     */
    @Transactional(rollbackFor = Exception.class)
    public void createPickTask(List<List<WaveStorageDTO>> list) {

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

        String[] billIds = list.stream().flatMap(Collection::stream).map(WaveStorageDTO::getBillId).distinct().toArray(String[]::new);
        String[] billDIds = list.stream().flatMap(Collection::stream).map(WaveStorageDTO::getBillDId).distinct().toArray(String[]::new);
        String[] storageIds = list.stream().flatMap(Collection::stream).map(WaveStorageDTO::getId).distinct().toArray(String[]::new);

        List<WaveBillDO> waveBillDO = billMapper.findByIds(WaveBillDO.class, billIds, null);
        List<WaveBillDDO> waveBillDDO = billDMapper.findByIds(WaveBillDDO.class, billDIds, null);
        List<MoveTaskDO> moveTasks = moveTaskMapper.getDetailIdByBillDIds(billDIds);

        Date date = new Date();
        List<PickTaskH> pickTaskHList = new ArrayList<>();
        List<PickTaskD> pickTaskDList = new ArrayList<>();
//        List<BarcodeHDO> barcodeHList = new ArrayList<>();
//        List<BarCodeDDO> barcodeDList = new ArrayList<>();
        // 循环所有装好的容器，生成拣选任务
        for (List<WaveStorageDTO> waveStorageLists : list) {
            Integer pickTaskType = getPickTaskType(waveStorageLists);
            BigDecimal volumeTotal = BigDecimal.ZERO;
            String pickTaskId = String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId));
            boolean replenishFlag = false;
            BigDecimal pcs = BigDecimal.ZERO;
            BigDecimal pcsTotal = getPcsTotal(waveStorageLists);

            // 循环库存预占,任务行
            for (WaveStorageDTO waveStorage : waveStorageLists) {
                volumeTotal = volumeTotal.add(waveStorage.getVolume());
                PickTaskD pickTaskD = new PickTaskD();
                pickTaskD.setPickTaskDId(String.valueOf(SnowFlakeUtils.getId(dataCenterId, machineId)));
                pickTaskD.setPickTaskId(pickTaskId);
                pickTaskD.setWaveStorageId(waveStorage.getId());
                pickTaskD.setWarehouseId(waveStorage.getWarehouseId());
                pickTaskD.setQty(waveStorage.getQty());
                pickTaskD.setEnterpriseId(waveStorage.getEnterpriseId());
                pickTaskD.setGmtCreate(date);
                pickTaskD.setPrintCount(0);
                pickTaskD.setFlowStatus("0");
                pickTaskD.setPickTaskType(Integer.valueOf(waveStorage.getWarehouseLocatorType()));
                if (waveStorage.getWarehouseLocatorType().equals("0")) {
                    pcs = pcs.add(pickTaskD.getQty().divide(waveStorage.getCaseConversionRate(), 0, RoundingMode.DOWN));
                    pickTaskD.setWholeNum(String.format("%s/%s", pcs, pcsTotal));
                }
                // 零货拣货明细冗余补货明细字段
                if (pickTaskD.getPickTaskType() == 1 || pickTaskD.getPickTaskType() == 2) {
                    //查询预占对应的补货单信息
                    MoveTaskDO moveTask = moveTasks.stream().filter(mt -> mt.getBillDId().equals(waveStorage.getBillDId())).findFirst().orElse(null);
                    if (moveTask != null) {
                        log.info("pickTaskD对应补货单信息:{}", JSONObject.toJSONString(moveTask));
                        pickTaskD.setDetailId(moveTask.getDetailId());
                        replenishFlag = true;
                    }
                }
                waveBillDO.stream().filter(h -> h.getId().equals(waveStorage.getBillId())).findFirst().ifPresent(h -> {
                    pickTaskD.setSrcId(h.getSrcId());
                    pickTaskD.setSrcCode(h.getSrcCode());
                });
                waveBillDDO.stream().filter(d -> d.getId().equals(waveStorage.getBillDId())).findFirst().ifPresent(d -> {
                    pickTaskD.setSrcLineId(d.getSrcLineId());
                });
                pickTaskD.setBillId(waveStorage.getBillId());
                pickTaskD.setBillDId(waveStorage.getBillDId());
                pickTaskD.setItemId(waveStorage.getItemId());
                pickTaskD.setBatchId(waveStorage.getBatchId());
                pickTaskD.setLocatorId(waveStorage.getWarehouseLocatorId());
                pickTaskD.setWarehouseAreaCode(waveStorage.getWarehouseAreaCode());
                pickTaskD.setPickModel(waveStorage.getPickModel());
                pickTaskDList.add(pickTaskD);

//                if (pickTaskType == 1) {
//                    BarcodeHDO barCodeHDO = wrapBarcodeHDO(waveStorage, pickTaskD, date);
//                    barcodeHList.add(barCodeHDO);
//
//                    BarCodeDDO barCodeDDO = wrapBarCodeDDO(waveStorage, barCodeHDO, date, pickTaskD);
//                    barcodeDList.add(barCodeDDO);
//                }
            }
            PickTaskH h = wrapPickTaskH(waveStorageLists, pickTaskId, pickTaskType, date, replenishFlag);
            pickTaskHList.add(h);
        }

        persistence(pickTaskHList, pickTaskDList, null, null, storageIds);
    }

    private static BarCodeDDO wrapBarCodeDDO(WaveStorageDTO waveStorage, BarcodeHDO barCodeHDO, Date date, PickTaskD pickTaskD) {
        BarCodeDDO barCodeDDO = new BarCodeDDO();
        barCodeDDO.setId(String.valueOf(SnowFlakeUtils.getId()));
        barCodeDDO.setBarcodeId(barCodeHDO.getId());
        barCodeDDO.setIsPiece(1);
        barCodeDDO.setGmtCreate(date);
        barCodeDDO.setGmtModified(date);
        barCodeDDO.setWmsPickTaskDId(pickTaskD.getPickTaskDId());
        barCodeDDO.setEnterpriseId(waveStorage.getEnterpriseId());
        barCodeDDO.setWarehouseId(waveStorage.getWarehouseId());
        barCodeDDO.setQty(pickTaskD.getQty());
        barCodeDDO.setItemId(waveStorage.getItemId());
        return barCodeDDO;
    }

    private BarcodeHDO wrapBarcodeHDO(WaveStorageDTO waveStorage, Date date) {
        BarcodeHDO barCodeHDO = new BarcodeHDO();
        barCodeHDO.setId(String.valueOf(SnowFlakeUtils.getId()));
        barCodeHDO.setType("0");
//        String barcode = BillUtils.getBarcode(redisTemplate);
//        barCodeHDO.setBarcode(barcode);
        //barcode留给EIS面单申请时生成
        barCodeHDO.setLclNo(1);
        barCodeHDO.setBillGroupId(waveStorage.getMergedBillId());
        barCodeHDO.setStatus('0');
        barCodeHDO.setEnterpriseId(waveStorage.getEnterpriseId());
        barCodeHDO.setWarehouseId(waveStorage.getWarehouseId());
        barCodeHDO.setBldgId(waveStorage.getBldgId());
        barCodeHDO.setBldgName(waveStorage.getBldgName());
        barCodeHDO.setGmtCreate(date);
        barCodeHDO.setGmtModified(date);
        barCodeHDO.setCheckStatus("0");
        //2024.1.9与张剑、杨波同步零货只生成面单
        barCodeHDO.setBarcodeType("1");
//                    barCodeHDO.setStationCode(stationCode);
        return barCodeHDO;
    }

    private static PickTaskH wrapPickTaskH(List<WaveStorageDTO> waveStorageLists, String pickTaskId, Integer pickTaskType, Date date, boolean replenishFlag) {
        WaveStorageDTO vo = waveStorageLists.get(0);
        PickTaskH h = new PickTaskH();
        h.setPickTaskId(pickTaskId);
        // 任务类型（0-整件/1-散件/2-整散合一/3-整单）
        h.setPickTaskType(pickTaskType);
        h.setEnterpriseId(vo.getEnterpriseId());
        h.setWarehouseId(vo.getWarehouseId());
        h.setPriority(vo.getPriority());
        h.setIsMerged(vo.getIsMerged());
        h.setWaveId(vo.getWaveId());
        h.setStatus("0");
        h.setWarehouseAreaCode(vo.getWarehouseAreaCode());
        h.setBldgId(vo.getBldgId());
        h.setBldgName(vo.getBldgName());
        h.setType(vo.getType());
        h.setBillGroupId(vo.getMergedBillId());
        h.setBillId(vo.getBillId());
        h.setGmtCreate(date);
        h.setGmtModified(date);
        if (replenishFlag) {
            h.setStatus("-1");
        }
        return h;
    }

    private void persistence(List<PickTaskH> pickTaskHList, List<PickTaskD> pickTaskDList, List<BarcodeHDO> barcodeHList, List<BarCodeDDO> barcodeDList, String[] storageIds) {
        if (CollUtil.isNotEmpty(pickTaskHList)) {
            List<List<PickTaskH>> partition = com.google.common.collect.Lists.partition(pickTaskHList, 300);
            partition.forEach(pickTaskHMapper::saveBatch);
        }

        if (CollUtil.isNotEmpty(pickTaskDList)) {
            List<List<PickTaskD>> partition = com.google.common.collect.Lists.partition(pickTaskDList, 300);
            partition.forEach(pickTaskDMapper::saveBatch);
        }

        if (CollUtil.isNotEmpty(barcodeHList)) {
            List<List<BarcodeHDO>> partition = com.google.common.collect.Lists.partition(barcodeHList, 300);
            partition.forEach(barcodeHMapper::saveBatch);
        }

        if (CollUtil.isNotEmpty(barcodeDList)) {
            List<List<BarCodeDDO>> partition = com.google.common.collect.Lists.partition(barcodeDList, 300);
            partition.forEach(barcodeDMapper::saveBatch);
        }

        // 更新库存预占状态
        Criteria criteria = new Criteria(WaveStorageDO.class);
        criteria.setRestriction(Restrictions.in("id", storageIds));
        waveStorageMapper.updateMapByCriteria(MapUtils.put("status", "1").getMap(), criteria);
    }

    private BigDecimal getPcsTotal(List<WaveStorageDTO> waveStorageLists) {
        BigDecimal pcsTotal = BigDecimal.ZERO;
        for (WaveStorageDTO waveStorage : waveStorageLists) {
            if (("0").equals(waveStorage.getWarehouseLocatorType())) {
                pcsTotal = pcsTotal.add(waveStorage.getQty().divide(waveStorage.getCaseConversionRate(), 0, RoundingMode.DOWN));
            }
        }
        return pcsTotal;
    }

    private Integer getPickTaskType(List<WaveStorageDTO> waveStorageLists) {
        Integer pickTaskType = null;
        if (waveStorageLists.get(0).getPickType() != null) {
            pickTaskType = waveStorageLists.get(0).getPickType();
        } else {
            pickTaskType = Integer.valueOf(waveStorageLists.get(0).getWarehouseLocatorType());
        }
        return pickTaskType;
    }

}
