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

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.codingapi.tx.annotation.TxTransaction;
import com.esotericsoftware.minlog.Log;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.prolog.common.util.ToolKits;
import com.prolog.cs.basic.chain.model.cargo.vo.CargoOwnerLicenseQueryVO;
import com.prolog.cs.basic.item.model.BaseMtlItemMst;
import com.prolog.cs.basic.item.model.BaseMtlItemUomConversions;
import com.prolog.cs.basic.item.model.vo.ItemBaseInfoVO;
import com.prolog.cs.biz.inbound.constant.BizConstant;
import com.prolog.cs.biz.inbound.dao.*;
import com.prolog.cs.biz.inbound.dao.failure.ExceptionLinesMapper;
import com.prolog.cs.biz.inbound.dao.rcv.*;
import com.prolog.cs.biz.inbound.dao.rqc.RqcLinesMapper;
import com.prolog.cs.biz.inbound.dao.rqc.RqcReLinesMapper;
import com.prolog.cs.biz.inbound.dto.*;
import com.prolog.cs.biz.inbound.dto.failure.ExceptionLineQueryDTO;
import com.prolog.cs.biz.inbound.dto.print.RcvLinesHeadPrintDTO;
import com.prolog.cs.biz.inbound.dto.print.RcvLinesPrintDTO;
import com.prolog.cs.biz.inbound.dto.rcv.*;
import com.prolog.cs.biz.inbound.dto.rqc.RqcLinesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcReLinesDTO;
import com.prolog.cs.biz.inbound.model.*;
import com.prolog.cs.biz.inbound.model.rcv.RcvHeaders;
import com.prolog.cs.biz.inbound.model.rcv.RcvLines;
import com.prolog.cs.biz.inbound.model.rcv.WmsInRcvTempSave;
import com.prolog.cs.biz.inbound.remote.BaseInventoryRemoteCaller;
import com.prolog.cs.biz.inbound.remote.BaseItemRemoteCaller;
import com.prolog.cs.biz.inbound.remote.ChainRemoteCaller;
import com.prolog.cs.biz.inbound.remote.StrategyClient;
import com.prolog.cs.biz.inbound.service.SerialGeneratorService;
import com.prolog.cs.biz.inbound.service.impl.BaseServiceImpl;
import com.prolog.cs.biz.inbound.service.rcv.RcvHeadersProfilesService;
import com.prolog.cs.biz.inbound.service.rcv.RcvHeadersService;
import com.prolog.cs.biz.inbound.service.rcv.RcvHeadersSrcBillsService;
import com.prolog.cs.biz.inbound.utils.ObjectUtils;
import com.prolog.cs.biz.inbound.utils.UserUtils;
import com.prolog.cs.biz.inbound.vo.*;
import com.prolog.cs.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.framework.authority.core.dto.UserDTO;
import com.prolog.framework.beans.BeanUtils;
import com.prolog.framework.bz.common.print.PrintData;
import com.prolog.framework.bz.common.print.ReportData;
import com.prolog.framework.bz.common.search.SearchApi;
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.pojo.Page;
import com.prolog.framework.core.restriction.*;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.framework.utils.*;
import com.prolog.upcloud.base.inventory.vo.AskIntegrationVo;
import com.prolog.upcloud.base.inventory.vo.BatchNumberListVO;
import com.prolog.wms.base.util.JsonMapper;
import com.prolog.wms.base.util.MD5Utils;
import com.prolog.wms.base.util.RestMsgUtils;
import com.prolog.wms.base.util.mapper.MapperCustom;
import lombok.extern.slf4j.Slf4j;
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.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
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.stream.Collectors;

@Service
@Slf4j
public class RcvHeadersServiceImpl extends BaseServiceImpl<RcvHeaders> implements RcvHeadersService {

    @Resource
    private RcvHeadersMapper mapper;

    @Resource
    private InRcvTempSaveMapper inRcvTempSaveMapper;

    @Resource
    private UserUtils userUtils;

    @Resource
    private RcvHeadersProfilesService rcvHeadersProfilesService;

    @Resource
    private RcvHeadersSrcBillsService rcvHeadersSrcBillsService;

    @Resource
    private RcvLinesMapper rcvLinesMapper;

    @Resource
    private RcvTypeService rcvTypeService;

    @Resource
    private StrategyClient strategyClient;

    @Resource
    private ReceivingRecordBackHMapper receivingRecordBackHMapper;

    @Resource
    private ReceivingRecordBackDMapper receivingRecordBackDMapper;
    /**
     * 通知url
     */
    @Value("${prolog.wms.print.printUrl3:http://minio.cloud.prolog.org/print/%E9%AA%8C%E6%94%B6%E9%80%9A%E7%9F%A5%E5%8D%95%20.grf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=nyu8dWdGLqiUkvgF4ue5%2F20210615%2F%2Fs3%2Faws4_request&X-Amz-Date=20210615T090441Z&X-Amz-Expires=432000&X-Amz-SignedHeaders=host&X-Amz-Signature=3cdae8675ea8d1cd6bf02ef2457e11408c1fbf0423f8a3053e2a8464045bbbcd}")
    private String printUrl3;

    @Value("${prolog.wms.print.printSolution:batch_order.grf}")
    private String printSolution;

    @Value("${prolog.wms.print.printName:}")
    private String printName;

    @Value("${prolog.wms.print.printCount:1}")
    private Integer printCount;

    @Value("${prolog.wms.print.preview:true}")
    private Boolean preview;

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


    @Resource
    private OmsAsnBillHMapper omsAsnBillHMapper;

    @Resource
    private OmsAsnBillDMapper omsAsnBillDMapper;

    @Resource
    private BaseInventoryRemoteCaller baseInventoryRemoteCaller;

    @Resource
    private RqcLinesMapper rqcLinesMapper;

    @Resource
    private RqcReLinesMapper rqcReLinesMapper;

    @Resource
    private RcvRejectLinesMapper rcvRejectLinesMapper;

    @Resource
    private ExceptionLinesMapper exceptionLinesMapper;

    @Resource
    private RcvInstockLinesMapper rcvInstockLinesMapper;

    @Resource
    private IncomingRecordHMapper incomingRecordHMapper;

    @Resource
    private IncomingRecordDMapper incomingRecordDMapper;

    @Resource
    private IncomingRecordBackHMapper incomingRecordBackHMapper;

    @Resource
    private IncomingRecordBackDMapper incomingRecordBackDMapper;

    @Resource
    private SearchApi searchApi;

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

    @Resource
    private ExchangeSender exchangeSender;

    @Resource
    private ChainRemoteCaller chainRemoteCaller;

    @Resource
    private BaseItemRemoteCaller itemClient;

    @Resource
    private SerialGeneratorService serialGeneratorService;

    @Resource
    private SupervisionCodeMapper supervisionCodeMapper;

    @Override
    public RcvDTO findByPkId(String pkId) {
        logger.info("开始根据主键id[{}]查询信息.", pkId);
        RcvHeaders rcvHeaders = this.findById(pkId);
        AssertUtils.notNull(rcvHeaders, "查询数据为空!!");
        RcvHeadersDTO rcvHeadersDTO = new RcvHeadersDTO();
        BeanUtils.copyProperties(rcvHeaders, rcvHeadersDTO);
        // 暂时携带基础数据
        RcvHeadersProfilesDTO profiles = rcvHeadersProfilesService.findByPkId(pkId);
        RcvDTO rcvDTO = new RcvDTO();
        rcvDTO.setRcvHeadersDTO(rcvHeadersDTO);
        rcvDTO.setRcvHeadersProfilesDTO(profiles);
        return rcvDTO;
    }

    @Override
    @Transactional
    public Object addWithRelated(RcvDTO rcvDTO) {
        Object addWithRelated = addWithRelated(rcvDTO, null, null);
        //收货保存后，更新收货明细对应的生产日期有效期---暂时注释
//        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();
//        for (RcvLinesDTO rcvLinesDTO : rcvLinesDTOList) {
//            Criteria c1 = Criteria.forClass(SupervisionCode.class);
//            Restriction r1 = Restrictions.eq("refBillLineId", rcvLinesDTO.getAsnLineId());
//            c1.setRestriction(r1);
//            supervisionCodeMapper.updateMapByCriteria(MapUtils.put("manufacturerLotNum",rcvLinesDTO.getManufacturerLotNum())
//                    .put("productionDate",rcvLinesDTO.getBatchProductionDate()).put("expiredDate",rcvLinesDTO.getBatchExpiredDate()).getMap(),c1);
//        }
        //添加到货数量 保存到 asnbilld
        //saveArriveQty(rcvDTO);
        return addWithRelated;
    }

    private void saveArriveQty(RcvDTO rcvDTO) {
        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();
        if (ToolKits.isNotEmpty(rcvLinesDTOList)) {
            for (RcvLinesDTO rcvLinesDTO : rcvLinesDTOList) {
                omsAsnBillDMapper.updateMapById(rcvLinesDTO.getAsnLineId(),
                        MapUtils.put("attrNum1", rcvLinesDTO.getAttrNum1()).put("attrNum2", rcvLinesDTO.getAttrNum2()).getMap(),
                        OmsAsnBillD.class);
            }
        }

    }

    private void excuteCallBackErp(String masterId, String mtlOwnerId, String asnHeaderId) {
        // 首先需要判断该asn单是否是wms制单的
//        OmsAsnBillH findById = this.omsAsnBillHMapper.findById(asnHeaderId, OmsAsnBillH.class);
//        if (findById != null && !StringUtils.isBlank(findById.getAttrStr14())) {
//            return;
//        }

        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("cargoOwnerId", mtlOwnerId);
        List<Map> searchForMap = null;
        Integer isOneReturnErp = 0;
        try {
            searchForMap = searchApi.searchForMap("getCargoOwnerProp", queryMap);
        } catch (Exception e1) {
            logger.info("找寻货主属性失败,原因{}", e1);
        }
        if (searchForMap != null) {
            Map map = searchForMap.get(0);
            if (map != null && map.containsKey("isOneReturnErp")) {
                isOneReturnErp = (Integer) map.get("isOneReturnErp");
            }
        }
        Set<String> rcvHeaderIdList = null;
        if (isOneReturnErp != null && isOneReturnErp == 1) {
            // 订单级别回传
            if (vaildateBillComplete(asnHeaderId)) {
                excuteSaveCallBackData(masterId, "1", asnHeaderId);

                // 回传应该是rcvHeaderId的集合
                List<RcvHeaders> findByMap = this.mapper.findByMap(MapUtils.put("asnHeaderId", asnHeaderId).getMap(),
                        RcvHeaders.class);
                rcvHeaderIdList = Optional.ofNullable(findByMap).orElse(new ArrayList<>()).stream()
                        .map(p -> p.getRcvHeaderId()).collect(Collectors.toSet());
            }
        } else {
            // 收货单级别回传
            excuteSaveCallBackData(masterId, "2", asnHeaderId);
            //拒收回传ERP
            excuteCallBackOms(masterId);
        }
//        if (ObjectUtils.isNotNull(rcvHeaderIdList)) {
//            for (String rcvHeaderId : rcvHeaderIdList) {
//                // 校验是否收货全部完成
//                logger.info("收货全拒收回传开始-------------------------------");
//                EtlMessage em = new EtlMessage();
//                em.setId(rcvHeaderId);
//                em.setEtlType(EtlTypeConstants.in_asn_w2o);
//                try {
//                    logger.info("收货全拒收回传给data-exchange数据:{}", JsonUtils.toString(em));
//                    exchangeSender.send(em);
//                    logger.info("收货全拒收回传data-exchange成功!");
//                    excuteUpdateRcvH(rcvHeaderId);
//                } catch (Exception e) {
//                    logger.error("收货全拒收回传失败,原因->{}", e);
//                }
//            }
//        }
    }

    private void excuteCallBackOms(String rcvHeaderId){
        List<IncomingRecordBackVO> backList = new ArrayList<>();
        List<IncomingRecordBackHVO> backHVOList = incomingRecordBackHMapper.getInsertDataReject(rcvHeaderId);
        if(backHVOList.size()>0) {
            List<IncomingRecordBackDVO> backDList = incomingRecordBackDMapper.getInsertDataReject(rcvHeaderId);
            for (IncomingRecordBackHVO incomingRecordBackHVO : backHVOList) {
                IncomingRecordBackVO backVO = new IncomingRecordBackVO();
                backVO.setContent(incomingRecordBackHVO);
                backVO.setDetailList(backDList);
                backList.add(backVO);
            }
            //TODO 调用接口平台回传OMS
            try {
//                String url = "http://integration.upcloud.prolog.org/api/rcvInstockLines/infTaskInBack";
//                if (StringUtils.isEmpty(incomingRecordBack)) {
//                    throw new BizException("请求路径配置为空");
//                }
//                System.out.println(JSON.toJSONString(backList));
//                String url = incomingRecordBack;
//                String result = HttpUtil.post(url, JSONObject.toJSONString(backList));
//                JSONObject parse = JSONObject.parseObject(result);
                AskIntegrationVo vo = new AskIntegrationVo();
                vo.setIntegrationCode("incomingRecordBack");
                vo.setParam(backList);
                RestMessage<?> msg = baseInventoryRemoteCaller.askIntegration(vo);
                if(msg.isSuccess()){
                    Criteria crt = Criteria.forClass(IncomingRecordH.class);
                    crt.restrictionBuilder().eq("billid",rcvHeaderId);
                    crt.buildRestriction();
                    incomingRecordHMapper.updateMapByCriteria(MapUtils.put("attrStr1","Y").getMap(),crt);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

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

    private boolean vaildateBillComplete(String asnHeaderId) {
        // 校验整个采购单是否收货上架完毕
        BigDecimal qty = null;
        try {
            qty = mapper.getRemainQtyByBillId(asnHeaderId);
            logger.info("剩余未上架数量" + qty.toString());
        } catch (Exception e) {
            logger.info("调用sql错误原因{}", e);
        }
        if (qty != null && qty.compareTo(BigDecimal.ZERO) == 0) {
            return true;
        }
        return false;
    }

    private void excuteSaveCallBackData(String masterId, String callType, String asnHeaderId) {
        IncomingRecordQueryVO vo = new IncomingRecordQueryVO();
        if (callType.equals("1")) {
            // 获取所有收货单头以及单头对应的上架明细
            AssertUtils.isNotBlank(asnHeaderId, "asn单id不可为空!");
            vo.setAsnHeaderId(asnHeaderId);
        } else if (callType.equals("2")) {
            String rcvHeaderId = masterId;
            AssertUtils.isNotBlank(rcvHeaderId, "收货单单id不可为空!");
            List<String> rcvHeaderIds = new ArrayList<>();
            rcvHeaderIds.add(rcvHeaderId);
            vo.setRcvHeaderIds(rcvHeaderIds);
        }
        List<IncomingRecordH> insertData = this.incomingRecordHMapper.getInsertData(vo);
        if (ObjectUtils.isNotNull(insertData)) {
            this.incomingRecordHMapper.saveBatch(insertData);
        }
        List<IncomingRecordD> insertDataD = this.incomingRecordDMapper.getInsertData(vo);
        if (ObjectUtils.isNotNull(insertData)) {
            this.incomingRecordDMapper.saveBatch(insertDataD);
        }
    }

    private void vaildateOvercharge(List<RcvLinesDTO> rcvLinesDTOList, UserDTO userDTO) {
        // 校验是否超收
        Set<String> collect = rcvLinesDTOList.stream().map(RcvLinesDTO::getAsnLineId).collect(Collectors.toSet());
        for (String asnLineId : collect) {
            // 获取asnLineId 已收货数量
            BigDecimal findRemainQty = this.rcvLinesMapper.findRemainQty(asnLineId, userDTO.getEnterpriseId());

            if (findRemainQty == null) {
                throw new BizException(String.format("收货原订单明细id[%s]对应的收货明细总量查询为空!请检查!", asnLineId));
            }
            Log.info("asn明细行id->" + asnLineId + ",剩余可收货数据->" + findRemainQty.toString());
            if (findRemainQty != null && findRemainQty.compareTo(BigDecimal.ZERO) == -1) {

                throw new BizException(String.format("asn行id[%s],实际收货的总数超出单据总量!,请检查重新提取操作!", asnLineId));
            }
        }
    }

    /**
     * 校验来源asn单订单的有效期
     *
     * @param asnHeaderId
     */
    private void excuteVaildateAsn(String asnHeaderId) {
        if (!StringUtils.isBlank(asnHeaderId)) {
            OmsAsnBillH findById = null;
            try {
                findById = omsAsnBillHMapper.findById(asnHeaderId, OmsAsnBillH.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (findById != null) {
                Date expirationdate = findById.getExpirationdate();
                if (expirationdate != null) {
                    Date now = new Date();
                    boolean before = now.before(expirationdate);
                    if (!before) {
                        throw new BizException(String.format("asn订单id[%s],订单有效期已超出,请检查!", asnHeaderId));
                    }
                }
            }
        }
    }

    @Override
    @Transactional
    public Boolean addWithRelatedTemp(RcvDTO rcvDTO) {
        RcvHeadersDTO rcvHeadersDTO = rcvDTO.getRcvHeadersDTO();
        AssertUtils.notNull(rcvHeadersDTO, "收货单不可为空!");

        String asnHeaderId = rcvDTO.getRcvHeadersDTO().getAsnHeaderId();
        WmsInRcvTempSave wmsInRcvTempSave = MapperCustom.builder(inRcvTempSaveMapper, WmsInRcvTempSave.class).andEq(WmsInRcvTempSave::getAsnHeaderId, asnHeaderId).findFirst();

        if (Objects.isNull(wmsInRcvTempSave)) {
            wmsInRcvTempSave = new WmsInRcvTempSave();
            wmsInRcvTempSave.setWarehouseId(rcvHeadersDTO.getWarehouseId());
            wmsInRcvTempSave.setAsnAutoBillNum(rcvHeadersDTO.getAutoBillNum());
            wmsInRcvTempSave.setAsnHeaderId(rcvHeadersDTO.getAsnHeaderId());
            wmsInRcvTempSave.setEnterpriseId(userUtils.getEnterpriseId());
            wmsInRcvTempSave.setContent(JSON.toJSONString(rcvDTO));
            Date gmtModified = new Date();
            wmsInRcvTempSave.setCreatorName(userUtils.getUserName());
            wmsInRcvTempSave.setGmtModified(gmtModified);
            wmsInRcvTempSave.setGmtCreate(gmtModified);
            return inRcvTempSaveMapper.save(wmsInRcvTempSave) > 0;
        } else {
            String content = wmsInRcvTempSave.getContent();
            RcvDTO oldRcvDTO = JsonMapper.parse(content, RcvDTO.class);
            List<RcvLinesDTO> rcvLinesDTOList = oldRcvDTO.getRcvLinesDTOList();
            rcvLinesDTOList.addAll(rcvDTO.getRcvLinesDTOList());
            oldRcvDTO.setRcvLinesDTOList(rcvLinesDTOList);
            wmsInRcvTempSave.setContent(JSON.toJSONString(oldRcvDTO));
            return inRcvTempSaveMapper.update(wmsInRcvTempSave) > 0;
        }
    }

    @Override
    public String findWithRelatedTemp(String warehouseId) {
        Criteria criteria1 = Criteria.forClass(WmsInRcvTempSave.class);
        // Restriction r4 = Restrictions.eq("warehouseId", warehouseId);
        Restriction r5 = Restrictions.eq("enterpriseId", userUtils.getEnterpriseId());
        // Restriction r6 = Restrictions.and(r4, r5);
        criteria1.setRestriction(r5);
        criteria1.setOrder(Order.newInstance().desc("gmtModified"));
        List<WmsInRcvTempSave> wmsInRcvTempSaveList = inRcvTempSaveMapper.findByCriteria(criteria1);
        if (wmsInRcvTempSaveList != null && wmsInRcvTempSaveList.size() >= 1) {
            return wmsInRcvTempSaveList.get(0).getContent();
        }
        return "";
    }

    @Override
    public Object findItemWithRelatedTemp(String tempSaveId) {
        WmsInRcvTempSave WmsInRcvTempSave = inRcvTempSaveMapper.findById(tempSaveId, WmsInRcvTempSave.class);
        String content = WmsInRcvTempSave.getContent();
        RcvDTO rcvDTO = JSON.parseObject(content, RcvDTO.class);
        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();
        List list = new ArrayList();
        for (int i = 0; i < rcvLinesDTOList.size(); i++) {
            Map map = new HashMap();
            try {
                RcvLinesDTO rcvLinesDTO = rcvLinesDTOList.get(i);
                map.putAll(bean2map(rcvLinesDTO.getRcvLinesProfilesDTO()));
                rcvLinesDTO.setRcvLinesProfilesDTO(null);
                map.putAll(bean2map(rcvLinesDTO));
            } catch (Exception e) {
                e.printStackTrace();
            }
            list.add(map);
        }
        return list;
    }

    // 把JavaBean转化为map
    public static Map<String, Object> bean2map(Object bean) throws Exception {
        Map<String, Object> map = new HashMap<>();
        // 获取JavaBean的描述器
        BeanInfo b = Introspector.getBeanInfo(bean.getClass(), Object.class);
        // 获取属性描述器
        PropertyDescriptor[] pds = b.getPropertyDescriptors();
        // 对属性迭代
        for (PropertyDescriptor pd : pds) {
            // 属性名称
            String propertyName = pd.getName();
            // 属性值,用getter方法获取
            Method m = pd.getReadMethod();
            Object properValue = m.invoke(bean);// 用对象执行getter方法获得属性值

            // 把属性名-属性值 存到Map中
            map.put(propertyName, properValue);
        }
        return map;
    }

    @Override
    public Page<WmsInRcvTempSave> findWithRelatedTempPage(WmsInRcvTempSave rcvQueryVO, PageParam pageParam) {
        Criteria criteria1 = Criteria.forClass(WmsInRcvTempSave.class);
        String asnAutoBillNum = rcvQueryVO.getAsnAutoBillNum();
        Restriction r1 = StringUtils.isBlank(asnAutoBillNum) ? null : Restrictions.eq("asnAutoBillNum", asnAutoBillNum);
        String creatorName = rcvQueryVO.getCreatorName();
        Restriction r2 = StringUtils.isBlank(creatorName) ? null : Restrictions.eq("creatorName", creatorName);
        Restriction r4 = Restrictions.eq("warehouseId", rcvQueryVO.getWarehouseId());
        Restriction r5 = Restrictions.eq("enterpriseId", userUtils.getEnterpriseId());
        Restriction r6 = Restrictions.and(r1, r2, r4, r5);
        criteria1.setRestriction(r6);
        criteria1.setOrder(Order.newInstance().desc("gmtModified"));
        String[] fields = new String[]{"id", "asnAutoBillNum", "creatorName", "gmtCreate"};
        List<WmsInRcvTempSave> wmsInRcvTempSaveList = inRcvTempSaveMapper
                .findFieldsByCriteria(FieldSelector.newInstance().include(fields), criteria1);
        this.startPage(pageParam);
        return PageUtils.getPage(wmsInRcvTempSaveList);
    }

    @Override
    public String findWithRelatedTempById(String id) {
        Criteria criteria1 = Criteria.forClass(WmsInRcvTempSave.class);
        Restriction r4 = Restrictions.eq("id", id);
        Restriction r5 = Restrictions.eq("enterpriseId", userUtils.getEnterpriseId());
        Restriction r6 = Restrictions.and(r4, r5);
        criteria1.setRestriction(r6);
        criteria1.setOrder(Order.newInstance().desc("gmtModified"));
        List<WmsInRcvTempSave> wmsInRcvTempSaveList = inRcvTempSaveMapper.findByCriteria(criteria1);
        if (wmsInRcvTempSaveList != null && wmsInRcvTempSaveList.size() >= 1) {
            return wmsInRcvTempSaveList.get(0).getContent();
        }
        return "";
    }

    @Override
    public Page<RcvHDTO> findListWithProfile(RcvQueryVO rcvQueryVO, PageParam pageParam) {
        rcvQueryVO.setEnterpriseId(userUtils.getEnterpriseId());
        String status = rcvQueryVO.getStatus();
        if (ObjectUtils.isNull(status))
            rcvQueryVO.setStatus("1"); // 默认可用的
        this.startPage(pageParam);
        List<RcvHDTO> list = this.mapper.findList(rcvQueryVO);
        return PageUtils.getPage(list);
    }

    @Override
    public Page<RcvHeadersDTO> findList(RcvQueryVO rcvQueryVO, PageParam pageParam) {

        Criteria criteria = buildPageParam(pageParam, true, null, RcvHeaders.class);
        Restriction r = buildCondition(rcvQueryVO);
        criteria.setRestriction(r);
        this.startPage(pageParam);
        List<RcvHeaders> list = this.mapper.findByCriteria(criteria);
        Page<RcvHeaders> page = PageUtils.getPage(list);
        Page<RcvHeadersDTO> page2 = this.buildPage(page, (p) -> {
            RcvHeadersDTO target = new RcvHeadersDTO();
            BeanUtils.copyProperties(p, target);
            return target;
        });
        return page2;
    }

    @Override
    public RcvHeaders findById(String id) {
        return this.mapper.findById(id, RcvHeaders.class);
    }

    private void buildField(RcvHeaders rcvHeaders, Boolean editFlag, UserDTO userDTO) {

    }

    private Restriction buildCondition(RcvQueryVO condition) {
        if (ObjectUtils.isNull(condition))
            return null;

        // 构建查询条件
        String autoBillNum = condition.getAutoBillNum();
        String customBillNum = condition.getCustomBillNum();
        String rcvHeaderId = condition.getRcvHeaderId();
        String rcvType = condition.getRcvType();
        String srcAsnAutoBullNums = condition.getSrcAsnAutoBullNums();
        String status = condition.getStatus();
        String enterpriseId = userUtils.getEnterpriseId();

        Restriction r0 = Restrictions.eq("enterpriseId", enterpriseId);
        Restriction r1 = ObjectUtils.isNull(rcvHeaderId) ? null : Restrictions.eq("rcvHeaderId", rcvHeaderId);
        Restriction r2 = ObjectUtils.isNull(autoBillNum) ? null : Restrictions.eq("autoBillNum", autoBillNum);
        Restriction r3 = ObjectUtils.isNull(rcvType) ? null : Restrictions.eq("rcvType", rcvType);
        Restriction r4 = ObjectUtils.isNull(status) ? null : Restrictions.eq("status", status);
        Restriction r5 = ObjectUtils.isNull(customBillNum) ? null
                : Restrictions.like("customBillNum", "%" + customBillNum + "%");
        Restriction r6 = ObjectUtils.isNull(srcAsnAutoBullNums) ? null
                : Restrictions.like("srcAsnAutoBullNums", "%" + srcAsnAutoBullNums + "%");

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

    @Override
    public Object add(RcvHeadersDTO rcvHeadersDTO, UserDTO userDTO) {
        if (ObjectUtils.isNull(userDTO))
            userDTO = userUtils.getUserDTO();
        RcvHeaders rcvHeaders = new RcvHeaders();
        rcvHeaders.setAttribute1(rcvHeadersDTO.getRcvUserId1());
        rcvHeaders.setAttribute2(rcvHeadersDTO.getRcvUserName1());
        rcvHeaders.setAttribute3(rcvHeadersDTO.getRcvUserId2());
        rcvHeaders.setAttribute4(rcvHeadersDTO.getRcvUserName2());
        BeanUtils.copyProperties(rcvHeadersDTO, rcvHeaders);
        this.vaildateModel(rcvHeaders, false, userDTO);
        super.setBaseSysField(rcvHeaders, userDTO);
        this.buildDefaultField(rcvHeaders, false, userDTO);
        rcvHeaders.setCreatorName(userDTO.getNickname());
        rcvHeaders.setModifierName(userDTO.getNickname());
        this.mapper.save(rcvHeaders);
        return rcvHeaders.getRcvHeaderId();
    }

    private void buildDefaultField(RcvHeaders rcvHeaders, boolean editFlag, UserDTO userDTO) {
        String status = rcvHeaders.getStatus();
        if (!editFlag && ObjectUtils.isNull(status))
            rcvHeaders.setStatus("1"); // 默认状态0 启用
        BigDecimal printCount = rcvHeaders.getPrintCount();
        if (!editFlag && ObjectUtils.isNull(printCount))
            rcvHeaders.setPrintCount(BigDecimal.ZERO); // 打印次数为0

//		rcvHeaders.setAutoBillNum(String.valueOf(SnowFlakeUtils.getId()));
        if (!editFlag) {
            //Long rcvNo;
            try {
                String rcvNo = serialGeneratorService.getSerialNum("wms", 4, "RCV_AUTO_BILL_NO", "yyMMdd");
                //rcvNo = this.mapper.getRcvSequence();
                //rcvHeaders.setAutoBillNum(ObjectUtils.getNumberStr(rcvNo, 8));
                rcvHeaders.setAutoBillNum(rcvNo);

            } catch (Exception e) {
                rcvHeaders.setAutoBillNum(String.valueOf(SnowFlakeUtils.getId()));
            }
//			rcvHeaders.setAutoBillNum(ObjectUtils.createSerial("RCV", 2));

        }
        String executorUser = rcvHeaders.getExecutorUser();
        if (ObjectUtils.isNull(executorUser)) {
            String username = userDTO.getUsername();
            rcvHeaders.setExecutorUser(username);
        }
        Date rcvDate = rcvHeaders.getRcvDate();
        if (!editFlag && rcvDate == null) {
            rcvHeaders.setRcvDate(new Date());
        }

    }

    @Override
    public Object edit(String pkId, RcvHeadersDTO rcvHeadersDTO) {
        UserDTO userDTO = userUtils.getUserDTO();
        RcvHeaders rcvHeaders = new RcvHeaders();
        BeanUtils.copyProperties(rcvHeadersDTO, rcvHeaders);
        this.vaildateModel(rcvHeaders, true, userDTO);
        super.setBaseSysField(rcvHeaders, true, userDTO);
        this.mapper.updateWithValidate(rcvHeaders,
                p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
        return rcvHeaders.getRcvHeaderId();
    }

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

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

    @Override
    @Transactional
    public Object batchAdd(List<RcvHeadersDTO> rcvHeadersDTOList) {
        UserDTO userDTO = userUtils.getUserDTO();
        for (RcvHeadersDTO rcvHeadersDTO : rcvHeadersDTOList) {
            RcvHeaders rcvHeaders = new RcvHeaders();
            BeanUtils.copyProperties(rcvHeadersDTO, rcvHeaders);
            this.vaildateModel(rcvHeaders, false, userDTO);
            this.buildField(rcvHeaders, false, userDTO);
            this.mapper.save(rcvHeaders);
        }
        return true;
    }

    @Override
    @Transactional
    public Object batchEdit(List<RcvHeadersDTO> rcvHeadersDTOList) {
        UserDTO userDTO = userUtils.getUserDTO();
        for (RcvHeadersDTO rcvHeadersDTO : rcvHeadersDTOList) {
            RcvHeaders rcvHeaders = new RcvHeaders();
            BeanUtils.copyProperties(rcvHeadersDTO, rcvHeaders);
            this.vaildateModel(rcvHeaders, true, userDTO);
            this.buildField(rcvHeaders, true, userDTO);
            this.mapper.updateWithValidate(rcvHeaders,
                    p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
        }
        return true;
    }

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

    @Override
    public Object editWithRelated(RcvDTO rcvDTO) {
        // 编辑

        return null;
    }

    @Override
    public Object batchAddWithRelated(List<RcvDTO> rcvDTOList) {
        return null;
    }

    @Override
    public Object batchEditWithRelated(List<RcvHeadersDTO> rcvHeadersDTOList) {
        return null;
    }

    @Override
    public Object submitConclusion(String pkId) {
        return null;
    }

    private void vaildateModel(RcvHeaders rcvHeaders, Boolean editFlag, UserDTO userDTO) {
        // 特殊校验
        if (!editFlag) {
        } else {
        }
        vaildateModelRepeated(rcvHeaders, editFlag, userDTO);
    }

    private void vaildateModelRepeated(RcvHeaders rcvHeaders, Boolean editFlag, UserDTO userDTO) {
        if (!editFlag) {
        } else {
        }
    }

    private boolean canEdit(String pkId) {
        boolean flag = false;
        RcvHeaders rcvHeaders = this.findById(pkId);
        AssertUtils.notNull(rcvHeaders, "查询数据为空!");
        if (true)
            flag = true;
        return flag;
    }

    @Override
    public Page<RcvHAndPDTO> findListWithPro(RcvQueryVO rcvQueryVO, PageParam pageParam) {

        List<String> hids = rcvQueryVO.getIncludeHids();
        String[] array = hids.toArray(new String[hids.size()]);
        this.startPage(pageParam);
        List<RcvHeaders> list = this.mapper.findByIds(RcvHeaders.class, array, null);
        Page<RcvHeaders> page = PageUtils.getPage(list);
        // 转换为dto
        List<RcvHeadersDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(p -> {
            RcvHeadersDTO target = new RcvHeadersDTO();
            BeanUtils.copyProperties(p, target);
            return target;
        }).collect(Collectors.toList());
        List<String> list2 = list.stream().distinct().map(RcvHeaders::getRcvHeaderId).collect(Collectors.toList());
        List<RcvHeadersProfilesDTO> proList = rcvHeadersProfilesService.findByPKIdList(list2);
        if (ObjectUtils.isNull(collect))
            return null;
        Map<String, List<RcvHeadersDTO>> map1 = collect.stream().distinct()
                .collect(Collectors.groupingBy(RcvHeadersDTO::getRcvHeaderId));
        Set<Entry<String, List<RcvHeadersDTO>>> entrySet = map1.entrySet();
        Map<String, List<RcvHeadersProfilesDTO>> map2 = proList.stream().distinct()
                .collect(Collectors.groupingBy(RcvHeadersProfilesDTO::getRcvHeaderId));
        List<RcvHAndPDTO> result = new ArrayList<>();
        for (Entry<String, List<RcvHeadersDTO>> entry : entrySet) {
            String hid = entry.getKey();
            List<RcvHeadersDTO> value1 = entry.getValue();
            List<RcvHeadersProfilesDTO> value2 = map2.get(hid);
            RcvHAndPDTO rcvHAndPDTO = new RcvHAndPDTO();
            if (ObjectUtils.isNotNull(value1))
                rcvHAndPDTO.setRcvHeadersDTO(value1.get(0));
            if (ObjectUtils.isNotNull(value2))
                rcvHAndPDTO.setRcvHeadersProfilesDTO(value2.get(0));
            result.add(rcvHAndPDTO);
        }
        Page<RcvHAndPDTO> page2 = new Page<>();
        page2.setList(result);
        page2.setStartRow(page.getStartRow());
        page2.setEndRow(page.getEndRow());
        page2.setPageCount(page.getPageCount());
        page2.setPageNum(page.getPageNum());
        page2.setPageSize(page.getPageSize());
        page2.setTotalCount(page.getTotalCount());
        return page2;
    }

    @Override
    public Object getRcvPrintData(RcvLinesQueryVO queryVo) {
        String rcvHeaderId = queryVo.getRcvHeaderId();
        AssertUtils.isNotBlank(rcvHeaderId, "收货单头id不可为空!");
        List<RcvLinesDTO> findList = rcvLinesMapper.findList(queryVo);
        if (ObjectUtils.isNull(findList))
            return null;
        RcvHDTO findByPkId = this.mapper.findByPkId(rcvHeaderId);
        AssertUtils.notNull(findByPkId, "收货单头为空!");
        // 组装报表头
        PrintData pd = new PrintData();
        pd.setCount(printCount); // 默认1份
        pd.setPreview(preview); // 是否预览
        pd.setPrintName(printName); // 打印机名称
        pd.setPrintSolution(printSolution); // 打印方案
        pd.setUrl(printUrl3); // 打印模板url
        RcvLinesHeadPrintDTO headDTO = new RcvLinesHeadPrintDTO();
        BeanUtils.copyProperties(findByPkId, headDTO);
        Date rcvDate = findByPkId.getRcvDate();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String rcvDateStr = sdf.format(rcvDate);
        headDTO.setRcvDate(rcvDateStr);

        @SuppressWarnings("unchecked")
        Map<String, Object> head = ObjectUtils.convertBean2MapForIngoreserialVersionUID(headDTO);
        List<ReportData> rdList = new ArrayList<ReportData>();
        ReportData rd = new ReportData();
        rd.setHead(head);

        List<Map<String, Object>> tableList = new ArrayList<Map<String, Object>>();
        for (RcvLinesDTO rcvLinesDTO : findList) {
            // 组装打印table数据
            // 为了计算准确性,重新计算
            BigDecimal pieceQty = rcvLinesDTO.getPieceQty();
            if (pieceQty == null)
                pieceQty = BigDecimal.ZERO;
            BigDecimal conversionRate = rcvLinesDTO.getConversionRate();
            if (conversionRate == null || conversionRate.compareTo(BigDecimal.ZERO) == 0)
                conversionRate = BigDecimal.ONE;
            // 计算出整件,零散
            BigDecimal caseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
            BigDecimal multiply = caseQty.multiply(conversionRate);
            BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
            RcvLinesPrintDTO rlpd = new RcvLinesPrintDTO();
            BeanUtils.copyProperties(rcvLinesDTO, rlpd);
            String stockStatus = rcvLinesDTO.getStockStatus();
            // 处理质检结论
            stockStatus = handleStockStatus(stockStatus);
            rlpd.setStockStatus(stockStatus);
            rlpd.setPieceQty(pieceQty.toString());
            rlpd.setCaseQty(caseQty.toString());
            rlpd.setOddPieceQty(oddPieceQty.toString());
            rlpd.setConversionRate(conversionRate.toString());

            // 处理生产日期,效期
            Date batchExpiredDate = rcvLinesDTO.getBatchExpiredDate();
            Date batchProductionDate = rcvLinesDTO.getBatchProductionDate();
            String expiredDateStr = sdf.format(batchExpiredDate);
            String productionDateStr = sdf.format(batchProductionDate);
            rlpd.setExpiredDate(expiredDateStr);
            rlpd.setProductionDate(productionDateStr);

            @SuppressWarnings("unchecked")
            Map<String, Object> table = ObjectUtils.convertBean2MapForIngoreserialVersionUID(rlpd);
            tableList.add(table);

        }
        rd.setTable(tableList);
        rdList.add(rd);
        pd.setData(rdList);
        return pd;
    }

    private String handleStockStatus(String stockStatus) {
        if (StringUtils.isBlank(stockStatus))
            return "";
        switch (stockStatus) {
            case "0":
                return "合格";
            case "1":
                return "不合格";
            case "2":
                return "待处理";
            case "3":
                return "拒绝";
            default:
                return "合格";
        }
    }

    @Override
    public Object getRcvItemLotNum(RcvLinesQueryVO queryVo) {
        // 获取商品以往收货的批号
        String itemId = queryVo.getItemId();
        String warehouseId = queryVo.getWarehouseId();
        String mtlOwnerId = queryVo.getMtlOwnerId();
        AssertUtils.isNotBlank(itemId, "查询的商品id不可为空!");
        AssertUtils.isNotBlank(mtlOwnerId, "查询的货主id不可为空!");
        String enterpriseId = queryVo.getEnterpriseId();
        if (StringUtils.isBlank(enterpriseId)) {
            String enterpriseId2 = userUtils.getEnterpriseId();
            queryVo.setEnterpriseId(enterpriseId2);
        }
        String manufacturerLotNum = queryVo.getManufacturerLotNum();
        Integer pageNum = queryVo.getPageNum();
        Integer pageSize = queryVo.getPageSize();
        if (pageNum == null) {
            pageNum = PageParam.DEFAULT_PAGE_NUM;
        }
        if (pageSize == null) {
            pageSize = PageParam.DEFAULT_PAGE_SIZE;
        }
        // 不能从本地收货表中取,需要远程调用库存服务获取
        RestMessage<Page<BatchNumberListVO>> batchNumber = null;
        try {
            batchNumber = baseInventoryRemoteCaller.getBatchNumber(warehouseId, mtlOwnerId, itemId, manufacturerLotNum,
                    pageSize, pageNum);
        } catch (Exception e) {
            // 打印日志
            e.printStackTrace();
        }
        if (batchNumber == null || !batchNumber.isSuccess() || null == batchNumber.getData()) {
            return null;
        }
        Page<BatchNumberListVO> data = batchNumber.getData();
//		List<RcvLineLotInfo> rcvPreItemLotNum = rcvLinesMapper.getRcvPreItemLotNum(queryVo);
//		Map<String, List<RcvLineLotInfo>> collect = rcvPreItemLotNum.stream()
//				.collect(Collectors.groupingBy(RcvLineLotInfo::getManufacturerLotNum));
//		List<RcvLineLotInfo> result = new ArrayList<>();
//		for (List<RcvLineLotInfo> list : collect.values()) {
//			List<RcvLineLotInfo> collect2 = list.stream()
//					.sorted(Comparator.comparing(RcvLineLotInfo::getBatchProductionDate).reversed()
//							.thenComparing(RcvLineLotInfo::getBatchProductionDate))
//					.collect(Collectors.toList());
//			RcvLineLotInfo rcvLineLotInfo = collect2.get(0);
//			result.add(rcvLineLotInfo);
//		}
//		return result;
        return data;
    }

    /**
     * 校验收货行批号数据是否可用
     */
    @Override
    public Object vaildateRcvItemLotNum(List<RcvLineLotInfo> rcvLineLotInfoList) {
//		String enterpriseId = userUtils.getEnterpriseId();
//		int row = 0;
//		for (RcvLineLotInfo rcvLineLotInfo : rcvLineLotInfoList) {
//			row++;
//			String enterpriseId2 = rcvLineLotInfo.getEnterpriseId();
//			if (StringUtils.isBlank(enterpriseId2))
//				rcvLineLotInfo.setEnterpriseId(enterpriseId);
//			rcvLinesService.excuteVaildateRcvItemLotNum(rcvLineLotInfo, row);
//		}
        return true;
    }

    @Override
    public boolean vaildateRcvComplete(String rcvHeaderId) {
        BigDecimal qty = null;
        try {
            qty = mapper.getRemainQty(rcvHeaderId);
            logger.info("收货剩余数量" + qty.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (qty == null) {
            throw new BizException(String.format("收货单id[%s]对应的收货明细总量查询为空!请检查!", rcvHeaderId));
        }
        if (qty != null && qty.compareTo(BigDecimal.ZERO) == 0) {
            return true;
        }
        return false;
    }

    @Override
    public Object vaildateRcvSplit(List<RcvLineSpiltInfo> rcvLineSpiltInfoList) {
        UserDTO userDTO = userUtils.getUserDTO();
        for (RcvLineSpiltInfo rcvLineSpiltInfo : rcvLineSpiltInfoList) {
            String asnLineId = rcvLineSpiltInfo.getAsnLineId();
            BigDecimal findRemainQty = this.rcvLinesMapper.findRemainQty(rcvLineSpiltInfo.getAsnLineId(),
                    userDTO.getEnterpriseId());
            if (findRemainQty == null) {
                throw new BizException(String.format("收货原订单明细id[%s]对应的收货明细总量查询为空!请检查!", asnLineId));
            }
            if (findRemainQty != null && findRemainQty.compareTo(rcvLineSpiltInfo.getPieceQty()) == -1) {
                throw new BizException(String.format("asn行id[%s],收货的总数超出!,请检查重新提取操作!", asnLineId));
            }
        }
        return true;
    }

    /**
     * 收货报表单头
     */
    @Override
    public Page<RcvHDTO> getReportHeader(RcvQueryVO rcvQueryVO, PageParam pageParam) {
        String enterpriseId = rcvQueryVO.getEnterpriseId();
        if (StringUtils.isBlank(enterpriseId)) {
            String enterpriseId2 = userUtils.getEnterpriseId();
            rcvQueryVO.setEnterpriseId(enterpriseId2);
        }
        this.startPage(pageParam);
        List<RcvHDTO> heads = this.mapper.getReportHeader(rcvQueryVO);
        return PageUtils.getPage(heads);
    }

    /**
     * 收货报表行
     */
    @Override
    public Page<RcvLinesDTO> getReportRcvLine(LineQueryVO lineQueryVO, PageParam pageParam) {
        this.startPage(pageParam);
        List<RcvLinesDTO> lines = this.rcvLinesMapper.getReport(lineQueryVO);
        return PageUtils.getPage(lines);
    }

    /**
     * 质检报表行
     */
    @Override
    public Page<RqcLinesDTO> getReportRqcLine(LineQueryVO lineQueryVO, PageParam pageParam) {
        this.startPage(pageParam);
        List<RqcLinesDTO> lines = this.rqcLinesMapper.getReport(lineQueryVO);
        return PageUtils.getPage(lines);
    }

    /**
     * 复检报表行
     */
    @Override
    public Page<RqcReLinesDTO> getReportRqcReLine(LineQueryVO lineQueryVO, PageParam pageParam) {
        this.startPage(pageParam);
        List<RqcReLinesDTO> lines = this.rqcReLinesMapper.getReport(lineQueryVO);
        return PageUtils.getPage(lines);
    }

    /**
     * 拒收报表行
     */
    @Override
    public Page<RcvRejectLinesDTO> getReportRejectLine(LineQueryVO lineQueryVO, PageParam pageParam) {
        this.startPage(pageParam);
        List<RcvRejectLinesDTO> lines = this.rcvRejectLinesMapper.getReport(lineQueryVO);
        return PageUtils.getPage(lines);
    }

    /**
     * 异常报表行
     */
    @Override
    public Page<ExceptionLineQueryDTO> getReportExceptionLine(LineQueryVO lineQueryVO, PageParam pageParam) {
        this.startPage(pageParam);
        List<ExceptionLineQueryDTO> lines = this.exceptionLinesMapper.getReport(lineQueryVO);
        return PageUtils.getPage(lines);
    }

    /**
     * 上架报表行
     */
    @Override
    public Page<RcvInstockLinesDTO> getReportInstockLine(LineQueryVO lineQueryVO, PageParam pageParam) {
        this.startPage(pageParam);
        List<RcvInstockLinesDTO> lines = this.rcvInstockLinesMapper.getReport(lineQueryVO);
        return PageUtils.getPage(lines);
    }

    @Override
    public Object testGetRcvNO() {
        Long rcvNo = this.mapper.getRcvSequence();
        return ObjectUtils.getNumberStr(rcvNo, 8);
    }

    /**
     * 锁定订单为待货主转换状态
     */
    @Override
    @Transactional
    public Object lockBill(String billId) {
        this.lockBill(billId, "");
        return true;
    }

    private void lockBill(String poBillId, String poBillNo) {
        Long updateBillStatus = this.mapper.updateBillStatus(poBillId, "100"); // 更新货主转换订单状态
        if (updateBillStatus == 0) {
            throw new BizException(String.format("当前货主转换的采购订单id[%s],单号[%s]不存在或是已经进行收货处理!无法加锁", poBillId, poBillNo));
        }
    }

    //	[{"poBillId":"13920599","poBillNo":"PDDQUC00041540","warehouseId":"599581702716788736","destCargoOwnerId":
//		"E23A4BUUPPW","refBillId":"636559912872316928","refBillNo":"636559912872316928","details":
//			[{"batchId":"L3FDTQEWGHW","quantity":1,"whLocatorId":"KQLOCATOR00191"}]}]
    @Transactional
    @TxTransaction
    @Override
    public Object cargoChangeIn(List<CargoChangeIn> cargoChangeInList) {
        String string = "";
        try {
            string = JsonUtils.toString(cargoChangeInList);
        } catch (JsonProcessingException e2) {
            e2.printStackTrace();
        }
        logger.info("货主转换接收数据---------" + string);
        // 执行货主转换操作
        for (CargoChangeIn cargoChangeIn : cargoChangeInList) {
            // 锁定订单
            String poBillId = cargoChangeIn.getPoBillId();
            String poBillNo = cargoChangeIn.getPoBillNo();
            this.lockBill(poBillId, poBillNo);

            // 校验数据
            vaildateCargoChange(cargoChangeIn);

            // 获取订单数据
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("billid", poBillId);
            List<Map> searchMap = null;
            try {
                searchMap = this.searchApi.searchForMap("in_asn_getByBillid", queryMap);
            } catch (Exception e) {
                logger.info("找寻订单信息失败,原因{}", e);
            }
            if (ObjectUtils.isNull(searchMap)) {
                throw new BizException(String.format("采购订单[%s]信息为空!请核对后重试!", poBillId));
            }
            List<BillDTO> searchDTO = null;
            try {
                searchDTO = convertMap2Bill(searchMap);
            } catch (Exception e1) {
                e1.printStackTrace();
            }

            // 获取订单明细
            List<Map> searchMap2 = null;
            List<BillLineDTO> searchLineDTO = null;
            try {
                searchMap2 = this.searchApi.searchForMap("578681744203583488", queryMap);
            } catch (Exception e) {
                logger.info("找寻订单明细信息失败,原因{}", e);
            }
            if (ObjectUtils.isNull(searchMap2)) {
                throw new BizException(String.format("采购订单[%s]明细信息为空!请核对后重试!", poBillId));
            }
            try {
                searchLineDTO = convertMap2BillLine(searchMap2);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            if (ObjectUtils.isNull(searchLineDTO)) {
                throw new BizException(String.format("采购订单[%s]明细信息为空!请核对后重试!", poBillId));
            }

            // 匹配置换数据和订单明细数据一致(数量,批号等等)
            List<BillLineDTO> matchingDetalis = matchingDetalis(searchLineDTO, cargoChangeIn.getDetails());

            // 组装入库数据并自动调用
            try {
                buildRcvData(cargoChangeIn, searchDTO, matchingDetalis);
            } catch (Exception e) {
                logger.error("货主转换异常,原因->{}", e);
                throw new BizException(String.format("[%s]订单转换异常!原因[%s]", poBillId, e.getMessage()));
            }
        }

        return true;
    }

    /**
     * 组装入库准备数据
     *
     * @param cargoChangeIn
     * @param searchDTO
     * @param matchingDetalis
     * @return
     * @throws ParseException
     */
    private Object buildRcvData(CargoChangeIn cargoChangeIn, List<BillDTO> searchDTO, List<BillLineDTO> matchingDetalis)
            throws ParseException {
        if (ObjectUtils.isNull(searchDTO)) {
            throw new BizException("订单数据为空!请重试");
        }
        Date now = new Date();
        RcvDTO rcvDTO = new RcvDTO();
        BillDTO billDTO = searchDTO.get(0);
        RcvHeadersDTO rcvHeaderDto = new RcvHeadersDTO();
        BeanUtils.copyProperties(billDTO, rcvHeaderDto);
        rcvHeaderDto.setAutoGen(true);
        rcvHeaderDto.setRcvDate(now);
        RcvHeadersProfilesDTO rcvHeaderProDto = new RcvHeadersProfilesDTO();
        BeanUtils.copyProperties(billDTO, rcvHeaderProDto);
        rcvHeaderProDto.setShipFromDate(new Date());
        String carrierName = billDTO.getCarrierName();
        if (!StringUtils.isBlank(carrierName)) {
            rcvHeaderProDto.setCarriername(carrierName);
        } else {
            rcvHeaderProDto.setCarriername("无");
        }
        String transportationParty = billDTO.getTransportationParty();
        if (!StringUtils.isBlank(transportationParty)) {
            rcvHeaderProDto.setTransportationParty(transportationParty);
        } else {
            rcvHeaderProDto.setTransportationParty("无");
        }
        String shipFromAdd = billDTO.getShipFromAdd();
        if (!StringUtils.isBlank(shipFromAdd)) {
            rcvHeaderProDto.setShipFromAdd(shipFromAdd);
        } else {
            rcvHeaderProDto.setShipFromAdd("无");
        }
        Integer onPassageDays = billDTO.getOnPassageDays();
        if (!ObjectUtils.isNull(onPassageDays)) {
            rcvHeaderProDto.setOnPassageDays(onPassageDays);
        } else {
            rcvHeaderProDto.setOnPassageDays(90);
        }
        String shipType = billDTO.getShipType();
        if (!StringUtils.isBlank(shipType)) {
            rcvHeaderProDto.setShipType(shipType);
        } else {
            rcvHeaderProDto.setShipType("无");
        }

        RcvHeadersSrcBillsDTO rcvSrcDto = new RcvHeadersSrcBillsDTO();
        BeanUtils.copyProperties(billDTO, rcvSrcDto);
        rcvSrcDto.setRcvDate(now);
        List<RcvHeadersSrcBillsDTO> rcvSrcList = new ArrayList<>();
        rcvSrcList.add(rcvSrcDto);
        rcvDTO.setRcvHeadersDTO(rcvHeaderDto);
        rcvDTO.setRcvHeadersProfilesDTO(rcvHeaderProDto);
        rcvDTO.setRcvHeadersSrcBillsDTOList(rcvSrcList);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMM");
        List<RcvLinesDTO> lineDetails = new ArrayList<>();
        int row = 0;
        for (BillLineDTO matchingDetails : matchingDetalis) {
            row++;
            RcvLinesDTO lineDto = new RcvLinesDTO();
            BeanUtils.copyProperties(matchingDetails, lineDto);
            lineDto.setEditFlag(2); // 批号不变
            lineDto.setLineNum(row);
            lineDto.setRcvType(rcvHeaderDto.getRcvType());

            String asnLineId = matchingDetails.getAsnLineId();
            // 需要计算数量
            BigDecimal pieceQty = lineDto.getPieceQty();
            BigDecimal conversionRate = lineDto.getConversionRate();
            if (conversionRate == null) {
                conversionRate = BigDecimal.ONE;
                lineDto.setConversionRate(conversionRate);
            }
            if (pieceQty == null) {
                pieceQty = BigDecimal.ZERO;
                lineDto.setPieceQty(pieceQty);
            }
            BigDecimal caseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
            BigDecimal multiply = caseQty.multiply(conversionRate);
            BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散

            BigDecimal qty = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN); // 包装总量
            // 保证数据正确性再次进行计算
            lineDto.setOddCaseQty(caseQty);
            lineDto.setOddPieceQty(oddPieceQty);
            Date batchProductionDate = matchingDetails.getBatchProductionDate();
            Date batchExpiredDate = matchingDetails.getBatchExpiredDate();
            if (batchProductionDate == null) {
                String showProductionDate = matchingDetails.getShowProductionDate();
                if (showProductionDate.length() == 8) {
                    Date parse = sdf.parse(showProductionDate);
                    lineDto.setBatchProductionDate(parse);
                }
                if (showProductionDate.length() == 6) {
                    Date parse = sdf2.parse(showProductionDate);
                    lineDto.setBatchProductionDate(parse);
                }
            }
            if (batchExpiredDate == null) {
                String showExpiredDate = matchingDetails.getShowExpiredDate();
                if (showExpiredDate.length() == 8) {
                    Date parse = sdf.parse(showExpiredDate);
                    lineDto.setBatchExpiredDate(parse);
                }
                if (showExpiredDate.length() == 6) {
                    Date parse = sdf2.parse(showExpiredDate);
                    lineDto.setBatchExpiredDate(parse);
                }
            }

            String stockStatus = lineDto.getStockStatus();
            if (StringUtils.isBlank(stockStatus)) {
                lineDto.setStockStatus("0");
            }

            RcvLinesProfilesDTO lineProfilesDto = new RcvLinesProfilesDTO();
            BeanUtils.copyProperties(matchingDetails, lineProfilesDto);
            lineProfilesDto.setLineNum(BigDecimal.valueOf(row));
            lineDto.setRcvLinesProfilesDTO(lineProfilesDto);

            lineDetails.add(lineDto);
        }
        rcvDTO.setRcvLinesDTOList(lineDetails);
        return this.addWithRelated(rcvDTO, cargoChangeIn, null);
    }

    private void extracted(Map<String, Set<String>> asnLineIdMap) {
        Criteria cr1 = Criteria.forClass(OmsAsnBillD.class);
        Restriction r1 = Restrictions.in("lineid", asnLineIdMap.keySet().toArray());
        Restriction r2 = Restrictions.isNotNull("batchLimit");
        cr1.setRestriction(Restrictions.and(r1, r2));
        List<OmsAsnBillD> omsBillDList = omsAsnBillDMapper.findByCriteria(cr1);
        if (omsBillDList != null && omsBillDList.size() > 0) {
            for (int i = 0; i < omsBillDList.size(); i++) {
                OmsAsnBillD omsAsnBillD = omsBillDList.get(i);
                int batchLimit = omsAsnBillD.getBatchLimit();
                String srcLineId = omsAsnBillD.getLineid();
                Criteria cr11 = Criteria.forClass(RcvLines.class);
                Restriction r11 = Restrictions.eq("srcLineId", srcLineId);
                cr11.setRestriction(Restrictions.and(r11));
                List<RcvLines> rcvLinesList = rcvLinesMapper.findByCriteria(cr11);
                Set<String> lotSet = asnLineIdMap.get(srcLineId);
                lotSet.addAll(rcvLinesList.stream().filter(p -> !StringUtils.isBlank(p.getManufacturerLotNum()))
                        .map(t -> t.getManufacturerLotNum()).collect(Collectors.toSet()));
                int size = lotSet.size();
                if (batchLimit < size) {
                    throw new BizException(
                            "商品[" + omsAsnBillD.getItemname() + "]批号个数[" + size + "]超过批号上限个数[" + batchLimit + "]");
                }
            }
        }
    }

    private Object addWithRelated(RcvDTO rcvDTO, CargoChangeIn cargoChangeIn, Boolean ispad) {

        // 没有草稿状态一说,直接保存
        // 添加自身及其关联表
        RcvHeadersDTO rcvHeadersDTO = rcvDTO.getRcvHeadersDTO();
        try {
            logger.info("开始级联保存收货信息:[{}]", JsonUtils.toString(rcvDTO));
//			logger.info("开始级联保存收货信息:[{}]", JsonUtils.toString(rcvHeadersDTO));
        } catch (JsonProcessingException e) {
        }
        rcvHeadersDTO.setAccessLevel("0"); // 默认数据级别0
        /* 添加思源收货的校验动作，on 2022-07-22 By 陈浩---开始 */
        String rcvType = rcvHeadersDTO.getRcvType();
//        if (BizConstant.PURCHASE_IN.equals(rcvType) || BizConstant.ALLOT_IN.equals(rcvType)
//                || BizConstant.FACTORY_MAINTENANCE_IN.equals(rcvType)
//                || BizConstant.CUSTORM_MAINTENANCE_IN.equals(rcvType) || BizConstant.SALE_RETURN_IN.equals(rcvType)) {
//            this.checkQualityInspectionReceipt(rcvDTO);
//        }
        /* 添加思源收货的校验动作，on 2022-07-22 By 陈浩---结束 */

        // 来源单效期,校验货主证件效期,仓库暂时不处理 TODO
        String asnHeaderId = rcvHeadersDTO.getAsnHeaderId();
        // 校验asn单订单效期,已有前端校验
//				excuteVaildateAsn(asnHeaderId);

        // 校验货主的资质,供应商,客户证照
        excuteVaildateOwnerAndShipper(rcvDTO);

        UserDTO userDTO = userUtils.getUserDTO();
        AssertUtils.notNull(rcvHeadersDTO, "收货单主表不可为空!");

        AssertUtils.notNull(rcvDTO.getRcvLinesDTOList(), "收货单明细不可为空!");
        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();

        //校验头单与明细行是否一致
        long count = rcvLinesDTOList.stream().filter(x -> x.getAsnHeaderId().equals(asnHeaderId)).count();
        if(count==0){
            throw new BizException("收货单主表与明细不一致，请检查！");
        }
        //校验批次号和生产日期有效期
        for (RcvLinesDTO rcvLinesDTO : rcvLinesDTOList) {
            if(StringUtils.isBlank(rcvLinesDTO.getManufacturerLotNum())){
                throw new BizException("批号不能为空!");
            }
            if(rcvLinesDTO.getBatchProductionDate() == null){
                throw new BizException("生产日期不能为空!");
            }
            if(rcvLinesDTO.getBatchExpiredDate() == null){
                throw new BizException("有效期不能为空!");
            }
        }
        //校验商品体积
        excuteVaildateItemVolume(rcvDTO.getRcvLinesDTOList());

        Map<String, Set<String>> asnLineIdMap = new HashMap();
        String[] itemIdsArr = rcvDTO.getRcvLinesDTOList().stream().filter(p -> !StringUtils.isBlank(p.getItemId()))
                .map(RcvLinesDTO::getItemId).distinct().toArray(String[]::new);
        RestMessage<List<ItemBaseInfoVO>> itemResult = null;
        if (itemIdsArr != null && itemIdsArr.length > 0) {
            itemResult = itemClient.getItemBaseList(itemIdsArr);
        }
        for (RcvLinesDTO rcvLinesDTO : rcvDTO.getRcvLinesDTOList()) {
            if ("1".equals(rcvDTO.getRcvHeadersDTO().getRcvType())) {
                if (itemResult.isSuccess() && itemResult.getData() != null && itemResult.getData().size() > 0) {
                    ItemBaseInfoVO ItemBaseInfoVO = itemResult.getData().stream()
                            .filter(t -> t.getItemId().equals(rcvLinesDTO.getItemId())).findFirst().orElse(null);
                    if (ItemBaseInfoVO != null && ItemBaseInfoVO.getItemIsUnpack() != null
                            && ItemBaseInfoVO.getItemIsUnpack() == 0
                            && rcvLinesDTO.getOddPieceQty().compareTo(BigDecimal.ZERO) > 0) {
                        logger.error("商品" + rcvLinesDTO.getItemName() + "不允许拆中包装");
                        throw new BizException("商品" + rcvLinesDTO.getItemName() + "不允许拆中包装");
                    }
                }
            }
            String asnLineId = rcvLinesDTO.getAsnLineId();
            if (asnLineIdMap.get(asnLineId) == null) {
                Set set = new HashSet();
                set.add(rcvLinesDTO.getManufacturerLotNum());
                asnLineIdMap.put(asnLineId, set);
            } else {
                Set set = asnLineIdMap.get(asnLineId);
                set.add(rcvLinesDTO.getManufacturerLotNum());
            }
        }
        extracted(asnLineIdMap);

        // 代管校验
        if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.HOSTED_IN)) {
            // 代管入库的处理,若是流通货主,不走验收,走货位推荐逻辑生生上架任务
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("cargoOwnerId", rcvHeadersDTO.getMtlOwnerId());
            List<Map> searchForMap = null;
            try {
                searchForMap = searchApi.searchForMap("getCargoOwnerProp", queryMap);
            } catch (Exception e) {
                logger.info("获取货主属性失败,原因{}", e);
            }
            if (!ObjectUtils.isNull(searchForMap)) {
                Map map = searchForMap.get(0);
                String cargoOwnerProp = (String) map.get("cargoOwnerProp");
                Object isHostedRcvObj = map.get("isHostedRcv");
                Integer isHostedRcv = 1;
                if (isHostedRcvObj instanceof String) {
                    isHostedRcv = Integer.parseInt((String) isHostedRcvObj);
                }
                if (isHostedRcvObj instanceof Integer) {
                    isHostedRcv = (Integer) isHostedRcvObj;
                }
                if (isHostedRcv != null && 0 == isHostedRcv) {
                    // 此货主不支持代管业务
                    throw new BizException("此货主不支持代管业务!请设置!");
                }
                if (!StringUtils.isBlank(cargoOwnerProp) && "0".equals(cargoOwnerProp)
                        && rcvType.equals(BizConstant.WAIT_CHECK_IN)) {
                    // 流通货主
                    throw new BizException("此货主不支持待检业务!请设置!");
                }
            }
        }

//		if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.STRAIGHT_IN)) {
//			throw new BizException("此货主暂不支持直通业务,请期待开放!");
//		}

        String masterId = (String) this.add(rcvHeadersDTO, userDTO);

        RcvHeadersProfilesDTO rcvHeadersProfilesDTO = rcvDTO.getRcvHeadersProfilesDTO();
        rcvHeadersProfilesDTO.setArrivalMode(rcvHeadersDTO.getArrivalMode());
        List<RcvHeadersSrcBillsDTO> rcvHeadersSrcBillsDTOList = rcvDTO.getRcvHeadersSrcBillsDTOList();

        if (ObjectUtils.isNotNull(rcvHeadersProfilesDTO)) {
            // 这里是否需要做更新?
            rcvHeadersProfilesDTO.setRcvHeaderId(masterId);
            rcvHeadersProfilesDTO.setRcvType(rcvHeadersDTO.getRcvType());
            rcvHeadersProfilesService.add(rcvHeadersProfilesDTO);
        }
        if (ObjectUtils.isNotNull(rcvHeadersSrcBillsDTOList)) {
            rcvHeadersSrcBillsService.batchAdd(rcvHeadersSrcBillsDTOList, masterId, userDTO);
        }
        // 收货,拒收,待处理,代管
        AssertUtils.notNull(rcvLinesDTOList, "收货单明细表不可为空!");

        boolean anyMatch = rcvLinesDTOList.stream().filter(p -> ObjectUtils.isNotNull(p.getIsDoubleReceive()))
                .anyMatch(p -> p.getIsDoubleReceive() == 1);
        if (anyMatch) {
            String rcvUserId1 = rcvHeadersDTO.getRcvUserId1();
            String rcvUserId2 = rcvHeadersDTO.getRcvUserId2();
            if (StringUtils.isBlank(rcvUserId1) || StringUtils.isBlank(rcvUserId2)) {
                throw new BizException("有商品需要双人收货,请切换账号,进行收货确认!");
            }
        }

//        Set<String> collect = rcvLinesDTOList.stream().map(x -> x.getStockStatus()).collect(Collectors.toSet());
//        if(collect.size()>1){
//            throw new BizException("收货与拒收结论请分开收货!");
//        }

        // 保存收货明细,根据收货类型做不同的逻辑处理
        rcvHeadersDTO.setRcvHeaderId(masterId);
        boolean ztFlag =false;
        Object excuteRcvLine = rcvTypeService.excuteRcvLine(rcvHeadersDTO, rcvLinesDTOList, userDTO, cargoChangeIn,ztFlag);

        // 校验是否超收,拆分加并发
        vaildateOvercharge(rcvLinesDTOList, userDTO);

        // 新增明细
//				rcvLinesService.batchAdd(rcvLinesDTOList, masterId, userDTO, mtlOwnerId, warehouseId);

        String mtlOwnerId = rcvHeadersDTO.getMtlOwnerId();
//        boolean allMatch = rcvLinesDTOList.stream().allMatch(p -> p.getStockStatus().equals("3"));
//        if (allMatch) {
//            BigDecimal remainQty = this.mapper.getRemainQty(masterId);
//            if (remainQty != null && BigDecimal.ZERO.compareTo(remainQty) == 0) {
//                // 整单拒收
//                excuteCallBackErp(masterId, mtlOwnerId, asnHeaderId);
//            }
//        }
        //青牛拒收不记录实收数量,不触发回传
//        boolean allMatch = rcvLinesDTOList.stream().allMatch(p -> p.getStockStatus().equals("3"));
//        if(allMatch){
//            //青牛没有OMS，不用生成receiving_record_back_d表
////            receivingRecordBackReject(rcvHeadersDTO,userDTO);
//            BigDecimal remainQty = this.mapper.getRemainQty(masterId);
//            if (remainQty != null && BigDecimal.ZERO.compareTo(remainQty) == 0) {
//                // 整单拒收
//                excuteCallBackErp(masterId, mtlOwnerId, asnHeaderId);
//            }
//        }

        return excuteRcvLine;
    }

    /**
     * 校验商品体积
     * @param rcvLinesDTOList
     */
    private void excuteVaildateItemVolume(List<RcvLinesDTO> rcvLinesDTOList) {

        List<String> itemIds = rcvLinesDTOList.stream().map(RcvLinesDTO::getItemId).distinct().collect(Collectors.toList());
        RestMessage<Map<String, List<BaseMtlItemUomConversions>>> uomConversionsByItemIds = itemClient.getUomConversionsByItemIds(String.join(",",itemIds));
        if(uomConversionsByItemIds == null || !uomConversionsByItemIds.isSuccess() || uomConversionsByItemIds.getData() == null || uomConversionsByItemIds.getData().size() <= 0){
            throw new BizException("商品："+JSON.toJSONString(itemIds) + "获取包装信息失败!");
        }
        Map<String, List<BaseMtlItemUomConversions>> data = uomConversionsByItemIds.getData();
        for (RcvLinesDTO rcvLinesDTO : rcvLinesDTOList) {
            List<BaseMtlItemUomConversions> baseMtlItemUomConversions = data.get(rcvLinesDTO.getItemId());
            if(baseMtlItemUomConversions == null || baseMtlItemUomConversions.size() <= 0){
                throw new BizException("商品："+rcvLinesDTO.getItemId() + "未维护包装信息!");
            }
            long count = baseMtlItemUomConversions.stream().filter(item -> "Y".equals(item.getMaxSu()) && item.getVolume() != null && item.getVolume().compareTo(BigDecimal.ZERO) > 0).count();
            if(count <= 0){
                throw new BizException("商品："+rcvLinesDTO.getItemId() + "最大单位包装体积不能为空!");
            }
        }
    }

    private void receivingRecordBackReject(RcvHeadersDTO rcvHeadersDTO,UserDTO userDTO){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        //保存记录到收货-拒收-验收记录表
        List<ReceivingRecordBackVO> backList = new ArrayList<>();
        List<ReceivingRecordBackH> backHList = receivingRecordBackHMapper.getRcvInsertData(rcvHeadersDTO.getRcvHeaderId());
        if(backHList.size()>0){
            List<ReceivingRecordBackD> backDList = receivingRecordBackDMapper.getRcvInsertData(rcvHeadersDTO.getRcvHeaderId());
            //收货明细
            List<ReceivingRecordBackDVO> rcvBackDVOList = new ArrayList<>();
            //拒收明细
            List<ReceivingRecordBackDVO> rejectBackDVOList = new ArrayList<>();
            if(backDList.size()>0){
                for (ReceivingRecordBackD receivingRecordBackD : backDList) {
                    ReceivingRecordBackDVO backDVO = convertBackDVO(receivingRecordBackD);
                    if(receivingRecordBackD.getStockstatus().equals("2")){
                        rejectBackDVOList.add(backDVO);
                    }else{
                        rcvBackDVOList.add(backDVO);
                    }
                }
            }
            if(rcvBackDVOList.size()>0){
                for (ReceivingRecordBackH receivingRecordBackH : backHList) {
                    ReceivingRecordBackVO backVO = new ReceivingRecordBackVO();
                    ReceivingRecordBackHVO backHVO = new ReceivingRecordBackHVO();
                    BeanUtils.copyProperties(receivingRecordBackH,backHVO);
                    backHVO.setRefBillno(receivingRecordBackH.getRefbillno());
                    backHVO.setPurorgId(receivingRecordBackH.getBuyerId());
                    backHVO.setPurorgName(receivingRecordBackH.getBuyerName());
                    backHVO.setShipmentDate(DateUtils.format(receivingRecordBackH.getRcvdate(),"yyyy-MM-dd HH:mm:ss"));
                    //backHVO.setRcvoperator(userDTO.getNickname());
                    backHVO.setPenterpriseid(receivingRecordBackH.getPEnterpriseid());
                    backHVO.setType("10");
                    backVO.setContent(backHVO);
                    backVO.setDetailList(rcvBackDVOList);
                    backList.add(backVO);
                }
            }
            if(rejectBackDVOList.size()>0){
                for (ReceivingRecordBackH receivingRecordBackH : backHList) {
                    ReceivingRecordBackVO backVO = new ReceivingRecordBackVO();
                    ReceivingRecordBackHVO backHVO = new ReceivingRecordBackHVO();
                    BeanUtils.copyProperties(receivingRecordBackH,backHVO);
                    backHVO.setRefBillno(receivingRecordBackH.getRefbillno());
                    backHVO.setPurorgId(receivingRecordBackH.getBuyerId());
                    backHVO.setPurorgName(receivingRecordBackH.getBuyerName());
                    backHVO.setShipmentDate(DateUtils.format(receivingRecordBackH.getRcvdate(),"yyyy-MM-dd HH:mm:ss"));
                    //backHVO.setRcvoperator(userDTO.getNickname());
                    backHVO.setPenterpriseid(receivingRecordBackH.getPEnterpriseid());
                    backHVO.setType("30");
                    backVO.setContent(backHVO);
                    backVO.setDetailList(rejectBackDVOList);
                    backList.add(backVO);
                }
            }
            receivingRecordBackHMapper.saveBatch(backHList);
            receivingRecordBackDMapper.saveBatch(backDList);
            //TODO 调用接口平台回传OMS
            try {
//                String url = "http://integration.upcloud.prolog.org/api/rcvInstockLines/infTaskInBack";
//                if(StringUtils.isEmpty(receivingRecordBack)){
//                    throw new BizException("请求路径配置为空");
//                }
                System.out.println(JSON.toJSONString(backList));
                //String url = receivingRecordBack;
                AskIntegrationVo vo = new AskIntegrationVo();
//                vo.setIntegrationCode("receivingRecordBack");//青牛没有OMS
                vo.setParam(backList);
                RestMessage<?> msg = baseInventoryRemoteCaller.askIntegration(vo);
//                String result = HttpUtil.post(url, JSONObject.toJSONString(backList));
//                JSONObject parse = JSONObject.parseObject(result);
                if(msg.isSuccess()){
                    String[] billids = backHList.stream().map(x -> x.getBillid()).toArray(String[]::new);
                    Criteria crt = Criteria.forClass(ReceivingRecordBackH.class);
                    crt.restrictionBuilder().in("billid",billids);
                    crt.buildRestriction();
                    receivingRecordBackHMapper.updateMapByCriteria(MapUtils.put("uploadStatus","1").getMap(),crt);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

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

    private void excuteVaildateOwnerAndShipper(RcvDTO rcvDTO) {
        RcvHeadersDTO rcvHeadersDTO = rcvDTO.getRcvHeadersDTO();
        String mtlOwnerId = rcvHeadersDTO.getMtlOwnerId();
        String vendorId = rcvHeadersDTO.getVendorId();
        String customerId = rcvHeadersDTO.getCustomerId();
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("cargoOwnerId", mtlOwnerId);
        List<Map> searchForMap = null;
        try {
            searchForMap = searchApi.searchForMap("getCargoOwnerProp", queryMap);
        } catch (Exception e) {
            logger.info("获取货主属性失败,原因{}", e);
        }
        if (!ObjectUtils.isNull(searchForMap)) {
            Map map = searchForMap.get(0);
            String flag1 = (String) map.get("vaildateLicense");
            String flag2 = (String) map.get("vaildateSuppilerAndCustomer");
            if (!StringUtils.isBlank(flag1) && "1".equals(flag1)) {
                // 校验货主
                CargoOwnerLicenseQueryVO cvo = new CargoOwnerLicenseQueryVO();
                cvo.setCargoOwnerId(mtlOwnerId);
                RestMessage<Object> vaildateLicense = null;
                try {
                    vaildateLicense = chainRemoteCaller.vaildateLicense(cvo);
                } catch (Exception e) {
                    logger.error("调用远程供应链服务失败,原因{}", e.getMessage());
                }
                if (vaildateLicense != null && !vaildateLicense.isSuccess()) {
                    throw new BizException(vaildateLicense.getMessage());
                }
            }
            if (!StringUtils.isBlank(flag2) && "1".equals(flag2)) {
                if (!StringUtils.isBlank(vendorId)) {
                    // 供应商
                    RestMessage<?> healthLicenseVaildateAll = null;
                    try {
                        healthLicenseVaildateAll = chainRemoteCaller
                                .healthLicenseVaildateAll(MapUtils.put("supplierId", vendorId).getMap());
                    } catch (Exception e) {
                        logger.error("调用远程供应链服务失败,原因{}", e.getMessage());
                    }
                    if (healthLicenseVaildateAll != null && !healthLicenseVaildateAll.isSuccess()) {
                        throw new BizException(healthLicenseVaildateAll.getMessage());
                    }
                }
                if (!StringUtils.isBlank(customerId)) {
                    // 客户
                    RestMessage<?> healthLicenseVaildateAll2 = null;
                    try {
                        healthLicenseVaildateAll2 = chainRemoteCaller
                                .healthLicenseVaildateAll2(MapUtils.put("customerId", customerId).getMap());
                    } catch (Exception e) {
                        logger.error("调用远程供应链服务失败,原因{}", e.getMessage());
                    }
                    if (healthLicenseVaildateAll2 != null && !healthLicenseVaildateAll2.isSuccess()) {
                        throw new BizException(healthLicenseVaildateAll2.getMessage());
                    }
                }
            }
        }
    }

    /**
     * 匹配订单明细是否和转换明细一致
     *
     * @param billLineDetails
     * @param changeDetails
     */
    private List<BillLineDTO> matchingDetalis(List<BillLineDTO> billLineDetails,
                                              List<CargoChangeInDetails> changeDetails) {
        // 获取转换的批次及货位数据
        buildCargoChangeInDetailField(changeDetails);

        Map<String, List<CargoChangeInDetails>> collect = changeDetails.stream()
                .collect(Collectors.groupingBy(e -> e.getDestItemId()));
        List<BillLineDTO> targetBillLines = new ArrayList<>();
        for (BillLineDTO billLine : billLineDetails) {
            billLine.setChangeMatchFlag(false);
            String itemId = billLine.getItemId();
            String itemNum = billLine.getItemNum();
            String itemName = billLine.getItemName();
            if (!ObjectUtils.isNull(collect.get(itemId))) {
                // 匹配批号信息成功
                // 匹配数量
                List<CargoChangeInDetails> list = collect.get(itemId);
                BigDecimal reduce = list.stream()
                        .map(vo -> ObjectUtils.isNull(vo.getQuantity()) ? new BigDecimal(0) : vo.getQuantity())
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal preQty = billLine.getPreQty();
                if (reduce.compareTo(preQty) == 0) {
                    // 数量一致成功
                    billLine.setChangeMatchFlag(true);

                    // 加入货位,批次等数据
                    for (CargoChangeInDetails changeLine : list) {
                        BillLineDTO targetBillLine = new BillLineDTO();
                        BeanUtils.copyProperties(billLine, targetBillLine);
                        targetBillLine.setBatchId(changeLine.getBatchId());
                        targetBillLine.setBatchNum(changeLine.getBatchNum());
                        targetBillLine.setBatchProductionDate(changeLine.getProductionDate());
                        targetBillLine.setBatchExpiredDate(changeLine.getExpiredDate());
                        targetBillLine.setShowExpiredDate(changeLine.getShowExpiredDate());
                        targetBillLine.setShowProductionDate(changeLine.getShowProductionDate());
                        targetBillLine.setManufacturerLotNum(changeLine.getManufacturerLotNum());
                        targetBillLine.setUom(changeLine.getUom());
                        targetBillLine.setConversionRate(changeLine.getConversionRate());
                        targetBillLine.setPieceQty(changeLine.getQuantity());
                        targetBillLine.setOddCaseQty(changeLine.getOddCaseQty());
                        targetBillLine.setOddPieceQty(changeLine.getOddPieceQty());
                        targetBillLine.setWhLocatorId(changeLine.getWhLocatorId());
                        targetBillLine.setWhLocatorCode(changeLine.getWhLocatorCode());
                        targetBillLine.setWhAreaCode(changeLine.getWhAreaCode());
                        targetBillLine.setWhAreaCategoryCode(changeLine.getWhAreaCategoryCode());
                        targetBillLine.setRefLineId(changeLine.getRefLineId());
                        targetBillLine.setRefLineRemark(changeLine.getRefLineRemark());
                        targetBillLine.setRefLineAttr1(changeLine.getRefLineAttr1());
                        targetBillLine.setRefLineAttr2(changeLine.getRefLineAttr2());

                        targetBillLines.add(targetBillLine);
                    }

                } else {
                    // 不一致抛错
                    throw new BizException(String.format("商品[%s],id[%s],编码[%s],需要转换的采购订单明细和转换的明细数量不一致!请检查!", itemName,
                            itemId, itemNum));
                }
            } else {
                // 批次信息等无法匹配成功
                throw new BizException(
                        String.format("商品[%s],id[%s],编码[%s],需要转换的采购订单明细和转换的明细数据对应不上!请检查!", itemName, itemId, itemNum));
            }
        }

        return targetBillLines;

    }

    private void buildCargoChangeInDetailField(List<CargoChangeInDetails> changeDetails) {
        Set<String> batchIds = changeDetails.stream().map(CargoChangeInDetails::getBatchId).collect(Collectors.toSet());
        if (ObjectUtils.isNull(batchIds)) {
            throw new BizException("批次id数据为空!请检查!");
        }
        Set<String> locatorIds = changeDetails.stream().map(CargoChangeInDetails::getWhLocatorId)
                .collect(Collectors.toSet());
        if (ObjectUtils.isNull(locatorIds)) {
            throw new BizException("货位id数据为空!请检查!");
        }
        List<Map> batchMap = null;
        try {
            batchMap = searchApi.searchForMap("batch_info_list", MapUtils.put("batchIds", batchIds).getMap());
        } catch (Exception e) {
            logger.error("入参" + batchIds.toString() + "远程调用searchApi查询批次(batch_info_list)信息错误!原因->{}", e);
        }
        if (ObjectUtils.isNull(batchMap)) {
            throw new BizException("查询的批次数据为空!请检查!");
        }
        List<Map> locatorMap = null;
        try {
            locatorMap = searchApi.searchForMap("locator_info_list", MapUtils.put("locatorIds", locatorIds).getMap());
        } catch (Exception e) {
            logger.error("入参" + locatorIds.toString() + "远程调用searchApi查询货位(locator_info_list)信息错误!原因->{}", e);
        }
        if (ObjectUtils.isNull(locatorMap)) {
            throw new BizException("查询的货位数据为空!请检查!");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map<String, List<Map>> collect = batchMap.stream()
                .collect(Collectors.groupingBy(e -> (String) e.get("batchId")));
        Map<String, List<Map>> collect2 = locatorMap.stream()
                .collect(Collectors.groupingBy(e -> (String) e.get("whLocatorId")));
        for (CargoChangeInDetails changeDetail : changeDetails) {
            String batchId = changeDetail.getBatchId();
            String whLocatorId = changeDetail.getWhLocatorId();

            // 商品批次信息
            List<Map> list = collect.get(batchId);
            if (!ObjectUtils.isNull(list)) {
                Map map = list.get(0);
                String batchNum = (String) map.get("batchNum");
                String itemId = (String) map.get("itemId");
                String itemNum = (String) map.get("itemCode");
                String itemName = (String) map.get("itemName");
                String uom = (String) map.get("uom");
                String manufacturerLotNum = (String) map.get("manufacturerLotNum");
                String rqcReportNo = (String) map.get("rqcReportNo");
                String showProductionDate = (String) map.get("showProductionDate");
                String showExpiredDate = (String) map.get("showExpiredDate");
                Object conversionRateObj = map.get("conversionRate");
                BigDecimal conversionRate = BigDecimal.ONE;
                if (conversionRateObj != null) {
                    String conversionRateStr = map.get("conversionRate").toString();
                    conversionRate = new BigDecimal(conversionRateStr);
                }

                Object productionDateObj = map.get("productionDate");
                Object expiredDateObj = map.get("expiredDate");
                Date productionDate = null;
                if (productionDateObj instanceof java.util.Date) {
                    productionDate = (Date) productionDateObj;
                }
                if (productionDateObj instanceof String) {
                    String productionDateStr = (String) productionDateObj;
                    try {
                        productionDate = sdf.parse(productionDateStr);
                    } catch (ParseException e1) {
                        e1.printStackTrace();
                    }
                }
                Date expiredDate = null;
                if (expiredDateObj instanceof java.util.Date) {
                    expiredDate = (Date) expiredDateObj;
                }
                if (expiredDateObj instanceof String) {
                    String expiredDateStr = (String) expiredDateObj;
                    try {
                        expiredDate = sdf.parse(expiredDateStr);
                    } catch (ParseException e1) {
                        e1.printStackTrace();
                    }
                }

                changeDetail.setBatchNum(batchNum);
                changeDetail.setConversionRate(conversionRate);
                changeDetail.setDestItemId(itemId);
                changeDetail.setDestItemCode(itemNum);
                changeDetail.setDestItemName(itemName);
                changeDetail.setExpiredDate(expiredDate);
                changeDetail.setManufacturerLotNum(manufacturerLotNum);
                changeDetail.setProductionDate(productionDate);
                changeDetail.setShowExpiredDate(showExpiredDate);
                changeDetail.setShowProductionDate(showProductionDate);
                changeDetail.setUom(uom);
                changeDetail.setRqcReportNo(rqcReportNo);
                BigDecimal pieceQty = changeDetail.getQuantity();
                if (conversionRate == null) {
                    conversionRate = BigDecimal.ONE;
                    changeDetail.setConversionRate(conversionRate);
                }
                if (pieceQty == null) {
                    pieceQty = BigDecimal.ZERO;
                    changeDetail.setQuantity(pieceQty);
                }
                BigDecimal caseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
                BigDecimal multiply = caseQty.multiply(conversionRate);
                BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
                BigDecimal qty = pieceQty.divide(conversionRate, 4, RoundingMode.DOWN); // 包装总量
                // 保证数据正确性再次进行计算
                changeDetail.setOddCaseQty(caseQty);
                changeDetail.setOddPieceQty(oddPieceQty);
            }

            // 货位信息
            List<Map> list2 = collect2.get("whLocatorId");
            if (!ObjectUtils.isNull(list2)) {
                Map map2 = list2.get(0);
                String warehouseAreaId = (String) map2.get("warehouseAreaId");
                String whAreaCode = (String) map2.get("whAreaCode");
                String whLocatorCode = (String) map2.get("whLocatorCode");
                String whLocatorName = (String) map2.get("whLocatorName");
                String whAreaCategoryCode = (String) map2.get("whAreaCategoryCode");
                Integer floorNum = (Integer) map2.get("floorNum");

                changeDetail.setWhAreaCategoryCode(whAreaCategoryCode);
                changeDetail.setWhAreaCode(whAreaCode);
                changeDetail.setWhLocatorCode(whLocatorCode);
            }

        }

    }

//	/**
//	 * 匹配订单明细是否和转换明细一致
//	 * 
//	 * @param billLineDetails
//	 * @param changeDetails
//	 */
//	private List<BillLineDTO> matchingDetalis(List<BillLineDTO> billLineDetails,
//			List<CargoChangeInDetails> changeDetails) {
//		Map<Object, List<CargoChangeInDetails>> collect = changeDetails.stream()
//				.collect(Collectors.groupingBy(e -> fetchGroupKey(e)));
//		List<BillLineDTO> targetBillLines = new ArrayList<>();
//		for (BillLineDTO billLine : billLineDetails) {
//			billLine.setChangeMatchFlag(false);
//			String itemId = billLine.getItemId();
//			String itemNum = billLine.getItemNum();
//			String itemName = billLine.getItemName();
//			String manufacturerLotNum = billLine.getManufacturerLotNum();
//			String showProductionDate = billLine.getShowProductionDate();
//			String showExpiredDate = billLine.getShowExpiredDate();
//			String getMD5Code = MD5Utils.GetMD5Code(itemId + manufacturerLotNum + showProductionDate + showExpiredDate);
//			if (!ObjectUtils.isNull(collect.get(getMD5Code))) {
//				// 匹配批号信息成功
//				// 匹配数量
//				List<CargoChangeInDetails> list = collect.get(getMD5Code);
//				BigDecimal reduce = list.stream()
//						.map(vo -> ObjectUtils.isNull(vo.getQuantity()) ? new BigDecimal(0) : vo.getQuantity())
//						.reduce(BigDecimal.ZERO, BigDecimal::add);
//				BigDecimal preQty = billLine.getPreQty();
//				if (reduce.compareTo(preQty) == 0) {
//					// 数量一致成功
//					billLine.setChangeMatchFlag(true);
//					
//					// 加入货位,批次等数据
//					for (CargoChangeInDetails changeLine : list) {
//						BillLineDTO targetBillLine = new BillLineDTO();
//						BeanUtils.copyProperties(billLine, targetBillLine);
//						targetBillLine.setBatchId(changeLine.getBatchId());
//						targetBillLine.setBatchNum(changeLine.getBatchNum());
//						targetBillLine.setBatchProductionDate(changeLine.getProductionDate());
//						targetBillLine.setBatchExpiredDate(changeLine.getExpiredDate());
//						targetBillLine.setUom(changeLine.getUom());
//						targetBillLine.setConversionRate(changeLine.getConversionRate());
//						targetBillLine.setPieceQty(changeLine.getQuantity());
//						targetBillLine.setOddCaseQty(changeLine.getOddCaseQty());
//						targetBillLine.setOddPieceQty(changeLine.getOddPieceQty());
//						targetBillLine.setWhLocatorId(changeLine.getWhLocatorId());
//						targetBillLine.setWhLocatorCode(changeLine.getWhLocatorCode());
//						targetBillLine.setWhAreaCode(changeLine.getWhAreaCode());
//						targetBillLine.setWhAreaCategoryCode(changeLine.getWhAreaCategoryCode());
//						targetBillLine.setRefLineId(changeLine.getRefLineId());
//						targetBillLine.setRefLineRemark(changeLine.getRefLineRemark());
//						targetBillLine.setRefLineAttr1(changeLine.getRefLineAttr1());
//						targetBillLine.setRefLineAttr2(changeLine.getRefLineAttr2());
//						
//						targetBillLines.add(targetBillLine);
//					}
//					
//				} else {
//					// 不一致抛错
//					throw new BizException(String.format("商品[%s],id[%s],编码[%s],需要转换的采购订单明细和转换的明细数量不一致!请检查!", itemName,
//							itemId, itemNum));
//				}
//			} else {
//				// 批次信息等无法匹配成功
//				throw new BizException(
//						String.format("商品[%s],id[%s],编码[%s],批号[%s],生产日期[%s],有效期至[%s],需要转换的采购订单明细和转换的明细数据对应不上!请检查!",
//								itemName, itemId, itemNum, manufacturerLotNum, showProductionDate, showExpiredDate));
//			}
//		}
//		
//		return targetBillLines;
//		
//	}

    private Object fetchGroupKey(CargoChangeInDetails e) {
        String destItemId = e.getDestItemId();
        String manufacturerLotNum = e.getManufacturerLotNum();
        String showProductionDate = e.getShowProductionDate();
        String showExpiredDate = e.getShowExpiredDate();
        String getMD5Code = MD5Utils.GetMD5Code(destItemId + manufacturerLotNum + showProductionDate + showExpiredDate);
        logger.info(destItemId + "---" + manufacturerLotNum + "---" + showProductionDate + "---" + showExpiredDate
                + "---" + getMD5Code);
        return getMD5Code;
    }

    private List<BillLineDTO> convertMap2BillLine(List<Map> searchMap)
            throws IllegalArgumentException, IllegalAccessException, InstantiationException, ParseException {
        List<BillLineDTO> lineList = new ArrayList<>();
        for (Map map : searchMap) {
            BillLineDTO billLine = new BillLineDTO();
            BeanUtils.copyProperties(map, billLine);

            Object caseConversionRate = map.get("caseConversionRate");
            if (caseConversionRate != null) {
                billLine.setCaseConversionRate(new BigDecimal(caseConversionRate.toString()));
            }
            Object conversionRate = map.get("conversionRate");
            if (conversionRate != null) {
                billLine.setConversionRate(new BigDecimal(conversionRate.toString()));
            }
            Object freeQty = map.get("freeQty");
            if (freeQty != null) {
                billLine.setFreeQty(new BigDecimal(freeQty.toString()));
            }
            Object inStoreDay = map.get("inStoreDay");
            if (inStoreDay != null) {
                billLine.setInStoreDay(new BigDecimal(inStoreDay.toString()));
            }
            Object itemVolume = map.get("itemVolume");
            if (itemVolume != null) {
                billLine.setItemVolume(new BigDecimal(itemVolume.toString()));
            }
            Object itemWeight = map.get("itemWeight");
            if (itemWeight != null) {
                billLine.setItemWeight(new BigDecimal(itemWeight.toString()));
            }
            Object oddCaseQty = map.get("oddCaseQty");
            if (oddCaseQty != null) {
                billLine.setOddCaseQty(new BigDecimal(oddCaseQty.toString()));
            }
            Object oddPieceQty = map.get("oddPieceQty");
            if (oddPieceQty != null) {
                billLine.setOddPieceQty(new BigDecimal(oddPieceQty.toString()));
            }
            Object pieceConversionRate = map.get("pieceConversionRate");
            if (pieceConversionRate != null) {
                billLine.setPieceConversionRate(new BigDecimal(pieceConversionRate.toString()));
            }
            Object piecePriceTe = map.get("piecePriceTe");
            if (piecePriceTe != null) {
                billLine.setPiecePriceTe(new BigDecimal(piecePriceTe.toString()));
            }
            Object piecePriceTi = map.get("piecePriceTi");
            if (piecePriceTi != null) {
                billLine.setPiecePriceTi(new BigDecimal(piecePriceTi.toString()));
            }
            Object pieceQty = map.get("pieceQty");
            if (pieceQty != null) {
                billLine.setPieceQty(new BigDecimal(pieceQty.toString()));
            }
            Object preQty = map.get("preQty");
            if (preQty != null) {
                billLine.setPreQty(new BigDecimal(preQty.toString()));
            }
            Object receivedQty = map.get("receivedQty");
            if (receivedQty != null) {
                billLine.setReceivedQty(new BigDecimal(receivedQty.toString()));
            }
            Object rejectQty = map.get("rejectQty");
            if (rejectQty != null) {
                billLine.setRejectQty(new BigDecimal(rejectQty.toString()));
            }
            Object remainShelfStockCount = map.get("remainShelfStockCount");
            if (remainShelfStockCount != null) {
                billLine.setRemainShelfStockCount(new BigDecimal(remainShelfStockCount.toString()));
            }
            Object remainStackStockCount = map.get("remainStackStockCount");
            if (remainStackStockCount != null) {
                billLine.setRemainStackStockCount(new BigDecimal(remainStackStockCount.toString()));
            }
            Object shelfLifeDays = map.get("shelfLifeDays");
            if (shelfLifeDays != null) {
                billLine.setShelfLifeDays(new BigDecimal(shelfLifeDays.toString()));
            }
            Object shelfLifeNum = map.get("shelfLifeNum");
            if (shelfLifeNum != null) {
                billLine.setShelfLifeNum(new BigDecimal(shelfLifeNum.toString()));
            }
            Object shelfStockCount = map.get("shelfStockCount");
            if (shelfStockCount != null) {
                billLine.setShelfStockCount(new BigDecimal(shelfStockCount.toString()));
            }

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); // 制定输出格式
            Object batchExpiredDate = map.get("batchExpiredDate");
            if (batchExpiredDate instanceof String) {
                if (ObjectUtils.isNull(batchExpiredDate)) {
                    Date parse = sdf.parse(batchExpiredDate.toString());
                    billLine.setBatchExpiredDate(parse);
                }
            }
            Object batchProductionDate = map.get("batchProductionDate");
            if (batchProductionDate instanceof String) {
                if (ObjectUtils.isNull(batchProductionDate)) {
                    Date parse2 = sdf.parse(batchProductionDate.toString());
                    billLine.setBatchProductionDate(parse2);
                }
            }

            lineList.add(billLine);
        }
        return lineList;
    }

    private List<BillDTO> convertMap2Bill(List<Map> searchMap)
            throws IllegalArgumentException, IllegalAccessException, InstantiationException, ParseException {
        // 把map转换为bill对象
        List<BillDTO> searchDTO = new ArrayList<>();
        for (Map map : searchMap) {
            BillDTO biil = new BillDTO();
            BeanUtils.copyProperties(map, biil);
            String pEnterprisename = (String) map.get("pEnterprisename");
            biil.setpEnterprisename(pEnterprisename);
            Object pieceQty = map.get("pieceQty");
            if (pieceQty != null) {
                biil.setPieceQty(new BigDecimal(pieceQty.toString()));
            }
            Object taTe = map.get("taTe");
            if (taTe != null) {
                biil.setTaTe(new BigDecimal(taTe.toString()));
            }
            Object remainqty = map.get("remainqty");
            if (remainqty != null) {
                biil.setRemainqty(new BigDecimal(remainqty.toString()));
            }
            Object totWeight = map.get("totWeight");
            if (totWeight != null) {
                biil.setTotWeight(new BigDecimal(totWeight.toString()));
            }
            Object totVolume = map.get("totVolume");
            if (totVolume != null) {
                biil.setTotVolume(new BigDecimal(totVolume.toString()));
            }
            Object taTi = map.get("taTi");
            if (taTi != null) {
                biil.setTaTi(new BigDecimal(taTi.toString()));
            }
            Object caseQty = map.get("caseQty");
            if (caseQty != null) {
                biil.setCaseQty(new BigDecimal(caseQty.toString()));
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); // 制定输出格式
            Object createdate = map.get("createdate");
            if (createdate instanceof String) {
                if (ObjectUtils.isNull(createdate)) {
                    Date parse = sdf.parse(createdate.toString());
                    biil.setCreatedate(parse);
                }
            }
            Object shipArriveTime = map.get("shipArriveTime");
            if (shipArriveTime instanceof String) {
                if (ObjectUtils.isNull(shipArriveTime)) {
                    Date parse2 = sdf.parse(shipArriveTime.toString());
                    biil.setShipArriveTime(parse2);
                }
            }
            Object lastmodifydate = map.get("lastmodifydate");
            if (lastmodifydate instanceof String) {
                if (ObjectUtils.isNull(lastmodifydate)) {
                    Date parse3 = sdf.parse(lastmodifydate.toString());
                    biil.setLastmodifydate(parse3);
                }
            }
            Object attainDate = map.get("attainDate");
            if (attainDate instanceof String) {
                if (ObjectUtils.isNull(attainDate)) {
                    Date parse4 = sdf.parse(attainDate.toString());
                    biil.setAttainDate(parse4);
                }
            }
            Object billDate = map.get("billDate");
            if (billDate instanceof String) {
                if (ObjectUtils.isNull(billDate)) {
                    Date parse5 = sdf.parse(billDate.toString());
                    biil.setBillDate(parse5);
                }
            }
            Object auditDate = map.get("auditDate");
            if (auditDate instanceof String) {
                if (ObjectUtils.isNull(auditDate)) {
                    Date parse6 = sdf.parse(auditDate.toString());
                    biil.setAuditDate(parse6);
                }
            }
            Object expirationdate = map.get("expirationdate");
            if (expirationdate instanceof String) {
                if (ObjectUtils.isNull(expirationdate)) {
                    Date parse7 = sdf.parse(expirationdate.toString());
                    biil.setExpirationdate(parse7);
                }
            }

            searchDTO.add(biil);
        }

        return searchDTO;
    }

    /**
     * 校验转换单
     *
     * @param cargoChangeIn
     */
    private void vaildateCargoChange(CargoChangeIn cargoChangeIn) {
        String destCargoOwnerId = cargoChangeIn.getDestCargoOwnerId();
        String destCargoOwnerCode = cargoChangeIn.getDestCargoOwnerCode();
        String poBillId = cargoChangeIn.getPoBillId();
        String poBillNo = cargoChangeIn.getPoBillNo();
        String warehouseId = cargoChangeIn.getWarehouseId();
        String warehouseCode = cargoChangeIn.getWarehouseCode();
//		if (StringUtils.isBlank(destCargoOwnerId)) {
//			throw new BizException("货主id不可为空!");
//		}
//		if (StringUtils.isBlank(destCargoOwnerCode)) {
//			throw new BizException("货主code不可为空!");
//		}
        if (StringUtils.isBlank(poBillId)) {
            throw new BizException("采购单id不可为空!");
        }
        if (StringUtils.isBlank(poBillNo)) {
            throw new BizException("采购单code不可为空!");
        }
//		if (StringUtils.isBlank(warehouseId)) {
//			throw new BizException("仓库id不可为空!");
//		}
//		if (StringUtils.isBlank(warehouseCode)) {
//			throw new BizException("仓库code不可为空!");
//		}
        List<CargoChangeInDetails> details = cargoChangeIn.getDetails();
        if (ObjectUtils.isNull(details)) {
            throw new BizException("转换商品明细不可为空!");
        }
        for (CargoChangeInDetails cargoChangeInDetails : details) {
            vaildateCargoChangeDetails(cargoChangeInDetails);
        }

    }

    /**
     * 校验转换单明细
     *
     * @param cargoChangeInDetail
     */
    private void vaildateCargoChangeDetails(CargoChangeInDetails cargoChangeInDetail) {
        String batchId = cargoChangeInDetail.getBatchId();
        String destItemId = cargoChangeInDetail.getDestItemId();
        String destItemCode = cargoChangeInDetail.getDestItemCode();
        String manufacturerLotNum = cargoChangeInDetail.getManufacturerLotNum();
        String showProductionDate = cargoChangeInDetail.getShowProductionDate();
        String showExpiredDate = cargoChangeInDetail.getShowExpiredDate();
        String uom = cargoChangeInDetail.getUom();
        BigDecimal conversionRate = cargoChangeInDetail.getConversionRate();
        BigDecimal quantity = cargoChangeInDetail.getQuantity();
        String whLocatorId = cargoChangeInDetail.getWhLocatorId();
        String whLocatorCode = cargoChangeInDetail.getWhLocatorCode();

        if (StringUtils.isBlank(batchId)) {
            throw new BizException("批次id(batchId)不可为空!");
        }
//		if (StringUtils.isBlank(destItemId)) {
//			throw new BizException("商品id(destItemId)不可为空!");
//		}
//		if (StringUtils.isBlank(destItemCode)) {
//			throw new BizException("商品编码(destItemCode)不可为空!");
//		}
//		if (StringUtils.isBlank(manufacturerLotNum)) {
//			throw new BizException("商品批号(manufacturerLotNum)不可为空!");
//		}
//		if (StringUtils.isBlank(showProductionDate)) {
//			throw new BizException("生产日期(showProductionDate)不可为空!");
//		}
//		if (StringUtils.isBlank(showExpiredDate)) {
//			throw new BizException("有效期至(showExpiredDate)不可为空!");
//		}
//		if (StringUtils.isBlank(uom)) {
//			throw new BizException("商品单位(uom)不可为空!");
//		}
//		if (ObjectUtils.isNull(conversionRate)) {
//			throw new BizException("包装含量(conversionRate)不可为空!");
//		}
        if (ObjectUtils.isNull(quantity)) {
            throw new BizException("转换数量(quantity)不可为空!");
        }
        if (StringUtils.isBlank(whLocatorId)) {
            throw new BizException("货位id(whLocatorId)不可为空!");
        }
//		if (StringUtils.isBlank(whLocatorCode)) {
//			throw new BizException("货位编码(whLocatorCode)不可为空!");
//		}

    }

    @Override
    public Object cargoChangeInBillInfo(List<String> billIds) {
        List<OmsAsnBillH> findByIds = this.omsAsnBillHMapper.findByIds(OmsAsnBillH.class, billIds.toArray(), null);
        Criteria crt = Criteria.forClass(OmsAsnBillD.class);
        crt.setRestriction(Restrictions.in("billid", billIds.toArray()));
        List<OmsAsnBillD> findByCriteria = omsAsnBillDMapper.findByCriteria(crt);
        Map<String, List<BillLineDTO>> collect = null;
        List<BillLineDTO> billLineList = new ArrayList<>();
        if (!ObjectUtils.isNull(findByCriteria)) {
            for (OmsAsnBillD omsAsnBillD : findByCriteria) {
                BillLineDTO bi = new BillLineDTO();
                BeanUtils.copyProperties(omsAsnBillD, bi);
                billLineList.add(bi);
            }
            collect = billLineList.stream().collect(Collectors.groupingBy(BillLineDTO::getBillid));
        }

        List<BillDTO> bills = new ArrayList<>();
        if (!ObjectUtils.isNull(findByIds)) {
            for (OmsAsnBillH billDTO : findByIds) {
                BillDTO b = new BillDTO();
                BeanUtils.copyProperties(billDTO, b);
                if (!ObjectUtils.isNull(collect)) {
                    String billid = b.getBillid();
                    List<BillLineDTO> list = collect.get(billid);
                    b.setBillLineList(list);
                }
                bills.add(b);
            }
        }

        return bills;
    }

    @Override
    @Transactional
    public Object addWithRelatedByPda(RcvDTO rcvDTO) {
        return this.addWithRelated(rcvDTO, null, true);
    }

    /**
     * 收货：存在质检策略的收货模式
     */
    public void checkQualityInspectionReceipt(RcvDTO rcvDTO) {
        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();
        /* PC采购收货校验添加 ---------------------on 2022-07-20 by chenhao ---开始-- */
        // 检查是否混批
        List<RcvLinesDTO> higCareList = rcvLinesDTOList.stream()
                .filter(i -> org.apache.commons.lang.StringUtils.isNotBlank(i.getWarehouseAreaCategory())
                        && i.getWarehouseAreaCategory().equals(BizConstant.LTK))
                .collect(Collectors.toList());
        Map<String, List<RcvLinesDTO>> higItemMap = higCareList.stream()
                .collect(Collectors.groupingBy(RcvLinesDTO::getItemId));
        if (higItemMap.size() > 4) {
            throw new BizException("立库容器最大支持混品4种，请注意 ！");
        }

        Map<String, List<RcvLinesDTO>> higBatchMap = higCareList.stream()
                .collect(Collectors.groupingBy(RcvLinesDTO::getManufacturerLotNum));

        if (higBatchMap.size()>0) {
            throw new BizException("立库不允许混批 ！");
        }

        Map<String, List<RcvLinesDTO>> warehouseMap = rcvLinesDTOList.stream()
                .filter(i -> org.apache.commons.lang.StringUtils.isNotBlank(i.getWarehouseAreaCategory())
                        && i.getOddPieceQty().compareTo(BigDecimal.ZERO) > 0)
                .collect(Collectors.groupingBy(RcvLinesDTO::getWarehouseAreaCategory));
        if (warehouseMap.size() > 1) {
            throw new BizException("有库别，零散数大于0，必须为零货库，请注意 ！");
        } else if (warehouseMap.size() == 1) {
            for (Entry<String, List<RcvLinesDTO>> i : warehouseMap.entrySet()) {
                if (!i.getKey().equals(BizConstant.LHK)) {// 零货库
                    throw new BizException("有库别，零散数大于0，必须为零货库，请注意 ！");
                }
            }
        }
        /* PC采购收货校验添加 ---------------------on 2022-07-20 by chenhao ---结束-- */
    }

    @Override
    @Transactional
    public Boolean rfSaveValidate(RcvDTO rcvDTO) {
        AssertUtils.notNull(rcvDTO.getRcvLinesDTOList(), "收货单明细不可为空!");
        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();
        for (RcvLinesDTO rcvLinesDTO : rcvLinesDTOList) {
            if (rcvLinesDTO.getQty().compareTo(BigDecimal.ZERO) < 0) {
                throw new BizException("收货数量必须大于0，请检查！");
            }
            if (StringUtils.isBlank(rcvLinesDTO.getContainerCode())) {
                throw new BizException("收货容器号不能为空，请检查！");
            }
            String showExpiredDate = rcvLinesDTO.getShowExpiredDate();
            String showProductionDate = rcvLinesDTO.getShowProductionDate();
            if (StringUtils.isBlank(showExpiredDate) || StringUtils.isBlank(showProductionDate)) {
                throw new BizException("显示生产日期或显示有效期至为空!请检查!");
            }
        }
        Set<String> itemIdsArr = rcvDTO.getRcvLinesDTOList().stream().map(RcvLinesDTO::getItemId)
                .filter(itemId -> !StringUtils.isBlank(itemId)).collect(Collectors.toSet());
        List<BaseMtlItemMst> itemResult = new ArrayList<>();
        if (itemIdsArr.size() > 0) {
            itemResult = RestMsgUtils.retrieveResult(itemClient.getListByIds(itemIdsArr));
        }
        itemResult.forEach(i -> {
            // 商品.是否批号=是，校验批号不能为空
            Integer isBatch = i.getBaseMtlItemWms().getItemIsBatch();
            if (isBatch != null && isBatch == 1) {
                RcvLinesDTO dto = rcvLinesDTOList.stream().filter(f -> f.getItemId().equals(i.getItemId())).findFirst()
                        .orElse(null);
                if (dto != null && StringUtils.isBlank(dto.getBatchNum())) {
                    throw new BizException("商品[%d],批号不能为空!请检查!" + dto.getItemName());
                }
            }
        });

        this.checkQualityInspectionReceipt(rcvDTO);

        //收货暂存
        return this.addWithRelatedTemp(rcvDTO);

    }

    @Override
    public RcvDTO buildRcvDto(RcvDetailsDTO rcvDetailsDTO) {
        RcvDTO rcvDTO = new RcvDTO();
        RcvHeadersDTO rcvHeadersDTO = new RcvHeadersDTO();
        RcvHeadersProfilesDTO rcvHeadersProfilesDTO = new RcvHeadersProfilesDTO();
        BeanUtils.copyProperties(rcvDetailsDTO, rcvHeadersDTO);
        rcvHeadersDTO.setRcvDate(new Date());
        BeanUtils.copyProperties(rcvDetailsDTO, rcvHeadersProfilesDTO);
        rcvDTO.setRcvHeadersDTO(rcvHeadersDTO);
        rcvHeadersProfilesDTO.setMtlOwnerName(rcvDetailsDTO.getMtlOwnerName());
        rcvHeadersProfilesDTO.setMtlOwnerNum(rcvDetailsDTO.getMtlOwnerNum());
        rcvDTO.setRcvHeadersProfilesDTO(rcvHeadersProfilesDTO);
        log.info("rcvDetailsDTO:{}", JsonMapper.toJson(rcvDetailsDTO));
        List<RcvLineDetailsDTO> rcvLineDetailsDTOS = rcvDetailsDTO.getRcvLineDetailsDTOS();

        List<RcvLinesDTO> rcvLinesDTOList = new ArrayList<>();
        for (RcvLineDetailsDTO rcvLineDetailsDTO : rcvLineDetailsDTOS) {
            RcvLinesDTO rcvLinesDTO = new RcvLinesDTO();
            BeanUtils.copyProperties(rcvLineDetailsDTO, rcvLinesDTO);
            RcvLinesProfilesDTO rcvLinesProfilesDTO = new RcvLinesProfilesDTO();
            BeanUtils.copyProperties(rcvLineDetailsDTO, rcvLinesProfilesDTO);

            rcvLinesDTO.setPieceQty(BigDecimal.valueOf(rcvLineDetailsDTO.getPieceQty()));
            rcvLinesDTO.setConversionRate(BigDecimal.valueOf(rcvLineDetailsDTO.getPieceConversionRate()));
            rcvLinesDTO.setRcvLinesProfilesDTO(rcvLinesProfilesDTO);
            rcvLinesDTO.setOddCaseQty(BigDecimal.valueOf(rcvLineDetailsDTO.getOddCaseQty()));
            rcvLinesDTO.setOddPieceQty(BigDecimal.valueOf(rcvLineDetailsDTO.getOddPieceQty()));
            rcvLinesDTO.setQty(rcvLinesDTO.getPieceQty().divide(rcvLinesDTO.getConversionRate()));
            rcvLinesDTO.setMtlOwnerId(rcvDetailsDTO.getMtlOwnerId());
            rcvLinesDTO.setMtlOwnerName(rcvDetailsDTO.getMtlOwnerName());
            rcvLinesDTO.setWarehouseName(rcvDetailsDTO.getWarehouseName());
            rcvLinesDTO.setSrcBillType(rcvDetailsDTO.getSrcBillType());
            rcvLinesDTO.setWhAreaCategoryCode(rcvDetailsDTO.getWarehouseAreaCode());
            //根据这个字段判断是不是要生成批次
            rcvLinesDTO.setEditFlag(0);
            rcvLinesDTOList.add(rcvLinesDTO);
        }
        rcvDTO.setRcvLinesDTOList(rcvLinesDTOList);
        return rcvDTO;
    }

    @Override
    public BigDecimal calculationQty(Boolean flag, RcvDTO rcvDTO) {
        if (flag) {
            RcvLinesDTO rcvLinesDTO = rcvDTO.getRcvLinesDTOList().stream().findFirst().orElseThrow(() -> new ParameterException("收货明细不存在"));
            //传入的收货数量
            BigDecimal pieceQty = rcvLinesDTO.getPieceQty();
            String asnLineId = rcvLinesDTO.getAsnLineId();
            String asnHeaderId = rcvLinesDTO.getAsnHeaderId();
            WmsInRcvTempSave rcvTempSave = MapperCustom.builder(inRcvTempSaveMapper, WmsInRcvTempSave.class).andEq(WmsInRcvTempSave::getAsnHeaderId, asnHeaderId).findFirst();
            String content = rcvTempSave.getContent();
            RcvDTO oldRcvDto = JsonMapper.parse(content, RcvDTO.class);
            List<RcvLinesDTO> rcvLinesDTOList = oldRcvDto.getRcvLinesDTOList();
            List<RcvLinesDTO> oldRcvLineDto = rcvLinesDTOList.stream().filter(old -> old.getAsnLineId().equals(asnLineId)).collect(Collectors.toList());
            if (oldRcvLineDto.isEmpty()) {
                throw new ParameterException("匹配不到收货明细暂存");
            }
            //收货行已收货暂存总数
            BigDecimal oldRcvLineDtoPieceQty = oldRcvLineDto.stream().map(RcvLinesDTO::getPieceQty).reduce(BigDecimal.ZERO, BigDecimal::add);
            //查询入库明细行待收货总数
            OmsAsnBillD asnBillD = MapperCustom.builder(omsAsnBillDMapper, OmsAsnBillD.class).andEq(OmsAsnBillD::getBillid, asnHeaderId).findFirst();
            BigDecimal itemQty = asnBillD.getItemQty();
            BigDecimal rejectQty = Convert.toBigDecimal(asnBillD.getRejectQty(), BigDecimal.ZERO);
            return itemQty.subtract(rejectQty).subtract(oldRcvLineDtoPieceQty);
        }
        throw new BizException("收货保存失败:" + JsonMapper.toJson(rcvDTO));
    }

    @Override
    public RcvDTO findRcvDtoByBillId(String billId) {
        WmsInRcvTempSave wmsInRcvTempSave = MapperCustom.builder(inRcvTempSaveMapper, WmsInRcvTempSave.class).andEq(WmsInRcvTempSave::getAsnHeaderId, billId).findFirst();
        if(Objects.isNull(wmsInRcvTempSave)){
            return new RcvDTO();
        }
        String content = wmsInRcvTempSave.getContent();
        RcvDTO rcvDTO = JsonMapper.parse(content, RcvDTO.class);
        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();
        for (RcvLinesDTO rcvLinesDTO : rcvLinesDTOList) {
            if (Objects.isNull(rcvLinesDTO.getBatchExpiredDate())) {
                rcvLinesDTO.setBatchExpiredDate(new Date());
            }

            if (Objects.isNull(rcvLinesDTO.getBatchProductionDate())) {
                rcvLinesDTO.setBatchProductionDate(new Date());
            }
        }
        rcvDTO.setRcvLinesDTOList(rcvLinesDTOList);
        return rcvDTO;
    }

    @Override
    public Boolean deleteRcvDByRcvLineId(DeleteTobeConfirmed deleteTobeConfirmed) {
        String billId = deleteTobeConfirmed.getBillId();
        List<String> tobeDeleteAsnLineIds = deleteTobeConfirmed.getAsnLineIdList();
        List<WmsInRcvTempSave> wmsInRcvTempSaves = MapperCustom.builder(inRcvTempSaveMapper, WmsInRcvTempSave.class).andEq(WmsInRcvTempSave::getAsnHeaderId, billId).findByCriteria();
        Optional<WmsInRcvTempSave> optionalWmsInRcvTempSave = wmsInRcvTempSaves.stream().findFirst();
        String content = optionalWmsInRcvTempSave.orElseThrow(() -> new BizException("不存在暂存记录" + billId)).getContent();
        RcvDTO rcvDTO = JSONObject.parseObject(content, RcvDTO.class);

        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();

        for (int i = 0; i < rcvLinesDTOList.size(); i++) {
            RcvLinesDTO rcvLinesDTO = rcvLinesDTOList.get(i);
            for (int j = 0; j < tobeDeleteAsnLineIds.size(); j++) {
                String tobeDeleteAsnLineId = tobeDeleteAsnLineIds.get(j);
                if(rcvLinesDTO.getAsnLineId().equals(tobeDeleteAsnLineId)){
                    rcvLinesDTOList.remove(i);
                }
            }
        }

        if (rcvLinesDTOList.isEmpty()) {
            return MapperCustom.builder(inRcvTempSaveMapper,WmsInRcvTempSave.class).andEq(WmsInRcvTempSave::getAsnHeaderId,billId).deleteByCriteria();
        }
        rcvDTO.setRcvLinesDTOList(rcvLinesDTOList);
        WmsInRcvTempSave wmsInRcvTempSave = optionalWmsInRcvTempSave.get();
        wmsInRcvTempSave.setContent(JSON.toJSONString(rcvDTO));
        wmsInRcvTempSave.setAsnHeaderId(billId);
        return inRcvTempSaveMapper.update(wmsInRcvTempSave) > 0;


    }

    @Override
    @Transactional
    public Object rfSaveConfrim(RcvDTO rcvDTO) {

        RcvHeadersDTO rcvHeadersDTO = rcvDTO.getRcvHeadersDTO();
        AssertUtils.notNull(rcvHeadersDTO, "收货单主不可为空!");
        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();
        AssertUtils.isNotEmpty(rcvLinesDTOList, "收货单明细表不可为空!");
        // 添加自身及其关联表
        rcvHeadersDTO.setAccessLevel("0"); // 默认数据级别0
        String rcvType = rcvHeadersDTO.getRcvType();
        /* 添加思源收货的校验动作，on 2022-07-22 By 陈浩---结束 */

        // 来源单效期,校验货主证件效期,仓库暂时不处理 TODO
        String asnHeaderId = rcvHeadersDTO.getAsnHeaderId();

        // 校验货主的资质,供应商,客户证照
        excuteVaildateOwnerAndShipper(rcvDTO);

        UserDTO userDTO = userUtils.getUserDTO();
        AssertUtils.notNull(rcvHeadersDTO, "收货单主表不可为空!");

        AssertUtils.notNull(rcvDTO.getRcvLinesDTOList(), "收货单明细不可为空!");

        Map<String, Set<String>> asnLineIdMap = new HashMap<>();
        String[] itemIdsArr = rcvDTO.getRcvLinesDTOList().stream().map(RcvLinesDTO::getItemId)
                .filter(itemId -> !StringUtils.isBlank(itemId)).distinct().toArray(String[]::new);
        RestMessage<List<ItemBaseInfoVO>> itemResult = new RestMessage<>();
        if (itemIdsArr.length > 0) {
            itemResult = itemClient.getItemBaseList(itemIdsArr);
        }
        for (RcvLinesDTO rcvLinesDTO : rcvDTO.getRcvLinesDTOList()) {
            if ("1".equals(rcvDTO.getRcvHeadersDTO().getRcvType())) {
                if (itemResult.isSuccess() && itemResult.getData() != null && itemResult.getData().size() > 0) {
                    ItemBaseInfoVO ItemBaseInfoVO = itemResult.getData().stream()
                            .filter(t -> t.getItemId().equals(rcvLinesDTO.getItemId())).findFirst().orElse(null);
                    if (ItemBaseInfoVO != null && ItemBaseInfoVO.getItemIsUnpack() != null
                            && ItemBaseInfoVO.getItemIsUnpack() == 0
                            && rcvLinesDTO.getOddPieceQty().compareTo(BigDecimal.ZERO) > 0) {
                        logger.error("商品" + rcvLinesDTO.getItemName() + "不允许拆中包装");
                        throw new BizException("商品" + rcvLinesDTO.getItemName() + "不允许拆中包装");
                    }
                }
            }
            String asnLineId = rcvLinesDTO.getAsnLineId();
            if (asnLineIdMap.get(asnLineId) == null) {
                Set set = new HashSet();
                set.add(rcvLinesDTO.getManufacturerLotNum());
                asnLineIdMap.put(asnLineId, set);
            } else {
                Set set = asnLineIdMap.get(asnLineId);
                set.add(rcvLinesDTO.getManufacturerLotNum());
            }
        }
        extracted(asnLineIdMap);

        // 代管校验
        if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.HOSTED_IN)) {
            // 代管入库的处理,若是流通货主,不走验收,走货位推荐逻辑生生上架任务
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("cargoOwnerId", rcvHeadersDTO.getMtlOwnerId());
            List<Map> searchForMap = null;
            try {
                searchForMap = searchApi.searchForMap("getCargoOwnerProp", queryMap);
            } catch (Exception e) {
                logger.info("获取货主属性失败,原因{}", e.getMessage());
            }
            if (!ObjectUtils.isNull(searchForMap)) {
                Map map = searchForMap.get(0);
                String cargoOwnerProp = (String) map.get("cargoOwnerProp");
                Object isHostedRcvObj = map.get("isHostedRcv");
                int isHostedRcv = 1;
                if (isHostedRcvObj instanceof String) {
                    isHostedRcv = Integer.parseInt((String) isHostedRcvObj);
                }
                if (isHostedRcvObj instanceof Integer) {
                    isHostedRcv = (Integer) isHostedRcvObj;
                }
                if (0 == isHostedRcv) {
                    // 此货主不支持代管业务
                    throw new BizException("此货主不支持代管业务!请设置!");
                }
            }
        }

        String masterId = (String) this.add(rcvHeadersDTO, userDTO);

        RcvHeadersProfilesDTO rcvHeadersProfilesDTO = rcvDTO.getRcvHeadersProfilesDTO();
        List<RcvHeadersSrcBillsDTO> rcvHeadersSrcBillsDTOList = rcvDTO.getRcvHeadersSrcBillsDTOList();

        if (ObjectUtils.isNotNull(rcvHeadersProfilesDTO)) {
            // 这里是否需要做更新?
            rcvHeadersProfilesDTO.setRcvHeaderId(masterId);
            rcvHeadersProfilesDTO.setRcvType(rcvHeadersDTO.getRcvType());
            rcvHeadersProfilesService.add(rcvHeadersProfilesDTO);
        }
        if (ObjectUtils.isNotNull(rcvHeadersSrcBillsDTOList)) {
            rcvHeadersSrcBillsService.batchAdd(rcvHeadersSrcBillsDTOList, masterId, userDTO);
        }
        // 收货,拒收,待处理,代管
        AssertUtils.notNull(rcvLinesDTOList, "收货单明细表不可为空!");

        boolean anyMatch = rcvLinesDTOList.stream().filter(p -> ObjectUtils.isNotNull(p.getIsDoubleReceive()))
                .anyMatch(p -> p.getIsDoubleReceive() == 1);
        if (anyMatch) {
            String rcvUserId1 = rcvHeadersDTO.getRcvUserId1();
            String rcvUserId2 = rcvHeadersDTO.getRcvUserId2();
            if (StringUtils.isBlank(rcvUserId1) || StringUtils.isBlank(rcvUserId2)) {
                throw new BizException("有商品需要双人收货,请切换账号,进行收货确认!");
            }
        }

        // 保存收货明细,根据收货类型做不同的逻辑处理
        rcvHeadersDTO.setRcvHeaderId(masterId);
        Object excuteRcvLine = rcvTypeService.rfExcuteRcvLine(rcvHeadersDTO, rcvLinesDTOList, userDTO, null);

        // 校验是否超收,拆分加并发
        vaildateOvercharge(rcvLinesDTOList, userDTO);


        String mtlOwnerId = rcvHeadersDTO.getMtlOwnerId();
        // 判断是否回传erp 拒收
        //青牛拒收数量只计数,不回传
//        boolean allMatch = rcvLinesDTOList.stream().allMatch(p -> p.getStockStatus().equals("3"));
//        if (allMatch) {
//            BigDecimal remainQty = this.mapper.getRemainQty(masterId);
//            if (remainQty != null && BigDecimal.ZERO.compareTo(remainQty) == 0) {
//                // 整单拒收
//                excuteCallBackErp(masterId, mtlOwnerId, asnHeaderId);
//            }
//        }

        return excuteRcvLine;
    }


    /**
     * @param billId
     * @return
     */
    @Override
    public List<RcvLineDetailsDTO> extractAsnLine(String billId) {
        List<RcvLineDetailsDTO> lineDetailsDTOS;
        try {
            log.info("调用data-api查询,appid:578681744203583488");
            lineDetailsDTOS = searchApi.search("578681744203583488", MapUtils.put("billid", billId).getMap(), RcvLineDetailsDTO.class);
            log.info("调用data-api查询,lineDetailsDTOS:{}", JsonMapper.toJson(lineDetailsDTOS));

        } catch (JsonProcessingException | InstantiationException | IllegalAccessException e) {
            throw new BizException("调用data-api服务失败:" + e.getMessage());
        }
        List<String> asnLineIds = lineDetailsDTOS.stream().map(RcvLineDetailsDTO::getAsnLineId).collect(Collectors.toList());
        List<RcvLines> rcvLinesList = MapperCustom.builder(rcvLinesMapper, RcvLines.class).andIn(RcvLines::getAsnLineId, asnLineIds).findByCriteria();
        for (RcvLineDetailsDTO lineDetailsDTO : lineDetailsDTOS) {
            if (rcvLinesList.isEmpty()) {
                lineDetailsDTO.setTobeQty(lineDetailsDTO.getPieceQty());
            } else {
                for (RcvLines rcvLines : rcvLinesList) {
                    if (rcvLines.getAsnLineId().equals(lineDetailsDTO.getAsnLineId())) {
                        log.info("dto=========:{}", JsonMapper.toJson(lineDetailsDTO));
                        double tobeQty = lineDetailsDTO.getPreQty() - rcvLines.getPieceQty().doubleValue();
                        lineDetailsDTO.setTobeQty(tobeQty);
                    }
                }
            }
        }
        return lineDetailsDTOS;
    }

    @Override
    public void saveItemLotArriveQty(RcvDTO rcvDTO) {
        List<RcvLinesDTO> rcvLinesDTOList = rcvDTO.getRcvLinesDTOList();
        if (ToolKits.isNotEmpty(rcvLinesDTOList)) {
            for (RcvLinesDTO rcvLinesDTO : rcvLinesDTOList) {
                Criteria crt = Criteria.forClass(RcvLines.class);
                Restriction r1 = Restrictions.eq("itemId", rcvLinesDTO.getItemId());
                Restriction r2 = Restrictions.eq("manufacturerLotNum", rcvLinesDTO.getManufacturerLotNum());
                Restriction r3 = Restrictions.eq("asnHeaderId", rcvLinesDTO.getAsnHeaderId());
                crt.setRestriction(Restrictions.and(r1, r2, r3));
                rcvLinesMapper.updateMapByCriteria(MapUtils.put("attrNum1", rcvLinesDTO.getAttrNum1()).put("attrNum2", rcvLinesDTO.getAttrNum2()).getMap(), crt);
            }
        }
    }

    @Override
    public RcvLines arriveQtyByItemLot(RcvLinesDTO rcvLinesDTO) {
        AssertUtils.isNotEmpty(rcvLinesDTO.getItemId(), "商品id不能为空");
        AssertUtils.isNotEmpty(rcvLinesDTO.getAsnHeaderId(), "单据号不能为空");
        if (ObjectUtil.isEmpty(rcvLinesDTO.getManufacturerLotNum())) return null;
        Criteria crt = Criteria.forClass(RcvLines.class);
        Restriction r1 = Restrictions.eq("itemId", rcvLinesDTO.getItemId());
        Restriction r2 = Restrictions.eq("manufacturerLotNum", rcvLinesDTO.getManufacturerLotNum());
        Restriction r3 = Restrictions.eq("asnHeaderId", rcvLinesDTO.getAsnHeaderId());
        crt.setRestriction(Restrictions.and(r1, r2, r3));
        List<RcvLines> result = rcvLinesMapper.findByCriteria(crt);
        if (ObjectUtil.isNotEmpty(result)) {
            return result.get(0);
        }
        return null;
    }
}
