package com.prolog.upcloud.base.wh.operate.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.codingapi.tx.annotation.TxTransaction;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.pagehelper.PageHelper;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import com.prolog.cs.basic.chain.model.cargo.BaseCargoOwnerMst;
import com.prolog.cs.basic.common.model.BaseCommonDict;
import com.prolog.cs.basic.item.model.BaseMtlItemMst;
import com.prolog.cs.basic.item.model.BaseMtlManufacturer;
import com.prolog.cs.basic.item.model.vo.ItemMstQueryVO;
import com.prolog.cs.basic.item.model.vo.ItemMstVO2;
import com.prolog.cs.basic.warehouse.model.BaseWmsWarehouseMst;
import com.prolog.cs.basic.warehouse.model.vo.WarehouseLocatorBasicInfo;
import com.prolog.cs.data.exchange.client.ExchangeSender;
import com.prolog.cs.data.exchange.client.core.EtlMessage;
import com.prolog.cs.data.exchange.client.core.EtlTypeConstants;
import com.prolog.entity.vo.CompleteTaskItemVO;
import com.prolog.entity.vo.InventoryAuditVO;
import com.prolog.enums.InventoryAuditEnum;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.authority.user.UserTemplate;
import com.prolog.framework.beans.BeanUtils;
import com.prolog.framework.bz.common.search.SearchApi;
import com.prolog.framework.bz.core.collection.ValidList;
import com.prolog.framework.bz.core.model.ModelUtils;
import com.prolog.framework.bz.core.util.ObjectUtils;
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.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.framework.utils.AssertUtils;
import com.prolog.framework.utils.JsonUtils;
import com.prolog.framework.utils.MapUtils;
import com.prolog.framework.utils.SnowFlakeUtils;
import com.prolog.inte.EisHandler;
import com.prolog.upcloud.base.inventory.vo.*;
import com.prolog.upcloud.base.wh.operate.constant.MsgTemplate;
import com.prolog.upcloud.base.wh.operate.core.RestMsgHelper;
import com.prolog.upcloud.base.wh.operate.dao.*;
import com.prolog.upcloud.base.wh.operate.model.*;
import com.prolog.upcloud.base.wh.operate.resource.*;
import com.prolog.upcloud.base.wh.operate.service.AdjustService;
import com.prolog.upcloud.base.wh.operate.utils.DateUtils;
import com.prolog.upcloud.base.wh.operate.utils.StringUtils;
import com.prolog.upcloud.base.wh.operate.vo.*;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static com.prolog.upcloud.base.wh.operate.constant.BizTemplate.QUALITY_CONTROL_AUDIT;
import static com.prolog.upcloud.base.wh.operate.constant.WhOperataConstant.PICK_MODE_DEVICE;

/**
 * @author zzz
 * @desc 损溢
 * @date 2021/4/7
 */
@Service
public class AdjustServiceImpl implements AdjustService {

    @Autowired
    private WmsAdjustHMapper adjustHMapper;

    @Autowired
    private WmsAdjustDMapper adjustDMapper;

    @Autowired
    private WmsInvCheckHMapper invCheckHMapper;

    @Autowired
    private WmsInvCheckDMapper invCheckDMapper;

    @Autowired
    private ItemResource itemResource;

    @Autowired
    private StockResource stockResource;

    @Autowired
    private UserTemplate userTemplate;

    @Autowired
    private WarehouseClient warehouseResource;

    @Autowired
    private ChainResource chainResource;

    @Autowired
    private ExchangeSender exchangeSender;

    @Resource
    private OmsInventoryOrderMapper omsInventoryOrderMapper;

    @Resource
    private OmsInventoryAuditMapper omsInventoryAuditMapper;

    @Resource
    private OmsInventoryResultMapper omsInventoryResultMapper;

    @Autowired
    WmsInvCheckDReMapper invCheckDReMapper;

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

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

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

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

    @Autowired
    private SearchApi searchApi;

    @Value("${prolog.integration.zftFlag:false}")
    private Boolean zftFlag;

    private Executor executor = Executors.newFixedThreadPool(10);

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

    private SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
    private SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMM");

    @Resource
    private CommonResource commonResource;
    @Resource
    private EisHandler eisHandler;

    /**
     * 损溢新增
     *
     * @param wmsAdjustAddVO
     */
    @Override
    @Transactional
    @TxTransaction(isStart = true)
    public void saveAdjust(WmsAdjustAddVO wmsAdjustAddVO) {
        String cargoOwnerId = wmsAdjustAddVO.getCargoOwnerId();
        if (StringUtils.isEmpty(cargoOwnerId))
            throw new ParameterException("货主id不能为空！");
        if (StringUtils.isEmpty(wmsAdjustAddVO.getWarehouseId()))
            throw new ParameterException("仓库id不能为空！");
        if (StringUtils.isEmpty(wmsAdjustAddVO.getDcId())) {
            try {
                RestMessage<BaseWmsWarehouseMst> byId = warehouseResource.getById(wmsAdjustAddVO.getWarehouseId());
                BaseWmsWarehouseMst data = byId.getData();
                if (!ObjectUtils.isNull(data)) {
                    String dcId = data.getDcId();
                    wmsAdjustAddVO.setDcId(dcId);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        Integer type = wmsAdjustAddVO.getType();
        if (type == null) {
            type = 1;
        }
        UserDTO userDTO = userTemplate.getUserDTO();

        String stockStatus = wmsAdjustAddVO.getStockStatus();
        if (StringUtils.isBlank(stockStatus)) {
            stockStatus = "1"; // 正常
        }
        Integer isHost = wmsAdjustAddVO.getIsHost();
        if (isHost != null && isHost == 1) {
            stockStatus = "5"; // 代管
        }
        wmsAdjustAddVO.setStockStatus(stockStatus);

        if (type == 0) {
            // 调整批号
            String manufacturerLotNumPre = wmsAdjustAddVO.getManufacturerLotNumPre();
            String manufacturerLotNum = wmsAdjustAddVO.getManufacturerLotNum();
            String batchIdNew = wmsAdjustAddVO.getBatchIdNew();
            String batchId = wmsAdjustAddVO.getBatchId();
            if (StringUtils.isEmpty(batchIdNew) || StringUtils.isEmpty(batchId)) {
                throw new ParameterException("新老批次id不可为空!");
            }
            if (batchIdNew.equals(batchId)) {
                // 批次id相同没有调整
                return;
            }
            if (StringUtils.isEmpty(manufacturerLotNumPre) || StringUtils.isEmpty(manufacturerLotNum)) {
                throw new ParameterException("新老批号不可为空!");
            }
            if (manufacturerLotNum.equals(manufacturerLotNumPre)) {
                // 批号相同没有调整
                return;
            }
            // 生成两次调整损溢单
            excuteAddAdjust(type, wmsAdjustAddVO, userDTO);

            // 远程调用修改批号(影响出入库批号,是否回传erp?)
            //          InvStockBatchNumberUpdate lotUp = new InvStockBatchNumberUpdate();
            //          lotUp.setBatchId(batchId);
            //          lotUp.setManufacturerLotNum(manufacturerLotNum);
            //          ValidList<InvStockBatchNumberUpdate> listUp = new ValidList<>();
            //          listUp.add(lotUp);
            //          stockResource.updateBatchNumber(listUp);
        }
        if (type == 1) {
            // 调整数量
            BigDecimal pieceAccount = wmsAdjustAddVO.getPieceAccount();
            BigDecimal pieceAccountFact = wmsAdjustAddVO.getPieceAccountFact();
            if (pieceAccount == null || pieceAccountFact == null) {
                throw new ParameterException("盘前盘后数量不可为空");
            }
            Integer isAdd = wmsAdjustAddVO.getIsAdd();
            // 根据批次查找库存数量
            if (isAdd != null && isAdd == 1) {
                String batchId = wmsAdjustAddVO.getBatchId();
                String whLocatorId = wmsAdjustAddVO.getWhLocatorId();
                String warehouseId = wmsAdjustAddVO.getWarehouseId();
                WmsInvStockQtyQueryVO stockQuery = new WmsInvStockQtyQueryVO();
                stockQuery.setBatchId(batchId);
                stockQuery.setWarehouseId(warehouseId);
                stockQuery.setCargoOwnerId(cargoOwnerId);
                stockQuery.setEnterpriseId(userDTO.getEnterpriseId());
                stockQuery.setLocatorId(whLocatorId);
                stockQuery.setStatus(stockStatus); // 看是否只筛选为合格的
                stockQuery.setSubStatus("1");
                // 调用远程库存服务看是否有库存信息,有就算出差异数,无就是新增库存信息
                RestMessage<List<WmsInvStockQtyVO>> availableQuantity2 = stockResource.getAvailableQuantity(BeanUtil.beanToMap(stockQuery));
                if (availableQuantity2 != null && availableQuantity2.isSuccess() && !ObjectUtils.isEmpty(availableQuantity2.getData())) {
                    List<WmsInvStockQtyVO> data = availableQuantity2.getData();
                    for (WmsInvStockQtyVO wmsInvStockQtyVO : data) {
                        BigDecimal quantity = wmsInvStockQtyVO.getQuantity();
                        if (quantity == null) {
                            quantity = BigDecimal.ZERO;
                        }
                        if (quantity.compareTo(BigDecimal.ZERO) == 1) {
                            // 说明有库存数据,抛出错误
                            throw new BizException("保存无计划损溢(无账存商品)失败,此批次商品已有库存信息,请根据货位或商品查询,然后进行无计划损溢修改操作!");
                        }
                    }
                }

            }

            BigDecimal pieceQuantity = pieceAccountFact.subtract(pieceAccount);
            wmsAdjustAddVO.setPieceQuantity(pieceQuantity);
            if (pieceQuantity.compareTo(BigDecimal.ZERO) == 0) {
                // 数量没有调整
                return;
            }
            // 生成损益单
            excuteAddAdjust(type, wmsAdjustAddVO, userDTO);
        }

    }

    private void excuteAddAdjust(Integer type, WmsAdjustAddVO wmsAdjustAddVO, UserDTO userDTO) {
        Integer isHost = wmsAdjustAddVO.getIsHost();
        if (isHost != null && isHost == 1) {
            // 无需审核,生成result数据,直接增减库存
        }
        Date date = new Date();
        String userId = userDTO.getId();
        String userName = userDTO.getNickname();
        String enterpriseId = userDTO.getEnterpriseId();
        WmsAdjustH wmsAdjustH = new WmsAdjustH();
        String adjustHeaderId = String.valueOf(SnowFlakeUtils.getId());// 主表id
        wmsAdjustH.setAdjustHeaderId(adjustHeaderId);
        wmsAdjustH.setAutoBillNum(adjustHeaderId);
        wmsAdjustH.setAccessLevel("9");
        wmsAdjustH.setWarehouseId(wmsAdjustAddVO.getWarehouseId());
        wmsAdjustH.setDcId(wmsAdjustAddVO.getDcId());
        wmsAdjustH.setCargoOwnerId(wmsAdjustAddVO.getCargoOwnerId());
        wmsAdjustH.setAdjustDate(date);
        wmsAdjustH.setEnterpriseId(enterpriseId);
        if (isHost != null && isHost == 1) {
            wmsAdjustH.setStatus("COMFIRM");
        } else {
            wmsAdjustH.setStatus("NEW");
        }
        wmsAdjustH.setCreator(userId);
        wmsAdjustH.setCreatorName(userName);
        wmsAdjustH.setGmtCreate(date);
        wmsAdjustH.setModifier(userId);
        wmsAdjustH.setModifierName(userName);
        wmsAdjustH.setGmtModified(date);
        wmsAdjustH.setAdjustType(wmsAdjustAddVO.getAdjustType());
        wmsAdjustH.setAttribute5("1");
        adjustHMapper.save(wmsAdjustH);

        WmsAdjustD model = new WmsAdjustD();
        BeanUtils.copyProperties(wmsAdjustAddVO, model);
        String stockStatus = wmsAdjustAddVO.getStockStatus();
        if (StringUtils.isEmpty(stockStatus)) {
            model.setStockStatus("1");
        }
        model.setLineNum(1L);
        model.setCreator(userId);
        model.setCreatorName(userName);
        model.setGmtCreate(date);
        model.setModifier(userId);
        model.setModifierName(userName);
        model.setGmtModified(date);
        model.setCargoOwnerId(wmsAdjustAddVO.getCargoOwnerId());
        model.setAdjustHeaderId(adjustHeaderId);
        model.setBatchId(stockStatus);
        // 加入时间
        //      model.setPieceQuantity(wmsAdjustAddVO.getQuantity().multiply(wmsAdjustAddVO.getQuantity()));
        if (isHost != null && isHost == 1) {
            model.setStatus("50");
        } else {
            model.setStatus("0");
        }
        model.setBatchId(wmsAdjustAddVO.getBatchId());
        model.setBatchNum(wmsAdjustAddVO.getBatchNum());
        model.setPieceQuantity(wmsAdjustAddVO.getPieceAccountFact().subtract(wmsAdjustAddVO.getPieceAccount())); // 差异数

        BigDecimal zero = BigDecimal.ZERO;
        List<InvStockAdjust> invStockList = new ArrayList<>();
        List<WmsAdjustD> adjustDList = new ArrayList<>();
        if (0 == type) {
            // 批次调整,损老批号
            BigDecimal pieceAccount = model.getPieceAccount(); // 账存数
            model.setPieceAccountFact(zero); // 盘点数
            model.setPieceQuantity(zero.subtract(pieceAccount)); // 差异数

            // 溢新批号
            WmsAdjustD model2 = new WmsAdjustD();
            BeanUtils.copyProperties(model, model2);
            model2.setAdjustLineId(null);
            model2.setLineNum(2L);
            model2.setBatchId(wmsAdjustAddVO.getBatchIdNew());
            model2.setBatchNum(wmsAdjustAddVO.getBatchNumNew());
            model2.setPieceAccountFact(pieceAccount);
            model2.setPieceAccount(zero);
            model2.setPieceQuantity(pieceAccount.subtract(zero)); // 差异数
            model2.setQuantity(model2.getPieceQuantity());
            model2.setEnterpriseId(enterpriseId);
            model2.setLineNum(2L);
            if (isHost != null && isHost == 1) {
                model2.setStatus("50");
            }
            adjustDMapper.save(model2);
            excutePreStock(invStockList, wmsAdjustH, model2);
            model2.setIsHost(isHost);
            adjustDList.add(model2);
        }
        model.setQuantity(model.getPieceQuantity());
        model.setEnterpriseId(enterpriseId);
        adjustDMapper.save(model);
        excutePreStock(invStockList, wmsAdjustH, model);
        adjustDList.add(model);

        if (isHost != null && isHost == 1) {
            // 直接增减库存
            RestMessage adjustStock = stockResource.adjustStockComfirm(invStockList);
            if (adjustStock != null && !adjustStock.isSuccess()) {
                throw new BizException("调用库存损溢增减失败!原因->" + adjustStock.getMessage());
            }
            // 组装数据result回传erp
            Date now = new Date();
            // 库存损溢成功,构造RESULT结果，回传ERP
            excuteCallback2Result(adjustDList, userDTO, now, "10");

        } else {
            // 库存预占
            RestMessage adjustStock = stockResource.adjustStock(invStockList);
            if (adjustStock != null && !adjustStock.isSuccess()) {
                throw new BizException("调用库存预占失败!原因->" + adjustStock.getMessage());
            }
        }
    }

    private void excuteCallback2Result(List<WmsAdjustD> adjustDList, UserDTO userDTO, Date now, String status) {
        List<OmsInventoryResult> resultList = new ArrayList<>();
        List<OmsInventoryResultVO> resultListVO = new ArrayList<>();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMM");
        // 远程获取商品数据
        Set<String> itemidSet = adjustDList.stream().filter(p -> StringUtils.isNotEmpty(p.getItemId())).map(WmsAdjustD::getItemId).collect(Collectors.toSet());
        ItemMstQueryVO itemQuery = new ItemMstQueryVO();
        itemQuery.setItemIds(itemidSet);
        RestMessage<List<ItemMstVO2>> listByRelated = itemResource.listByRelated(itemQuery);
        if (!listByRelated.isSuccess() || listByRelated.getData() == null) {
            throw new BizException("查询商品关联信息失败!请重试或联系管理员!");
        }
        List<ItemMstVO2> itemList = listByRelated.getData();
        Map<String, List<ItemMstVO2>> itemMap = Optional.of(itemList).orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(ItemMstVO2::getItemId));
        // 远程获取仓库数据
        Set<String> locatorId = adjustDList.stream().filter(p -> StringUtils.isNotEmpty(p.getWhLocatorId())).map(WmsAdjustD::getWhLocatorId).collect(Collectors.toSet());
        RestMessage<List<WarehouseLocatorBasicInfo>> locationBasicInfos = warehouseResource.getLocationBasicInfos(locatorId.toArray(new String[locatorId.size()]));
        if (!locationBasicInfos.isSuccess() || locationBasicInfos.getData() == null) {
            throw new BizException("查询货位关联信息失败!请重试或联系管理员!");
        }
        List<WarehouseLocatorBasicInfo> locatorData = locationBasicInfos.getData();
        Map<String, List<WarehouseLocatorBasicInfo>> locatorMap = Optional.of(locatorData).orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(WarehouseLocatorBasicInfo::getWarehouseLocatorId));
        // 远程获取货主数据
        Set<String> cargoOwnerId = adjustDList.stream().filter(p -> StringUtils.isNotEmpty(p.getCargoOwnerId())).map(WmsAdjustD::getCargoOwnerId).collect(Collectors.toSet());
        RestMessage<Map<String, BaseCargoOwnerMst>> cargoOwner = chainResource.getCargoOwerByIds(cargoOwnerId);
        if (!cargoOwner.isSuccess() || cargoOwner.getData() == null) {
            throw new BizException("查询货主关联信息失败!请重试或联系管理员!");
        }
        Map<String, BaseCargoOwnerMst> cargoOwnerMap = cargoOwner.getData();
        // 远程获取批次信息数据
        Set<String> batchId = adjustDList.stream().filter(p -> StringUtils.isNotEmpty(p.getBatchId())).map(WmsAdjustD::getBatchId).collect(Collectors.toSet());
        RestMessage<List<BatchNumberListVO>> batchNumberBasicInfo = stockResource.getBatchNumberBasicInfo(batchId.toArray(new String[batchId.size()]));
        if (!batchNumberBasicInfo.isSuccess() || batchNumberBasicInfo.getData() == null) {
            throw new BizException("查询批次关联信息失败!请重试或联系管理员!");
        }
        List<BatchNumberListVO> batchNumberData = batchNumberBasicInfo.getData();
        Map<String, List<BatchNumberListVO>> batchNumberMap = Optional.of(batchNumberData).orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(BatchNumberListVO::getBatchId));
        int count = 0;
        BigDecimal zero = BigDecimal.ZERO;
        for (WmsAdjustD wmsAdjustD : adjustDList) {
            count++;
            OmsInventoryResult result = new OmsInventoryResult();
            BeanUtils.copyProperties(wmsAdjustD, result);
            result.setBillid(wmsAdjustD.getAdjustHeaderId());
            //          result.setBillid(wmsAdjustD.getAdjustLineId());
            result.setSeqno(String.valueOf(count));
            BigDecimal pieceQuantity = wmsAdjustD.getPieceQuantity();
            if (pieceQuantity == null) {
                pieceQuantity = zero;
            }
            if (pieceQuantity.compareTo(zero) == -1) {
                // < 0 为损
                result.setType("1"); // 报损单
            } else {
                result.setType("2");
            }
            result.setAmount(wmsAdjustD.getPieceQuantity().abs());
            result.setBilldate(now);
            // 设置批次相关数据
            String batchId2 = wmsAdjustD.getBatchId();
            if (StringUtils.isNotEmpty(batchNumberMap)) {
                List<BatchNumberListVO> list = batchNumberMap.get(batchId2);
                if (StringUtils.isNotEmpty(list) && null != list.get(0)) {
                    BatchNumberListVO batchNumberListVO = list.get(0);
                    result.setAttrStr2(batchNumberListVO.getBatchProductionDateShow()); // 显示生产日期
                    result.setAttrStr3(batchNumberListVO.getBatchExpiredDateShow()); // 显示有效期至
                    result.setBatchNum(batchNumberListVO.getManufacturerLotNum()); // 批号
                }
            }
            // 设置仓库相关数据
            String whLocatorId = wmsAdjustD.getWhLocatorId();
            if (StringUtils.isNotEmpty(locatorMap)) {
                List<WarehouseLocatorBasicInfo> list = locatorMap.get(whLocatorId);
                if (StringUtils.isNotEmpty(list) && null != list.get(0)) {
                    WarehouseLocatorBasicInfo warehouseLocatorBasicInfo = list.get(0);
                    result.setBranchid(warehouseLocatorBasicInfo.getWarehouseId()); // 仓库id
                    result.setBranchname(warehouseLocatorBasicInfo.getWarehouseName()); // 仓库名称
                    result.setBranchcode(warehouseLocatorBasicInfo.getWarehouseCode());
                    // 还需要建筑物
                    String bldgName = warehouseLocatorBasicInfo.getBldgName();
                    result.setBuilding(bldgName);
                    // 设置库别
                    result.setAttrStr1(warehouseLocatorBasicInfo.getWarehouseAreaCategory());
                }
            }
            // 设置货主相关
            String cargoOwnerId2 = wmsAdjustD.getCargoOwnerId();
            String consignorcode = "";
            if (StringUtils.isNotEmpty(cargoOwnerMap)) {
                BaseCargoOwnerMst baseCargoOwnerMst = cargoOwnerMap.get(cargoOwnerId2);
                if (baseCargoOwnerMst != null) {
                    result.setConsignorid(cargoOwnerId2);
                    result.setConsignorname(baseCargoOwnerMst.getCargoOwnerName());
                    consignorcode = baseCargoOwnerMst.getCargoOwnerCode();
                }
            }
            // 设置商品相关
            String itemId = wmsAdjustD.getItemId();
            if (StringUtils.isNotEmpty(itemMap)) {
                List<ItemMstVO2> list = itemMap.get(itemId);
                if (StringUtils.isNotEmpty(list) && null != list.get(0)) {
                    ItemMstVO2 itemMstVO2 = list.get(0);
                    result.setItemid(itemId);
                    result.setItemcode(itemMstVO2.getItemCode());
                    result.setItemname(itemMstVO2.getItemName());
                    result.setApprovalNumber(itemMstVO2.getItemHealthApprovalNbr());
                    result.setPrice(itemMstVO2.getPiecePurchasePriceTi());
                    result.setSpec(itemMstVO2.getSpecification());
                    result.setPlace(itemMstVO2.getCountryOriginId());
                    result.setManufacturer(itemMstVO2.getManufacturerId());
                }
            }
            result.setLineid(wmsAdjustD.getAdjustLineId());
            BigDecimal price = result.getPrice();
            if (price != null) {
                result.setTotalPrice(price.multiply(wmsAdjustD.getPieceQuantity().abs()));
            }
            result.setPackUnit(wmsAdjustD.getUom());
            result.setPackAmount(wmsAdjustD.getConversionRate());
            result.setStockstatus(wmsAdjustD.getStockStatus());
            result.setEnterpriseid(userDTO.getEnterpriseId());
            result.setEnterprisename(userDTO.getEnterpriseName());
            result.setStatus(status);
            result.setCreatedate(now);
            result.setCreateby(userDTO.getNickname());
            result.setLastmodifydate(now);
            result.setLastmodifyby(userDTO.getNickname());
            Date productionDate = result.getProductionDate();
            Date expiredDate = result.getExpiredDate();
            if (productionDate == null) {
                Date productionDate2 = new Date();
                String attrStr2 = result.getAttrStr2();
                if (!StringUtils.isEmpty(attrStr2)) {
                    if (attrStr2.length() == 6) {
                        try {
                            productionDate2 = sdf2.parse(attrStr2);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                    if (attrStr2.length() == 8) {
                        try {
                            productionDate2 = sdf1.parse(attrStr2);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }
                result.setProductionDate(productionDate2);
            }
            if (expiredDate == null) {
                Date expiredDate2 = new Date();
                String attrStr3 = result.getAttrStr3();
                if (!StringUtils.isEmpty(attrStr3)) {
                    if (attrStr3.length() == 6) {
                        try {
                            expiredDate2 = sdf2.parse(attrStr3);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                    if (attrStr3.length() == 8) {
                        try {
                            expiredDate2 = sdf1.parse(attrStr3);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }
                result.setExpiredDate(expiredDate2);
            }
            String reason = result.getReason();
            if (StringUtils.isEmpty(reason)) {
                result.setReason("N/A");
            }
            // 单据编号取检查头表的headerId,若为空，则取billId
            if (!StringUtils.isEmpty(wmsAdjustD.getSrcBillHId())) {
                result.setBillno(wmsAdjustD.getSrcBillHId());
            }
            if (StringUtils.isEmpty(result.getBillno())) {
                result.setBillno(result.getBillid());
            }
            result.setDatasource("1");
            result.setAttrStr5("N"); // 用来判断 是否上传后期会修改为Y,龚昑添加

            Integer isHost = wmsAdjustD.getIsHost();
            if (isHost != null && isHost == 1) {
                // 无需审核,生成result数据,直接增减库存
                result.setAttrStr5("N"); // 是否回传erp
            }

            resultList.add(result);

            //回传OMS 通过接口平台
            OmsInventoryResultVO resultVO = new OmsInventoryResultVO();
            resultVO.setBillno(result.getBillno());
            resultVO.setBilldate(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", result.getBilldate()));
            resultVO.setInventoryby(wmsAdjustD.getModifierName());
            resultVO.setSeqNo(result.getSeqno());
            resultVO.setItemcode(result.getItemcode());
            resultVO.setCausticQty(result.getAmount());
            resultVO.setCausticReason(result.getReason());
            resultVO.setLotNo(result.getBatchNum());
            resultVO.setPdateFrom(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", result.getProductionDate()));
            resultVO.setValidUntil(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", result.getExpiredDate()));
            resultVO.setCausticType(result.getType());
            resultVO.setQty(BigDecimal.ZERO);
            resultVO.setConsignorcode(consignorcode);
            resultVO.setBranchcode(result.getBranchcode());
            resultVO.setPenterpriseid(result.getEnterpriseid());
            resultVO.setItemid(result.getItemid());
            resultListVO.add(resultVO);
        }

        omsInventoryResultMapper.saveBatch(resultList);
        logger.info("omsResult=====>" + JSON.toJSONString(resultListVO));
        try {
            if (resultListVO.size() > 0) {
                if (StringUtils.isEmpty(omsInventoryResultUrl)) {
                    throw new BizException("请求路径配置为空");
                }
                logger.info("omsResult=====>" + JSON.toJSONString(resultListVO));
                System.out.println(JSON.toJSONString(resultListVO));
                String url = omsInventoryResultUrl;
                String result = HttpUtil.post(url, JSONObject.toJSONString(resultListVO));
                JSONObject parse = JSONObject.parseObject(result);
                logger.info("omsResultBack=====>" + JSON.toJSONString(parse));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //      Set<String> collect = adjustDList.stream().map(WmsAdjustD::getAdjustLineId).collect(Collectors.toSet());
        Set<String> collect = adjustDList.stream().map(WmsAdjustD::getAdjustHeaderId).collect(Collectors.toSet());
        executor.execute(() -> {
            try {
                Thread.sleep(callSleepTimes);
                asyncResult(collect);
            } catch (Exception e) {
                logger.error("损溢结果回传失败,单id:" + new ArrayList(collect).toString());
            }
        });
    }

    /**
     * 损溢预占库存
     *
     * @param invStockList
     * @param wmsAdjustH
     * @param model
     */
    private void excutePreStock(List<InvStockAdjust> invStockList, WmsAdjustH wmsAdjustH, WmsAdjustD model) {
        InvStockAdjust adjust = new InvStockAdjust();
        adjust.setBillId(wmsAdjustH.getAdjustHeaderId());
        adjust.setLineBillId(model.getAdjustLineId());
        adjust.setWarehouseId(wmsAdjustH.getWarehouseId());

        InvStockAdjustDetail adjustD = new InvStockAdjustDetail();
        adjustD.setBatchId(model.getBatchId());
        adjustD.setComments(model.getComments());
        String containerCode = model.getContainerCode();
        if (StringUtils.isEmpty(containerCode)) {
            containerCode = "N/A";
        }
        adjustD.setContainerCode(containerCode);
        String goodsCaseCode = model.getGoodsCaseCode();
        if (StringUtils.isEmpty(goodsCaseCode)) {
            goodsCaseCode = "N/A";
        }
        adjustD.setGoodsCaseCode(goodsCaseCode);
        adjustD.setLocatorId(model.getWhLocatorId());
        adjustD.setQuantity(model.getPieceQuantity());
        adjustD.setStatus(model.getStockStatus());
        List<InvStockAdjustDetail> adjustDList = new ArrayList<>();
        adjustDList.add(adjustD);
        adjust.setDetails(adjustDList);
        invStockList.add(adjust);
    }

    /**
     * 盘点单转损溢单
     *
     * @param checkLineIds
     */
    @Override
    @Transactional
    @TxTransaction(isStart = true)
    public void saveBatchAdjust(String checkLineIds) {
        if (StringUtils.isEmpty(checkLineIds))
            throw new ParameterException("明细id不能为空！");
        WmsAdjustH wmsAdjustH = new WmsAdjustH();
        List<WmsInvCheckD> invCheckDS = invCheckDMapper.findByIds(WmsInvCheckD.class, checkLineIds.split(","), null);
        if (CollUtil.isEmpty(invCheckDS)) {
            throw new ParameterException("未找到对应盘点明细！");
        }
        Set<String> checkHeaderIds = invCheckDS.stream().map(WmsInvCheckD::getCheckHeaderId).filter(StrUtil::isNotEmpty).collect(Collectors.toSet());
        if (checkHeaderIds.size() > 1) {
            throw new ParameterException("明细属于不同的盘点单！");
        }
        String checkHeadId = new ArrayList<>(checkHeaderIds).get(0);
        WmsInvCheckH wmsInvCheckH = invCheckHMapper.findById(checkHeadId, WmsInvCheckH.class);
        if (wmsInvCheckH == null)
            throw new ParameterException("未找到对应盘点头单！");
        Date date = new Date();
        UserDTO userDTO = userTemplate.getUserDTO();
        String userId;
        String userName;
        String enterpriseId;
        if (null != userDTO) {
            userId = userDTO.getId();
            userName = userDTO.getNickname();
            enterpriseId = userDTO.getEnterpriseId();
        } else {
            userId = wmsInvCheckH.getModifier();
            userName = wmsInvCheckH.getModifierName();
            enterpriseId = wmsInvCheckH.getEnterpriseId();
        }
        String adjustHId = String.valueOf(SnowFlakeUtils.getId());
        wmsAdjustH.setAdjustHeaderId(adjustHId);
        wmsAdjustH.setAutoBillNum(adjustHId);
        wmsAdjustH.setDcId(wmsInvCheckH.getDcId());
        wmsAdjustH.setWarehouseId(wmsInvCheckH.getWarehouseId());
        wmsAdjustH.setCargoOwnerId(wmsInvCheckH.getCargoOwnerId());
        wmsAdjustH.setStatus("NEW");
        wmsAdjustH.setAccessLevel("9");
        wmsAdjustH.setSrcBillHId(wmsInvCheckH.getCheckHeaderId());
        wmsAdjustH.setCreator(userId);
        wmsAdjustH.setCreatorName(userName);
        wmsAdjustH.setGmtCreate(date);
        wmsAdjustH.setAdjustDate(date);
        wmsAdjustH.setModifier(userId);
        wmsAdjustH.setModifierName(userName);
        wmsAdjustH.setGmtModified(date);
        wmsAdjustH.setEnterpriseId(enterpriseId);
        wmsAdjustH.setAdjustType("0");
        wmsAdjustH.setAttribute5("1");
        adjustHMapper.save(wmsAdjustH);
        //商品id集合
        Set<String> itemIds = invCheckDS.stream().map(WmsInvCheckD::getItemId).filter(StrUtil::isNotEmpty).collect(Collectors.toSet());
        Set<String> cargoOwerIds = invCheckDS.stream().map(WmsInvCheckD::getCargoOwnerId).filter(StrUtil::isNotEmpty).collect(Collectors.toSet());
        Set<String> locatorIds = invCheckDS.stream().map(WmsInvCheckD::getWhLocatorId).filter(StrUtil::isNotEmpty).collect(Collectors.toSet());
        RestMessage<List<BaseMtlItemMst>> itemMsg = itemResource.getListByIds(itemIds);
        if (!itemMsg.isSuccess() || CollUtil.isEmpty(itemMsg.getData())) {
            throw new BizException("查询商品信息失败！");
        }
        RestMessage<Map<String, BaseCargoOwnerMst>> cargoMsg = chainResource.getCargoOwerByIds(cargoOwerIds);
        if (!cargoMsg.isSuccess() || CollUtil.isEmpty(cargoMsg.getData())) {
            throw new BizException("查询货主信息失败！");
        }
        RestMessage<List<WarehouseLocatorBasicInfo>> locatorMsg = warehouseResource.getLocationBasicInfos(locatorIds.toArray(new String[]{}));
        if (!locatorMsg.isSuccess() || CollUtil.isEmpty(locatorMsg.getData())) {
            throw new BizException("查询货位信息失败！");
        }
        List<WmsAdjustD> adjustDList = new ArrayList<>();
//        List<InventoryAuditVO> toEisVos = new ArrayList<>();
        long row = 0;
        for (WmsInvCheckD wmsInvCheckD : invCheckDS) {
            row++;
            WarehouseLocatorBasicInfo locatorBasicInfo = locatorMsg.getData().stream().filter(var -> var.getWarehouseLocatorId().equals(wmsInvCheckD.getWhLocatorId())).findFirst().orElse(null);
            if (null == locatorBasicInfo) {
                throw new BizException("获取货位信息失败！");
            }
            WmsAdjustD wmsAdjustD = new WmsAdjustD();
            wmsAdjustD.setAdjustHeaderId(adjustHId);
            wmsAdjustD.setWhLocatorId(wmsInvCheckD.getWhLocatorId());
            wmsAdjustD.setContainerCode(wmsInvCheckD.getContainerCode());
            wmsAdjustD.setGoodsCaseCode(wmsInvCheckD.getGoodsCaseCode());
            wmsAdjustD.setItemId(wmsInvCheckD.getItemId());
            wmsAdjustD.setBatchId(wmsInvCheckD.getBatchId());
            wmsAdjustD.setBatchNum(wmsInvCheckD.getBatchNum());
            wmsAdjustD.setStockStatus(wmsInvCheckD.getStockStatus());
            wmsAdjustD.setLineNum(row);
            BaseMtlItemMst itemMst = itemMsg.getData().stream().filter(var -> var.getItemId().equals(wmsInvCheckD.getItemId())).findFirst().orElse(null);
            if (itemMst == null) {
                throw new RuntimeException("未找到商品信息！");
            }
            wmsAdjustD.setUom(wmsInvCheckD.getUom());
            //              wmsAdjustD.setUom(itemMst.getPieceUom());
            wmsAdjustD.setConversionRate(wmsInvCheckD.getConversionRate());
            //              wmsAdjustD.setConversionRate(itemMst.getPieceConversionRate());
            //              wmsAdjustD.setPieceQuantity(itemMst.getPieceConversionRate().multiply(wmsInvCheckD.getQuantityDiff()));
            //              wmsAdjustD.setPieceQuantity(wmsInvCheckD.getPieceQuantityFact().subtract(wmsInvCheckD.getPieceQuantityAccount()));
            wmsAdjustD.setPieceQuantity(wmsInvCheckD.getQuantityDiff());
            wmsAdjustD.setQuantity(wmsInvCheckD.getQuantityDiff());
            wmsAdjustD.setStatus("0");
            wmsAdjustD.setSrcBillDId(wmsInvCheckD.getCheckLineId());
            wmsAdjustD.setSrcBillHId(wmsInvCheckH.getCheckHeaderId());
            wmsAdjustD.setCreator(userId);
            wmsAdjustD.setCreatorName(userName);
            wmsAdjustD.setGmtCreate(date);
            wmsAdjustD.setModifier(userId);
            wmsAdjustD.setModifierName(userName);
            wmsAdjustD.setGmtModified(date);
            wmsAdjustD.setAdjustDate(date);
            wmsAdjustD.setPieceAccount(wmsInvCheckD.getPieceQuantityAccount());
            wmsAdjustD.setPieceAccountFact(wmsInvCheckD.getPieceQuantityFact());
            wmsAdjustD.setPieceQuantity(wmsInvCheckD.getPieceQuantityFact().subtract(wmsInvCheckD.getPieceQuantityAccount()));
            wmsAdjustD.setQuantity(wmsAdjustD.getPieceQuantity());
            wmsAdjustD.setEnterpriseId(enterpriseId);
            wmsAdjustD.setCargoOwnerId(wmsInvCheckD.getCargoOwnerId());
            adjustDMapper.save(wmsAdjustD);
            adjustDList.add(wmsAdjustD);
            // 无差异的盘点审核信息调整到质管审核通过后推送
//            if (locatorBasicInfo.getWarehouseAreaCategory().equals("AGVZ") || locatorBasicInfo.getWarehouseAreaCategory().equals("MJK")
//                    || locatorBasicInfo.getWarehouseAreaCategory().equals("AGVSP") || locatorBasicInfo.getWarehouseAreaCategory().equals("AGVQX")
//                    || locatorBasicInfo.getWarehouseAreaCategory().equals("AGVL")) {
//                if (wmsAdjustD.getPieceAccount().compareTo(wmsAdjustD.getPieceAccountFact()) == 0) {
//                    // 无差异的盘点记录，则调用接口【盘点审核信息推送】同步发送盘点审核指令到EIS
//                    // 盘点回传EIS
//                    InventoryAuditVO toEisVo = new InventoryAuditVO();
//                    toEisVo.setMsgId(IdUtil.fastSimpleUUID());
//                    toEisVo.setWarehouseId(locatorBasicInfo.getWarehouseId());
//                    toEisVo.setWorkType(InventoryAuditEnum.INV_ADJUST.getWorkType());
//                    toEisVo.setBusinessType(InventoryAuditEnum.INV_ADJUST.getBusinessType());
//                    toEisVo.setOwnerId(wmsAdjustD.getCargoOwnerId());
//                    toEisVo.setItemId(wmsAdjustD.getItemId());
//                    toEisVo.setLotId(wmsAdjustD.getBatchId());
//                    toEisVo.setTaskLineId(wmsInvCheckD.getCheckLineId());
//                    String packId = "";
//                    if (CollUtil.isNotEmpty(itemMst.getBaseMtlItemUomConversionsList())) {
//                        packId = itemMst.getBaseMtlItemUomConversionsList().get(0).getItemUomId();
//                    }
//                    if (StringUtils.isNotEmpty(wmsInvCheckD.getContainerCode()) && !"N/A".equals(wmsAdjustD.getContainerCode())) {
//                        toEisVo.setContainerNo(wmsInvCheckD.getContainerCode());
//                    }
//                    if (StringUtils.isNotEmpty(wmsInvCheckD.getGoodsCaseCode()) && !"N/A".equals(wmsAdjustD.getGoodsCaseCode())) {
//                        toEisVo.setLocNo(wmsInvCheckD.getGoodsCaseCode());
//                    }
//                    toEisVo.setPackId(packId);
//                    toEisVo.setWmsLocationCode("MJK".equals(locatorBasicInfo.getWarehouseAreaCode()) ? "MJZ" : locatorBasicInfo.getWarehouseAreaCode());
//                    toEisVo.setConfirmQty(wmsAdjustD.getPieceAccountFact().toString());
//                    toEisVos.add(toEisVo);
//                }
//            }
        }
//        // 盘点转损溢需预占库存（生成盘点任务时已经生成了预占，盘点转损益则不生成预占，盘点质管审核通过清除预占，根据库存调整单直接更新库存数据）
//        if (ObjectUtils.isNotEmpty(adjustDList)) {
//            List<InvStockAdjust> invStockList = new ArrayList<>();
//            for (WmsAdjustD wmsAdjustD : adjustDList) {
//                if (wmsAdjustD.getPieceQuantity().compareTo(BigDecimal.ZERO) == 0) {
//                    continue;
//                }
//                excutePreStock(invStockList, wmsAdjustH, wmsAdjustD);
//            }
//            if (ObjectUtils.isEmpty(invStockList)) {
//                return;
//            }
//            RestMessage adjustStock = stockResource.adjustStock(invStockList);
//            if (adjustStock != null && !adjustStock.isSuccess()) {
//                throw new BizException("调用库存预占失败!原因->" + adjustStock.getMessage());
//            }
//        }
        // 转损溢不回传EIS，损溢审核再回传
//        if (!toEisVos.isEmpty()) {
//            logger.info("saveBatchAdjust 盘点审核信息推送EIS入参：{}", JSONObject.toJSONString(toEisVos));
//            // 回传EIS
//            eisHandler.inventoryAudit(toEisVos);
//        }
    }

    /**
     * 损溢修改(没有损溢调整一说,无计划的话)
     *
     * @param vo
     */
    @Override
    @Transactional
    public void updateAdjust(WmsAdjustUpdateVO vo) {
        String adjustLineId = vo.getAdjustLineId();
        if (StringUtils.isEmpty(adjustLineId))
            throw new ParameterException("id不能为空！");
        if (vo.getQuantity() == null)
            throw new ParameterException("数量不能为空！");
        Map<String, Object> map = new HashMap<>();
        map.put("quantity", vo.getQuantity());
        if (StringUtils.isBlank(vo.getBatchId()))
            map.put("batchId", vo.getBatchId());
        if (StringUtils.isBlank(vo.getBatchNum()))
            map.put("batchNum", vo.getBatchNum());
        if (StringUtils.isBlank(vo.getWhLocatorId()))
            map.put("whLocatorId", vo.getWhLocatorId());
        if (StringUtils.isBlank(vo.getStockStatus()))
            map.put("stockStatus", vo.getStockStatus());
        UserDTO userDTO = userTemplate.getUserDTO();
        String userId = userDTO.getId();
        String userName = userDTO.getNickname();
        map.put("modifierName", userName);
        map.put("modifier", userId);
        map.put("gmtModified", new Date());
        adjustDMapper.updateMapById(adjustLineId, map, WmsAdjustD.class);

        // 若要修改,则需要重新调整预占

        // 修改批号

    }

    /**
     * 损溢审核
     *
     * @param map
     */
    @Override
    @Transactional
    @TxTransaction(isStart = true)
    public void examineAdjust(Map<String, Object> map) {
        String adjustLineIds = (String) map.get("adjustLineIds");
        String status = (String) map.get("status");
        if (StringUtils.isEmpty(adjustLineIds))
            throw new ParameterException("id不能为空！");
        if (StringUtils.isBlank(status))
            throw new ParameterException("审核状态不能为空！");
        String adjustStatus = null;

        String checkStatus = null;
        if (status.equals("1")) {
            checkStatus = "60"; // 审核不通过直接作废掉
        }
        Date date = new Date();
        UserDTO userDTO = userTemplate.getUserDTO();
        String userId = userDTO.getId();
        String userName = userDTO.getNickname();
        String[] split = adjustLineIds.split(",");
        // 根据选中的库存调整单ID查询库存调整单
        List<WmsAdjustD> checkList = adjustDMapper.findByIds(WmsAdjustD.class, split, null);
        if (ObjectUtils.isNull(checkList)) {
            throw new BizException("损溢行id -> " + adjustLineIds + "在数据库查询的数据为空!请刷新重试");
        }
        // 根据库存调整单的srcBillDId查询出盘点明细关联的所有库存调整单
        Object[] srcIds = checkList.stream().map(WmsAdjustD::getSrcBillDId).distinct().toArray();
        if (ObjectUtils.isNotNull(srcIds)) {
            Criteria adjustCri = Criteria.forClass(WmsAdjustD.class);
            Restriction r1 = Restrictions.in("srcBillDId", srcIds);
            Restriction r2 = Restrictions.in("status", new String[]{"0", "5"});
            adjustCri.setRestriction(Restrictions.and(r1, r2));
            List<WmsAdjustD> allAdjust = adjustDMapper.findByCriteria(adjustCri);

            // 盘点仓储审核和盘点质管审核每个盘点明细下生成的库存调整单只能审核一次（全部通过后全部驳回）
            if(allAdjust == null || allAdjust.size() <= 0){
                split = checkList.stream().map(WmsAdjustD::getAdjustLineId).toArray(String[]::new);
            }else {
                split = allAdjust.stream().map(WmsAdjustD::getAdjustLineId).toArray(String[]::new);
            }

        }

        String adjustHeaderId = checkList.get(0).getAdjustHeaderId();
        WmsAdjustH wmsAdjustHhhh = adjustHMapper.findById(adjustHeaderId, WmsAdjustH.class);
        String adjustType = wmsAdjustHhhh.getAdjustType();
        boolean containsKey = map.containsKey("adjustType");
        if ((containsKey && "3".equals((String) map.get("adjustType"))) || adjustType.equals("3")) {
            // 为erp调整
            if (status.equals("1")) {
                // 审核不通过,整单驳回
                excuteAuditErpNoPass(adjustLineIds, userDTO, date, checkStatus, adjustStatus);
            } else {
                // 审核通过
                excuteAuditErpPass(adjustLineIds, userDTO, date, checkStatus, adjustStatus);
            }
            return;
        }
        // 其他wms调整
        List<String> lineBillIds = new ArrayList<>();
        String billId = null;
        int i = 0;
        List<WmsAdjustD> adjustDList = new ArrayList<>();
        for (String adjustLineId : split) {
            Map<String, Object> map2 = MapUtils.put("gmtModified", date).put("modifier", userId).put("modifierName", userName).put("adjustDate", date).getMap();
            if (i == 0) {
                WmsAdjustD adjustD = adjustDMapper.findById(adjustLineId, WmsAdjustD.class);
                if (adjustD != null) {
                    billId = adjustD.getAdjustHeaderId();
                    if (status.equals("0")) {
                        if (adjustD.getStatus().equals("0")) {
                            checkStatus = "5";
                            map2.put("opUser1", userName);
                            map2.put("opDate1", date);
                            map2.put("status", checkStatus);
                        } else if (adjustD.getStatus().equals("5")) {
                            checkStatus = "30"; // 看是否改为10
                            map2.put("opUser1", userName);
                            map2.put("opDate1", date);
                            map2.put("status", checkStatus);
                        }
                    }
                    adjustD.setStatus(checkStatus);
                    if(StringUtils.isBlank(adjustD.getSrcBillDId())){
                        adjustD.setSrcBillDId(adjustD.getAdjustLineId());
                    }
                    if(StringUtils.isBlank(adjustD.getSrcBillHId())){
                        adjustD.setSrcBillHId(adjustD.getAdjustHeaderId());
                    }
                    adjustDList.add(adjustD);
                }
            }
            lineBillIds.add(adjustLineId);
            map2.put("status", checkStatus);
            adjustDMapper.updateMapById(adjustLineId, map2, WmsAdjustD.class);

            adjustHMapper.updateMapById(billId, MapUtils.put("status", "COMFIRM").put("auditDate", date).put("auditedName", userName).put("auditedBy", userId).getMap(), WmsAdjustH.class);
        }


        // 库存修改
        // 若每次审核不通过,需释放预占
        if (status.equals("1")) {
            // 审核驳回需要生成复盘任务，不需要发送盘点审核信息至EIS
            List<WmsAdjustD> asjustList = adjustDMapper.findByIds(WmsAdjustD.class, split, null);
            // 生成复盘任务
            List<String> checkLineIds = asjustList.stream().map(WmsAdjustD::getSrcBillDId).distinct().collect(Collectors.toList());
            addInvCheckRe(checkLineIds, userDTO);

            // 审核驳回需要发送盘点审核信息至EIS解锁库存
//                this.pushAdjustResultToEis(adjustDList, status);
            // 有差异的需要释放预占（盘点转损益时没有生成预占，所以这里也不需要释放预占）
//            String[] cancelIds = asjustList.stream().filter(adjust -> adjust.getPieceQuantity().compareTo(BigDecimal.ZERO) != 0)
//                    .map(WmsAdjustD::getAdjustLineId).toArray(String[]::new);
//            if (ObjectUtils.isNotNull(adjustLineIds)) {
//                InvStockCancel cancel = new InvStockCancel();
//                cancel.setLineBillIds(cancelIds);
//                stockResource.adjustCancel(cancel);
//            }
            // 审核驳回不用回传ERP
            return;
        }
        // 第二次wms审通过后会回传erp审核
        BaseCommonDict dict = getBaseCommonDict();
        if (ObjectUtils.isNotEmpty(adjustDList) && adjustDList.get(0).getStatus().trim().equals(dict.getDictCode())) {
//            // 差异数量不为0的才需要调整库存（因为生成库存调整单时没有生成预占，所以不能根据库存调整单ID调整库存）
//            List<String> passAuditIds = adjustDList.stream()
//                    .filter(adjust -> adjust.getPieceQuantity().compareTo(BigDecimal.ZERO) != 0)
//                    .map(WmsAdjustD::getAdjustLineId).collect(Collectors.toList());
//            this.confirmAdjust(passAuditIds);
            // 需要释放生成盘点任务时的盘点预占
            String[] cancelIds = adjustDList.stream().map(WmsAdjustD::getSrcBillDId).distinct().toArray(String[]::new);
            if (ObjectUtils.isNotNull(cancelIds)) {
                InvStockCancel cancel = new InvStockCancel();
                cancel.setLineBillIds(cancelIds);
                stockResource.adjustCancel(cancel);
            }
            // 需要调整库存
            List<InvStockAdjust> invStockList = new ArrayList<>();
            for (WmsAdjustD wmsAdjustD : adjustDList) {
                if (wmsAdjustD.getPieceQuantity().compareTo(BigDecimal.ZERO) == 0) {
                    continue;
                }
                excutePreStock(invStockList, wmsAdjustHhhh, wmsAdjustD);
            }
            if (ObjectUtils.isNotNull(invStockList)) {
                // 损益不预占，直接调整库存
                RestMessage adjustMsg = stockResource.adjustStockComfirm(invStockList);
                if (adjustMsg != null && !adjustMsg.isSuccess()) {
                    throw new BizException("调用库存损溢增减库存失败!原因->" + adjustMsg.getMessage());
                }
            }

            // 回传ERP和EIS
            this.doCallBack(adjustDList);
        }
    }

    /**
     * 生成复盘任务
     *
     * @param checkLineIds 盘点明细ID
     * @param userDTO 当前登录用户
     */
    private void addInvCheckRe(List<String> checkLineIds, UserDTO userDTO) {
        // 复盘
        String type = "30";
        String userId = userDTO.getId();
        String userName = userDTO.getNickname();
        Date date = new Date();
        // 更新盘点单状态
        for (String checkLineId : checkLineIds) {
            invCheckDMapper.updateMapById(checkLineId, MapUtils.put("status", type).put("gmtModified", date).put("modifier", userId).put("modifierName", userName).put("outboundInstruct", null).getMap(), WmsInvCheckD.class);
        }
        // 更新汇总状态为NEW
        invCheckHMapper.updateCheckNewStatus(checkLineIds.stream().toArray(String[]::new));
        for (String checkLineId : checkLineIds) {
            WmsInvCheckDRe checkDRe = invCheckDReMapper.findById(checkLineId, WmsInvCheckDRe.class);
            if (checkDRe == null) {
                // 需新增新的复盘记录
                WmsInvCheckD checkD = invCheckDMapper.findById(checkLineId, WmsInvCheckD.class);
                checkDRe = new WmsInvCheckDRe();
                BeanUtils.copyProperties(checkD, checkDRe);
                checkDRe.setPieceQuantityFact(checkD.getPieceQuantityFact());
                ModelUtils.setBaseInfo(checkDRe, ModelUtils.OpType.INSERT, userDTO);
                checkDRe.setCheckTimes(0);
                invCheckDReMapper.save(checkDRe);
            }
        }
    }

    private void pushAdjustResultToEis(List<WmsAdjustD> adjustDList, String status) {
        // 远程获取商品数据
        Set<String> itemidSet = adjustDList.stream().map(WmsAdjustD::getItemId).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        RestMessage<List<BaseMtlItemMst>> itemMsg = itemResource.getListByIds(itemidSet);
        if (!itemMsg.isSuccess() || CollUtil.isEmpty(itemMsg.getData())) {
            throw new BizException("查询商品信息失败！");
        }
        // 远程获取仓库数据
        RestMessage<List<WarehouseLocatorBasicInfo>> locationBasicInfos = warehouseResource.getLocationBasicInfos(adjustDList.stream().map(WmsAdjustD::getWhLocatorId).filter(StringUtils::isNotEmpty).distinct().toArray(String[]::new));
        if (!locationBasicInfos.isSuccess() || locationBasicInfos.getData() == null) {
            throw new BizException("查询货位关联信息失败!请重试或联系管理员!");
        }
        List<WarehouseLocatorBasicInfo> locatorData = locationBasicInfos.getData();
        // 远程获取批次信息数据
        Set<String> batchId = adjustDList.stream().map(WmsAdjustD::getBatchId).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        RestMessage<List<BatchNumberListVO>> batchNumberBasicInfo = stockResource.getBatchNumberBasicInfo(batchId.toArray(new String[]{}));
        if (!batchNumberBasicInfo.isSuccess() || batchNumberBasicInfo.getData() == null) {
            throw new BizException("查询批次关联信息失败!请重试或联系管理员!");
        }
        List<BatchNumberListVO> batchNumberData = batchNumberBasicInfo.getData();

        // 盘点审核信息推送EIS入参
        List<InventoryAuditVO> toEisVos = new ArrayList<>();
        for (WmsAdjustD wmsAdjustD : adjustDList) {
            // 设置商品相关
            String itemId = wmsAdjustD.getItemId();
            BaseMtlItemMst itemMstVO2 = itemMsg.getData().stream().filter(var -> var.getItemId().equals(itemId)).findFirst().orElse(null);
            if (null == itemMstVO2) {
                throw new BizException("查询商品信息失败！");
            }
            BatchNumberListVO bacthNum = batchNumberData.stream().filter(batch -> batch.getBatchId().equals(wmsAdjustD.getBatchId())).findFirst().orElse(null);
            if (null == bacthNum) {
                throw new BizException("查询批次信息失败！");
            }

            WarehouseLocatorBasicInfo locatorBasicInfo = locatorData.stream().filter(var -> wmsAdjustD.getWhLocatorId().equals(var.getWarehouseLocatorId())).findFirst().orElse(null);
            if (locatorBasicInfo != null && PICK_MODE_DEVICE.equals(locatorBasicInfo.getPickMode())) {
                InventoryAuditVO toEis = new InventoryAuditVO();
                toEis.setMsgId(IdUtil.fastSimpleUUID());
                toEis.setWarehouseId(locatorBasicInfo.getWarehouseId());
                toEis.setWorkType(InventoryAuditEnum.INV_ADJUST.getWorkType());
                toEis.setBusinessType(InventoryAuditEnum.INV_ADJUST.getBusinessType());
                toEis.setOwnerId(wmsAdjustD.getCargoOwnerId());
                toEis.setItemId(wmsAdjustD.getItemId());
                toEis.setLotId(wmsAdjustD.getBatchId());
                toEis.setTaskLineId(wmsAdjustD.getSrcBillDId());
                String packId = "";
                if (CollUtil.isNotEmpty(itemMstVO2.getBaseMtlItemUomConversionsList())) {
                    packId = itemMstVO2.getBaseMtlItemUomConversionsList().get(0).getItemUomId();
                }
                if (StringUtils.isNotEmpty(wmsAdjustD.getContainerCode()) && !"N/A".equals(wmsAdjustD.getContainerCode())) {
                    toEis.setContainerNo(wmsAdjustD.getContainerCode());
                }
                if (StringUtils.isNotEmpty(wmsAdjustD.getGoodsCaseCode()) && !"N/A".equals(wmsAdjustD.getGoodsCaseCode())) {
                    // 设置货格号
                    toEis.setLocNo(wmsAdjustD.getGoodsCaseCode());
                }
                toEis.setPackId(packId);
                toEis.setWmsLocationCode("MJK".equals(locatorBasicInfo.getWarehouseAreaCode()) ? "MJZ" : locatorBasicInfo.getWarehouseAreaCode());
                toEis.setConfirmQty("1".equals(status) ? wmsAdjustD.getPieceAccount().toString() : wmsAdjustD.getPieceAccountFact().toString());
                toEisVos.add(toEis);
            }
        }
        if (CollUtil.isNotEmpty(toEisVos)) {
            eisHandler.inventoryAudit(toEisVos);
        }
    }

    private BaseCommonDict getBaseCommonDict() {
        List<BaseCommonDict> dicts = RestMsgHelper.unpack(commonResource.getListByDicttype(null, QUALITY_CONTROL_AUDIT));
        Assert.notEmpty(dicts, "请在公共字典中设置盘点审核节点【{}】", QUALITY_CONTROL_AUDIT);

        if (dicts.stream().filter(t -> MsgTemplate.YES.equals(t.getIsEnable())).count() > 1) {
            throw new PrologException("不可同时启用多级审核");
        }
        BaseCommonDict dict = dicts.stream().filter(t -> MsgTemplate.YES.equals(t.getIsEnable())).findFirst().orElse(null);
        Assert.notNull(dict, "请启用一条盘点审核节点");
        return dict;
    }

    /**
     * erp审核通过
     */
    private void excuteAuditErpPass(String adjustLineIds, UserDTO userDTO, Date date, String checkStatus, String adjustStatus) {
        String userId = userDTO.getId();
        String userName = userDTO.getNickname();
        Set<String> billidSet = new HashSet<>();
        String[] split = adjustLineIds.split(",");
        List<String> adjustLineIdList = new ArrayList<>();
        int row = 0;
        for (String adjustLineId : split) {
            row++;
            Map<String, Object> map2 = MapUtils.put("gmtModified", date).put("modifier", userId).put("modifierName", userName).put("adjustDate", date).getMap();
            WmsAdjustD adjustD = adjustDMapper.findById(adjustLineId, WmsAdjustD.class);
            AssertUtils.notNull(adjustD, "损溢行id->" + adjustLineId + "在数据库查询的数据为空!请刷新重试");
            String billId = adjustD.getAdjustHeaderId();

            // 判断billid是否存在驳回的明细
            vaildateReject(row, billId, "60");

            billidSet.add(billId);
            if (adjustD.getStatus().equals("0")) {
                // 一次
                checkStatus = "5";
                map2.put("opUser1", userName);
                map2.put("opDate1", date);
                map2.put("status", checkStatus);
            } else if (adjustD.getStatus().equals("5")) {
                // 二次
                checkStatus = "30"; // 看是否改为10
                map2.put("opUser1", userName);
                map2.put("opDate1", date);
                map2.put("status", checkStatus);

            }

            map2.put("status", checkStatus);
            adjustDMapper.updateMapById(adjustLineId, map2, WmsAdjustD.class);
            adjustHMapper.updateMapById(billId, MapUtils.put("status", "COMFIRM").put("auditDate", date).put("auditedName", userName).put("auditedBy", userId).getMap(), WmsAdjustH.class);

        }

        Criteria crt = Criteria.forClass(OmsInventoryOrder.class);
        List<OmsInventoryResult> resultList = new ArrayList<>();
        for (String billid : billidSet) {
            crt.setRestriction(Restrictions.eq("billid", billid));
            List<OmsInventoryOrder> findByCriteria = omsInventoryOrderMapper.findByCriteria(crt);
            AssertUtils.isNotEmpty(findByCriteria, "billid->" + billid + "对应的损益单明细数据库数据为空!请检查重试!");
            // 校验是否全部二审通过数量是否和总数量一致
            List<WmsAdjustD> vaildateErpAmoutAudit = vaildateErpAmoutAudit(billid);
            if (ObjectUtils.isNotEmpty(vaildateErpAmoutAudit)) {
                for (OmsInventoryOrder omsInventoryOrder : findByCriteria) {
                    OmsInventoryResult result = new OmsInventoryResult();
                    result.setStatus("10"); // wms审核通过
                    excuteOrder2Result(omsInventoryOrder, result, userDTO, date);
                    resultList.add(result);

                    // 更新状态为已经审核
                    omsInventoryOrder.setStatus("40"); // 已审核
                    Criteria crt22 = Criteria.forClass(OmsInventoryOrder.class);
                    crt22.setRestriction(Restrictions.eq("lineid", omsInventoryOrder.getLineid()));
                    this.omsInventoryOrderMapper.updateMapByCriteria(MapUtils.put("status", "40").getMap(), crt22);
                }

                // 第二次wms审通过后整单扣减库存
                //              doCallBackToErp(vaildateErpAmoutAudit);
                adjustLineIdList = vaildateErpAmoutAudit.stream().map(WmsAdjustD::getAdjustLineId).collect(Collectors.toList());
            }
        }
        if (!ObjectUtils.isEmpty(adjustLineIdList)) {
            confirmAdjust(adjustLineIdList);
        }
        if (ObjectUtils.isNotEmpty(resultList)) {
            omsInventoryResultMapper.saveBatch(resultList);
            Set<String> collect2 = resultList.stream().map(OmsInventoryResult::getBillid).collect(Collectors.toSet());

            executor.execute(() -> {
                try {
                    Thread.sleep(callSleepTimes);
                    asyncResult(collect2);
                } catch (InterruptedException | IllegalArgumentException e) {
                    logger.error("损溢结果回传失败,单id:" + new ArrayList<String>(collect2).toString());
                }
            });
        }

    }

    private void vaildateReject(int row, String billId, String status) {
        Criteria crt111 = Criteria.forClass(WmsAdjustD.class);
        Restriction eq = Restrictions.eq("adjustHeaderId", billId);
        Restriction eq2 = Restrictions.eq("status", status); // 存在报损的
        crt111.setRestriction(Restrictions.and(eq, eq2));
        long count = adjustDMapper.findCountByCriteria(crt111);
        if (count > 0) {
            throw new BizException(String.format("第[%d]行,单据id[%s],存在不同审核状态的损溢明细!", row, billId));
        }
    }

    /**
     * 校验erp整单数量和wms损溢数量是否一致
     *
     * @param billid
     * @return
     */
    private List<WmsAdjustD> vaildateErpAmoutAudit(String billid) {

        // 校验生成损溢总量和erp待调整总量是否一致,通过adjustHeaderId找到对应的明细的数据(多条总数)
        Criteria crt = Criteria.forClass(WmsAdjustD.class);
        crt.setRestriction(Restrictions.eq("adjustHeaderId", billid).and(Restrictions.eq("status", "30")));
        List<WmsAdjustD> findByCriteria = this.adjustDMapper.findByCriteria(crt);
        AssertUtils.notNull(findByCriteria, "erp损溢单id->" + billid + "对应的wms损溢数据为空!");
        BigDecimal dTotal = findByCriteria.stream().map(i -> {
            if (i.getPieceQuantity() == null) {
                return BigDecimal.ZERO;
            } else {
                return i.getPieceQuantity().abs();
            }
        }).reduce(BigDecimal.ZERO, BigDecimal::add);

        Criteria crt2 = Criteria.forClass(OmsInventoryOrder.class);
        crt2.setRestriction(Restrictions.eq("billid", billid));
        List<OmsInventoryOrder> findByCriteria2 = omsInventoryOrderMapper.findByCriteria(crt2);
        AssertUtils.isNotEmpty(findByCriteria2, "损溢单id->" + billid + "对应的损益单数据库数据为空!请检查重试!");
        BigDecimal oTotal = findByCriteria2.stream().map(i -> {
            if (i.getAmount() == null) {
                return BigDecimal.ZERO;
            } else {
                return i.getAmount().abs();
            }
        }).reduce(BigDecimal.ZERO, BigDecimal::add);

        if (dTotal.compareTo(oTotal) == 0) {
            return findByCriteria;
        }
        return null;
    }

    /**
     * erp发起审核驳回
     *
     * @param adjustLineIds
     * @param userDTO
     * @param date
     * @param checkStatus
     * @param adjustStatus
     */
    private void excuteAuditErpNoPass(String adjustLineIds, UserDTO userDTO, Date date, String checkStatus, String adjustStatus) {
        String userId = userDTO.getId();
        String userName = userDTO.getNickname();
        // 释放损溢预占
        InvStockCancel cancel = new InvStockCancel();
        cancel.setLineBillIds(adjustLineIds.split(","));
        stockResource.adjustCancel(cancel);

        // 更新头表,明细状态
        Set<String> billidSet = new HashSet<>();
        Criteria crt = Criteria.forClass(WmsAdjustD.class);
        int row = 0;
        String[] split = adjustLineIds.split(",");
        List<String> asList = Arrays.asList(split);
        for (String adjustLineId : asList) {
            row++;
            Map<String, Object> map2 = MapUtils.put("gmtModified", date).put("modifier", userId).put("modifierName", userName).put("adjustDate", date).getMap();
            WmsAdjustD adjustD = adjustDMapper.findById(adjustLineId, WmsAdjustD.class);
            String billId = adjustD.getAdjustHeaderId();
            String status = adjustD.getStatus();

            // 需要判断是否是整单驳回,不是需要抛错
            vaildateAllReject(asList, billId, status, row);

            billidSet.add(billId);
            map2.put("status", checkStatus);

            crt.setRestriction(Restrictions.eq("adjustHeaderId", billId));
            adjustDMapper.updateMapByCriteria(map2, crt);
            adjustHMapper.updateMapById(billId, MapUtils.put("status", "COMFIRM").put("auditDate", date).put("auditedName", userName).put("auditedBy", userId).getMap(), WmsAdjustH.class);
        }
        // 整单驳回erp
        List<OmsInventoryResult> resultList = new ArrayList<>();
        Criteria crt2 = Criteria.forClass(OmsInventoryOrder.class);
        for (String billid : billidSet) {
            crt2.setRestriction(Restrictions.eq("billid", billid));
            List<OmsInventoryOrder> findByCriteria = omsInventoryOrderMapper.findByCriteria(crt2);
            AssertUtils.isNotEmpty(findByCriteria, "billid->" + billid + "对应的损益单明细数据库数据为空!请检查重试!");

            for (OmsInventoryOrder omsInventoryOrder : findByCriteria) {
                OmsInventoryResult result = new OmsInventoryResult();
                result.setReason("wms审核不通过.");
                result.setStatus("0"); // wms驳回
                excuteOrder2Result(omsInventoryOrder, result, userDTO, date);
                resultList.add(result);

                omsInventoryOrder.setStatus("30"); // 已驳回
                Criteria crt22 = Criteria.forClass(OmsInventoryOrder.class);
                crt22.setRestriction(Restrictions.eq("lineid", omsInventoryOrder.getLineid()));
                this.omsInventoryOrderMapper.updateMapByCriteria(MapUtils.put("status", "30").getMap(), crt22);
            }
        }
        if (ObjectUtils.isNotEmpty(resultList)) {
            omsInventoryResultMapper.saveBatch(resultList);
            Set<String> collect2 = resultList.stream().map(OmsInventoryResult::getBillid).collect(Collectors.toSet());

            executor.execute(() -> {
                try {
                    Thread.sleep(callSleepTimes);
                    asyncResult(collect2);
                } catch (InterruptedException | IllegalArgumentException e) {
                    logger.error("损溢结果回传失败,单id:" + new ArrayList<String>(collect2).toString());
                }
            });
        }

    }

    private void vaildateAllReject(List<String> asList, String billId, String status, int row) {
        Criteria crt111 = Criteria.forClass(WmsAdjustD.class);
        Restriction eq = Restrictions.eq("adjustHeaderId", billId);
        Restriction ne = Restrictions.ne("status", status); // 不等于本身状态
        crt111.setRestriction(Restrictions.and(eq, ne));
        long count = adjustDMapper.findCountByCriteria(crt111);
        if (count > 0) {
            throw new BizException(String.format("第[%d]行,单据id[%s],存在不同状态的损溢明细,需要整单驳回!", row, billId));
        }

        crt111.setRestriction(Restrictions.and(eq));
        List<WmsAdjustD> findByCriteria = adjustDMapper.findByCriteria(crt111);
        List<String> collect = findByCriteria.stream().map(WmsAdjustD::getAdjustLineId).collect(Collectors.toList());
        if (!asList.containsAll(collect)) {
            throw new BizException(String.format("第[%d]行,单据id[%s],需要整单驳回!", row, billId));
        }

    }

    @Override
    public Page<WmsAdjustH> getAdjustHPage(String warehouseId, String srcBillHId, String status, Integer pageSize, Integer pageNum) {
        UserDTO userDTO = userTemplate.getUserDTO();
        String enterpriseId = userDTO.getEnterpriseId();
        Criteria crt = Criteria.forClass(BaseMtlManufacturer.class);
        Restriction r1 = StringUtils.isEmpty(warehouseId) ? null : Restrictions.eq("warehouseId", warehouseId);
        Restriction r2 = StringUtils.isEmpty(srcBillHId) ? null : Restrictions.like("srcBillHId", "%" + srcBillHId + "%");
        Restriction r3 = StringUtils.isEmpty(status) ? null : Restrictions.eq("status", status);
        crt.setRestriction(Restrictions.and(r1, r2, r3, Restrictions.eq("enterpriseId", enterpriseId)));
        crt.setOrder(Order.newInstance().desc("gmtCreate"));
        PageHelper.startPage(pageNum, pageSize);
        List<WmsAdjustH> list = adjustHMapper.findByCriteria(crt);
        return PageUtils.getPage(list);
    }

    /**
     * pad损溢新增(无计划)
     */
    @Override
    public void saveAdjustByPad(WmsAdjustAddVO wmsAdjustAddVO) {
        wmsAdjustAddVO.setAdjustType("1");
        this.saveAdjust(wmsAdjustAddVO);
    }

    /**
     * 损溢驳回处理
     */
    @Override
    @Transactional
    @TxTransaction(isStart = true)
    public void rejectAdjust(Map<String, Object> map) {
        String adjustLineIds = (String) map.get("adjustLineIds");
        if (StringUtils.isEmpty(adjustLineIds))
            throw new ParameterException("id集合不能为空！");
        UserDTO userDTO = userTemplate.getUserDTO();
        String userId = userDTO.getId();
        String userName = userDTO.getNickname();
        Date date = new Date();
        for (String adjustLineId : adjustLineIds.split(",")) {
            WmsAdjustD adjustD = adjustDMapper.findById(adjustLineId, WmsAdjustD.class);
            if (adjustD != null) {
                String billId = adjustD.getAdjustHeaderId();
                // 作废掉
                adjustDMapper.updateMapById(adjustLineId, MapUtils.put("status", "60").put("gmtModified", date).put("modifier", userId).put("modifierName", userName).put("adjustDate", date).getMap(), WmsAdjustD.class);
                adjustHMapper.updateMapById(billId, MapUtils.put("auditDate", date).put("auditedName", userName).put("auditedBy", userId).getMap(), WmsAdjustH.class);
            }
        }

        // 释放预占
        InvStockCancel cancel = new InvStockCancel();
        cancel.setLineBillIds(adjustLineIds.split(","));
        stockResource.adjustCancel(cancel);

        // 回传erp结果
        Criteria crt = Criteria.forClass(OmsInventoryAudit.class);
        crt.setRestriction(Restrictions.in("lineid", adjustLineIds.split(",")));
        List<OmsInventoryAudit> findByCriteria = omsInventoryAuditMapper.findByCriteria(crt);
        for (OmsInventoryAudit omsInventoryAudit : findByCriteria) {
            String billno2 = omsInventoryAudit.getBillno();
            omsInventoryAudit.setBillno(billno2 + "N");
            omsInventoryAudit.setBillid(billno2 + "N");
            String seqno = omsInventoryAudit.getSeqno();
            Restriction eq = null;
            if (!StringUtils.isEmpty(seqno)) {
                eq = Restrictions.eq("seqno", seqno);
            }
            Criteria crt2 = Criteria.forClass(OmsInventoryOrder.class);
            crt2.setRestriction(Restrictions.and(Restrictions.eq("billno", billno2), eq));
            List<OmsInventoryOrder> OmsInventoryOrders = this.omsInventoryOrderMapper.findByCriteria(crt2);
            if (!ObjectUtils.isNull(OmsInventoryOrders)) {
                OmsInventoryOrder omsInventoryOrder = OmsInventoryOrders.get(0);
                Date productionDate = omsInventoryOrder.getProductionDate();
                Date expiredDate = omsInventoryOrder.getExpiredDate();
                omsInventoryAudit.setProductionDate(productionDate);
                omsInventoryAudit.setExpiredDate(expiredDate);
                omsInventoryAudit.setBillid(omsInventoryOrder.getBillid() + "N");
                omsInventoryAudit.setType(omsInventoryOrder.getType());
            }
        }
        excuteCallbackResult(findByCriteria, userDTO, date, "0");
    }

    /**
     * 回传erp审核
     */
    private void doCallBack(List<WmsAdjustD> adjustDList) {
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); // 精确到毫秒
        String dateStr = sdf.format(now);

        // 远程获取商品数据
        Set<String> itemidSet = adjustDList.stream().map(WmsAdjustD::getItemId).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        RestMessage<List<BaseMtlItemMst>> itemMsg = itemResource.getListByIds(itemidSet);
        if (!itemMsg.isSuccess() || CollUtil.isEmpty(itemMsg.getData())) {
            throw new BizException("查询商品信息失败！");
        }
        // 远程获取仓库数据
        RestMessage<List<WarehouseLocatorBasicInfo>> locationBasicInfos = warehouseResource.getLocationBasicInfos(adjustDList.stream().map(WmsAdjustD::getWhLocatorId).filter(StringUtils::isNotEmpty).distinct().toArray(String[]::new));
        if (!locationBasicInfos.isSuccess() || locationBasicInfos.getData() == null) {
            throw new BizException("查询货位关联信息失败!请重试或联系管理员!");
        }
        List<WarehouseLocatorBasicInfo> locatorData = locationBasicInfos.getData();
        // 远程获取批次信息数据
        Set<String> batchId = adjustDList.stream().map(WmsAdjustD::getBatchId).filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
        RestMessage<List<BatchNumberListVO>> batchNumberBasicInfo = stockResource.getBatchNumberBasicInfo(batchId.toArray(new String[]{}));
        if (!batchNumberBasicInfo.isSuccess() || batchNumberBasicInfo.getData() == null) {
            throw new BizException("查询批次关联信息失败!请重试或联系管理员!");
        }
        List<BatchNumberListVO> batchNumberData = batchNumberBasicInfo.getData();

        // 盘点审核信息推送EIS入参
        List<InventoryAuditVO> toEisVos = new ArrayList<>();
        // 回传ERP入参
        List<LockToErpVo> toErpVos = new ArrayList<>();
        for (WmsAdjustD wmsAdjustD : adjustDList) {
            LockToErpVo toErpVo = new LockToErpVo();
            // 设置商品相关
            String itemId = wmsAdjustD.getItemId();
            BaseMtlItemMst itemMstVO2 = itemMsg.getData().stream().filter(var -> var.getItemId().equals(itemId)).findFirst().orElse(null);
            if (null == itemMstVO2) {
                throw new BizException("查询商品信息失败！");
            }
            BatchNumberListVO bacthNum = batchNumberData.stream().filter(batch -> batch.getBatchId().equals(wmsAdjustD.getBatchId())).findFirst().orElse(null);
            if (null == bacthNum) {
                throw new BizException("查询批次信息失败！");
            }
            WarehouseLocatorBasicInfo locatorBasicInfo = locatorData.stream().filter(var -> wmsAdjustD.getWhLocatorId().equals(var.getWarehouseLocatorId())).findFirst().orElse(null);
            // 损益数量不为0则回传ERP, 盘损的才回传ERP， 盘溢的不回传ERP
            if (wmsAdjustD.getPieceQuantity().compareTo(BigDecimal.ZERO) < 0) {
                // 构建回传ERP参数
                toErpVo.setGoodSn(itemMstVO2.getItemCode());
                toErpVo.setFLot(bacthNum.getManufacturerLotNum());
                toErpVo.setStockNum(wmsAdjustD.getPieceAccountFact().toString());
                toErpVo.setAlterTime(dateStr);
                toErpVo.setAlterRemark("盘点审核");
                if (null != locatorBasicInfo) {
                    toErpVo.setBeforeWNo(locatorBasicInfo.getWarehouseAreaCategory());
                }
                toErpVos.add(toErpVo);
            }
            if (locatorBasicInfo != null && PICK_MODE_DEVICE.equals(locatorBasicInfo.getPickMode())) {
                InventoryAuditVO toEis = new InventoryAuditVO();
                toEis.setMsgId(IdUtil.fastSimpleUUID());
                toEis.setWarehouseId(locatorBasicInfo.getWarehouseId());
                toEis.setWorkType(InventoryAuditEnum.INV_ADJUST.getWorkType());
                toEis.setBusinessType(InventoryAuditEnum.INV_ADJUST.getBusinessType());
                toEis.setOwnerId(wmsAdjustD.getCargoOwnerId());
                toEis.setItemId(wmsAdjustD.getItemId());
                toEis.setLotId(wmsAdjustD.getBatchId());
                toEis.setTaskLineId(wmsAdjustD.getSrcBillDId());
                String packId = "";
                if (CollUtil.isNotEmpty(itemMstVO2.getBaseMtlItemUomConversionsList())) {
                    packId = itemMstVO2.getBaseMtlItemUomConversionsList().get(0).getItemUomId();
                }
                if (StringUtils.isNotEmpty(wmsAdjustD.getContainerCode()) && !"N/A".equals(wmsAdjustD.getContainerCode())) {
                    toEis.setContainerNo(wmsAdjustD.getContainerCode());
                }
                if (StringUtils.isNotEmpty(wmsAdjustD.getGoodsCaseCode()) && !"N/A".equals(wmsAdjustD.getGoodsCaseCode())) {
                    // 设置货格号
                    toEis.setLocNo(wmsAdjustD.getGoodsCaseCode());
                }
                toEis.setPackId(packId);
                toEis.setWmsLocationCode("MJK".equals(locatorBasicInfo.getWarehouseAreaCode()) ? "MJZ" : locatorBasicInfo.getWarehouseAreaCode());
                toEis.setConfirmQty(wmsAdjustD.getPieceAccountFact().toString());
                toEisVos.add(toEis);
            }
        }
        // 封装参数调EIS
        if (CollUtil.isNotEmpty(toEisVos)) {
            logger.info("doCallBack盘点审核信息推送EIS入参：{}", JSONObject.toJSONString(toEisVos));
            eisHandler.inventoryAudit(toEisVos);
        }
        if (CollUtil.isNotEmpty(toErpVos)) {
            logger.info("doCallBack损益结果回传ERP入参：{}", JSONObject.toJSONString(toErpVos));
            for (LockToErpVo toErpVo : toErpVos) {
                stockResource.askIntegration(new AskIntegrationVo("inventoryCallback", toErpVo));
            }
        }
    }

    /**
     * zft回传erp审核
     *
     * @param adjustDList 调整行
     * @param userDTO     userDTO
     * @author lihao lihao
     * @since 2021-12-1
     */
    private void doCallBackToErpZft(List<WmsAdjustD> adjustDList, UserDTO userDTO) {
        List<String> passAuditIds = adjustDList.stream().map(WmsAdjustD::getAdjustLineId).collect(Collectors.toList());
        logger.info("损溢通过的行id" + passAuditIds);
        if (confirmAdjust(passAuditIds)) {
            Date now = new Date();
            // 库存损溢成功,构造RESULT结果，回传ERP
            excuteCallbackZftResult(adjustDList, userDTO, now, "10");
        }
    }

    private void asyncOrder(Set<String> collect) {
        for (String string : collect) {
            EtlMessage em = new EtlMessage();
            em.setId(string);
            em.setEtlType(EtlTypeConstants.op_pl_w2o);
            try {
                logger.info("盘点损溢申请数据->data-exchange{}", JsonUtils.toString(em));
                exchangeSender.send(em);
            } catch (Exception e) {
                logger.error("回传data-exchange错误!原因{}", e);
            }
        }

    }

    /**
     * 监听erp下发的审核损溢结果,执行损溢确认/损溢驳回操作
     */
    @Override
    @Transactional
    @TxTransaction(isStart = true)
    public void procesAdjustAudit(String ids) {
        // 解决HystrixRequestContext问题
        if (!HystrixRequestContext.isCurrentThreadInitialized()) {
            HystrixRequestContext.initializeContext();
        }
        String[] split = ids.trim().split(",");
        if (split.length > 0) {
            Criteria crt = Criteria.forClass(OmsInventoryAudit.class);
            crt.setRestriction(Restrictions.in("billid", split));
            List<OmsInventoryAudit> audit = omsInventoryAuditMapper.findByCriteria(crt);
            if (ObjectUtils.isNotEmpty(audit)) {
                Map<String, List<OmsInventoryAudit>> collect = audit.stream().filter(p -> StringUtils.isNotEmpty(p.getAuditStatus())).collect(Collectors.groupingBy(OmsInventoryAudit::getAuditStatus));
                List<String> passAuditIds = new ArrayList<>();
                List<String> noPassAuditIds = new ArrayList<>();
                //              监听的消息为多线程无法拿到用户信息数据,只能在传过来的数据中取
                UserDTO userDTO = null;
                try {
                    userDTO = userTemplate.getUserDTO();
                } catch (Exception e) {
                    logger.info("从mq中做任务,获取用户失败!");
                }
                if (userDTO == null) {
                    userDTO = new UserDTO();
                    OmsInventoryAudit omsInventoryAudit = audit.get(0);
                    String lastmodifyby = omsInventoryAudit.getLastmodifyby();
                    if (StringUtils.isBlank(lastmodifyby)) {
                        lastmodifyby = omsInventoryAudit.getCreateby();
                    }
                    userDTO.setUsername(lastmodifyby);
                    //                  userDTO.setId(omsInventoryAudit.getLastmodifyby());
                    userDTO.setEnterpriseId(omsInventoryAudit.getEnterpriseid());
                    userDTO.setEnterpriseName(omsInventoryAudit.getEnterprisename());
                }
                //              AssertUtils.notNull(userDTO, "用户信息为空!");
                logger.info("开始进行损溢确认处理-----------------");
                List<OmsInventoryAudit> passList = new ArrayList<>();
                List<OmsInventoryAudit> noPassList = new ArrayList<>();
                for (List<OmsInventoryAudit> auditList : collect.values()) {
                    String auditStatus = "";
                    OmsInventoryAudit omsInventoryAudit = null;
                    if (!ObjectUtils.isNull(auditList) && auditList.get(0) != null) {
                        omsInventoryAudit = auditList.get(0);
                        auditStatus = omsInventoryAudit.getAuditStatus();
                    } else {
                        continue;
                    }
                    if (StringUtils.isNotEmpty(auditStatus) && ("Y".equals(auditStatus) || "1".equals(auditStatus))) {
                        // 审核通过,损溢调整通过,修改erp审核状态 30,库存占用后,且回传erp成功后改为50
                        logger.info("执行损溢通过处理-------------------");
                        //                      List<String> collect2 = auditList.stream().filter(p -> !StringUtils.isEmpty(p.getLineid()))
                        //                              .map(OmsInventoryAudit::getLineid).collect(Collectors.toList());
                        //                      if (ObjectUtils.isNull(collect2)) {
                        String billno = omsInventoryAudit.getBillno();
                        String seqno = omsInventoryAudit.getSeqno();
                        Restriction eq = null;
                        if (!StringUtils.isEmpty(seqno)) {
                            eq = Restrictions.eq("seqno", seqno);
                        }
                        Criteria crt2 = Criteria.forClass(OmsInventoryOrder.class);
                        crt2.setRestriction(Restrictions.and(Restrictions.eq("billno", billno), eq));
                        List<OmsInventoryOrder> OmsInventoryOrders = this.omsInventoryOrderMapper.findByCriteria(crt2);
                        if (!ObjectUtils.isNull(OmsInventoryOrders)) {
                            OmsInventoryOrder omsInventoryOrder = OmsInventoryOrders.get(0);
                            Date productionDate = omsInventoryOrder.getProductionDate();
                            Date expiredDate = omsInventoryOrder.getExpiredDate();
                            omsInventoryAudit.setProductionDate(productionDate);
                            omsInventoryAudit.setExpiredDate(expiredDate);
                            omsInventoryAudit.setBillid(omsInventoryOrder.getBillid());
                            omsInventoryAudit.setType(omsInventoryOrder.getType());
                            String lineid = OmsInventoryOrders.get(0).getLineid();
                            WmsAdjustD adjustD = this.adjustDMapper.findById(lineid, WmsAdjustD.class);
                            if (!ObjectUtils.isNull(adjustD)) {
                                //                              Set<String> collect4 = adjustd.stream()
                                //                                      .filter(p -> !StringUtils.isEmpty(p.getAdjustLineId()))
                                //                                      .map(WmsAdjustD::getAdjustLineId).collect(Collectors.toSet());
                                //                              if (!ObjectUtils.isNull(collect4)) {
                                //                                  collect2 = new ArrayList<String>(collect4);
                                //                              }
                                passAuditIds.add(lineid);
                                passList.add(omsInventoryAudit);
                            } else {
                                logger.error("审核对应的损溢明细为空!行id->" + lineid);
                            }
                        } else {
                            logger.error("审核对应的申请明细为空!单号" + billno + "行号" + seqno);
                        }
                        //                      }
                        //                      passAuditIds.addAll(collect2);

                        //                      if (!ObjectUtils.isNull(passAuditIds)) {
                        //                          logger.info("需要扣减库存的损溢行id->" + passAuditIds.toString());
                        //                          excuteAuditPass(passAuditIds, auditList, userDTO);
                        //                      } else {
                        //                          logger.error("审核对应的损溢明细为空!单号" + billno + "行号" + seqno);
                        //                      }

                    }
                    if (StringUtils.isNotEmpty(auditStatus) && ("N".equals(auditStatus) || "0".equals(auditStatus))) {
                        // 审核不通过,需要将对应的损溢调整表置为驳回状态 40,驳回处理完毕后改为50
                        logger.info("执行损溢不通过处理-------------------");
                        //                      List<String> collect3 = auditList.stream().filter(p -> !StringUtils.isEmpty(p.getLineid()))
                        //                              .map(OmsInventoryAudit::getLineid).collect(Collectors.toList());
                        //                      if (ObjectUtils.isNull(collect3)) {
                        //                          String billno = omsInventoryAudit.getBillno();
                        //                          String seqno = omsInventoryAudit.getSeqno();
                        //                          Restriction eq2 = null;
                        //                          if (!StringUtils.isEmpty(seqno)) {
                        //                              eq2 = Restrictions.eq("lineNum", seqno);
                        //                          }
                        //                          Criteria crt3 = Criteria.forClass(WmsAdjustD.class);
                        //                          crt3.setRestriction(Restrictions.and(Restrictions.eq("billno", billno), eq2));
                        //                          List<WmsAdjustD> findByCriteria3 = this.adjustDMapper.findByCriteria(crt3);
                        //                          if (!ObjectUtils.isNull(findByCriteria3)) {
                        //                              Set<String> collect5 = findByCriteria3.stream()
                        //                                      .filter(p -> !StringUtils.isEmpty(p.getAdjustLineId()))
                        //                                      .map(WmsAdjustD::getAdjustLineId).collect(Collectors.toSet());
                        //                              if (!ObjectUtils.isNull(collect5)) {
                        //                                  collect3 = new ArrayList<String>(collect5);
                        //                              }
                        //                          }
                        //                      }
                        //                      noPassAuditIds.addAll(collect3);
                        //                      excuteAuditNoPass(noPassAuditIds, auditList, userDTO);

                        String billno = omsInventoryAudit.getBillno();
                        String seqno = omsInventoryAudit.getSeqno();
                        Restriction eq = null;
                        if (!StringUtils.isEmpty(seqno)) {
                            eq = Restrictions.eq("seqno", seqno);
                        }
                        Criteria crt2 = Criteria.forClass(OmsInventoryOrder.class);
                        crt2.setRestriction(Restrictions.and(Restrictions.eq("billno", billno), eq));
                        List<OmsInventoryOrder> OmsInventoryOrders = this.omsInventoryOrderMapper.findByCriteria(crt2);
                        if (!ObjectUtils.isNull(OmsInventoryOrders)) {
                            String lineid = OmsInventoryOrders.get(0).getLineid();
                            OmsInventoryOrder omsInventoryOrder = OmsInventoryOrders.get(0);
                            Date productionDate = omsInventoryOrder.getProductionDate();
                            Date expiredDate = omsInventoryOrder.getExpiredDate();
                            omsInventoryAudit.setProductionDate(productionDate);
                            omsInventoryAudit.setExpiredDate(expiredDate);
                            omsInventoryAudit.setBillid(omsInventoryOrder.getBillid());
                            omsInventoryAudit.setType(omsInventoryOrder.getType());
                            WmsAdjustD adjustD = this.adjustDMapper.findById(lineid, WmsAdjustD.class);
                            if (!ObjectUtils.isNull(adjustD)) {
                                noPassAuditIds.add(lineid);
                                noPassList.add(omsInventoryAudit);
                            } else {
                                logger.error("审核对应的损溢明细为空!行id->" + lineid);
                            }
                        } else {
                            logger.error("审核对应的申请明细为空!单号" + billno + "行号" + seqno);
                        }
                        //                      if (!ObjectUtils.isNull(noPassAuditIds)) {
                        //                          logger.info("需要损溢不通过的损溢行id->" + noPassAuditIds.toString());
                        //                          excuteAuditNoPass(noPassAuditIds, auditList, userDTO);
                        //                      } else {
                        //                          logger.error("审核对应的损溢明细为空!单号" + billno + "行号" + seqno);
                        //                      }

                    }

                }

                if (!ObjectUtils.isNull(passList)) {
                    logger.info("需要扣减库存的损溢行id->" + passAuditIds.toString());
                    excuteAuditPass(passAuditIds, passList, userDTO);
                } else {
                    logger.info("审核对应的损溢明细为空!");
                }

                if (!ObjectUtils.isNull(noPassList)) {
                    logger.info("需要损溢不通过的损溢行id->" + noPassAuditIds.toString());
                    excuteAuditNoPass(noPassAuditIds, noPassList, userDTO);
                } else {
                    logger.info("审核对应的损溢明细为空!");
                }

            }
        }
        if (HystrixRequestContext.isCurrentThreadInitialized()) {
            HystrixRequestContext.getContextForCurrentThread().shutdown();
        }
    }

    /**
     * erp损溢通过处理
     *
     * @param passAuditIds
     */
    private void excuteAuditPass(List<String> passAuditIds, List<OmsInventoryAudit> AuditModelList, UserDTO userDTO) {
        if (!ObjectUtils.isNull(passAuditIds)) {
            logger.info("损溢通过的行id" + passAuditIds);
            if (confirmAdjust(passAuditIds)) {
                Date now = new Date();
                // 库存损溢成功,回传erp结果
                excuteCallbackResult(AuditModelList, userDTO, now, "10");
                // 更新状态
                excuteUpdateAdjustStatus(passAuditIds, userDTO, now, "50");
            }
        }
    }

    /**
     * 更新损溢调整状态
     *
     * @param passAuditIds
     * @param userDTO
     * @param now
     * @param status
     */
    private void excuteUpdateAdjustStatus(List<String> passAuditIds, UserDTO userDTO, Date now, String status) {
        String userId = userDTO.getId();
        String username = userDTO.getUsername();
        Criteria criteria = Criteria.forClass(WmsAdjustD.class);
        criteria.setRestriction(Restrictions.in("adjustLineId", passAuditIds.toArray(new String[passAuditIds.size()])));
        // 更新状态
        Map<String, Object> map = MapUtils.put("status", status).put("gmtModified", now).put("modifierName", username).getMap();
        if (!StringUtils.isEmpty(userId)) {
            map.put("modifier", userId);
        }
        adjustDMapper.updateMapByCriteria(map, criteria);

    }

    /**
     * 执行回传erp 损溢调整成功后数据保存 损溢结果回传
     *
     * @param auditModelList
     * @param userDTO
     * @param now
     */
    public void excuteCallbackResult(List<OmsInventoryAudit> auditModelList, UserDTO userDTO, Date now, String status) {
        logger.info("回传erp损溢结果数据------------------------------");
        List<OmsInventoryResult> resultList = new ArrayList<>();
        for (OmsInventoryAudit omsInventoryAudit : auditModelList) {
            OmsInventoryResult result = new OmsInventoryResult();
            //          // 需要查询对应的order表取效期数据
            //          String billno = omsInventoryAudit.getBillno();
            //          List<OmsInventoryOrder> findByMap = omsInventoryOrderMapper
            //                  .findByMap(MapUtils.put("billno", billno).getMap(), OmsInventoryOrder.class);
            //          if (!ObjectUtils.isNull(findByMap) && findByMap.get(0) != null) {
            //              OmsInventoryOrder omsInventoryOrder = findByMap.get(0);
            //              Date productionDate = omsInventoryOrder.getProductionDate();
            //              Date expiredDate = omsInventoryOrder.getExpiredDate();
            //              result.setProductionDate(productionDate);
            //              result.setExpiredDate(expiredDate);
            //          }

            BeanUtils.copyProperties(omsInventoryAudit, result);
            result.setStatus(status);
            result.setCreatedate(now);
            result.setCreateby(userDTO.getUsername());
            result.setLastmodifydate(now);
            result.setLastmodifyby(userDTO.getUsername());
            Date productionDate = result.getProductionDate();
            Date expiredDate = result.getExpiredDate();
            if (productionDate == null) {
                Date productionDate2 = new Date();
                String attrStr2 = result.getAttrStr2();
                if (!StringUtils.isEmpty(attrStr2)) {
                    if (attrStr2.length() == 6) {
                        try {
                            productionDate2 = sdf2.parse(attrStr2);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                    if (attrStr2.length() == 8) {
                        try {
                            productionDate2 = sdf1.parse(attrStr2);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }
                result.setProductionDate(productionDate2);
            }
            if (expiredDate == null) {
                Date expiredDate2 = new Date();
                String attrStr3 = result.getAttrStr3();
                if (!StringUtils.isEmpty(attrStr3)) {
                    if (attrStr3.length() == 6) {
                        try {
                            expiredDate2 = sdf2.parse(attrStr3);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                    if (attrStr3.length() == 8) {
                        try {
                            expiredDate2 = sdf1.parse(attrStr3);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }
                result.setExpiredDate(expiredDate2);
            }

            String reason = result.getReason();
            if (StringUtils.isEmpty(reason)) {
                result.setReason("N/A");
            }
            result.setDatasource("1");
            resultList.add(result);
        }
        omsInventoryResultMapper.saveBatch(resultList);
        Set<String> collect = auditModelList.stream().map(OmsInventoryAudit::getBillid).collect(Collectors.toSet());
        //      String billid = String.join(",", collect);

        executor.execute(() -> {
            try {
                Thread.sleep(callSleepTimes);
                asyncResult(collect);
            } catch (InterruptedException | IllegalArgumentException e) {
                logger.error("损溢结果回传失败,单id:" + new ArrayList(collect).toString());
            }
        });

    }

    /**
     * 执行回传erp 损溢调整成功后数据保存 损溢结果回传
     *
     * @param adjustDList adjustDList
     * @param userDTO     userDTO
     * @param now         now
     * @author lihao lihao
     * @since 2021-12-1
     */
    public void excuteCallbackZftResult(List<WmsAdjustD> adjustDList, UserDTO userDTO, Date now, String status) {
        logger.info("回传erp损溢结果数据------------------------------正方体");
        excuteCallback2Result(adjustDList, userDTO, now, status);
    }

    private void asyncResult(Set<String> collect) {
        for (String billid : collect) {
            // 回传损溢结果
            EtlMessage em = new EtlMessage();
            em.setId(billid);
            em.setEtlType(EtlTypeConstants.op_pl_audit_w2o);
            try {
                logger.info("盘点损溢回传结果数据->data-exchange{}", JsonUtils.toString(em));
                exchangeSender.send(em);
            } catch (Exception e) {
                logger.error("回传data-exchange错误!原因{}", e);
            }
        }

    }

    /**
     * erp损溢不通过处理
     *
     * @param noPassAuditIds
     */
    private void excuteAuditNoPass(List<String> noPassAuditIds, List<OmsInventoryAudit> AuditModelList, UserDTO userDTO) {
        String username = userDTO.getUsername();
        String userId = userDTO.getId();
        Date now = new Date();
        Criteria criteria = Criteria.forClass(WmsAdjustD.class);
        criteria.setRestriction(Restrictions.in("adjustLineId", noPassAuditIds.toArray(new String[noPassAuditIds.size()])));
        Map<String, Object> map = MapUtils.put("status", "40").put("gmtModified", now).put("modifierName", username).getMap();
        if (!StringUtils.isEmpty(userId)) {
            map.put("modifier", userId);
        }
        // 更新状态
        adjustDMapper.updateMapByCriteria(map, criteria);

        // 是否需要回传erp驳回结果?
        // 取消预占

    }

    /**
     * 损溢确认 扣减库存
     */
    private boolean confirmAdjust(List<String> adjustLineIds) {
        logger.info("损溢确认执行远程调用库存服务---------------------------------");
        if (!ObjectUtils.isNull(adjustLineIds)) {
            logger.info("开始调用库存服务,确认损溢->数据{}", adjustLineIds);
            InvStockCheck c = new InvStockCheck();
            c.setLineBillIds(adjustLineIds.toArray(new String[adjustLineIds.size()]));
            @SuppressWarnings("rawtypes") RestMessage result = null;
            try {
                result = stockResource.adjustStockCheck(c);
            } catch (Exception e) {
                logger.error("调用库存服务失败!原因:{}", e);
                return false;
            }
            if (result != null && result.isSuccess()) {
                logger.info("调用库存服务成功!");
                return true;
            }
            if (result != null && !result.isSuccess()) {
                Object data = result.getData();
                if (data != null) {
                    logger.info("调用库存服务成功,操作失败,原因{}", data.toString());
                } else {
                    logger.info("调用库存服务成功,操作失败,原因{}", result.getMessage());
                }

                return false;
            }
        }
        return false;
    }

    @Override
    public void doCallBack2erp(String billno) {
        String[] split = billno.split(",");
        Criteria crt = Criteria.forClass(OmsInventoryAudit.class);
        crt.setRestriction(Restrictions.in("billno", split));
        List<OmsInventoryAudit> findByIds = this.omsInventoryAuditMapper.findByCriteria(crt);

        for (OmsInventoryAudit omsInventoryAudit : findByIds) {
            String billno2 = omsInventoryAudit.getBillno();
            omsInventoryAudit.setBillid(billno2);
            String seqno = omsInventoryAudit.getSeqno();
            Restriction eq = null;
            if (!StringUtils.isEmpty(seqno)) {
                eq = Restrictions.eq("seqno", seqno);
            }
            Criteria crt2 = Criteria.forClass(OmsInventoryOrder.class);
            crt2.setRestriction(Restrictions.and(Restrictions.eq("billno", billno2), eq));
            List<OmsInventoryOrder> OmsInventoryOrders = this.omsInventoryOrderMapper.findByCriteria(crt2);
            if (!ObjectUtils.isNull(OmsInventoryOrders)) {
                OmsInventoryOrder omsInventoryOrder = OmsInventoryOrders.get(0);
                Date productionDate = omsInventoryOrder.getProductionDate();
                Date expiredDate = omsInventoryOrder.getExpiredDate();
                omsInventoryAudit.setProductionDate(productionDate);
                omsInventoryAudit.setExpiredDate(expiredDate);
                omsInventoryAudit.setBillid(omsInventoryOrder.getBillid());
                omsInventoryAudit.setType(omsInventoryOrder.getType());
            }
        }

        excuteCallbackResult(findByIds, userTemplate.getUserDTO(), new Date(), "10");

    }

    @Override
    public void doCallBackResult2erp(String billids) {
        // 取回传结果直接使用mq同步到oms
        String[] split = billids.split(",");
        Criteria crt = Criteria.forClass(OmsInventoryResult.class);
        crt.setRestriction(Restrictions.in("billid", split));
        List<OmsInventoryResult> findByIds = this.omsInventoryResultMapper.findByCriteria(crt);
        if (!ObjectUtils.isNull(findByIds)) {
            Set<String> collect = findByIds.stream().map(OmsInventoryResult::getBillid).collect(Collectors.toSet());
            for (String id : collect) {
                // 回传损溢结果
                EtlMessage em = new EtlMessage();
                em.setId(id);
                em.setEtlType(EtlTypeConstants.op_pl_audit_w2o);
                try {
                    logger.info("盘点损溢回传结果数据->data-exchange{}", JsonUtils.toString(em));
                    exchangeSender.send(em);
                } catch (Exception e) {
                    logger.error("回传data-exchange错误!原因{}", e);
                }
            }
        }

    }

    /**
     * erp盘点生成损益单
     */
    @Override
    @Transactional
    // 无法加分布式事务又生产批次又预占
    public void genAdjust(List<ErpAdjustAddVO> ErpAdjustAddVOList) {
        AssertUtils.isNotEmpty(ErpAdjustAddVOList, "转损溢的数据不可为空!");
        Map<String, List<ErpAdjustAddVO>> collect = ErpAdjustAddVOList.stream().collect(Collectors.groupingBy(ErpAdjustAddVO::getAdjustHeaderId));
        try {
            String string = JsonUtils.toString(ErpAdjustAddVOList);
            logger.info("转损溢的数据->" + string);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        for (List<ErpAdjustAddVO> wmsAdjustAddVOL : collect.values()) {
            ErpAdjustAddVO wmsAdjustAddVO = wmsAdjustAddVOL.get(0);
            UserDTO userDTO = userTemplate.getUserDTO();
            Date date = new Date();
            String userId = userDTO.getId();
            String userName = userDTO.getNickname();
            String enterpriseId = userDTO.getEnterpriseId();

            // 保存头表
            WmsAdjustH wmsAdjustH = new WmsAdjustH();
            String adjustHeaderId = wmsAdjustAddVO.getAdjustHeaderId();
            String autoBillNum = wmsAdjustAddVO.getAutoBillNum();
            wmsAdjustH.setAdjustHeaderId(adjustHeaderId);
            wmsAdjustH.setAutoBillNum(autoBillNum);
            wmsAdjustH.setAccessLevel("9");
            wmsAdjustH.setWarehouseId(wmsAdjustAddVO.getWarehouseId());
            wmsAdjustH.setCargoOwnerId(wmsAdjustAddVO.getCargoOwnerId());
            wmsAdjustH.setAdjustDate(date);
            wmsAdjustH.setEnterpriseId(enterpriseId);
            wmsAdjustH.setStatus("NEW");
            wmsAdjustH.setCreator(userId);
            wmsAdjustH.setCreatorName(userName);
            wmsAdjustH.setGmtCreate(date);
            wmsAdjustH.setModifier(userId);
            wmsAdjustH.setModifierName(userName);
            wmsAdjustH.setGmtModified(date);
            wmsAdjustH.setAdjustType("3"); // erp发起的调整
            wmsAdjustH.setAttribute5("2"); // 数据来源 erp发起的调整
            adjustHMapper.save(wmsAdjustH);

            // 保存明细
            Long row = 0L;
            List<InvStockAdjust> invStockList = new ArrayList<>();
            Map<String, BigDecimal> lineTotal = new HashMap<>();
            //          BigDecimal total = BigDecimal.ZERO;

            List<ErpAdjustAddVO> addList = new ArrayList<>();
            List<WmsAdjustD> preInstockList = new ArrayList<>();
            for (ErpAdjustAddVO wmsAdjustAddVO2 : wmsAdjustAddVOL) {
                row++;
                vaildateDatails(wmsAdjustAddVO2);

                excuteHandleDate(wmsAdjustAddVO2);

                // 校验并生成批次数据
                String id = String.valueOf(SnowFlakeUtils.getId());
                wmsAdjustAddVO2.setAdjustLineId(id);
                vaildateDatailsBatchInfo(wmsAdjustAddVO2, addList);

                //              String batchId = wmsAdjustAddVO2.getBatchId();
                //              AssertUtils.isNotBlank(batchId, "批次id(batchId)不可为空!");
                BigDecimal pieceQuantity = wmsAdjustAddVO2.getPieceQuantity();
                if (pieceQuantity == null) {
                    pieceQuantity = BigDecimal.ZERO;
                }
                String lineId = wmsAdjustAddVO2.getLineId();
                BigDecimal bigDecimal = lineTotal.get(lineId);
                if (bigDecimal != null) {
                    BigDecimal add = bigDecimal.add(pieceQuantity);
                    lineTotal.put(lineId, add);
                } else {
                    lineTotal.put(lineId, pieceQuantity);
                }

                //              total.add(pieceQuantity);

                WmsAdjustD model = new WmsAdjustD();
                BeanUtils.copyProperties(wmsAdjustAddVO2, model);
                String stockStatus = wmsAdjustAddVO2.getStockStatus();
                if (StringUtils.isEmpty(stockStatus)) {
                    model.setStockStatus("1");
                }

                //              model.setLineNum(row); // 行号前端传
                model.setLineNum(Long.parseLong(wmsAdjustAddVO2.getSeqno()));
                model.setSegment5(wmsAdjustAddVO2.getLineId()); // erp明细行号
                model.setCreator(userId);
                model.setCreatorName(userName);
                model.setGmtCreate(date);
                model.setModifier(userId);
                model.setModifierName(userName);
                model.setGmtModified(date);
                model.setCargoOwnerId(wmsAdjustAddVO2.getCargoOwnerId());
                model.setAdjustHeaderId(adjustHeaderId);
                model.setBatchId(stockStatus);
                model.setStatus("0");
                model.setBatchId(wmsAdjustAddVO2.getBatchId());
                model.setBatchNum(wmsAdjustAddVO2.getBatchNum());
                model.setBillno(autoBillNum);
                model.setAdjustLineId(id);
                String adjustBillType = wmsAdjustAddVO2.getAdjustBillType();
                if (!StringUtils.isBlank(adjustBillType) && adjustBillType.equals("1")) {
                    // 报溢单取反
                    pieceQuantity = pieceQuantity.negate();
                }
                model.setPieceQuantity(pieceQuantity); // 差异数
                model.setQuantity(model.getPieceQuantity());
                model.setEnterpriseId(enterpriseId);
                adjustDMapper.save(model);
                preInstockList.add(model);

            }
            // 校验erp发起损溢明细拆分后,生成wms损溢明细数量应该一致
            if (!ObjectUtils.isEmpty(lineTotal)) {
                vaildateErpLine(lineTotal, autoBillNum);
            }

            //          // 校验生成损溢总量和erp待调整总量是否一致,通过adjustHeaderId找到对应的明细的数据(多条总数)
            //          Criteria crt = Criteria.forClass(OmsInventoryOrder.class);
            //          crt.setRestriction(Restrictions.eq("billid", adjustHeaderId));
            //          List<OmsInventoryOrder> findByCriteria = omsInventoryOrderMapper.findByCriteria(crt);
            //          AssertUtils.isNotEmpty(findByCriteria, "损溢单号->" + autoBillNum + "对应的损益单数据库数据为空!请检查重试!");
            //          BigDecimal reduce = findByCriteria.stream().map(i -> {
            //              if (i.getAmount() == null) {
            //                  return BigDecimal.ZERO;
            //              } else {
            //                  return i.getAmount();
            //              }
            //          }).reduce(BigDecimal.ZERO, BigDecimal::add);
            //          if (reduce.compareTo(total) != 0) {
            //              throw new BizException("生成的损溢单数量对不上erp需要调整的数量!请检查重试!");
            //          }
            if (!ObjectUtils.isNull(addList)) {
                // 生成批次数据,并更新明细
                genBatchInfo(addList, invStockList);
            }

            for (WmsAdjustD model : preInstockList) {
                excutePreStock(invStockList, wmsAdjustH, model);
            }

            // 进行库存预占(可能和生成批次发生冲突,导致抛错,除非异步预占)
            RestMessage adjustStock = stockResource.adjustStock(invStockList);
            if (adjustStock != null && !adjustStock.isSuccess()) {
                throw new BizException("调用库存预占失败!原因->" + adjustStock.getMessage());
            }
        }
    }

    /**
     * 转换日期
     *
     * @param wmsAdjustAddVO2
     */
    private void excuteHandleDate(ErpAdjustAddVO wmsAdjustAddVO2) {
        Date expiredDate = wmsAdjustAddVO2.getBatchExpiredDate();
        Date productionDate = wmsAdjustAddVO2.getProductionDate();
        if (expiredDate != null && productionDate != null) {
            return;
        }
        String showProductionDate = wmsAdjustAddVO2.getShowProductionDate();
        String showExpiredDate = wmsAdjustAddVO2.getShowExpiredDate();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMM");
        Date date = new Date();
        if (productionDate == null) {
            if (StringUtils.isBlank(showProductionDate)) {
                Date parse1 = null;
                if ("*".equals(showProductionDate)) {
                    date.setHours(0);
                    date.setMinutes(0);
                    date.setSeconds(0);
                    parse1 = date;
                } else if (showProductionDate.length() == 6) {
                    try {
                        parse1 = sdf2.parse(showProductionDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                } else if (showProductionDate.length() == 8) {
                    try {
                        parse1 = sdf1.parse(showProductionDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                if (parse1 == null) {
                    parse1 = date;
                }
                productionDate = parse1;
            }
        }
        if (expiredDate == null) {
            if (StringUtils.isBlank(showExpiredDate)) {
                Date parse = null;
                if ("*".equals(showExpiredDate)) {
                    try {
                        parse = sdf1.parse("20990101");
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                } else if (showExpiredDate.length() == 6) {
                    try {
                        parse = sdf2.parse(showExpiredDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                } else if (showExpiredDate.length() == 8) {
                    try {
                        parse = sdf1.parse(showExpiredDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                if (parse == null) {
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(date);// 设置起时间
                    cal.add(Calendar.YEAR, 100);// 增加100年
                    parse = cal.getTime();
                }
                expiredDate = parse;
            }
        }
        wmsAdjustAddVO2.setProductionDate(productionDate);
        wmsAdjustAddVO2.setBatchExpiredDate(expiredDate);
    }

    /**
     * 生产新的批次信息
     *
     * @param addList
     * @param invStockList
     */
    private void genBatchInfo(List<ErpAdjustAddVO> addList, List<InvStockAdjust> invStockList) {
        ValidList<InvStockBatchNumber> invStockBatchNumberList = new ValidList<InvStockBatchNumber>();
        excuteBuildGetBatchIdCondition(addList, invStockBatchNumberList, new Date());
        RestMessage<List<InvStockBatchNumberResult>> genBatchNumber = null;
        List<InvStockBatchNumberResult> data = excuteHandlerRemoteError(invStockBatchNumberList, genBatchNumber);
        AssertUtils.isNotEmpty(data, "生成的批次信息为空!");

        Map<String, List<InvStockBatchNumberResult>> collect2 = Optional.ofNullable(data).orElse(Collections.emptyList()).stream().filter(p -> !StringUtils.isBlank(p.getRcvLineId())).collect(Collectors.groupingBy(InvStockBatchNumberResult::getRcvLineId));
        // Step3: 更新的batchNum,batchId
        for (ErpAdjustAddVO dto : addList) {
            String rcvLineId = dto.getAdjustLineId();
            List<InvStockBatchNumberResult> list = collect2.get(rcvLineId);
            if (!ObjectUtils.isNull(list)) {
                InvStockBatchNumberResult invStockBatchNumberResult = list.get(0);
                String batchId = invStockBatchNumberResult.getBatchId();
                String batchNum = invStockBatchNumberResult.getBatchNum();
                this.adjustDMapper.updateMapById(rcvLineId, MapUtils.put("batchId", batchId).put("batchNum", batchNum).getMap(), WmsAdjustD.class);
                dto.setBatchId(batchId);
                dto.setBatchNum(batchNum);
            }

        }
    }

    private List<InvStockBatchNumberResult> excuteHandlerRemoteError(ValidList<InvStockBatchNumber> invStockBatchNumberList, RestMessage<List<InvStockBatchNumberResult>> genBatchNumber) {
        if (ObjectUtils.isNull(invStockBatchNumberList)) {
            return null;
        }
        try {
            // logger.info("调用库存接口genBatchNumber，入参："+
            // JsonUtils.toString(invStockBatchNumberList));
            logger.info("调用库存接口genBatchNumber，入参：" + JsonUtils.toString(invStockBatchNumberList));
            genBatchNumber = stockResource.genBatchNumber(invStockBatchNumberList);
            if (genBatchNumber != null) {
                logger.info("返回结果：" + JsonUtils.toString(genBatchNumber));
            }
        } catch (Exception e) {
            logger.error("调用远程生成批次信息出现错误错误!", e);
            throw new BizException("调用远程库存服务生成批次信息错误!请联系管理员处理!");
        }
        if (genBatchNumber == null)
            throw new BizException("远程调用库存服务获取数据为空!请联系管理员处理!");

        if (genBatchNumber.isSuccess() && genBatchNumber.getData() == null)
            throw new BizException("生成批次信息为空!请联系管理员处理!");

        if (!genBatchNumber.isSuccess()) {
            if (!ObjectUtils.isNull(genBatchNumber.getData())) {
                throw new BizException("远程调用库存服务错误!原因->" + genBatchNumber.getMessage() + genBatchNumber.getData());
            } else {
                throw new BizException("远程调用库存服务错误!原因->" + genBatchNumber.getMessage());
            }

        }

        List<InvStockBatchNumberResult> data = genBatchNumber.getData();
        return data;
    }

    private void excuteBuildGetBatchIdCondition(List<ErpAdjustAddVO> addList, ValidList<InvStockBatchNumber> invStockBatchNumberList, Date now) {
        // 组装生产批次数据
        ErpAdjustAddVO erpAdjustAddVO = addList.get(0);
        String asnHeaderId = erpAdjustAddVO.getAdjustHeaderId();
        Date rcvDate = now;
        String mtlOwnerId = erpAdjustAddVO.getCargoOwnerId();
        String vendorId = "N/A";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        for (ErpAdjustAddVO rcvLinesDTO : addList) {
            InvStockBatchNumber result = new InvStockBatchNumber();
            Date batchExpiredDate = rcvLinesDTO.getBatchExpiredDate();
            Date batchProductionDate = rcvLinesDTO.getProductionDate();
            String erpBatchNum = "N/A";
            String itemId = rcvLinesDTO.getItemId();
            String manufacturerLotNum = rcvLinesDTO.getManufacturerLotNum();
            String orgId = "N/A";
            BigDecimal piecePriceTe = BigDecimal.ONE;
            BigDecimal piecePriceTi = BigDecimal.ONE;
            String productionPlace = "N/A";
            BigDecimal shelfLifeDays = BigDecimal.ONE;
            BigDecimal taxRate = BigDecimal.ONE;
            if (null == piecePriceTe)
                piecePriceTe = BigDecimal.ZERO; // 不含税
            if (null == piecePriceTi)
                piecePriceTi = BigDecimal.ZERO; // 含税
            // 税率 = (含税-不含税)/不含税
            if (null == taxRate && BigDecimal.ZERO.compareTo(piecePriceTe) != 0)
                taxRate = (piecePriceTe.subtract(piecePriceTe)).divide(piecePriceTe, 4, RoundingMode.HALF_UP);
            if (null == taxRate)
                taxRate = BigDecimal.ONE;
            String vendorBatchNum = "N/A";
            String rcvLineId = rcvLinesDTO.getAdjustLineId();

            // 需要加入批次id的处理

            result.setRcvLineId(rcvLineId);
            result.setAsnId(asnHeaderId);
            result.setBatchExpiredDate(batchExpiredDate);
            result.setBatchProductionDate(batchProductionDate);
            result.setCargoOwnerId(mtlOwnerId);
            result.setErpBatchNum(erpBatchNum);
            result.setGradeId("9");
            result.setItemId(itemId);
            result.setManufacturerLotNum(manufacturerLotNum);
            result.setOrgnId(orgId);
            result.setPieceCostTe(piecePriceTe);
            result.setPieceCostTi(piecePriceTi);
            result.setProductionPlace(productionPlace);
            result.setRcvDate(rcvDate);
            if (shelfLifeDays != null) {
                result.setShelfLifeDays(shelfLifeDays);
            } else {
                result.setShelfLifeDays(BigDecimal.valueOf(90));
            }
            result.setTaxRate(taxRate);
            result.setVendorBatchNum(vendorBatchNum);
            result.setVendorId(vendorId);
            String showProductionDate = rcvLinesDTO.getShowProductionDate();
            String showExpiredDate = rcvLinesDTO.getShowExpiredDate();
            if (StringUtils.isBlank(showProductionDate)) {
                showProductionDate = sdf.format(batchProductionDate);
            }
            if (StringUtils.isBlank(showExpiredDate)) {
                showExpiredDate = sdf.format(batchExpiredDate);
            }
            result.setBatchProductionDateShow(showProductionDate);
            result.setBatchExpiredDateShow(showExpiredDate);
            invStockBatchNumberList.add(result);
        }
    }

    /**
     * 校验并生成批次数据
     *
     * @param wmsAdjustAddVO2
     * @param addList
     */
    private void vaildateDatailsBatchInfo(ErpAdjustAddVO wmsAdjustAddVO2, List<ErpAdjustAddVO> addList) {
        String manufacturerLotNum = wmsAdjustAddVO2.getManufacturerLotNum();
        String showExpiredDate = wmsAdjustAddVO2.getShowExpiredDate();
        String showProductionDate = wmsAdjustAddVO2.getShowProductionDate();
        String itemId = wmsAdjustAddVO2.getItemId();
        String batchId = wmsAdjustAddVO2.getBatchId();
        Set<String> set = new HashSet<>();
        if (!StringUtils.isBlank(batchId)) {
            set.add(batchId);
        }
        Set<String> set2 = new HashSet<>();
        Set<String> set3 = new HashSet<>();
        set2.add(itemId);
        set3.add(manufacturerLotNum);
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("batchIds", set);
        queryMap.put("itemIds", set2);
        queryMap.put("manufacturerLotNums", set3);
        queryMap.put("showProductionDate", showProductionDate);
        queryMap.put("showExpiredDate", showExpiredDate);
        String cargoOwnerId = wmsAdjustAddVO2.getCargoOwnerId();
        // 货主
        queryMap.put("cargoOwnerId", cargoOwnerId);

        String format = String.format("商品id[%s],批次id[%s],批号[%s],生产日期[%s],有效期至[%s],商品批次信息表中不存在,请检查后联系管理员处理!", itemId, batchId, manufacturerLotNum, showProductionDate, showExpiredDate);
        List<Map> searchForMap = null;
        try {
            searchForMap = searchApi.searchForMap("getBatchInfo", queryMap);
        } catch (Exception e1) {
            logger.info(format + "找寻商品批次信息失败,原因{}", e1);
            throw new BizException(format + "找寻商品批次信息失败,原因->" + e1.getMessage());
        }
        if (ObjectUtils.isNull(searchForMap)) {
            logger.info(format + "找寻商品批次信息为空!准备生成新的批次信息!");
            addList.add(wmsAdjustAddVO2);
        } else {
            // 匹配批次
            boolean flag = matchBatchInfo(searchForMap, wmsAdjustAddVO2);
            if (!flag) {
                addList.add(wmsAdjustAddVO2);
            }
        }
    }

    private boolean matchBatchInfo(List<Map> searchForMap, ErpAdjustAddVO wmsAdjustAddVO2) {
        for (Map map : searchForMap) {
            // 如果batchId匹配成功,则不发生改变
            String batchId2 = (String) map.get("batchId");
            String batchNum2 = (String) map.get("batchNum");
            String batchId = wmsAdjustAddVO2.getBatchId();
            if (!StringUtils.isBlank(batchId) && batchId2.equals(batchId)) {
                return true;
            }
            String showProductionDate2 = (String) map.get("showProductionDate");
            String showExpiredDate2 = (String) map.get("showExpiredDate");
            String manufacturerLotNum2 = (String) map.get("manufacturerLotNum");
            String manufacturerLotNum = wmsAdjustAddVO2.getManufacturerLotNum();
            String showExpiredDate = wmsAdjustAddVO2.getShowExpiredDate();
            String showProductionDate = wmsAdjustAddVO2.getShowProductionDate();
            if (StringUtils.isBlank(batchId) && !StringUtils.isBlank(manufacturerLotNum2) && !StringUtils.isBlank(showProductionDate2) && !StringUtils.isBlank(showExpiredDate2) && manufacturerLotNum2.equals(manufacturerLotNum) && showProductionDate2.equals(showProductionDate) && showExpiredDate2.equals(showExpiredDate)) {
                wmsAdjustAddVO2.setBatchId(batchId2);
                wmsAdjustAddVO2.setBatchNum(batchNum2);
                return true;
            }
        }
        return false;
    }

    private void vaildateErpLine(Map<String, BigDecimal> lineTotal, String autoBillNum) {
        Set<Entry<String, BigDecimal>> entrySet = lineTotal.entrySet();
        for (Entry<String, BigDecimal> entry : entrySet) {
            String lineid = entry.getKey();
            Criteria crt = Criteria.forClass(OmsInventoryOrder.class);
            crt.setRestriction(Restrictions.eq("lineid", lineid));
            List<OmsInventoryOrder> findByCriteria = omsInventoryOrderMapper.findByCriteria(crt);
            AssertUtils.isNotEmpty(findByCriteria, "损溢单号->" + autoBillNum + "," + "linid->" + lineid + "对应的损益单明细数据库数据为空!请检查重试!");
            OmsInventoryOrder omsInventoryOrder = findByCriteria.get(0);
            String seqno = omsInventoryOrder.getSeqno();
            BigDecimal amount = omsInventoryOrder.getAmount();
            if (amount == null) {
                amount = BigDecimal.ZERO;
            }
            BigDecimal value = entry.getValue();
            if (value.compareTo(amount) != 0) { // 拆分的wms明细大于erp明细行,抛错
                throw new BizException(String.format("损溢单号[%s],明细id[%s],行号[%s],对应的wms损溢数量[%s]不等于原erp明细数量[%s],请检查重试!", autoBillNum, lineid, seqno, value.toString(), amount.toString()));
            }

            // 更新order表状态
            if (value.compareTo(amount) == 0) {
                omsInventoryOrderMapper.updateMapByCriteria(MapUtils.put("status", "20").put("lastmodifydate", new Date()).getMap(), crt);
            }
        }

    }

    private void vaildateDatails(ErpAdjustAddVO adjustAddVO2) {
        // 校验损溢数据
        String adjustHeaderId = adjustAddVO2.getAdjustHeaderId();
        AssertUtils.isNotBlank(adjustHeaderId, "单据id(adjustHeaderId)不可为空!");
        String autoBillNum = adjustAddVO2.getAutoBillNum();
        AssertUtils.isNotBlank(autoBillNum, "单据编号(autoBillNum)不可为空!");
        String warehouseId = adjustAddVO2.getWarehouseId();
        AssertUtils.isNotBlank(warehouseId, "仓库id(warehouseId)不可为空!");
        String cargoOwnerId = adjustAddVO2.getCargoOwnerId();
        AssertUtils.isNotBlank(cargoOwnerId, "货主id(cargoOwnerId)不可为空!");
        String whLocatorId = adjustAddVO2.getCargoOwnerId();
        AssertUtils.isNotBlank(whLocatorId, "货位id(whLocatorId)不可为空!");
        String itemId = adjustAddVO2.getItemId();
        AssertUtils.isNotBlank(itemId, "商品id(itemId)不可为空!");
        BigDecimal pieceQuantity = adjustAddVO2.getPieceQuantity();
        AssertUtils.isNotNull(pieceQuantity, "调整数量(pieceQuantity)不可为空!");
        String adjustBillType = adjustAddVO2.getAdjustBillType();
        AssertUtils.isNotBlank(adjustBillType, "损溢类型(adjustBillType)不可为空!");
        String seqno = adjustAddVO2.getSeqno();
        AssertUtils.isNotBlank(seqno, "明细行号(seqno)不可为空!");

        String manufacturerLotNum = adjustAddVO2.getManufacturerLotNum();
        AssertUtils.isNotBlank(manufacturerLotNum, "商品批号(manufacturerLotNum)不可为空!");
        String showProductionDate = adjustAddVO2.getShowProductionDate();
        AssertUtils.isNotBlank(showProductionDate, "显示生产日期(showProductionDate)不可为空!");
        String showExpiredDate = adjustAddVO2.getShowExpiredDate();
        AssertUtils.isNotBlank(showProductionDate, "显示有效期至(showExpiredDate)不可为空!");

    }

    @Override
    @Transactional
    public void rejectErpForGen(List<ErpAdjustAddVO> erpAdjustAddVOList) {
        // 生成损溢单时驳回erp损溢请求
        logger.info("erp发起损溢全驳回开始-----------------------------------");
        AssertUtils.isNotEmpty(erpAdjustAddVOList, "损溢驳回的数据不可为空!");
        Map<String, List<ErpAdjustAddVO>> collect = erpAdjustAddVOList.stream().collect(Collectors.groupingBy(ErpAdjustAddVO::getAdjustHeaderId));
        UserDTO userDTO = userTemplate.getUserDTO();
        AssertUtils.notNull(userDTO, "用户对象为空!");
        Date now = new Date();
        for (List<ErpAdjustAddVO> wmsAdjustAddVOL : collect.values()) {
            // 多单回传
            ErpAdjustAddVO erpAdjustAddVO = wmsAdjustAddVOL.get(0);
            String autoBillNum = erpAdjustAddVO.getAutoBillNum();
            String adjustHeaderId = erpAdjustAddVO.getAdjustHeaderId();

            Map<String, String> lineRemark = new HashMap<>();
            for (ErpAdjustAddVO wmsAdjustAddVO2 : wmsAdjustAddVOL) {
                String lineId = wmsAdjustAddVO2.getLineId();
                String remark = wmsAdjustAddVO2.getRemark();
                String remarkm = lineRemark.get(lineId);
                if (StringUtils.isNotEmpty(remarkm)) {
                    String concat = remarkm.concat(remark);
                    lineRemark.put(lineId, concat);
                } else {
                    lineRemark.put(lineId, remark);
                }
            }
            Criteria crt2 = Criteria.forClass(OmsInventoryOrder.class);
            crt2.setRestriction(Restrictions.eq("billid", adjustHeaderId));
            logger.info("erp发起损溢全驳回更新order表-----------------------------------");
            omsInventoryOrderMapper.updateMapByCriteria(MapUtils.put("status", "30").put("lastmodifydate", new Date()).getMap(), crt2); // 状态置为驳回
            List<OmsInventoryOrder> findByCriteria = omsInventoryOrderMapper.findByCriteria(crt2);
            AssertUtils.isNotEmpty(findByCriteria, "损溢单号->" + autoBillNum + "对应的损益单数据库数据为空!请检查重试!");
            List<OmsInventoryResult> resultList = new ArrayList<>();
            for (OmsInventoryOrder omsInventoryOrder : findByCriteria) {
                String lineid = omsInventoryOrder.getLineid();
                if (!ObjectUtils.isNull(lineRemark)) {
                    String value = lineRemark.get(lineid);
                    omsInventoryOrder.setRemark(value);
                    omsInventoryOrder.setReason(value);
                }
                OmsInventoryResult result = new OmsInventoryResult();
                excuteOrder2Result(omsInventoryOrder, result, userDTO, now);
                resultList.add(result);
            }

            omsInventoryResultMapper.saveBatch(resultList);
            Set<String> collect2 = resultList.stream().map(OmsInventoryResult::getBillid).collect(Collectors.toSet());

            executor.execute(() -> {
                try {
                    Thread.sleep(callSleepTimes);
                    asyncResult(collect2);
                } catch (InterruptedException | IllegalArgumentException e) {
                    logger.error("损溢结果回传失败,单id:" + new ArrayList<String>(collect2).toString());
                }
            });
        }
    }

    private void excuteOrder2Result(OmsInventoryOrder omsInventoryOrder, OmsInventoryResult result, UserDTO userDTO, Date now) {
        BeanUtils.copyProperties(omsInventoryOrder, result);
        result.setStatus("30");
        result.setCreatedate(now);
        result.setCreateby(userDTO.getUsername());
        result.setLastmodifydate(now);
        result.setLastmodifyby(userDTO.getUsername());
        Date productionDate = result.getProductionDate();
        Date expiredDate = result.getExpiredDate();
        if (productionDate == null) {
            Date productionDate2 = new Date();
            String attrStr2 = result.getAttrStr2();
            if (!StringUtils.isEmpty(attrStr2)) {
                if (attrStr2.length() == 6) {
                    try {
                        productionDate2 = sdf2.parse(attrStr2);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                if (attrStr2.length() == 8) {
                    try {
                        productionDate2 = sdf1.parse(attrStr2);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
            }
            result.setProductionDate(productionDate2);
        }
        if (expiredDate == null) {
            Date expiredDate2 = new Date();
            String attrStr3 = result.getAttrStr3();
            if (!StringUtils.isEmpty(attrStr3)) {
                if (attrStr3.length() == 6) {
                    try {
                        expiredDate2 = sdf2.parse(attrStr3);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                if (attrStr3.length() == 8) {
                    try {
                        expiredDate2 = sdf1.parse(attrStr3);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
            }
            result.setExpiredDate(expiredDate2);
        }

        String reason = result.getReason();
        if (StringUtils.isEmpty(reason)) {
            result.setReason("N/A");
        }
        String datasource = result.getDatasource();
        if (StringUtils.isEmpty(datasource)) {
            result.setDatasource("2");
        }
    }

    @Override
    public Object genBatchInfo(WmsAdjustAddVO addVO) {
        ValidList<InvStockBatchNumber> invStockBatchNumberList = new ValidList<InvStockBatchNumber>();
        excuteBuildGetBatchIdCondition(addVO, invStockBatchNumberList, new Date());
        RestMessage<List<InvStockBatchNumberResult>> genBatchNumber = null;
        List<InvStockBatchNumberResult> data = excuteHandlerRemoteError(invStockBatchNumberList, genBatchNumber);
        AssertUtils.isNotEmpty(data, "生成的批次信息为空!");
        return data;
    }

    private void excuteBuildGetBatchIdCondition(WmsAdjustAddVO addVO, ValidList<InvStockBatchNumber> invStockBatchNumberList, Date now) {
        // 组装生产批次数据
        String id = String.valueOf(SnowFlakeUtils.getId());
        String asnHeaderId = addVO.getAdjustHeaderId();
        if (StringUtils.isBlank(asnHeaderId)) {
            asnHeaderId = id;
            addVO.setAdjustHeaderId(id);
        }
        Date rcvDate = now;
        String mtlOwnerId = addVO.getCargoOwnerId();
        String vendorId = "N/A";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

        InvStockBatchNumber result = new InvStockBatchNumber();
        Date batchExpiredDate = addVO.getBatchExpiredDate();
        Date batchProductionDate = addVO.getProductionDate();
        String erpBatchNum = "N/A";
        String itemId = addVO.getItemId();
        String manufacturerLotNum = addVO.getManufacturerLotNum();
        String orgId = "N/A";
        BigDecimal piecePriceTe = BigDecimal.ONE;
        BigDecimal piecePriceTi = BigDecimal.ONE;
        String productionPlace = "N/A";
        BigDecimal shelfLifeDays = BigDecimal.ONE;
        BigDecimal taxRate = BigDecimal.ONE;
        if (null == piecePriceTe)
            piecePriceTe = BigDecimal.ZERO; // 不含税
        if (null == piecePriceTi)
            piecePriceTi = BigDecimal.ZERO; // 含税
        // 税率 = (含税-不含税)/不含税
        if (null == taxRate && BigDecimal.ZERO.compareTo(piecePriceTe) != 0)
            taxRate = (piecePriceTe.subtract(piecePriceTe)).divide(piecePriceTe, 4, RoundingMode.HALF_UP);
        if (null == taxRate)
            taxRate = BigDecimal.ONE;
        String vendorBatchNum = "N/A";
        String rcvLineId = id;
        result.setRcvLineId(rcvLineId);
        result.setAsnId(asnHeaderId);
        result.setBatchExpiredDate(batchExpiredDate);
        result.setBatchProductionDate(batchProductionDate);
        result.setCargoOwnerId(mtlOwnerId);
        result.setErpBatchNum(erpBatchNum);
        result.setGradeId("9");
        result.setItemId(itemId);
        result.setManufacturerLotNum(manufacturerLotNum);
        result.setOrgnId(orgId);
        result.setPieceCostTe(piecePriceTe);
        result.setPieceCostTi(piecePriceTi);
        result.setProductionPlace(productionPlace);
        result.setRcvDate(rcvDate);
        if (shelfLifeDays != null) {
            result.setShelfLifeDays(shelfLifeDays);
        } else {
            result.setShelfLifeDays(BigDecimal.valueOf(90));
        }
        result.setTaxRate(taxRate);
        result.setVendorBatchNum(vendorBatchNum);
        result.setVendorId(vendorId);
        String showProductionDate = addVO.getProductionDateShow();
        String showExpiredDate = addVO.getBatchExpiredDateShow();
        if (StringUtils.isBlank(showProductionDate)) {
            showProductionDate = sdf.format(batchProductionDate);
        }
        if (StringUtils.isBlank(showExpiredDate)) {
            showExpiredDate = sdf.format(batchExpiredDate);
        }
        result.setBatchProductionDateShow(showProductionDate);
        result.setBatchExpiredDateShow(showExpiredDate);
        invStockBatchNumberList.add(result);

    }

    @Override
    public Object hostAdd(WmsAdjustAddVO addVO) {
        String stockStatus = addVO.getStockStatus();
        if (StringUtils.isBlank(stockStatus) || !"5".equals(stockStatus)) {
            throw new BizException("不是代管库存状态的数据!请检查重试!");
        }
        addVO.setIsHost(1);
        this.saveAdjust(addVO);
        return true;
    }

    @Override
    public void buildAndSaveAdjust(Map<String, List<CompleteTaskItemVO>> backMap) {
        if (ObjectUtils.isNull(backMap)) {
            return;
        }
        // 根据ID查询盘点明细数据
        List<WmsInvCheckD> checkDList = invCheckDMapper.findByIds(WmsInvCheckD.class, backMap.keySet().toArray(), null);
        if (ObjectUtils.isNull(checkDList) || checkDList.size() != backMap.size()) {
            throw new BizException("没有查询到盘点明细数据！");
        }
        // 根据盘点汇总ID查询盘点汇总数据
        Object[] headerIds = checkDList.stream().map(WmsInvCheckD::getCheckHeaderId).distinct().toArray();
        List<WmsInvCheckH> checkHList = invCheckHMapper.findByIds(WmsInvCheckH.class, headerIds, null);
        if (ObjectUtils.isNull(checkHList)) {
            throw new BizException("没有查询到盘点汇总数据！");
        }
        Date date = DateUtils.getNowDate();
        List<WmsAdjustH> adjustHList = new ArrayList<>();
        List<WmsAdjustD> adjustDList = new ArrayList<>();
        for (WmsInvCheckD wmsInvCheckD : checkDList) {
            List<CompleteTaskItemVO> taskItemList = backMap.get(wmsInvCheckD.getCheckLineId());
            WmsInvCheckH wmsInvCheckH = checkHList.stream().filter(checkh -> checkh.getCheckHeaderId().equals(wmsInvCheckD.getCheckHeaderId())).findFirst().orElse(null);
            if (ObjectUtils.isNull(wmsInvCheckH)) {
                throw new BizException("没有查询到盘点汇总数据！");
            }
            WmsAdjustH wmsAdjustH = new WmsAdjustH();
            String adjustHId = String.valueOf(SnowFlakeUtils.getId());
            wmsAdjustH.setAdjustHeaderId(adjustHId);
            wmsAdjustH.setAutoBillNum(adjustHId);
            wmsAdjustH.setDcId(wmsInvCheckH.getDcId());
            wmsAdjustH.setWarehouseId(wmsInvCheckH.getWarehouseId());
            wmsAdjustH.setCargoOwnerId(wmsInvCheckH.getCargoOwnerId());
            wmsAdjustH.setStatus("NEW");
            wmsAdjustH.setAccessLevel("9");
            wmsAdjustH.setSrcBillHId(wmsInvCheckH.getCheckHeaderId());
            wmsAdjustH.setCreator("EIS");
            wmsAdjustH.setCreatorName("EIS");
            wmsAdjustH.setGmtCreate(date);
            wmsAdjustH.setAdjustDate(date);
            wmsAdjustH.setModifier("EIS");
            wmsAdjustH.setModifierName("EIS");
            wmsAdjustH.setGmtModified(date);
            wmsAdjustH.setEnterpriseId(wmsInvCheckH.getEnterpriseId());
            wmsAdjustH.setAdjustType("0");
            wmsAdjustH.setAttribute5("1");
            adjustHList.add(wmsAdjustH);
            long row = 0;
            for (CompleteTaskItemVO taskItem : taskItemList) {
                row++;
                WmsAdjustD wmsAdjustD = new WmsAdjustD();
                wmsAdjustD.setAdjustHeaderId(adjustHId);
                wmsAdjustD.setWhLocatorId(wmsInvCheckD.getWhLocatorId());
                wmsAdjustD.setContainerCode(wmsInvCheckD.getContainerCode());
                // 设置货格号
                wmsAdjustD.setGoodsCaseCode(taskItem.getLocationNo());
                wmsAdjustD.setItemId(wmsInvCheckD.getItemId());
                wmsAdjustD.setBatchId(wmsInvCheckD.getBatchId());
                wmsAdjustD.setBatchNum(wmsInvCheckD.getBatchNum());
                wmsAdjustD.setStockStatus(wmsInvCheckD.getStockStatus());
                wmsAdjustD.setLineNum(row);
                wmsAdjustD.setUom(wmsInvCheckD.getUom());
                wmsAdjustD.setConversionRate(wmsInvCheckD.getConversionRate());
                wmsAdjustD.setStatus("0");
                wmsAdjustD.setSrcBillDId(wmsInvCheckD.getCheckLineId());
                wmsAdjustD.setSrcBillHId(wmsInvCheckH.getCheckHeaderId());
                wmsAdjustD.setCreator("EIS");
                wmsAdjustD.setCreatorName("EIS");
                wmsAdjustD.setGmtCreate(date);
                wmsAdjustD.setModifier("EIS");
                wmsAdjustD.setModifierName("EIS");
                wmsAdjustD.setGmtModified(date);
                wmsAdjustD.setAdjustDate(date);
                wmsAdjustD.setPieceAccount(new BigDecimal(taskItem.getInventoryQty().toString()));
                wmsAdjustD.setPieceAccountFact(new BigDecimal(taskItem.getConfirmQty().toString()));
                wmsAdjustD.setPieceQuantity(wmsAdjustD.getPieceAccountFact().subtract(wmsAdjustD.getPieceAccount()));
                wmsAdjustD.setQuantity(wmsAdjustD.getPieceQuantity());

                wmsAdjustD.setEnterpriseId(wmsInvCheckH.getEnterpriseId());
                wmsAdjustD.setCargoOwnerId(wmsInvCheckD.getCargoOwnerId());
                adjustDList.add(wmsAdjustD);
            }
        }
        if (ObjectUtils.isNotNull(adjustHList)) {
            adjustHMapper.saveBatch(adjustHList);
        }
        if (ObjectUtils.isNotNull(adjustDList)) {
            adjustDMapper.saveBatch(adjustDList);

            // 不生成预占，因为创建盘点单的时候已经生成了盘点预占了
//            List<InvStockAdjust> invStockList = new ArrayList<>();
//            for (WmsAdjustD wmsAdjustD : adjustDList) {
//                WmsAdjustH wmsAdjustH = adjustHList.stream().filter(adjusth -> adjusth.getAdjustHeaderId().equals(wmsAdjustD.getAdjustHeaderId())).findFirst().orElse(null);
//                excutePreStock(invStockList, wmsAdjustH, wmsAdjustD);
//            }
//            RestMessage adjustStock = stockResource.adjustStock(invStockList);
//            if (adjustStock != null && !adjustStock.isSuccess()) {
//                throw new BizException("调用库存预占失败!原因->" + adjustStock.getMessage());
//            }
        }
    }
}
