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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Maps;
import com.prolog.common.util.ToolKits;
import com.prolog.cs.basic.chain.model.customer.BaseCustomerMst;
import com.prolog.cs.basic.chain.model.supplier.BaseSupplierMst;
import com.prolog.cs.basic.common.model.SysRegistry;
import com.prolog.cs.basic.common.model.print.PrintParam;
import com.prolog.cs.basic.item.model.BaseMtlItemHealth;
import com.prolog.cs.basic.item.model.BaseMtlItemMst;
import com.prolog.cs.biz.inbound.constant.BizConstant;
import com.prolog.cs.biz.inbound.constant.OperationConstant;
import com.prolog.cs.biz.inbound.dao.*;
import com.prolog.cs.biz.inbound.dao.rcv.RcvHeadersMapper;
import com.prolog.cs.biz.inbound.dao.rcv.RcvInstockLinesMapper;
import com.prolog.cs.biz.inbound.dao.rcv.RcvLinesMapper;
import com.prolog.cs.biz.inbound.dao.rqc.RqcHeadersMapper;
import com.prolog.cs.biz.inbound.dao.rqc.RqcLinesMapper;
import com.prolog.cs.biz.inbound.dao.task.TaskInstockDetailMapper;
import com.prolog.cs.biz.inbound.dao.task.TaskQcDetailMapper;
import com.prolog.cs.biz.inbound.dto.PageParam;
import com.prolog.cs.biz.inbound.dto.RelationCodeResult;
import com.prolog.cs.biz.inbound.dto.RelationCodeResultDTO;
import com.prolog.cs.biz.inbound.dto.print.*;
import com.prolog.cs.biz.inbound.dto.rcv.*;
import com.prolog.cs.biz.inbound.dto.rqc.RcvLineResult;
import com.prolog.cs.biz.inbound.dto.rqc.RqcDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcHeadersDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcLinesDTO;
import com.prolog.cs.biz.inbound.dto.task.TaskInstockDetailDTO;
import com.prolog.cs.biz.inbound.dto.task.TaskQcDetailDTO;
import com.prolog.cs.biz.inbound.model.*;
import com.prolog.cs.biz.inbound.model.rcv.RcvHeaders;
import com.prolog.cs.biz.inbound.model.rcv.RcvInstockLines;
import com.prolog.cs.biz.inbound.model.rcv.RcvLines;
import com.prolog.cs.biz.inbound.model.rqc.RqcHeaders;
import com.prolog.cs.biz.inbound.model.rqc.RqcLines;
import com.prolog.cs.biz.inbound.model.task.TaskInstockDetail;
import com.prolog.cs.biz.inbound.model.task.TaskQcDetail;
import com.prolog.cs.biz.inbound.model.task.TaskRejectedDetail;
import com.prolog.cs.biz.inbound.remote.*;
import com.prolog.cs.biz.inbound.service.OrderInboundStatusBackService;
import com.prolog.cs.biz.inbound.service.SupervisionCodeService;
import com.prolog.cs.biz.inbound.service.impl.AutoStockHandler;
import com.prolog.cs.biz.inbound.service.impl.BaseServiceImpl;
import com.prolog.cs.biz.inbound.service.impl.task.TaskRejectedDetailServiceImpl;
import com.prolog.cs.biz.inbound.service.rcv.RcvHeadersService;
import com.prolog.cs.biz.inbound.service.rcv.RcvLinesPicService;
import com.prolog.cs.biz.inbound.service.rqc.RqcHeadersService;
import com.prolog.cs.biz.inbound.service.rqc.RqcLinesService;
import com.prolog.cs.biz.inbound.service.task.TaskExceptionDetailService;
import com.prolog.cs.biz.inbound.service.task.TaskQcDetailService;
import com.prolog.cs.biz.inbound.service.task.TaskRejectedDetailService;
import com.prolog.cs.biz.inbound.utils.ObjectUtils;
import com.prolog.cs.biz.inbound.utils.TaobaoUtil;
import com.prolog.cs.biz.inbound.utils.UploadCircubillUtil;
import com.prolog.cs.biz.inbound.utils.UserUtils;
import com.prolog.cs.biz.inbound.vo.*;
import com.prolog.cs.biz.inbound.vo.task.TaskQcDetailQueryVO;
import com.prolog.cs.biz.inbound.vo.task.TaskQueryVO;
import com.prolog.cs.biz.outbound.model.PickTaskH;
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.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.framework.exception.AssertException;
import com.prolog.framework.utils.*;
import com.prolog.wms.base.util.mapper.MapperCustom;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RqcHeadersServiceImpl extends BaseServiceImpl<RqcHeaders> implements RqcHeadersService {

	@Resource
	private RqcHeadersMapper mapper;

	@Resource
	private UserUtils userUtils;

	@Resource
	private Validator validator;

	@Resource
	private RqcLinesService rqcLinesService;

	@Resource
	private RqcLinesMapper rqcLinesMapper;

	@Resource
	private TaskQcDetailService taskQcDetailService;

	@Resource
	private RcvHeadersService rcvHeadersService;

	@Resource
	private TaskExceptionDetailService taskExceptionDetailService;

	@Resource
	private TaskQcDetailMapper taskQcDetailMapper;

	@Resource
	private TaskInstockDetailMapper taskInstockDetailMapper;

	@Resource
	private AutoStockHandler autoStockHandler;

	@Resource
	private RcvLinesPicService rcvLinesPicService;

	@Resource
	private RcvHeadersMapper rcvMapper;

	@Resource
	private OmsAsnBillHMapper omsAsnBillHMapper;

	@Resource
	private RcvHeadersMapper rcvHeadersMapper;


	@Resource
	private ReceivingRecordBackHMapper receivingRecordBackHMapper;

	@Resource
	private ReceivingRecordBackDMapper receivingRecordBackDMapper;

	@Resource
	private SearchApi searchApi;

	@Resource
	private BaseInventoryRemoteCaller baseInventoryRemoteCaller;

	@Resource
	private SupervisionCodeMapper supervisionCodeMapper;

	@Resource
	private ChainRemoteCaller chainRemoteCaller;

	@Resource
	private OutboundCaller outboundCaller;

	@Resource
	private SupervisionCodeSmallMapper codeSmallMapper;

	@Resource
	private SupervisionCodeSmallHisMapper codeSmallHisMapper;

    @Resource
    private OmsAsnBillDMapper omsAsnBillDMapper;

	@Autowired
	private TaobaoUtil taobaoUtil;

	/**
	 * 通知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%2F20210623%2F%2Fs3%2Faws4_request&X-Amz-Date=20210623T132157Z&X-Amz-Expires=432000&X-Amz-SignedHeaders=host&X-Amz-Signature=9558c7331c63c500ab70d55553e550c7acf1466ad334c297cddd706bc7ceed4a}")
	private String printUrl3;

	/**
	 * 上架标签
	 */
	@Value("${prolog.wms.print.printUrl:http://minio.cloud.prolog.org/print/%E4%B8%8A%E6%9E%B6%E6%A0%87%E7%AD%BE.grf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=nyu8dWdGLqiUkvgF4ue5%2F20210623%2F%2Fs3%2Faws4_request&X-Amz-Date=20210623T132354Z&X-Amz-Expires=432000&X-Amz-SignedHeaders=host&X-Amz-Signature=fbf832cea892e1b5651bc2c8337fba97759285cc944ffa894d698b73e5a24b34}")
	private String printUrl;

	/**
	 * 质检行明细
	 */
	@Value("${prolog.wms.print.printUrl2:http://minio.cloud.prolog.org/print/%E8%B4%A8%E6%A3%80%E6%98%8E%E7%BB%86%E5%8D%95.grf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=nyu8dWdGLqiUkvgF4ue5%2F20210623%2F%2Fs3%2Faws4_request&X-Amz-Date=20210623T132012Z&X-Amz-Expires=432000&X-Amz-SignedHeaders=host&X-Amz-Signature=d03d6685318f0363e3537e5078d964f0bd02637f71b3adad8f60535ecd80f741}")
	private String printUrl2;

	/**
	 * 质检行汇总
	 */
	@Value("${prolog.wms.print.printUrl4:http://minio.cloud.prolog.org/print/%E8%B4%A8%E6%A3%80%E6%B1%87%E6%80%BB%E5%8D%95.grf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=nyu8dWdGLqiUkvgF4ue5%2F20210623%2F%2Fs3%2Faws4_request&X-Amz-Date=20210623T132057Z&X-Amz-Expires=432000&X-Amz-SignedHeaders=host&X-Amz-Signature=1c9cb14a204b5a27a7044282bd066715d465af8c4c71a99a8c9f6bb3da786089}")
	private String printUrl4;

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

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

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

	@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("${prolog.wms.print.isLabel:false}")
	private Boolean isLabel;

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

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

	@Resource
	private RcvLinesMapper rcvLinesMapper;

	@Resource
	private RcvInstockLinesMapper rcvInstockLinesMapper;

	private final static String addMsg = "质检头保存操作";
	private final static String batchAddMsg = "质检头批量保存操作";

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

	@Resource
	private ExchangeSender exchangeSender;

	@Resource
	private IncomingRecordHMapper incomingRecordHMapper;

	@Resource
	private IncomingRecordDMapper incomingRecordDMapper;

	@Resource
	private TaskRejectedDetailService taskRejectedDetailService;
	@Resource
	private SupervisionCodeService supervisionCodeService;

	@Resource
	private OrderInboundStatusBackService orderStatusBackService;

	@Resource
	private CommonCaller commonCaller;

	@Override
	public Object splitTask(List<TaskQcDetailDTO> taskQcDetailDTOList) {
		return taskQcDetailService.splitTask(taskQcDetailDTOList);
	}

	@Override
	@Transactional
	public Object addWithRelated(RqcDTO rqcDTO) {
		//添加容器校验
		List<RqcLinesDTO> rqcLinesDTOList = rqcDTO.getRqcLinesDTOList();
		for (RqcLinesDTO rqcLinesDTO : rqcLinesDTOList) {
			if(StringUtils.isBlank(rqcLinesDTO.getContainerCode())){
				throw new BizException("containerCode不能为空!");
			}
		}
		return this.addWithRelatedAll(rqcDTO, false);
	}

	private Object addWithRelatedAll(RqcDTO rqcDTO, boolean isPad, boolean isAdd) {
		AssertUtils.notNull(rqcDTO, "入参数据不可为空!");
		AssertUtils.notNull(rqcDTO.getRqcHeadersDTO(), "主表数据不可为空!");
		UserDTO userDTO = userUtils.getUserDTO();
		//极联保存关联数据
		RqcHeadersDTO rqcHeadersDTO = rqcDTO.getRqcHeadersDTO();
		Date autoTime = rqcDTO.getAutoTime() == null ? new Date() : rqcDTO.getAutoTime();
		Object excuteAssembleInstockPrintData = null;
//		String rcvType = rqcHeadersDTO.getRcvType();
		//直调自动验收上架逻辑 极联保存关联数据
		List<RqcLinesDTO> rqcLinesDTOList = rqcDTO.getRqcLinesDTOList();
		if(!isPad){
			//若有选择库别且为立体库，则校验当前容器上存放的同商品不可混批，支持最大混品4种；
			//若有选择库别，零散数大于0，必须为零货库
			//当库别有值时，依据企业+仓+货主+数据来源（1）+订单类型+质量状态+收货数(0整/1全散/2整散)+收货件数+是否异型(0否，1是)，调取入库库别选择策略，获取库别list。校验选择的库别是否在库别list里。不存在报错“数量或质量状态变化，需要重新选择库别”
//			checkBatchAndItem(rqcLinesDTOList);
			//青牛的最新校验
			//若有选择库别，零散数等于0，选择库别为AVG托盘库、立体库、一楼地堆库别，则校验当前容器上存放的商品不可混品混批
			//若没有选择库别，收货结论为合格或不合格，拦截并提示：请选择库别
			checkBatchAndItem1(rqcLinesDTOList);
		}
		//校验头单与明细行是否一致
		long count = rqcLinesDTOList.stream().filter(x -> x.getRcvHeaderId().equals(rqcHeadersDTO.getRcvHeaderId())).count();
		if(count==0){
			throw new BizException("验收单主表与明细不一致，请检查！");
		}

		String masterId = rqcHeadersDTO.getRqcHeaderId();
		if (isAdd) {
			//保存rqcHeader数据，返回主表id
			masterId = (String) this.add(rqcHeadersDTO, true, userDTO, autoTime);
			rqcHeadersDTO.setRqcHeaderId(masterId);
		}
		String asnHeaderId = "";
		if (ObjectUtils.isNotNull(rqcLinesDTOList)) {
			// 执行保存质检明细操作
			asnHeaderId = rqcLinesDTOList.get(0).getAsnHeaderId();
			rqcLinesService.batchAdd(rqcLinesDTOList, rqcHeadersDTO, userDTO, autoTime, isPad);
		}

		try{
			//如果收货结论选择的是 3 拒收，需要更新收货单的状态stockStatus
			List<String> RcvLineIds= rqcLinesDTOList.stream().filter(x-> x.getStockStatus().equals("3")).map(RqcLinesDTO :: getRcvLineId).collect(Collectors.toList());
			if(ToolKits.isNotEmpty(RcvLineIds)){
				MapperCustom.builder(rcvLinesMapper, RcvLines.class).addParameter(RcvLines::getStockStatus, "3")
						.andIn(RcvLines::getRcvLineId, RcvLineIds)
						.updateFieldsByCriteria();
			}
		}catch (Exception e) {
			logger.info("更新收货结论失败->原因{}", e);
		}

		try{
			//拒收后需要保存到拒收任务池
			List<RqcLinesDTO> rqcLinesDTOListReject = rqcLinesDTOList.stream().filter(x-> x.getStockStatus().equals("3")).collect(Collectors.toList());
			if(ToolKits.isNotEmpty(rqcLinesDTOListReject)){
				taskRejectedDetailService.excuteTask3(rqcLinesDTOListReject,false);
			}
		}catch (Exception e) {
			logger.info("拒收后需要保存到拒收任务池失败->原因"+ e);
		}


		// 执行上架标签打印
		logger.info("开始执行自动打印上架标签/验收上架单逻辑.", rqcHeadersDTO.getRqcHeaderId());
		try {
			List<String> collect = rqcLinesDTOList.stream()
					.filter(p -> !StringUtils.isBlank(p.getRcvLineId()) && ("1".equals(p.getStockStatus()) || "0".equals(p.getStockStatus())))
					.map(p -> p.getRcvLineId())
					.collect(Collectors.toList());
			RqcDQueryVO qu = new RqcDQueryVO();
			qu.setIncludeIds(collect);
			qu.setTaskStatus("1");
			if (isLabel) {
				// 打印标签
				excuteAssembleInstockPrintData = excuteAssembleInstockPrintData(qu, rqcHeadersDTO, userDTO, false);
			} else if (!isLabel && ToolKits.isNotEmpty(collect)){
				// 打印纸单
				excuteAssembleInstockPrintData = excuteAssembleInstockPrintBillData(qu, rqcHeadersDTO, userDTO, false);
			}
		} catch (Exception e) {
			logger.info("生成打印数据失败->原因", e);
		}

		try{
			// 判断并执行是否全拒收回传 erp
			boolean allMatch = rqcLinesDTOList.stream().allMatch(p -> p.getStockStatus().equals("3"));
			if (allMatch) {
				BigDecimal remainQty = this.rcvHeadersMapper.getRemainQty(masterId);
				if (remainQty != null && BigDecimal.ZERO.compareTo(remainQty) == 0) {
					// 整单拒收
					excuteCallBackErp(rqcHeadersDTO.getRcvHeaderId(), asnHeaderId, rqcHeadersDTO.getMtlOwnerId());
				}
			}
		}catch (Exception e) {
			logger.info("整单全拒收回传erp失败->原因", e);
		}

        try{
            //监管码上传码上放心平台
            List<String> rcvHeaderIds = rqcLinesDTOList.stream().map(RqcLinesDTO::getRcvHeaderId).distinct().collect(Collectors.toList());
            List<String> rcvLineIds = rqcLinesDTOList.stream().map(RqcLinesDTO::getRcvLineId).distinct().collect(Collectors.toList());
            List<String> itemIds = rqcLinesDTOList.stream().map(RqcLinesDTO::getItemId).distinct().collect(Collectors.toList());
            List<SupervisionCode> supervisionCodes = MapperCustom.builder(supervisionCodeMapper,SupervisionCode.class)
                    .andIn(SupervisionCode::getRefBillId,rcvHeaderIds)
                    .andIn(SupervisionCode::getRefBillLineId,rcvLineIds)
                    .andIn(SupervisionCode::getItemId,itemIds)
                    .andIn(SupervisionCode::getUploadFlag,Arrays.asList("0","2"))
                    .findByCriteria();
            if(ToolKits.isNotEmpty(supervisionCodes)){
                Integer uploadType= 0; //从入库直接扫的监管码，默认为入库
                //根据REF_BILL_LINE_ID分组
                Map<String, List<SupervisionCode>> listByRcvHeaderId = supervisionCodes.stream().collect(Collectors.groupingBy(SupervisionCode::getRefBillLineId));
                for (Map.Entry<String, List<SupervisionCode>> entry : listByRcvHeaderId.entrySet()) {
                    String rcvLineId = entry.getKey();
                    SupervisionCode supervisionCode = entry.getValue().get(0);
                    String rcvHeaderId = supervisionCode.getRefBillId();
                    String supplierId = rcvMapper.findSupplierId(rcvHeaderId);
                    if(ToolKits.isNotEmpty(supplierId)){
                        List<String> refbilllineids = new ArrayList<>();
                        refbilllineids.add(rcvLineId);
                        //更新监管码对应的类型为入库，同时保存供应商ID或者客户ID到监管码表中,可能会死锁，进行重试
						tryUpdateSupervisionCodeType(refbilllineids,supplierId,uploadType);
                    }
                }
            }
        }catch (Exception e) {
            logger.info("监管码上传码上放心平台失败->原因", e);
        }

		return excuteAssembleInstockPrintData;
	}

	public void tryUpdateSupervisionCodeType(List<String> refbilllineids, String supplierId,Integer uploadType){
		//这里可能出现死锁，尝试三次
		int i = 0;
		while (true) {
			try {
				//操作数据库
				rcvMapper.updateSupervisionCodeType(refbilllineids,supplierId,uploadType);
				break;
			} catch (Exception e) {
				i++;
				if (i >= 3) {
					logger.error("更新失败", e.getMessage());
					throw e;
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e1) {
					e1.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"):"");
		if(receivingRecordBackD.getStockstatus().equals("1")){
			backDVO.setResult("合格");
		}
		if(receivingRecordBackD.getStockstatus().equals("2")){
			backDVO.setResult("不合格");
		}
		if(receivingRecordBackD.getStockstatus().equals("3")){
			backDVO.setResult("待处理");
		}
		if(receivingRecordBackD.getStockstatus().equals("4")){
			backDVO.setResult("拒收");
		}
		return backDVO;
	}

	private boolean autoStock(boolean isPad, UserDTO userDTO, RqcHeadersDTO rqcHeadersDTO, Date autoTime, Object excuteAssembleInstockPrintData, String rcvType, List<RqcLinesDTO> rqcLinesDTOList) {
		if (rcvType.equals(BizConstant.STRAIGHT_IN)) {
			Random rand = new Random();
			int l2 = 30 * 1000;
			int time2 = rand.nextInt(l2) + l2;
			long time = autoTime.getTime() + time2;
			Date date = new Date(time);
			rqcHeadersDTO.setBillDate(date);
			String masterId = (String) this.add(rqcHeadersDTO, true, userDTO, date);
			rqcHeadersDTO.setRqcHeaderId(masterId);
			if (ObjectUtils.isNotNull(rqcLinesDTOList)) {
				//执行保存质检明细操作 需要走双人质检逻辑,正常逻辑
				rqcLinesService.batchAdd(rqcLinesDTOList, rqcHeadersDTO, userDTO, date, isPad);
			}
			// 判断并执行是否全拒收回传 erp
			boolean allMatch = rqcLinesDTOList.stream().allMatch(p -> p.getStockStatus().equals("3"));
			if (allMatch) {
				BigDecimal remainQty = this.rcvHeadersMapper.getRemainQty(masterId);
				if (remainQty != null && BigDecimal.ZERO.compareTo(remainQty) == 0) {
					// 整单拒收
					excuteCallBackErp(rqcHeadersDTO.getRcvHeaderId(), rqcHeadersDTO.getAsnHeaderId(), rqcHeadersDTO.getMtlOwnerId());
				} else {
					excuteDoAutoStock(rqcHeadersDTO, rqcLinesDTOList, userDTO, autoTime);
				}
			} else {
				excuteDoAutoStock(rqcHeadersDTO, rqcLinesDTOList, userDTO, autoTime);
			}
			return true;
		}
		return false;
	}

	private void checkBatchAndItem(List<RqcLinesDTO> rqcLinesDTOList) {
		//只有未复检过,来源于收货才校验
		if(rqcLinesDTOList==null || rqcLinesDTOList.size()==0){
			return;
		}
//		if(rqcLinesDTOList.get(0).getIsRechecked()>0){
//			return;
//		}
		List<RqcLinesDTO> rqcLineLtkList= rqcLinesDTOList.stream().filter(line-> Objects.equals("LTK",line.getWhAreaCategory())).collect(Collectors.toList());
		if(rqcLineLtkList!=null && rqcLineLtkList.size()>0){
			Map<String,List<RqcLinesDTO>> map=rqcLineLtkList.stream().filter(line->!StringUtils.isBlank(line.getContainerCode()) && !"N/A".equals(line.getContainerCode())).collect(Collectors.groupingBy(RqcLinesDTO::getContainerCode));
			for(Map.Entry<String,List<RqcLinesDTO>> entry : map.entrySet()){
				List<String> batchNums=entry.getValue().stream().filter(num->!StringUtils.isBlank(num.getManufacturerLotNum()) && !Objects.equals("N/A",num.getManufacturerLotNum())).map(RqcLinesDTO::getManufacturerLotNum).distinct().collect(Collectors.toList());
				if(batchNums.size()>1){
					throw new AssertException(String.format("容器号【%s】,不可混批",entry.getKey()));
				}
				List<String> itemIds=entry.getValue().stream().map(RqcLinesDTO::getItemId).distinct().collect(Collectors.toList());
				if(itemIds.size()>4){
					throw new AssertException(String.format("容器号【%s】,支持最大混品4种",entry.getKey()));
				}
			}
		}
		List<RqcLinesDTO> rqcLineRoomList= rqcLinesDTOList.stream().filter(line->!StringUtils.isBlank(line.getWhAreaCategory()) && !"N/A".equals(line.getWhAreaCategory())).collect(Collectors.toList());
		for(RqcLinesDTO line : rqcLineRoomList){
			BigDecimal pieceQty = line.getPieceQty();
			BigDecimal conversionRate = line.getConversionRate();
			BigDecimal oddCaseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN);
			BigDecimal oddPieceQty = pieceQty.subtract(oddCaseQty.multiply(conversionRate));
			//存在零散数,必须是零货库
			if(oddPieceQty!=null && oddPieceQty.compareTo(BigDecimal.ZERO)>0 && !Objects.equals("LHK",line.getWhAreaCategory())){
				throw new AssertException(String.format("库别【%s】,存在零散数,必须是零货库",line.getWhAreaCategory()));
			}
		}
		if(rqcLineRoomList!=null && rqcLineRoomList.size()>0){
			try {
				Map<RqcLinesDTO,List<RcvLineResult>> rcvLineResult=rqcLinesService.recommendRoom(rqcLineRoomList);
				for(Map.Entry<RqcLinesDTO,List<RcvLineResult>> entry : rcvLineResult.entrySet()){
					List<String> roomList= entry.getValue().stream().map(RcvLineResult::getWarehouseRoomCode).distinct().collect(Collectors.toList());
					if(!roomList.contains(entry.getKey().getWhAreaCategory())){
						throw new AssertException(String.format("库别【%s】,数量或质量状态变化，需要重新选择库别",entry.getKey().getWhAreaCategory()));
					}
				}
			} catch (Exception e) {
				throw new AssertException(String.format("入库库别选择发生异常,详情【%s】",e.getMessage()));
			}
		}
	}

	private void checkBatchAndItem1(List<RqcLinesDTO> rqcLinesDTOList) {
		//注释掉，后端不做库别策略查询
//		List<RqcLinesDTO> rqcLineRoomList= rqcLinesDTOList.stream().filter(line->!StringUtils.isBlank(line.getWhAreaCategoryCode()) && !"N/A".equals(line.getWhAreaCategoryCode())).collect(Collectors.toList());
//		if(rqcLineRoomList!=null && rqcLineRoomList.size()>0){
//			try {
//				Map<RqcLinesDTO,List<RcvLineResult>> rcvLineResult=rqcLinesService.recommendRoom(rqcLineRoomList);
//				for(Map.Entry<RqcLinesDTO,List<RcvLineResult>> entry : rcvLineResult.entrySet()){
//					List<String> roomList= entry.getValue().stream().map(RcvLineResult::getWarehouseRoomCode).distinct().collect(Collectors.toList());
//					if(!roomList.contains(entry.getKey().getWhAreaCategoryCode())){
//						throw new AssertException(String.format("库别【%s】,数量或质量状态变化，需要重新选择库别",entry.getKey().getWhAreaCategoryCode()));
//					}
//				}
//			} catch (Exception e) {
//				throw new AssertException(String.format("入库库别选择发生异常,详情【%s】",e.getMessage()));
//			}
//		}

		for (RqcLinesDTO rqcLinesDTO : rqcLinesDTOList) {
			//效验输入的批号、生产日期、有效期与收货行保存的是否一致，不一致，拦截并提示：****与收货不一致，请检查
			ToolKits.isParamNull(rqcLinesDTO.getManufacturerLotNum(), "批号不能为空");
			ToolKits.isParamNull(rqcLinesDTO.getShowExpiredDate(), "显示有效期至不能为空");
			ToolKits.isParamNull(rqcLinesDTO.getShowProductionDate(), "显示生产日期不能为空");
			//查询对应的rcv明细数据
			RcvLines rcvLines = rcvLinesMapper.findById(rqcLinesDTO.getRcvLineId(), RcvLines.class);
			if(!rqcLinesDTO.getManufacturerLotNum().equals(rcvLines.getManufacturerLotNum()) ){
				throw new AssertException("批号："+ rqcLinesDTO.getManufacturerLotNum()+"与收货批号："+ rcvLines.getManufacturerLotNum()+"不一致，请检查");
			}
			if(!rqcLinesDTO.getShowExpiredDate().equals(rcvLines.getShowExpiredDate()) ){
				throw new AssertException("显示有效期至"+ rqcLinesDTO.getShowExpiredDate()+"与收货"+ rcvLines.getShowExpiredDate()+"不一致，请检查");
			}
			if(!rqcLinesDTO.getShowProductionDate().equals(rcvLines.getShowProductionDate()) ){
				throw new AssertException("显示生产日期"+ rqcLinesDTO.getShowProductionDate()+"与收货"+ rcvLines.getShowProductionDate()+"不一致，请检查");
			}

			if(ToolKits.isNotEmpty(rqcLinesDTO.getWhAreaCategoryCode())){
				//若有选择库别，零散数等于0，选择库别为AVG托盘库、立体库、一楼地堆库别，则校验当前容器上存放的商品不可混品混批
				if(rqcLinesDTO.getOddPieceQty()!=null && rqcLinesDTO.getOddPieceQty().compareTo(BigDecimal.ZERO)==0 ){
					if(rqcLinesDTO.getWhAreaCategoryCode().equals("AGVZ") ||
							rqcLinesDTO.getWhAreaCategoryCode().equals("MJK") || rqcLinesDTO.getWhAreaCategoryCode().equals("ZJK")){
						Map<String,List<RqcLinesDTO>> containerMap = rqcLinesDTOList.stream().filter(line->!StringUtils.isBlank(line.getContainerCode()) && !"N/A".equals(line.getContainerCode())).collect(Collectors.groupingBy(RqcLinesDTO::getContainerCode));
						for(Map.Entry<String,List<RqcLinesDTO>> entry : containerMap.entrySet()){
							//按我物料和批次分组，size大于1则报错
							Map<String, List<RqcLinesDTO>> collect = entry.getValue().stream().filter(line -> !StringUtils.isBlank(line.getManufacturerLotNum()) && !"N/A".equals(line.getManufacturerLotNum())).collect(Collectors.groupingBy(x -> x.getManufacturerLotNum() + "_" + x.getItemId()));
							if(collect.size()>1){
								throw new AssertException("当前容器"+ entry.getValue()+"上存放的商品不可混品混批");
							}
						}
					}
				}
			}else {
				//没有选择库别时，收货结论为合格或不合格，拦截并提示：请选择库别
				if(rqcLinesDTO.getStockStatus().equals("0") || rqcLinesDTO.getStockStatus().equals("1")){
					throw new AssertException("请选择库别");
				}
			}
		}

	}


	private void excuteDoAutoStock(RqcHeadersDTO rqcHeadersDTO, List<RqcLinesDTO> rqcLinesDTOList, UserDTO userDTO,
								   Date autoTime) {
		if (rqcHeadersDTO.getRcvType().equals(BizConstant.STRAIGHT_IN)) {
			// 直调
			// 需要判断是否有双人验收的数据
			Set<String> areaCategoryCodeSet = new HashSet<>();
			if (enableAutoFixedAreaCategoryCode) {
				List<RqcLinesDTO> list = rqcLinesDTOList.stream().filter(x -> "ZDK".equals(x.getWhAreaCategoryCode()))
						.collect(Collectors.toList());
				if (list != null && list.size() > 0) {
					areaCategoryCodeSet.add(BizConstant.ZDK);
					autoStockHandler.autoStock(rqcHeadersDTO, list, userDTO, areaCategoryCodeSet, autoTime);
				}
			} else {
				// 看是否给默认库别
				autoStockHandler.autoStock(rqcHeadersDTO, rqcLinesDTOList, userDTO, areaCategoryCodeSet, autoTime);
			}
//			return excuteAssembleInstockPrintData;
		}
	}

	private void excuteCallBackErp(String rcvHeaderId, String asnHeaderId, String mtlOwnerId) {
		// 首先需要判断该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(rcvHeaderId, "1", asnHeaderId);

				// 回传应该是rcvHeaderId的集合
				List<RcvHeaders> findByMap = this.rcvHeadersMapper
						.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(rcvHeaderId, "2", asnHeaderId);
			rcvHeaderIdList = new HashSet<String>();
			rcvHeaderIdList.add(rcvHeaderId);
		}

		if (ObjectUtils.isNotNull(rcvHeaderIdList)) {
			for (String rcvHeaderIdstr : rcvHeaderIdList) {
				// 校验是否收货全部完成
				logger.info("验收全拒收回传开始-------------------------------");
				EtlMessage em = new EtlMessage();
				em.setId(rcvHeaderIdstr);
				em.setEtlType(EtlTypeConstants.in_asn_w2o);
				try {
					logger.info("验收全拒收回传给data-exchange数据:{}", JsonUtils.toString(em));
					exchangeSender.send(em);
					logger.info("验收全拒收回传data-exchange成功!");
					excuteUpdateRcvH(rcvHeaderIdstr);
				} catch (Exception e) {
					logger.error("验收全拒收回传失败,原因->{}", e);
				}
			}
		}

	}

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

	private void excuteSaveCallBackData(String rcvHeaderId, 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")) {
			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 boolean vaildateBillComplete(String asnHeaderId) {
		// 校验整个采购单是否收货上架完毕
		BigDecimal qty = null;
		try {
			qty = rcvHeadersMapper.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;
	}

	@Override
	public Page<TaskQcDetailDTO> extractRqcTask(TaskQcDetailQueryVO taskQcDetailQueryVO) {
		// 提取质检任务池中数据
		Page<TaskQcDetailDTO> findList = taskQcDetailService.extractTaskWithNativeSql(taskQcDetailQueryVO);
		return findList;
	}

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

		return rcvHeadersService.findListWithPro(rcvQueryVO, pageParam);
	}

	@Override
	public Page<RcvHDTO> extractRcvHAndPro(RcvQueryVO rcvQueryVO, PageParam pageParam) {
		return taskQcDetailService.extractRcvHWithNativeSql(rcvQueryVO, pageParam);

	}

	public Page<RcvHDTO> extractRcvHAndPro1(RcvQueryVO rcvQueryVO, PageParam pageParam) {
		return taskQcDetailService.extractRcvHWithNativeSql1(rcvQueryVO, pageParam);
	}

	private Object add(RqcHeadersDTO rqcHeadersDTO, boolean vaildateFlag, UserDTO userDTO, Date now) {
		if (ObjectUtils.isNull(userDTO))
			userDTO = userUtils.getUserDTO();
		if (ObjectUtils.isNull(now))
			now = new Date();
		boolean editFlag = Boolean.FALSE;
		// 1. 构建默认字段
		this.buildDefaultField(rqcHeadersDTO, editFlag, userDTO, now);
		if (vaildateFlag) {
			int row = 0;
			// 2. 校验数据
			super.vaildateModel(rqcHeadersDTO, editFlag, userDTO, row, validator, addMsg);
		}
		RqcHeaders rqcHeaders = new RqcHeaders();
		BeanUtils.copyProperties(rqcHeadersDTO, rqcHeaders);
		// 3. 构建系统级字段
		this.buildField(rqcHeaders, editFlag, userDTO, now); // 携带数据校验
//		super.setBaseSysField(rqcHeaders, editFlag, userDTO, now); // 不带数据校验
		this.mapper.save(rqcHeaders);
		BeanUtils.copyProperties(rqcHeaders, rqcHeadersDTO);
		return rqcHeaders.getRqcHeaderId();
	}

	private void buildDefaultField(RqcHeadersDTO rqcHeadersDTO, boolean editFlag, UserDTO userDTO, Date now) {
		// 构建默认字段
		String status = rqcHeadersDTO.getStatus();
		Date billDate = rqcHeadersDTO.getBillDate();
		if (!editFlag && ObjectUtils.isNull(status))
			rqcHeadersDTO.setStatus("1"); // 默认状态为可用

		if (!editFlag && ObjectUtils.isNull(billDate))
			rqcHeadersDTO.setBillDate(now);
		String qcOperator1 = rqcHeadersDTO.getQcOperator1();
		if (StringUtils.isBlank(qcOperator1)) {
			rqcHeadersDTO.setQcOperator1(userDTO.getUsername());
		}
		String autoBillNum = rqcHeadersDTO.getAutoBillNum();
		if (!editFlag && StringUtils.isBlank(autoBillNum)) {
			try {
				Long rcvNo = this.rcvMapper.getRcvSequence();
				rqcHeadersDTO.setAutoBillNum("QC" + ObjectUtils.getNumberStr(rcvNo, 8));
			} catch (Exception e) {
				rqcHeadersDTO.setAutoBillNum(String.valueOf(SnowFlakeUtils.getId()));
			}
		}
	}

	@Override
	public Page<RqcHeadersDTO> findList(RqcHeadersDTO rqcHeadersDTO, PageParam pageParam) {
		Criteria criteria = buildPageParam(pageParam, true, null, RqcHeaders.class);
		Restriction r = buildCondition(rqcHeadersDTO);
		criteria.setRestriction(r);
		this.startPage(pageParam);
		List<RqcHeaders> list = this.mapper.findByCriteria(criteria);
		Page<RqcHeaders> page = PageUtils.getPage(list);
		Page<RqcHeadersDTO> page2 = this.buildPage(page, (p) -> {
			RqcHeadersDTO target = new RqcHeadersDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		});
		return page2;
	}

	private void buildField(RqcHeaders rqcHeaders, boolean editFlag, UserDTO userDTO, Date now) {
		this.setBaseSysField(rqcHeaders, editFlag, userDTO, now);
		vaildateModelRepeated(rqcHeaders, editFlag, userDTO);

	}

	@Override
	public Object add(RqcHeadersDTO rqcHeadersDTO) {
		// TODO vaildate
		UserDTO userDTO = userUtils.getUserDTO();
		Date now = new Date();
		return this.add(rqcHeadersDTO, false, userDTO, now);
	}

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

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

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

	@Override
	@Transactional
	public Object batchAdd(List<RqcHeadersDTO> rqcHeadersDTOList) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		int row = 0;
		Date now = new Date();
		boolean editFlag = Boolean.FALSE;
		for (RqcHeadersDTO rqcHeadersDTO : rqcHeadersDTOList) {
			row++;
			this.vaildateModel(rqcHeadersDTO, editFlag, userDTO, row, validator, batchAddMsg);
			RqcHeaders rqcHeaders = new RqcHeaders();
			BeanUtils.copyProperties(rqcHeadersDTO, rqcHeaders);
			this.buildField(rqcHeaders, editFlag, userDTO, now);
			this.mapper.save(rqcHeaders);
		}
		return true;
	}

	@Override
	@Transactional
	public Object batchEdit(List<RqcHeadersDTO> rqcHeadersDTOList) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		for (RqcHeadersDTO rqcHeadersDTO : rqcHeadersDTOList) {
			RqcHeaders rqcHeaders = new RqcHeaders();
			BeanUtils.copyProperties(rqcHeadersDTO, rqcHeaders);
			this.vaildateModel(rqcHeaders, true, userDTO);
			this.buildField(rqcHeaders, true, userDTO);
			this.mapper.updateWithValidate(rqcHeaders,
					p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
		}
		return true;
	}

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

	private RqcHeaders findById(String id) {
		return this.mapper.findById(id, RqcHeaders.class);
	}

	private void vaildateModel(RqcHeaders rqcHeaders, Boolean editFlag, UserDTO userDTO) {
		if (!editFlag) {
			// TODO add
		} else {
			// TODO
		}
	}

	private void buildField(RqcHeaders rqcHeaders, Boolean editFlag, UserDTO userDTO) {
		buildField(rqcHeaders, editFlag, userDTO, new Date());
	}

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

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

	private Restriction buildCondition(RqcHeadersDTO rqcHeadersDTO) {
		// TODO
		return null;
	}

	@Override
	public RqcHeadersDTO findByPkId(String pkId) {
		// TODO
		RqcHeadersDTO rqcHeadersDTO = this.mapper.findByPkId(pkId);
		AssertUtils.notNull(rqcHeadersDTO, "查询对象为空!");
//		RqcHeaders rqcHeaders = this.findById(pkId);
//		RqcHeadersDTO rqcHeadersDTO = new RqcHeadersDTO();
//		BeanUtils.copyProperties(rqcHeaders, rqcHeadersDTO);
		return rqcHeadersDTO;
	}

	@Override
	public Page<RqcHeadersDTO> findList(RqcHQueryVO rqcHQueryVO, PageParam pageParam) {
		rqcHQueryVO.setEnterpriseId(userUtils.getEnterpriseId());
		String status = rqcHQueryVO.getStatus();
//		if (ObjectUtils.isNull(status))
//			rqcHQueryVO.setStatus("1"); // 默认可用的
		this.startPage(pageParam);
		// 去空格转大写
		String itemZjm = rqcHQueryVO.getItemZjm();
		if (!StringUtils.isBlank(itemZjm)) {
			rqcHQueryVO.setItemZjm(itemZjm.trim().toUpperCase());
		}
		List<RqcHeadersDTO> list = this.mapper.findList(rqcHQueryVO);
		return PageUtils.getPage(list);
	}

	@Transactional
	@Override
	public Object doException(List<RqcLinesDTO> rqcLinesDTOList) {
		// 把有问题的质检任务
		AssertUtils.isNotEmpty(rqcLinesDTOList, OperationConstant.COLLECTION_NULL_MSG);
		// 把对应的质检池任务暂时加锁
//		List<String> taskQcIdList = rqcLinesDTOList.stream().distinct().map(RqcLinesDTO::getTaskRqcId)
//				.collect(Collectors.toList());
//		updateTaskPoolStatus(taskQcIdList);
		return taskExceptionDetailService.saveTaskListByRq(rqcLinesDTOList);
	}

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

			Integer dataVersion = taskQcDetail.getDataVersion();

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

	/**
	 * 验收完后打印验收上架纸单
	 *
	 * @param qu
	 * @param rqcHeadersDTO
	 * @param userDTO
	 * @param reFlag
	 * @return
	 */
	private Object excuteAssembleInstockPrintBillData(RqcDQueryVO qu, RqcHeadersDTO rqcHeadersDTO, UserDTO userDTO,
													  boolean reFlag) {
		String rcvType = rqcHeadersDTO.getRcvType();
		if (BizConstant.PURCHASE_IN.equals(rcvType) || BizConstant.SALE_RETURN_IN.equals(rcvType)) {
			return getRqcDetailsPrintData(qu);
		}
		return null;
	}

	/**
	 * 质检完成后打印上架标签的数据
	 *
	 * @param queryVO
	 *
	 * @param rqcHeadersDTO
	 * @param userDTO
	 * @return
	 */
	// 需要区分补打和质检上架后打印的区别
	@Override
	public Object excuteAssembleInstockPrintData(RqcDQueryVO queryVO, RqcHeadersDTO rqcHeadersDTO, UserDTO userDTO,
												 boolean reFlag) {
		// 组装需要打印的上架标签数据
		// 排除不需要打印的
		Integer isInstockPrint = rqcHeadersDTO.getIsInstockPrint();
		String rcvType = rqcHeadersDTO.getRcvType();
		String mtlOwnerName = rqcHeadersDTO.getMtlOwnerName();
		if (isInstockPrint == null || 0 == isInstockPrint) {
			logger.info("当前验收明细无需打印上架标签!请检查!" + rqcHeadersDTO.getAutoBillNum());
			throw new BizException("当前验收明细无需打印上架标签!请检查!");
		}
		if (1 == isInstockPrint
				&& (BizConstant.PURCHASE_IN.equals(rcvType) || BizConstant.SALE_RETURN_IN.equals(rcvType))) {
			// 获取数据库的基础数据
			String rqcHeaderId = rqcHeadersDTO.getRqcHeaderId();
			TaskQueryVO queryVO2 = new TaskQueryVO();
//			queryVO2.setStatus("1");
			if (queryVO != null && ObjectUtils.isNotNull(queryVO.getIncludeIds())) {
				queryVO2.setStatus(queryVO.getTaskStatus());
				queryVO2.setIncloudRefIds(queryVO.getIncludeIds()); // 加入关联的rqcLine查询
			} else {
				queryVO2.setStatus("1");
			}
			queryVO2.setRqcHeaderId(rqcHeaderId);
			try {
				logger.info("上架标签打印查询参数-------------->" + JsonUtils.toString(queryVO2));
			} catch (JsonProcessingException e1) {
				e1.printStackTrace();
			}
			List<TaskInstockDetailDTO> findList = taskInstockDetailMapper.findList(queryVO2);

			if (ObjectUtils.isNull(findList))
				throw new BizException("当前验收明细无需打印上架标签!请检查!");
			logger.info("上架任务数" + findList.size());

			// 调用searchApi获取打印模板
			String warehouseId = rqcHeadersDTO.getWarehouseId();
			Map<String, Object> queryMap = new HashMap<>();
			queryMap.put("warehouseId", warehouseId);
			queryMap.put("tempType", "SJ_BQ"); // 可查询字典表灵活些
			List<Map> searchMap = null;
			try {
				logger.info("远程调用查询服务找寻打印模板配置,入参->", JsonUtils.toString(queryMap));
				searchMap = this.searchApi.searchForMap("getPrintTemplate", queryMap);
			} catch (Exception e) {
				logger.info("远程调用查询服务找寻打印模板配置失败,原因{}", e);
//				throw new BizException("远程调用查询服务找寻打印模板配置失败,请检查!");
			}
			if (!ObjectUtils.isNull(searchMap)) {
				Map map = searchMap.get(0);
				if (!ObjectUtils.isNull(map)) {
					printSolution1 = (String) map.get("tempname");
					printUrl = (String) map.get("temppath");
				} else {
					logger.info("查询服务找寻打印模板配置为空!");
					return null;
				}
			} else {
				logger.info("查询服务找寻打印模板配置为空!");
				return null;
			}

			PrintData pd = new PrintData();
			pd.setCount(printCount); // 默认1份
			pd.setPreview(preview1); // 是否预览
			pd.setPrintName(printName); // 打印机名称
			pd.setPrintSolution(printSolution1); // 打印方案
			pd.setUrl(printUrl); // 打印模板url
			List<ReportData> reportDataList = new ArrayList<>();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
			SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd");
			for (TaskInstockDetailDTO taskInstockDetail : findList) {
				String itemIsPieceOrCase = taskInstockDetail.getItemIsPieceOrCase();
				if (StringUtils.isBlank(itemIsPieceOrCase))
					itemIsPieceOrCase = "0"; // 默认整散合一

				BigDecimal pieceQty = taskInstockDetail.getPieceQty();
				if (pieceQty == null)
					pieceQty = BigDecimal.ZERO;
				BigDecimal conversionRate = taskInstockDetail.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); // 零散
//				if (BigDecimal.ZERO.compareTo(caseQty) == 0 && BigDecimal.ZERO.compareTo(oddPieceQty) == 0)
				if (BigDecimal.ZERO.compareTo(caseQty) == 0)
					continue; // 无整件,无需打印
				if (BigDecimal.ZERO.compareTo(caseQty) == -1 && BigDecimal.ZERO.compareTo(oddPieceQty) == -1)
					continue; // 有整有散件,无需打印
				if (itemIsPieceOrCase.equals("1") && (BigDecimal.ZERO.compareTo(caseQty) == 0
						|| (BigDecimal.ZERO.compareTo(caseQty) == -1 && BigDecimal.ZERO.compareTo(oddPieceQty) == -1)))
					// 整散需分开 且 (无整件 或者 有整件也有散件)无需打印
					continue;
				// 组装待打印处理的数据 TODO
				InstockTaskPrintDTO printDTO = new InstockTaskPrintDTO();
				BeanUtils.copyProperties(taskInstockDetail, printDTO);
				printDTO.setDrawer(userDTO.getUsername());
				String saleBillType = printDTO.getSaleBillType();
				String orgName = printDTO.getOrgName();
				String bizUser = printDTO.getBizUser();
				if (StringUtils.isBlank(saleBillType)) {
					printDTO.setSaleBillType("");
				}
				if (StringUtils.isBlank(orgName)) {
					printDTO.setOrgName("");
				}
				if (StringUtils.isBlank(bizUser)) {
					printDTO.setBizUser("");
				}
				String categoryName = taskInstockDetail.getCategoryName();
				printDTO.setItemCategory(categoryName);
				String rqcUser = taskInstockDetail.getRqcUser();
				printDTO.setRcvUser(rqcUser);
//				打印标签无需容器号
//				String containerCode = printDTO.getContainerCode();
//				if (!StringUtils.isBlank(containerCode) && "N/A".equalsIgnoreCase(containerCode)) {
//					printDTO.setContainerCode(null);
//				}
				if (reFlag) {
					printDTO.setReFlag("重");
				}
				printDTO.setCategoryName(categoryName);

				String showExpiredDate = taskInstockDetail.getShowExpiredDate();
				if (StringUtils.isBlank(showExpiredDate)) {
					Date batchExpiredDate = taskInstockDetail.getBatchExpiredDate();
					if (batchExpiredDate != null) {
						showExpiredDate = sdf2.format(batchExpiredDate);
					}
				}
				printDTO.setExpiredDate(showExpiredDate);
				String showProductionDate = taskInstockDetail.getShowProductionDate();
				if (StringUtils.isBlank(showProductionDate)) {
					Date batchProductionDate = taskInstockDetail.getBatchProductionDate();
					if (batchProductionDate != null) {
						showProductionDate = sdf2.format(batchProductionDate);
					}
				}
				printDTO.setProductionDate(showProductionDate);

				String mtlOwnerName2 = taskInstockDetail.getMtlOwnerName();
				printDTO.setMtlOwnerName(mtlOwnerName);
				if (StringUtils.isBlank(mtlOwnerName) || !mtlOwnerName.equals(mtlOwnerName2)) {
					printDTO.setMtlOwnerName(mtlOwnerName2);
				}
				String mtlOwnerName3 = printDTO.getMtlOwnerName();
				int indexOf = mtlOwnerName3.indexOf("有限");
				if (indexOf != -1) {
					String substring = mtlOwnerName3.substring(0, indexOf);
					printDTO.setMtlOwnerName(substring);
				}
				// 调整库别名称
				excuteHandleAreaCategory(taskInstockDetail, printDTO);
				// TODO 调整显示生产日期/有效期至
				ReportData reportData = new ReportData();
				@SuppressWarnings("unchecked")
				Map<String, Object> head = ObjectUtils.convertBean2MapForIngoreserialVersionUID(printDTO);
				reportData.setHead(head);
				reportDataList.add(reportData);
			}
			logger.info("应打印标签数:" + reportDataList.size());
			pd.setData(reportDataList);
			return pd;
		} else {
			throw new BizException("当前单据类型不支持打印上架标签!请检查!");
		}
	}

	private void excuteHandleAreaCategory(TaskInstockDetailDTO taskInstockDetail, InstockTaskPrintDTO printDTO) {
		// 把库别编码变为名称
		String whAreaCategoryCode = taskInstockDetail.getWhAreaCategoryCode();
		if (StringUtils.isBlank(whAreaCategoryCode))
			return;
		// 应该远程调用公共服务获取库别名称,这里先用常量代替
		switch (whAreaCategoryCode) {
			case "ZCQ":
				printDTO.setWhAreaCategoryName("暂存区");
				break;
			case "LHK":
				printDTO.setWhAreaCategoryName("零货库");
				break;
			case "ZJK":
				printDTO.setWhAreaCategoryName("整件库");
				break;
			case "LTK":
				printDTO.setWhAreaCategoryName("立体库");
				break;
			case "BHK":
				printDTO.setWhAreaCategoryName("备货库");
				break;
			case "NHK":
				printDTO.setWhAreaCategoryName("不合格库");
				break;
			case "THK":
				printDTO.setWhAreaCategoryName("退货库");
				break;
			case "PDK":
				printDTO.setWhAreaCategoryName("盘点库");
				break;
			case "DYK":
				printDTO.setWhAreaCategoryName("待验库");
				break;
			case "HYK":
				printDTO.setWhAreaCategoryName("整散合一库");
				break;
			case "CLK":
				printDTO.setWhAreaCategoryName("待处理库");
				break;
			case "ADJ":
				printDTO.setWhAreaCategoryName("调整库");
				break;
			case "DGK":
				printDTO.setWhAreaCategoryName("代管库");
				break;
			case "YKQ":
				printDTO.setWhAreaCategoryName("越库区");
				break;
			case "KRK":
				printDTO.setWhAreaCategoryName("空入库");
				break;
			case "XTK":
				printDTO.setWhAreaCategoryName("箱体库");
				break;
			case "ZDK":
				printDTO.setWhAreaCategoryName("直调库");
				break;
			default:
				break;
		}
	}

	public Object getRqcDetailsPrintData(RqcDQueryVO queryVO) {
		logger.info("{}, {}", queryVO, JSON.toJSONString(queryVO));
		PrintParam printParam = new PrintParam();
		printParam.setPrintBillCode("RqcQn");
		Map<String, Object> querymap = new HashMap<>();
		querymap.put("rcvLineId",queryVO.getIncludeIds());
		printParam.setParams(querymap);
		logger.info("打印出库单入参：{}", printParam);
		return printParam;
	}

/*	public Object getRqcDetailsPrintData(RqcDQueryVO queryVO) {
		logger.info("{}, {}", queryVO, JSON.toJSONString(queryVO));
		//List<PrintParam> printParamList = new ArrayList<>();
		PrintParam printParam = new PrintParam();
		printParam.setPrintBillCode("RqcQn");
		Map<String, Object> querymap = new HashMap<>();
//		querymap.put("rcvHeaderId",queryVO.getRcvHeaderId());
//		logger.info("rcvHeaderId", JSON.toJSONString(querymap));
		querymap.put("rcvLineId",queryVO.getIncludeIds());
		logger.info("rcvLineId", JSON.toJSONString(querymap), JSON.toJSONString(queryVO.getRcvLineId()), JSON.toJSONString(queryVO.getRcvHeaderId()));
		printParam.setParams(querymap);
		//printParamList.add(printParam);
		logger.info("打印出库单入参：{}", printParam);
		logger.info("打印出库单入参：{}", printParam.toString());
		RestMessage<?> restMessage = commonCaller.getPrintInfo(printParam);
		if (!restMessage.isSuccess()) {
			throw new RuntimeException("打印失败:" + restMessage.getMessage());
		}
		logger.info("打印出库清单返回结果：{}", JSON.toJSONString(restMessage));
		return restMessage;
	}*/


	/**
	 * 获取质检明细行打印数据
	 */
    /*@Override
	public Object getRqcDetailsPrintData(RqcDQueryVO queryVO) {
		String enterpriseId = queryVO.getEnterpriseId();
		if (StringUtils.isBlank(enterpriseId))
			queryVO.setEnterpriseId(userUtils.getEnterpriseId());
		UserDTO userDTO = userUtils.getUserDTO();
		String enterpriseName = userDTO.getEnterpriseName();
		List<RqcLinesDTO> findList = rqcLinesMapper.findList(queryVO);
		if (ObjectUtils.isNull(findList))
			return null;
		RqcLinesDTO rqcLinesDTO2 = findList.get(0);
		// 组装报表头数据
		RqcLinesHeadPrintDTO hDto = new RqcLinesHeadPrintDTO();
		String mtlOwnerName = rqcLinesDTO2.getMtlOwnerName();
		String vendorName = rqcLinesDTO2.getVendorName();
		String orgnName = rqcLinesDTO2.getOrgnName();
		String linkMan = rqcLinesDTO2.getLinkMan();
		String poNum = rqcLinesDTO2.getPoNum();
		String rcvUser = rqcLinesDTO2.getRcvUser();
		String remarks = rqcLinesDTO2.getRemarks();
		String saleBillType = rqcLinesDTO2.getSaleBillType();
		String username = userDTO.getUsername();
		String rcvType = rqcLinesDTO2.getRcvType();

		hDto.setDrawer(username);
		hDto.setPaymentType(saleBillType);
		hDto.setRemark(remarks);
		hDto.setLinkMan(linkMan);
		hDto.setMtlOwnerName(mtlOwnerName);
		hDto.setOrgnName(orgnName);
		hDto.setPoNum(poNum);
		hDto.setRcvUser(rcvUser);
		hDto.setVendorName(vendorName);
		hDto.setEnterpriseName(enterpriseName);
		if (!ObjectUtils.isNull(rcvType) && BizConstant.SALE_RETURN_IN.equals(rcvType)) {
			hDto.setBillType("销售退回");
		}
//		BeanUtils.copyProperties(rqcLinesDTO2, hDto); 类型不同会抛错
		String qcOpcode1 = rqcLinesDTO2.getQcOpcode1();
		hDto.setRqcUser(qcOpcode1);
		Date rqcDate = rqcLinesDTO2.getRqcDate();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		String rqcDateStr = sdf.format(rqcDate);
		hDto.setRqcDate(rqcDateStr);

		//调用searchApi获取打印模板
		Map<String, Object> queryMap = new HashMap<>();
		queryMap.put("warehouseId", warehouseId);
		queryMap.put("tempType", "ZJ_MX"); // 可查询字典表灵活些
		List<Map> searchMap = null;
		try {
			logger.info("远程调用查询服务找寻打印模板配置,入参->", JsonUtils.toString(queryMap));
			searchMap = this.searchApi.searchForMap("getPrintTemplate", queryMap);
		} catch (Exception e) {
			logger.info("远程调用查询服务找寻打印模板配置失败,原因{}", e);
//			throw new BizException("远程调用查询服务找寻打印模板配置失败,请检查!");
		}
		if (!ObjectUtils.isNull(searchMap)) {
			Map map = searchMap.get(0);
			if (!ObjectUtils.isNull(map)) {
				printSolution = (String) map.get("tempname");
				printUrl2 = (String) map.get("temppath");
			} else {
				logger.info("查询服务找寻打印模板配置为空!");
				return null;
			}
		} else {
			logger.info("查询服务找寻打印模板配置为空!");
			return null;
		}

		PrintData pd = new PrintData();
		pd.setTempType("ZJ_MX");
		pd.setCount(printCount); // 默认1份
		pd.setPreview(preview); // 是否预览
		pd.setPrintName(printName); // 打印机名称
		pd.setPrintSolution(printSolution); // 打印方案
		pd.setUrl(printUrl2); // 打印模板url
		@SuppressWarnings("unchecked")
		Map<String, Object> head = ObjectUtils.convertBean2MapForIngoreserialVersionUID(hDto);
		List<ReportData> rdList = new ArrayList<ReportData>();
		ReportData rd = new ReportData();
		rd.setHead(head);
		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd");
		List<Map<String, Object>> tableList = new ArrayList<Map<String, Object>>();
		// 按照库别排序(把整散分考)
		List<RqcLinesDTO> collect = findList.stream().sorted(
				Comparator.comparing(RqcLinesDTO::getWhAreaCategoryCode, Comparator.nullsLast(String::compareTo)))
				.collect(Collectors.toList());

		for (RqcLinesDTO rqcLinesDTO : collect) {
			// 组装报表列数据
			BigDecimal pieceQty = rqcLinesDTO.getPieceQty();
			if (pieceQty == null)
				pieceQty = BigDecimal.ZERO;
			BigDecimal conversionRate = rqcLinesDTO.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); // 零散
			RqcLinesPrintDTO rpd = new RqcLinesPrintDTO();
			String specification = rqcLinesDTO.getSpecification();
			String itemName = rqcLinesDTO.getItemName();
			String manufacturerName = rqcLinesDTO.getManufacturerName();
			String uom = rqcLinesDTO.getUom();
			String stockStatus = rqcLinesDTO.getStockStatus();
//			BeanUtils.copyProperties(rqcLinesDTO, rpd);
			rpd.setSpecification(specification);
			rpd.setItemName(itemName);
			rpd.setManufacturerName(manufacturerName);
			rpd.setUom(uom);
			// 处理质检结论
			stockStatus = handleStockStatus(stockStatus);
			rpd.setStockStatus(stockStatus);
			rpd.setPieceQty(pieceQty.toString());
			rpd.setCaseQty(caseQty.toString());
			rpd.setOddPieceQty(oddPieceQty.toString());
			rpd.setConversionRate(conversionRate.toString());
			rpd.setLocatorName(rqcLinesDTO.getWhLocatorCode()); // 质检有货位数据来源这个待确认
			rpd.setTrayBarcode(rqcLinesDTO.getContainerCode());
			rpd.setItemCode(rqcLinesDTO.getItemBarcode());
			rpd.setItemCode(rqcLinesDTO.getItemNum());
			rpd.setRcvRtReason(rqcLinesDTO.getRcvRtReason());
			String whAreaCategory = rqcLinesDTO.getWhAreaCategory();
			rpd.setWhAreaCategoryCode(whAreaCategory);
			rpd.setLocatorFloorNum(rqcLinesDTO.getLocatorFloorNum());
			rpd.setInstockLabel(rqcLinesDTO.getInstockLabel());
			rpd.setWhAreaCode(rqcLinesDTO.getWhAreaCode());
			rpd.setWhAreaCategoryCode(rqcLinesDTO.getWhAreaCategoryCode());
			String showExpiredDate = rqcLinesDTO.getShowExpiredDate();
			if (StringUtils.isBlank(showExpiredDate)) {
				Date batchExpiredDate = rqcLinesDTO.getBatchExpiredDate();
				if (batchExpiredDate != null) {
					showExpiredDate = sdf2.format(batchExpiredDate);
				}
			}
			rpd.setExpiredDate(showExpiredDate);
			String showProductionDate = rqcLinesDTO.getShowProductionDate();
			if (StringUtils.isBlank(showProductionDate)) {
				Date batchProductionDate = rqcLinesDTO.getBatchProductionDate();
				if (batchProductionDate != null) {
					showProductionDate = sdf2.format(batchProductionDate);
				}
			}
			rpd.setProductionDate(showProductionDate);

			String manufacturerLotNum = rqcLinesDTO.getManufacturerLotNum();
			rpd.setManufacturerLotNum(manufacturerLotNum);
			@SuppressWarnings("unchecked")
			Map<String, Object> table = ObjectUtils.convertBean2MapForIngoreserialVersionUID(rpd);
			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 getRqcGatherPrintData(RqcHQueryVO queryVO) {
		// 质检单汇总打印
		String enterpriseId = userUtils.getEnterpriseId();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		queryVO.setEnterpriseId(enterpriseId);
		List<RqcHeadersDTO> list = this.mapper.findList(queryVO);
		if (ObjectUtils.isNull(list))
			return null;
		List<String> rqcHList = list.stream().map(RqcHeadersDTO::getRqcHeaderId).distinct()
				.collect(Collectors.toList());
		RqcDQueryVO dQueryVO = new RqcDQueryVO();
		dQueryVO.setIncludeHIds(rqcHList);
		dQueryVO.setEnterpriseId(enterpriseId);
		List<RqcLinesDTO> findList = rqcLinesMapper.findList(dQueryVO);
		Map<String, List<RqcLinesDTO>> collect = findList.stream().distinct()
				.collect(Collectors.groupingBy(p -> p.getItemId() + p.getManufacturerLotNum()));

		// 组装报表头
		RqcHeadersDTO rqcHeadersDTO = list.get(0);
		String asnBillNo = rqcHeadersDTO.getAsnBillNo();
		Date billDate = rqcHeadersDTO.getBillDate();
		String buyerMane = rqcHeadersDTO.getBuyerMane();
		String orgnName = rqcHeadersDTO.getOrgnName();
		String qcOperator1 = rqcHeadersDTO.getQcOperator1();
		String mtlOwnerName = rqcHeadersDTO.getMtlOwnerName();
		String vendorName = rqcHeadersDTO.getVendorName();
		String enterpriseName = userUtils.getUserDTO().getEnterpriseName();
		String rcvType = rqcHeadersDTO.getRcvType();
		RqcHzHeadPrintDTO hzDto = new RqcHzHeadPrintDTO();
		hzDto.setBillDate(sdf.format(billDate));
		hzDto.setBizUser(buyerMane);
		hzDto.setDepartment(orgnName);
		hzDto.setEnterpriseName(enterpriseName);
		hzDto.setPoNo(asnBillNo);
		hzDto.setRqcMan(qcOperator1);
		hzDto.setMtlOwnerName(mtlOwnerName);
		hzDto.setSupplyUnit(vendorName);
		if (!ObjectUtils.isNull(rcvType) && BizConstant.SALE_RETURN_IN.equals(rcvType)) {
			hzDto.setBillType("销售退回");
		}
		PrintData pd = new PrintData();
		pd.setCount(printCount); // 默认1份
		pd.setPreview(preview); // 是否预览
		pd.setPrintName(printName); // 打印机名称
		pd.setPrintSolution(printSolution); // 打印方案
		pd.setUrl(printUrl4); // 打印模板url
		@SuppressWarnings("unchecked")
		Map<String, Object> head = ObjectUtils.convertBean2MapForIngoreserialVersionUID(hzDto);
		List<ReportData> rdList = new ArrayList<ReportData>();
		ReportData rd = new ReportData();
		rd.setHead(head);
		List<Map<String, Object>> tableList = new ArrayList<Map<String, Object>>();
		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd");
		for (List<RqcLinesDTO> rqcLinesDTOList : collect.values()) {
			if (ObjectUtils.isNull(rqcLinesDTOList))
				continue;
			RqcLinesDTO rqcLinesDTO = rqcLinesDTOList.get(0);
			String manufacturerLotNum = rqcLinesDTO.getManufacturerLotNum();
			BigDecimal conversionRate = rqcLinesDTO.getConversionRate();
			if (null == conversionRate)
				conversionRate = BigDecimal.ONE;
			String itemId = rqcLinesDTO.getItemId();
			// 统计总数
			BigDecimal pieceQtyTotal = BigDecimal.ZERO;
			for (RqcLinesDTO rqcLinesDTO2 : rqcLinesDTOList) {
				BigDecimal pieceQty = rqcLinesDTO2.getPieceQty();
				if (null == pieceQty)
					pieceQty = BigDecimal.ZERO;
				pieceQtyTotal = pieceQtyTotal.add(pieceQty);
			}
			// 计算整件,零散
			BigDecimal caseQty = pieceQtyTotal.divide(conversionRate, 0, RoundingMode.DOWN);
			BigDecimal multiply = caseQty.multiply(conversionRate);
			BigDecimal oddPieceQty = pieceQtyTotal.subtract(multiply);

			// 组装table数据
			RqcHzPrintDTO table = new RqcHzPrintDTO();
			table.setCaseQty(caseQty.stripTrailingZeros().toPlainString());
			table.setCategoryName(rqcLinesDTO.getCategoryName());
			table.setConversionRate(conversionRate.stripTrailingZeros().toPlainString());
			table.setItemCode(rqcLinesDTO.getItemNum());
			table.setItemName(rqcLinesDTO.getItemName());
			table.setManufacturerLotNum(manufacturerLotNum);
			table.setManufacturerName(rqcLinesDTO.getManufacturerName());
			table.setOddPieceQty(oddPieceQty.stripTrailingZeros().toPlainString());
			table.setPieceQty(pieceQtyTotal.stripTrailingZeros().toPlainString());

			String showExpiredDate = rqcLinesDTO.getShowExpiredDate();
			if (StringUtils.isBlank(showExpiredDate)) {
				Date batchExpiredDate = rqcLinesDTO.getBatchExpiredDate();
				if (batchExpiredDate != null) {
					showExpiredDate = sdf2.format(batchExpiredDate);
				}
			}
			table.setExpiredDate(showExpiredDate);
			String showProductionDate = rqcLinesDTO.getShowProductionDate();
			if (StringUtils.isBlank(showProductionDate)) {
				Date batchProductionDate = rqcLinesDTO.getBatchProductionDate();
				if (batchProductionDate != null) {
					showProductionDate = sdf2.format(batchProductionDate);
				}
			}
			table.setProductionDate(showProductionDate);
			table.setItemCode(rqcLinesDTO.getItemNum());
			table.setCategoryName(rqcLinesDTO.getCategoryName());
			table.setSpecification(rqcLinesDTO.getSpecification());
			table.setStockStatus(handleStockStatus(rqcLinesDTO.getStockStatus()));
			table.setUom(rqcLinesDTO.getUom());

			@SuppressWarnings("unchecked")
			Map<String, Object> tableMap = ObjectUtils.convertBean2MapForIngoreserialVersionUID(table);
			tableList.add(tableMap);
		}
		rd.setTable(tableList);
		rdList.add(rd);
		pd.setData(rdList);

		return pd;
	}

	/**
	 * 打印入库验收通知单头查询
	 */
	@Override
	public Object getRqcNoticeHeader(RcvQueryVO rcvQueryVO, PageParam pageParam) {
		return this.extractRcvHAndPro1(rcvQueryVO, pageParam);
	}

	/**
	 * 打印入库验收通知单明细查询
	 */
	@Override
	public Object getRqcNoticeDetails(String rcvHeaderId,String printStatus, PageParam pageParam) {
		TaskQcDetailQueryVO taskQcDetailQueryVO = new TaskQcDetailQueryVO();
		taskQcDetailQueryVO.setRcvHeaderId(rcvHeaderId);
		if(!StringUtils.isEmpty(printStatus)){
			taskQcDetailQueryVO.setPrintStatus(printStatus);
		}
		if (pageParam != null)
			BeanUtils.copyProperties(pageParam, taskQcDetailQueryVO);
		return this.extractRqcTask(taskQcDetailQueryVO);
	}

	@Override
	public Object getRqcNoticePrintData(TaskQcDetailQueryVO queryVo) {
		String rcvHeaderId = queryVo.getRcvHeaderId();
		AssertUtils.isNotBlank(rcvHeaderId, "收货单头id不可为空!");
		String enterpriseId = queryVo.getEnterpriseId();
		String status = queryVo.getStatus();
		if (StringUtils.isBlank(enterpriseId)) {
			queryVo.setEnterpriseId(userUtils.getEnterpriseId());
		}
		if (StringUtils.isBlank(status)) {
			queryVo.setStatus("1");
		}
		queryVo.setItemId(null);
		queryVo.setWarehouseId(null);
		queryVo.setMtlOwnerId(null);
		queryVo.setRcvLineId(null);
		List<TaskQcDetailDTO> findList = taskQcDetailMapper.findList3(queryVo);
		if (ObjectUtils.isNull(findList))
			return null;
		RcvHDTO findByPkId = this.rcvHeadersMapper.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);
		headDTO.setBillType("采购入库");
		if(headDTO.getRcvType().equals("2")){
			headDTO.setBillType("销退入库");
		}

		@SuppressWarnings("unchecked")
		Map<String, Object> head = ObjectUtils.convertBean2MapForIngoreserialVersionUID(headDTO);
		List<ReportData> rdList = new ArrayList<ReportData>();
		ReportData rd = new ReportData();
		head.put("vendorNumTitle","供应商编码");
		head.put("vendorNameTitle","供应商名称");
		if(headDTO.getRcvType().equals("2")){
			head.put("vendorNumTitle","客户编码");
			head.put("vendorNameTitle","客户名称");
		}
		boolean isFlag = findList.stream().anyMatch(x -> x.getCategoryId().equals("06") || x.getCategoryId().equals("15"));
		head.put("approvalNumberTitle","批准文号");
		head.put("lotNoTitle","批号");
		if(isFlag){
			head.put("approvalNumberTitle","注册证号");
			head.put("lotNoTitle","批号/序列号");
		}
		rd.setHead(head);
		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd");
		List<Map<String, Object>> tableList = new ArrayList<Map<String, Object>>();

        for (TaskQcDetailDTO 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.getResult();
			// 处理质检结论
			stockStatus = handleStockStatus(stockStatus);
			rlpd.setStockStatus(stockStatus);
			rlpd.setPieceQty(String.valueOf(pieceQty.intValue()));
			rlpd.setCaseQty(String.valueOf(caseQty.intValue()));
			rlpd.setOddPieceQty(String.valueOf(oddPieceQty.intValue()));
			rlpd.setConversionRate(String.valueOf(conversionRate.intValue()));
			rlpd.setIsSupervise("");
			if(rcvLinesDTO.getIsRetrospect()!=null&&rcvLinesDTO.getIsRetrospect()==1){
				head.put("isSupervise","√");
			}
			rlpd.setWhAreaCategoryCode(rcvLinesDTO.getWhAreaCategoryCode());

			// 处理生产日期,效期
			Date batchExpiredDate = rcvLinesDTO.getBatchExpiredDate();
			Date batchProductionDate = rcvLinesDTO.getBatchProductionDate();
			String showExpiredDate = rcvLinesDTO.getShowExpiredDate();
			String showProductionDate = rcvLinesDTO.getShowProductionDate();
			if (StringUtils.isBlank(showExpiredDate) && null != batchExpiredDate) {
				showExpiredDate = sdf2.format(batchExpiredDate);
			}
			if (StringUtils.isBlank(showProductionDate) && null != batchProductionDate) {
				showProductionDate = sdf2.format(batchProductionDate);
			}
			rlpd.setExpiredDate(showExpiredDate);
			rlpd.setProductionDate(showProductionDate);

            String manufacturerName = StringUtils.isEmpty(rcvLinesDTO.getManufacturerName())?"":rcvLinesDTO.getManufacturerName();
            String itemHealthListedLicensor = StringUtils.isEmpty(rcvLinesDTO.getItemHealthListedLicensor())?"":rcvLinesDTO.getItemHealthListedLicensor();
            String productionPlace = StringUtils.isEmpty(rcvLinesDTO.getProductionPlace())?"":rcvLinesDTO.getProductionPlace();

            rlpd.setManufacturerName(manufacturerName+"/"+itemHealthListedLicensor+"/"+productionPlace);

            @SuppressWarnings("unchecked")
			Map<String, Object> table = ObjectUtils.convertBean2MapForIngoreserialVersionUID(rlpd);
			tableList.add(table);
		}
		rd.setTable(tableList);
		rdList.add(rd);
		pd.setData(rdList);
		//更新任务池状态为已打印
		String[] taskIds = findList.stream().map(x -> x.getTaskRqcId()).toArray(String[]::new);
		Criteria crt = Criteria.forClass(TaskQcDetail.class);
		crt.restrictionBuilder().in("taskRqcId",taskIds);
		crt.buildRestriction();
		taskQcDetailMapper.updateMapByCriteria(MapUtils.put("segment1","1").getMap(),crt);
		return pd;
	}

	/**
	 * 质检明细查询
	 */
	@Override
	public Object getRqcDetailsList(RqcDQueryVO queryVO) {
		queryVO.setEnterpriseId(userUtils.getEnterpriseId());
		if (queryVO.getPageNum() != null && queryVO.getPageSize() != null) {
			this.startPage(queryVO);
			List<RqcLinesDTO> list = this.rqcLinesMapper.findList(queryVO);
			for (RqcLinesDTO rqcLinesDTO : list) {
				if(rqcLinesDTO.getUploadCircubillStatus() == 1){//需要追溯监管码时，查询监管码的上传状态
					List<SupervisionCode> supervisionCodes = MapperCustom.builder(supervisionCodeMapper,SupervisionCode.class)
							.andEq(SupervisionCode::getRefBillId,rqcLinesDTO.getRcvHeaderId())
							.andEq(SupervisionCode::getRefBillLineId,rqcLinesDTO.getRcvLineId())
							.andEq(SupervisionCode::getItemId,rqcLinesDTO.getItemId())
							.findByCriteria();
					if(ToolKits.isEmpty(supervisionCodes)){
						throw new BizException("监管码查询为空");
					}
/*					if(supervisionCodes.size()> 1){
						throw new BizException("监管码查询出多条记录");
					}*/
					SupervisionCode code = supervisionCodes.get(0);
					if(code.getUploadFlag().equals("1")){
						rqcLinesDTO.setUploadCircubillStatus(1);
					}else {
						rqcLinesDTO.setUploadCircubillStatus(2);
					}
				}
			}
			return PageUtils.getPage(list);
		}

		return this.rqcLinesMapper.findList(queryVO);
	}

	/**
	 * 上架标签补打
	 */
	@Override
	public Object getRqcInstockLabelPrintData(RqcDQueryVO queryVO) {
		String rqcHeaderId = queryVO.getRqcHeaderId();
		AssertUtils.isNotBlank(rqcHeaderId, "质检单id不可为空!(rqcHeaderId)");
		RqcHeadersDTO findByPkId = this.mapper.findByPkId(rqcHeaderId);
		AssertUtils.notNull(findByPkId, "查询的质检单信息为空!请刷新重试!");
		boolean reFlag = true;
		// 现在没实现上架任务中绑定质检行的id,所以无法根据质检行抓取到上架任务数据
		return this.excuteAssembleInstockPrintData(queryVO, findByPkId, userUtils.getUserDTO(), reFlag);
	}

	/**
	 * 提取确认判断任务是否被领取
	 */
	@Override
	public Object checkTaskExcute(List<String> taskIds) {
		AssertUtils.isNotEmpty(taskIds, "查询的任务id集合不可为空!");
		int row = 0;
		for (String taskId : taskIds) {
			row++;
			TaskQcDetail taskQcDetail = taskQcDetailMapper.findById(taskId, TaskQcDetail.class);
			String status = taskQcDetail.getStatus();
			if (!StringUtils.isBlank(status) && status.equals("0")) {
				throw new BizException(String.format("第[%d]行,质检任务id[%s],质检任务已被领取执行,请刷新!", row, taskId));
			}
		}
		return true;
	}

	@Override
	public List<RcvLinesPicDTO> showRcvLinePic(String rcvLineId) {
		RcvLinesPicDTO dto = new RcvLinesPicDTO();
		dto.setRcvLineId(rcvLineId);
		return rcvLinesPicService.findAll(dto);
	}

	@Override
	public Object taskMerge(List<TaskQcDetailDTO> taskQcDetailDTOList) {
		return taskQcDetailService.taskMerge(taskQcDetailDTOList);
	}

	@Override
	@Transactional
	public Object addWithRelatedAuto(RqcDTO rqcDTO) {
		// 极联保存关联数据
		RqcHeadersDTO rqcHeadersDTO = rqcDTO.getRqcHeadersDTO();
		AssertUtils.notNull(rqcHeadersDTO, "主表数据不可为空!");
		UserDTO userDTO = userUtils.getUserDTO();
		Date autoTime = rqcDTO.getAutoTime() == null ? new Date() : rqcDTO.getAutoTime();
		Random rand = new Random();
//		int l = 60 * 60 * 1000;
		int l2 = 30 * 60 * 1000;
		int time2 = rand.nextInt(l2) + l2;
		long time = autoTime.getTime() + time2;
		Date date = new Date(time);
		if (rqcDTO.getAutoTime() == null) {
			rqcHeadersDTO.setBillDate(date);
		} else {
			date = autoTime;
			rqcHeadersDTO.setBillDate(date);
		}
		String masterId = (String) this.add(rqcHeadersDTO, true, userDTO, date);
		rqcHeadersDTO.setRqcHeaderId(masterId);
		List<RqcLinesDTO> rqcLinesDTOList = rqcDTO.getRqcLinesDTOList();
		if (ObjectUtils.isNotNull(rqcLinesDTOList)) {
			// 执行保存质检明细操作
			rqcLinesService.batchAddAuto(rqcLinesDTOList, rqcHeadersDTO, userDTO, date, false);
		}
		// 自动单据无需打印数据
		return null;
	}

	@Override
	public TaskQcDetailDTO getRqcTask(String taskRqcId) {
		return taskQcDetailMapper.findByPKId(taskRqcId);
	}

	/**
	 * pad拆分任务(拆分时需生成新的验收单)
	 */
	@Override
	public Object splitTaskByPad(List<TaskQcDetailDTO> taskQcDetailDTOList) {
		return this.splitTask(taskQcDetailDTOList);
	}

	@Override
	public Page<TaskQcDetailDTO> extractRqcTaskByPad(TaskQcDetailQueryVO taskQcDetailQueryVO) {
		return this.extractRqcTask(taskQcDetailQueryVO);
	}

	/**
	 * pad保存方法
	 */
	@Override
	@Transactional
	public Object addWithRelatedByPad(RqcDTO rqcDTO) {
		// 如果是pad新增,需要判断是否是第一次验收,主要看当前收货单下面是否有验收记录,当然排除为0的数据
		// 没有就保存验收单,然后收货下所有的质检任务生成质检行,状态为初始状态(需要额外字段)
		// 有的话不保存验收单,然后更改对应的质检行状态为可用即可.
		// 此处还得考虑自动生成单据的情况,以及打印,以及拒收处理
//		RqcHeadersDTO rqcHeadersDTO = rqcDTO.getRqcHeadersDTO();
		List<RqcLinesDTO> rqcLinesDTOList = rqcDTO.getRqcLinesDTOList();
		AssertUtils.isNotEmpty(rqcLinesDTOList, "验收明细数据不可为空!");
		RqcLinesDTO rqcLinesDTO = rqcLinesDTOList.get(0);
		String rcvHeaderId = rqcLinesDTO.getRcvHeaderId();
//		Long count = this.rqcLinesMapper.findCountByRcvHeaderId(rcvHeaderId);
//		if (count > 0) {
		RqcHeadersDTO rqcHeaderByRcvId = this.getRqcHeaderByRcvId(rcvHeaderId);
		if (rqcHeaderByRcvId != null) {
			// 有质检数据,不新增验收单,只是把验收明细挂到此验收单下面
			rqcDTO.setRqcHeadersDTO(rqcHeaderByRcvId);
			return this.addWithRelatedAll(rqcDTO, true, false);
		} else {
			// 无质检数据,需要生成初始验收
			RcvHDTO findByPkId = this.rcvHeadersMapper.findByPkId(rcvHeaderId);
			AssertUtils.notNull(findByPkId, "收货单头为空!");
			RqcHeadersDTO rqcDto = new RqcHeadersDTO();
			BeanUtils.copyProperties(findByPkId, rqcDto);
			rqcDto.setIsInstockPrint(1); // 默认打印
//			String masterId = (String) this.add(rqcDto, true, userUtils.getUserDTO(), new Date());
//			rqcDto.setRqcHeaderId(masterId);

			// 保存验收明细数据
			rqcDTO.setRqcHeadersDTO(rqcDto);
			return this.addWithRelatedAll(rqcDTO, true);

		}
	}

	private Object addWithRelatedAll(RqcDTO rqcDTO, boolean isPad) {
		return this.addWithRelatedAll(rqcDTO, isPad, true);
	}

	@Override
	public Page<RcvHDTO> extractRcvHByPad(RcvQueryVO rcvQueryVO, PageParam pageParam) {
		return this.extractRcvHAndPro(rcvQueryVO, pageParam);
	}

	@Override
	public RqcHeadersDTO getRqcHeaderByRcvId(String rcvHeaderId) {
		return this.mapper.findByRcvId(rcvHeaderId);
	}

	@Override
	public List<RqcLinesDTO> getHostRqcResult(String itemId, String batchId) {
		return rqcLinesMapper.getHostRqcResult(itemId, batchId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Object addWithRelatedRf(RqcDTO rqcDTO) {
		AssertUtils.isNotTrue(rqcDTO==null, "入参数据不可为空!");
		AssertUtils.isNotTrue(rqcDTO.getRqcHeadersDTO()==null, "主表数据不可为空!");
		AssertUtils.isNotTrue(rqcDTO.getRqcLinesDTOList()==null || rqcDTO.getRqcLinesDTOList().size()==0, "明细数据不可为空!");
		RqcLinesDTO rqcLinesDTO=rqcDTO.getRqcLinesDTOList().get(0);
		if(rqcLinesDTO!=null && rqcLinesDTO.getUnlock()==null){
			rqcLinesDTO.setUnlock(0);
		}
		AssertUtils.isNotTrue(StringUtils.isBlank(rqcLinesDTO.getTaskRqcId()), "质检任务池id不可为空!");
		rqcLinesService.checkRfRqcQty(rqcDTO.getRqcLinesDTOList());
		AssertUtils.isNotTrue(Objects.equals(rqcLinesDTO.getStockStatus(),"1") && (StringUtils.isBlank(rqcLinesDTO.getDefReason()) || StringUtils.isBlank(rqcLinesDTO.getHandlingReason())), "质量状态为不合格时,处理原因和不足原因不能为空");
		//AssertUtils.isNotTrue(StringUtils.isBlank(rqcLinesDTO.getWhAreaCategory()), "库别不能为空!");
		AssertUtils.isNotTrue(StringUtils.isBlank(rqcLinesDTO.getContainerCode()) || Objects.equals("N/A",rqcLinesDTO.getContainerCode()), "容器不能为空!");
		AssertUtils.isNotTrue(rqcLinesDTO.getIsSupervise()==null, "是否监管码扫描不能为空!");
		//AssertUtils.isNotTrue(rqcLinesDTO.getUnlock()==null, "是否解锁不能为空!");
		AssertUtils.isNotTrue(rqcLinesDTO.getIsRechecked()==null, "是否复检过不能为空!");
		TaskQcDetail taskQcDetail = taskQcDetailMapper.findById(rqcLinesDTO.getTaskRqcId(), TaskQcDetail.class);
		AssertUtils.isNotTrue(taskQcDetail==null, "质检任务不存在,请检查!");
		Assert.isFalse(taskQcDetail.getPieceQty()==null, "质检数量不能为空");
		String rcvLineId = taskQcDetail.getRcvLineId();
		RcvLines findById = this.rcvLinesMapper.findById(rcvLineId, RcvLines.class);
		if (findById != null && taskQcDetail.getPieceQty().compareTo(rqcLinesDTO.getPieceQty()) < 0) {
			throw new BizException("拆分的数量不可大于质检数量");
		}
//		if(Objects.equals(rqcLinesDTO.getIsSupervise(),1) && 0==rqcLinesDTO.getIsRechecked()){
//			AssertUtils.isNotTrue(Objects.equals(rqcLinesDTO.getUnlock(),0) && (rqcDTO.getSupervisionCodeList()==null || rqcDTO.getSupervisionCodeList().size()==0), "未扫描监管码,请检查!");
//			if(rqcDTO.getSupervisionCodeList()!=null && rqcDTO.getSupervisionCodeList().size()>0){
//				for(SupervisionCode code : rqcDTO.getSupervisionCodeList()){
//					AssertUtils.isNotTrue(StringUtils.isBlank(code.getSupervisionCode()), "监管码不能为空,请检查!");
//					AssertUtils.isNotTrue(StringUtils.isBlank(code.getTaskRqcId()), "验收任务id不能为空,请检查!");
//					AssertUtils.isNotTrue(StringUtils.isBlank(code.getPackLevel()), "包装等级不能为空,请检查!");
//					//从明细中填充监管码的信息
//					BeanUtil.copyProperties(rqcLinesDTO,code);
//					code.setRefBillId(rqcLinesDTO.getRcvHeaderId());
//					code.setRefBillLineId(rqcLinesDTO.getRcvLineId());
//					code.setWhAreaCategoryCode(rqcLinesDTO.getWhAreaCategory());
//					code.setBillType(rqcLinesDTO.getRcvType());
//					code.setStage(0);
//					code.setItemCode(rqcLinesDTO.getItemNum());
//					if(Objects.equals(code.getPackLevel(),"0")){
//						code.setPackSize(code.getMaxSu());
//					}else if(Objects.equals(code.getPackLevel(),"1")){
//						code.setPackSize(code.getMiddleSu());
//					}else if(Objects.equals(code.getPackLevel(),"2")){
//						code.setPackSize(code.getMinSu());
//					}
//					code.setPieceQty(rqcLinesDTO.getPieceQty().toString());
//					code.setConsignorId(rqcLinesDTO.getMtlOwnerId());
//				}
//				BigDecimal totalQty = rqcDTO.getSupervisionCodeList().stream()
//						.map(s->new BigDecimal(s.getPackSize())).reduce(BigDecimal.ZERO, BigDecimal::add);
//				AssertUtils.isNotTrue(Objects.equals(rqcLinesDTO.getUnlock(),0) && rqcLinesDTO.getPieceQty().intValue()!=totalQty.intValue(), "监管码扫描数不等于应扫数,请检查!");
//				supervisionCodeService.addSupervisionCodeRqcRF(rqcDTO.getSupervisionCodeList());
//			}
//		}
		Page<TaskQcDetailDTO> task=null;
		if (taskQcDetail.getPieceQty().compareTo(rqcLinesDTO.getPieceQty()) >0 && 0==rqcLinesDTO.getIsRechecked()) {
			BigDecimal conversionRate = rqcLinesDTO.getConversionRate();
			List<TaskQcDetailDTO> taskQcDetailDTOList= Lists.newArrayList();
			TaskQcDetailDTO taskQcDetailDTOOld=new TaskQcDetailDTO();
			BeanUtils.copyProperties(taskQcDetail,taskQcDetailDTOOld);
			taskQcDetailDTOOld.setPieceQty(rqcLinesDTO.getPieceQty());
			BigDecimal oddCaseQtyOld = rqcLinesDTO.getPieceQty().divide(conversionRate, 0, RoundingMode.DOWN);
			BigDecimal oddPieceQtyOld = rqcLinesDTO.getPieceQty().subtract(oddCaseQtyOld.multiply(conversionRate));
			taskQcDetailDTOOld.setOddPieceQty(oddPieceQtyOld);
			taskQcDetailDTOOld.setOddCaseQty(oddCaseQtyOld);
			BigDecimal qtyOld = rqcLinesDTO.getPieceQty().divide(conversionRate, 4, RoundingMode.DOWN);
			taskQcDetailDTOOld.setQty(qtyOld);
			taskQcDetailDTOList.add(taskQcDetailDTOOld);

			TaskQcDetailDTO taskQcDetailDTONew=new TaskQcDetailDTO();
			BeanUtils.copyProperties(taskQcDetail,taskQcDetailDTONew);
			BigDecimal pieceQtyNew=taskQcDetail.getPieceQty().subtract(rqcLinesDTO.getPieceQty());
			taskQcDetailDTONew.setPieceQty(pieceQtyNew);
			BigDecimal oddCaseQtyNew = pieceQtyNew.divide(conversionRate, 4, RoundingMode.DOWN);
			BigDecimal oddPieceQtyNew = pieceQtyNew.subtract(oddCaseQtyNew.multiply(conversionRate));
			taskQcDetailDTONew.setOddPieceQty(oddPieceQtyNew);
			taskQcDetailDTONew.setOddCaseQty(oddCaseQtyNew);
			BigDecimal qtyNew = pieceQtyNew.divide(conversionRate, 7, RoundingMode.DOWN);
			taskQcDetailDTONew.setQty(qtyNew);
			taskQcDetailDTONew.setTaskRqcId(null);
			taskQcDetailDTOList.add(taskQcDetailDTONew);
			List<String> idList =(List<String>)taskQcDetailService.splitTask(taskQcDetailDTOList);
			String taskRqcIdNew=idList.stream().filter(id->!Objects.equals(rqcLinesDTO.getTaskRqcId(),id)).findFirst().orElse(null);
			TaskQcDetailQueryVO qcDetailQueryVO=new TaskQcDetailQueryVO();
			qcDetailQueryVO.setTaskRqcId(taskRqcIdNew);
			task=extractRqcTask(qcDetailQueryVO);
		}
		this.addWithRelatedAll(rqcDTO, false);
		if(task==null){
			return "";
		}
		return task.getList().get(0);
	}


	@Override
	public Object getRqcNoticeHeaderNew(RcvQueryVO rcvQueryVO, PageParam pageParam) {
		return taskQcDetailService.extractRcvHWithNativeSqlNew(rcvQueryVO, pageParam);
	}

	/**
	 * 打印入库验收通知单明细查询
	 */
	@Override
	public Object getRqcNoticeDetailsNew(String rcvHeaderId, PageParam pageParam) {
		TaskQcDetailQueryVO taskQcDetailQueryVO = new TaskQcDetailQueryVO();
		taskQcDetailQueryVO.setRcvHeaderId(rcvHeaderId);
		if (pageParam != null)
			BeanUtils.copyProperties(pageParam, taskQcDetailQueryVO);
		return taskQcDetailService.extractTaskWithNativeSqlNew(taskQcDetailQueryVO);
	}

	@Override
	public Object getRqcNoticePrintDataNew(RcvLinesQueryVO queryVo) {
		String rcvHeaderId = queryVo.getRcvHeaderId();
		String warehouseId = queryVo.getWarehouseId();
		AssertUtils.isNotBlank(rcvHeaderId, "收货单头id不可为空!");
		AssertUtils.isNotBlank(warehouseId, "仓id不可为空!");
		List<String> rcvHeaderIdList= Arrays.asList(rcvHeaderId.split(","));
		List<RcvLinesDTO> findList = rcvLinesMapper.findListNew(rcvHeaderIdList);
		AssertUtils.isNotTrue(findList==null || findList.size()==0, "收货单明细为空!");
		List<RcvHDTO> findByPkIdList = rcvHeadersMapper.findByPkIdNew(rcvHeaderIdList);
		AssertUtils.isNotTrue(findByPkIdList==null || findByPkIdList.size()==0, "收货单明细为空!");
//		List<Map<String, Object>> searchMap = rcvLinesMapper.findPrintTempInfo(warehouseId,"RCV_PRINT_TEMP");
//		AssertUtils.isNotTrue(searchMap==null || searchMap.size()!=1, "查询服务找寻收货单打印模板不能为空!");
//		Map map = searchMap.get(0);
//		printSolution = (String) map.get("tempname");
//		printUrl2 = (String) map.get("temppath");
		//组装报表头
		PrintData pd = new PrintData();
		pd.setTempType("RCV_PRINT_TEMP");
//		// 默认1份
//		pd.setCount(printCount);
//		// 是否预览
//		pd.setPreview(preview);
//		// 打印机名称
//		pd.setPrintName(printName);
//		// 打印方案
//		pd.setPrintSolution(printSolution);
//		// 打印模板url
//		pd.setUrl(printUrl2);
		List<ReportData> rdList =Lists.newArrayList();
		for(RcvHDTO findByPkId : findByPkIdList){
			ReportData rd = new ReportData();
			Map<String, Object> head = Maps.newHashMap();
			head.put("remark",!StringUtils.isBlank(findByPkId.getRcvRemark()) ? findByPkId.getRcvRemark() : "");
			head.put("companyName",!StringUtils.isBlank(findByPkId.getMtlOwnerName()) ? findByPkId.getMtlOwnerName() : "");
			head.put("rcvNo",!StringUtils.isBlank(findByPkId.getRcvNo()) ? findByPkId.getRcvNo() : "");
			head.put("warehouseName",!StringUtils.isBlank(findByPkId.getWarehouseName()) ? findByPkId.getWarehouseName() : "");
			head.put("printDateTime",DateUtils.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
			head.put("vendorName",!StringUtils.isBlank(findByPkId.getVendorName()) ? findByPkId.getVendorName() : "");
			head.put("vendorPhone",!StringUtils.isBlank(findByPkId.getVendorPhone()) ? findByPkId.getVendorPhone() : "");
			head.put("rcvUser",!StringUtils.isBlank(findByPkId.getRcvUser()) ? findByPkId.getRcvUser() : "");
			head.put("operaterUser",!StringUtils.isBlank(findByPkId.getRcvUser()) ? findByPkId.getRcvUser() : "");
			rd.setHead(head);
			List<RcvLinesDTO> linesDTOS =findList.stream().filter(l->Objects.equals(l.getRcvHeaderId(),findByPkId.getRcvHeaderId())).collect(Collectors.toList());
			AssertUtils.isNotTrue(linesDTOS==null || linesDTOS.size()==0, "收货单:"+findByPkId.getRcvHeaderId()+",明细为空!");
			List<Map<String, Object>> tableList =Lists.newArrayList();
			Map<String,List<RcvLinesDTO>> mapResult =linesDTOS.stream().collect(Collectors.groupingBy(l->l.getItemNum()+l.getManufacturerLotNum()+l.getShowProductionDate()+l.getShowExpiredDate()+l.getUom()+l.getConversionRate(),LinkedHashMap::new,Collectors.toList()));
			for (Map.Entry<String,List<RcvLinesDTO>> entry : mapResult.entrySet()) {
				RcvLinesDTO rcvLinesDTO=entry.getValue().get(0);
				Map<String, Object> table = Maps.newHashMap();
				table.put("itemNum",!StringUtils.isBlank(rcvLinesDTO.getItemNum()) ? rcvLinesDTO.getItemNum() : "");
				table.put("itemName",!StringUtils.isBlank(rcvLinesDTO.getItemName()) ? rcvLinesDTO.getItemName() : "");
				table.put("specification",!StringUtils.isBlank(rcvLinesDTO.getSpecification()) ? rcvLinesDTO.getSpecification() : "");
				table.put("manufacturerName",!StringUtils.isBlank(rcvLinesDTO.getManufacturerName()) ? rcvLinesDTO.getManufacturerName() : "");
				table.put("manufacturerLotNum",!StringUtils.isBlank(rcvLinesDTO.getManufacturerLotNum()) ? rcvLinesDTO.getManufacturerLotNum() : "");
				// 组装打印table数据
				BigDecimal conversionRate = rcvLinesDTO.getConversionRate();
				if (conversionRate == null || conversionRate.compareTo(BigDecimal.ZERO) == 0){
					conversionRate = BigDecimal.ONE;
				}
				BigDecimal pieceQtyTotal = entry.getValue().stream().filter(qty->qty.getPieceQty()!=null).map(RcvLinesDTO::getPieceQty).reduce(BigDecimal.ZERO, BigDecimal::add);
				BigDecimal oddCaseQtyTotal = pieceQtyTotal.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
				BigDecimal oddPieceQtyTotal = pieceQtyTotal.subtract(oddCaseQtyTotal.multiply(conversionRate)); // 零散
				table.put("pieceQty",pieceQtyTotal.doubleValue());
				table.put("oddCaseQty",oddCaseQtyTotal.doubleValue());
				table.put("oddPieceQty",oddPieceQtyTotal.doubleValue());
				table.put("productionDate",rcvLinesDTO.getBatchProductionDate()!=null ?  DateUtils.format(rcvLinesDTO.getBatchProductionDate(),DatePattern.NORM_DATE_PATTERN) : "");
				table.put("expiredDate",rcvLinesDTO.getBatchExpiredDate()!=null ?  DateUtils.format(rcvLinesDTO.getBatchExpiredDate(),DatePattern.NORM_DATE_PATTERN) : "");
				table.put("uom",!StringUtils.isBlank(rcvLinesDTO.getUom()) ? rcvLinesDTO.getUom() : "");
				table.put("conversionRate",conversionRate.doubleValue());
				tableList.add(table);
			}
			rd.setTable(tableList);
			rdList.add(rd);
		}
		pd.setData(rdList);
		return pd;
	}

	@Override
	public Object getRqcDetailsPrintDataNew(RqcDQueryVO queryVO) {
		String rqcHeaderId = queryVO.getRqcHeaderId();
		String warehouseId = queryVO.getWarehouseId();
		AssertUtils.isNotBlank(rqcHeaderId, "验收单头id不可为空!");
		AssertUtils.isNotBlank(warehouseId, "仓id不可为空!");
		List<RqcLinesDTO> findList = rqcLinesMapper.findListNew(queryVO);
		AssertUtils.isNotTrue(findList==null || findList.size()==0, "验收单明细为空!");

		List<String> rqcLineIds = queryVO.getIncludeIds();
		String[] rqcLineIdArray = rqcLineIds.stream().toArray(String[]::new);
		Criteria crt1 = Criteria.forClass(RqcLines.class);
		crt1.restrictionBuilder().in("rqcLineId",rqcLineIdArray);
		crt1.buildRestriction();
		List<RqcLines> rqcLines = rqcLinesMapper.findByCriteria(crt1);
		List<String> rcvLineIds = rqcLines.stream().filter(a -> !a.getRcvLineId().isEmpty()).map(b -> b.getRcvLineId()).collect(Collectors.toList());

		logger.info("{}, {}", queryVO, JSON.toJSONString(queryVO));
		PrintParam printParam = new PrintParam();
		printParam.setPrintBillCode("RqcQn");
/*		Map<String, Object> querymap = new HashMap<>();
		querymap.put("rcvLineId",MapUtils.put("rcvLineId", rcvLineIds).getMap());*/
		//logger.info("rcvLineId", JSON.toJSONString(querymap), JSON.toJSONString(queryVO.getRcvLineId()), JSON.toJSONString(queryVO.getRcvHeaderId()));
		printParam.setParams(MapUtils.put("rcvLineId", rcvLineIds).getMap());
		logger.info("打印出库单入参：{}", JSON.toJSONString(printParam));
		RestMessage<?> restMessage = commonCaller.getPrintInfo(printParam);
		if (!restMessage.isSuccess()) {
			throw new RuntimeException("打印失败:" + restMessage.getMessage());
		}
		logger.info("打印出库清单返回结果：{}", JSON.toJSONString(restMessage));
		//更新任务池状态为已打印
		String[] lineIds = findList.stream().map(x -> x.getRqcLineId()).toArray(String[]::new);
		Criteria crt = Criteria.forClass(RqcLines.class);
		crt.restrictionBuilder().in("rqcLineId",lineIds);
		crt.buildRestriction();
		rqcLinesMapper.updateMapByCriteria(MapUtils.put("secondStatus","1").getMap(),crt);
		return restMessage;
	}

    /*@Override
	public Object getRqcDetailsPrintDataNew1(RqcDQueryVO queryVO) {
		String rqcHeaderId = queryVO.getRqcHeaderId();
		String warehouseId = queryVO.getWarehouseId();
		AssertUtils.isNotBlank(rqcHeaderId, "验收单头id不可为空!");
		AssertUtils.isNotBlank(warehouseId, "仓id不可为空!");
		List<RqcLinesDTO> findList = rqcLinesMapper.findListNew(queryVO);
		AssertUtils.isNotTrue(findList==null || findList.size()==0, "验收单明细为空!");
//		List<Map<String, Object>> searchMap = rcvLinesMapper.findPrintTempInfo(warehouseId,"RQC_PRINT_TEMP");
//		AssertUtils.isNotTrue(searchMap==null || searchMap.size()!=1, "查询服务找寻验收单打印模板不能为空!");
//		Map map = searchMap.get(0);
//		printSolution = (String) map.get("tempname");
//		printUrl2 = (String) map.get("temppath");
//		//组装报表头
		PrintData pd = new PrintData();
		pd.setTempType("RQC_PRINT_TEMP");
//		// 默认1份
//		pd.setCount(printCount);
//		// 是否预览
//		pd.setPreview(preview);
//		// 打印机名称
//		pd.setPrintName(printName);
//		// 打印方案
//		pd.setPrintSolution(printSolution);
//		// 打印模板url
//		pd.setUrl(printUrl2);
		Map<String, Object> head = Maps.newHashMap();
		UserDTO userDTO = userUtils.getUserDTO();
		// 组装报表头数据
		RqcLinesDTO rqcLinesDTO2 = findList.get(0);
		head.put("enterpriseName",userDTO.getEnterpriseName());
		head.put("rcvNo",rqcLinesDTO2.getRcvNo());
		head.put("poNum",rqcLinesDTO2.getPoNum());
		head.put("rcvDate",rqcLinesDTO2.getRcvDate());
		head.put("billType",rqcLinesDTO2.getBillTypeName());
		head.put("vendorCode",!StringUtils.isBlank(rqcLinesDTO2.getVendorNum()) ? rqcLinesDTO2.getVendorNum() : "");
		head.put("vendorName",!StringUtils.isBlank(rqcLinesDTO2.getVendorName()) ? rqcLinesDTO2.getVendorName() : "");
		head.put("drawer",!StringUtils.isBlank(rqcLinesDTO2.getLinkMan()) ? rqcLinesDTO2.getLinkMan() : "");
		head.put("rqcDate",rqcLinesDTO2.getRqcDate());
		head.put("mtlOwnerName",!StringUtils.isBlank(rqcLinesDTO2.getMtlOwnerName()) ? rqcLinesDTO2.getMtlOwnerName() : "");
		head.put("isSupervise","");
		if(rqcLinesDTO2.getIsRetpospect().equals("1")){
			head.put("isSupervise","√");
		}

		head.put("rqcNo",!StringUtils.isBlank(rqcLinesDTO2.getRqcNo()) ? rqcLinesDTO2.getRqcNo() : "");
		head.put("warehouseName",!StringUtils.isBlank(rqcLinesDTO2.getWarehouseName()) ? rqcLinesDTO2.getWarehouseName() : "");
		head.put("preAreaName","");
		head.put("printDateTime",DateUtils.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
		head.put("vendorPhone",!StringUtils.isBlank(rqcLinesDTO2.getVendorPhone()) ? rqcLinesDTO2.getVendorPhone() : "");
		head.put("rcvUser",!StringUtils.isBlank(rqcLinesDTO2.getRcvUser()) ? rqcLinesDTO2.getRcvUser() : "");
		head.put("rqcUser",!StringUtils.isBlank(rqcLinesDTO2.getRqcUser()) ? rqcLinesDTO2.getRqcUser() : "");
		List<ReportData> rdList =Lists.newArrayList();
		ReportData rd = new ReportData();
		rd.setHead(head);
		List<Map<String, Object>> tableList =Lists.newArrayList();
		for (RqcLinesDTO rqcLinesDTO : findList) {
			Map<String, Object> table = Maps.newHashMap();
			table.put("itemCode",!StringUtils.isBlank(rqcLinesDTO.getItemNum()) ? rqcLinesDTO.getItemNum() : "");
			table.put("itemName",!StringUtils.isBlank(rqcLinesDTO.getItemName()) ? rqcLinesDTO.getItemName() : "");
			table.put("itemHealthType",rqcLinesDTO.getItemHealthType());
			table.put("specification",!StringUtils.isBlank(rqcLinesDTO.getSpecification()) ? rqcLinesDTO.getSpecification() : "");
			table.put("manufacturerName",!StringUtils.isBlank(rqcLinesDTO.getManufacturerName()) ? rqcLinesDTO.getManufacturerName() : "");
			table.put("manufacturerLotNum",!StringUtils.isBlank(rqcLinesDTO.getManufacturerLotNum()) ? rqcLinesDTO.getManufacturerLotNum() : "");
			table.put("itemHealthListedLicensor",rqcLinesDTO.getItemHealthListedLicensor());
			// 组装打印table数据
			BigDecimal conversionRate = rqcLinesDTO.getConversionRate();
			if (conversionRate == null || conversionRate.compareTo(BigDecimal.ZERO) == 0){
				conversionRate = BigDecimal.ONE;
			}
			BigDecimal pieceQtyTotal = rqcLinesDTO.getPieceQty();
			BigDecimal oddCaseQtyTotal = pieceQtyTotal.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
			BigDecimal oddPieceQtyTotal = pieceQtyTotal.subtract(oddCaseQtyTotal.multiply(conversionRate)); // 零散
			table.put("pieceQty",pieceQtyTotal.doubleValue());
			table.put("oddCaseQty",oddCaseQtyTotal.doubleValue());
			table.put("oddPieceQty",oddPieceQtyTotal.doubleValue());
			table.put("productionDate",rqcLinesDTO.getBatchProductionDate()!=null ?  DateUtils.format(rqcLinesDTO.getBatchProductionDate(),DatePattern.PURE_DATE_PATTERN) : "");
			table.put("expiredDate",rqcLinesDTO.getBatchExpiredDate()!=null ?  DateUtils.format(rqcLinesDTO.getBatchExpiredDate(),DatePattern.PURE_DATE_PATTERN) : "");
			table.put("uom",!StringUtils.isBlank(rqcLinesDTO.getUom()) ? rqcLinesDTO.getUom() : "");
			table.put("conversionRate",conversionRate.doubleValue());
			table.put("whAreaCategoryCode",rqcLinesDTO.getWhAreaCategoryCode());
			table.put("whLocatorCode",rqcLinesDTO.getWhLocatorCode());
			table.put("containerCode",rqcLinesDTO.getContainerCode());
			table.put("stockStatus","合格");
			if(rqcLinesDTO.getStockStatus().equals("1")){
				table.put("stockStatus","不合格");
			}
			if(rqcLinesDTO.getStockStatus().equals("2")){
				table.put("stockStatus","待处理");
			}
			if(rqcLinesDTO.getStockStatus().equals("3")){
				table.put("stockStatus","拒收");
			}

			tableList.add(table);
		}
		rd.setTable(tableList);
		rdList.add(rd);
		pd.setData(rdList);
		//更新任务池状态为已打印
		String[] lineIds = findList.stream().map(x -> x.getRqcLineId()).toArray(String[]::new);
		Criteria crt = Criteria.forClass(RqcLines.class);
		crt.restrictionBuilder().in("rqcLineId",lineIds);
		crt.buildRestriction();
		rqcLinesMapper.updateMapByCriteria(MapUtils.put("secondStatus","1").getMap(),crt);
		return pd;
	}*/

	@Override
	public Object getRqcInstockLabelPrintDataNew(RqcDQueryVO queryVO) {
		String taskId = queryVO.getTaskId();
		String warehouseId = queryVO.getWarehouseId();
		AssertUtils.isNotBlank(taskId, "上架任务池行id不能为空");
		AssertUtils.isNotBlank(warehouseId, "仓id不能为空");
		List<String> taskIdList= Arrays.asList(taskId.split(","));
		RcvInstockLinesQueryVO vo=new RcvInstockLinesQueryVO();
		vo.setTaskIdList(taskIdList);
		List<RcvInstockLinesDTO> findList = rcvInstockLinesMapper.findListNew(vo);
		AssertUtils.isNotTrue(findList==null || findList.size()==0, "上架单明细为空!");
		//	long flag=findList.stream().filter(l -> StringUtils.isBlank(l.getInBoundLineId())).count();
		//	long flag1=findList.stream().filter(l -> !StringUtils.isBlank(l.getInBoundLineId())).count();
		long flag2=findList.stream().map(l -> l.getAsnNo()).distinct().count();
		AssertUtils.isNotTrue( flag2!=1, "选择的数据必须是同一采购单");
//		List<Map<String, Object>> searchMap = rcvLinesMapper.findPrintTempInfo(warehouseId,"INSTOCK_PRINT_TEMP");
//		AssertUtils.isNotTrue(searchMap==null || searchMap.size()!=1, "查询服务找寻上架单打印模板不能为空!");
//		Map map = searchMap.get(0);
//		printSolution = (String) map.get("tempname");
//		printUrl2 = (String) map.get("temppath");
		//组装报表头
		PrintData pd = new PrintData();
		pd.setTempType("INSTOCK_PRINT_TEMP");
//		// 默认1份
//		pd.setCount(printCount);
//		// 是否预览
//		pd.setPreview(preview);
//		// 打印机名称
//		pd.setPrintName(printName);
//		// 打印方案
//		pd.setPrintSolution(printSolution);
//		// 打印模板url
//		pd.setUrl(printUrl2);
        //根据库区分组
        UserDTO userDTO = userUtils.getUserDTO();
        List<ReportData> rdList =Lists.newArrayList();
		for (RcvInstockLinesDTO rcvInstockLinesDTO : findList) {
			if(rcvInstockLinesDTO.getWhAreaCategoryCode().equals("MJK")){
				rcvInstockLinesDTO.setWhAreaCode("SX01-R01");
				rcvInstockLinesDTO.setWhLocatorCode("SX01");
			}
			if(rcvInstockLinesDTO.getWhAreaCategoryCode().equals("AGVZ")){
				rcvInstockLinesDTO.setWhAreaCode("AGVTP01-R01");
				rcvInstockLinesDTO.setWhLocatorCode("AGVTP01");
			}
			if(rcvInstockLinesDTO.getWhAreaCategoryCode().equals("AGVL")){
				rcvInstockLinesDTO.setWhAreaCode("AGVHJ01-R01");
				rcvInstockLinesDTO.setWhLocatorCode("AGVHJ01");
			}
		}
        Map<String, List<RcvInstockLinesDTO>> collect = findList.stream().collect(Collectors.groupingBy(x -> x.getWhAreaCode()));
        Set<Map.Entry<String, List<RcvInstockLinesDTO>>> entries = collect.entrySet();
        for (Map.Entry<String, List<RcvInstockLinesDTO>> entry : entries) {
            Map<String, Object> head = Maps.newHashMap();
            // 组装报表头数据
            RcvInstockLinesDTO rqcLinesDTO2 = entry.getValue().get(0);
            head.put("enterpriseName",userDTO.getEnterpriseName());
            head.put("areaCode",rqcLinesDTO2.getWhAreaCode());
            head.put("companyName",!StringUtils.isBlank(rqcLinesDTO2.getMtlOwnerName()) ? rqcLinesDTO2.getMtlOwnerName() : "");
            head.put("billNo",!StringUtils.isBlank(rqcLinesDTO2.getAsnNo()) ? rqcLinesDTO2.getAsnNo() : "");
            head.put("poNo",!StringUtils.isBlank(rqcLinesDTO2.getAsnNo()) ? rqcLinesDTO2.getAsnNo() : "");
            head.put("printDateTime",DateUtils.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
            head.put("vendorName",!StringUtils.isBlank(rqcLinesDTO2.getVendorName()) ? rqcLinesDTO2.getVendorName() : "");
            head.put("inStockDate",rqcLinesDTO2.getGmtCreateTime());
            head.put("rcvNo",rqcLinesDTO2.getRcvNo());
            head.put("billType","采购入库");
            if(rqcLinesDTO2.getRcvType().equals("2")){
                head.put("billType","销退入库");
            }
            ReportData rd = new ReportData();
            rd.setHead(head);
            List<Map<String, Object>> tableList =Lists.newArrayList();
            for (RcvInstockLinesDTO rqcLinesDTO : entry.getValue()) {
                Map<String, Object> table = Maps.newHashMap();
                table.put("itemNum",!StringUtils.isBlank(rqcLinesDTO.getItemNum()) ? rqcLinesDTO.getItemNum() : "");
                table.put("itemName",!StringUtils.isBlank(rqcLinesDTO.getItemName()) ? rqcLinesDTO.getItemName() : "");
                table.put("specification",!StringUtils.isBlank(rqcLinesDTO.getSpecification()) ? rqcLinesDTO.getSpecification() : "");
                table.put("manufacturerName",!StringUtils.isBlank(rqcLinesDTO.getManufacturerName()) ? rqcLinesDTO.getManufacturerName() : "");
                table.put("manufacturerLotNum",!StringUtils.isBlank(rqcLinesDTO.getManufacturerLotNum()) ? rqcLinesDTO.getManufacturerLotNum() : "");
//			// 组装打印table数据
                BigDecimal conversionRate = rqcLinesDTO.getConversionRate();
                if (conversionRate == null || conversionRate.compareTo(BigDecimal.ZERO) == 0){
                    conversionRate = BigDecimal.ONE;
                }
                BigDecimal pieceQty =rqcLinesDTO.getPieceQty();
                BigDecimal oddCaseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
                BigDecimal oddPieceQty = pieceQty.subtract(oddCaseQty.multiply(conversionRate)); // 零散
                table.put("pieceQty",pieceQty.doubleValue());
                table.put("oddCaseQty",oddCaseQty.doubleValue());
                table.put("oddPieceQty",oddPieceQty.doubleValue());
                table.put("conversionRate",conversionRate);
                table.put("uom",rqcLinesDTO.getUom());
                table.put("whLocatorCode",!StringUtils.isBlank(rqcLinesDTO.getWhLocatorCode()) ? rqcLinesDTO.getWhLocatorCode() : "");
                table.put("whLocatorCodeRecommend",!StringUtils.isBlank(rqcLinesDTO.getWhLocatorCodeRecommend()) ? rqcLinesDTO.getWhLocatorCodeRecommend() : "");
                table.put("containerCode",!StringUtils.isBlank(rqcLinesDTO.getContainerCode()) ? rqcLinesDTO.getContainerCode() : "");
                table.put("whAreaName",!StringUtils.isBlank(rqcLinesDTO.getWhAreaName()) ? rqcLinesDTO.getWhAreaName() : "");
                table.put("itemHealthListedLicensor",rqcLinesDTO.getItemHealthListedLicensor());
                table.put("approvalNumber",rqcLinesDTO.getApprovalNumber());
                table.put("productionDate",rqcLinesDTO.getShowProductionDate());
                table.put("expiredDate",rqcLinesDTO.getShowExpiredDate());
                table.put("areaCOde",rqcLinesDTO.getWhAreaCode());
                table.put("locatorCode",rqcLinesDTO.getWhLocatorCode());
                table.put("containerCode",rqcLinesDTO.getContainerCode());

                tableList.add(table);
            }
            rd.setTable(tableList);
            rdList.add(rd);
        }
		pd.setData(rdList);
		//更新任务池状态为已打印
		String[] lineIds = findList.stream().map(x -> x.getInBoundLineId()).toArray(String[]::new);
		Criteria crt = Criteria.forClass(RcvInstockLines.class);
		crt.restrictionBuilder().in("inBoundLineId",lineIds);
		crt.buildRestriction();
		rcvInstockLinesMapper.updateMapByCriteria(MapUtils.put("secondStatus","1").getMap(),crt);
		return pd;
	}

//	@Override
//	public Object uploadCircubillRcvDetails(RqcLinesDTO rqcLinesDTO) {
//		UserDTO userDTO = userUtils.getUserDTO();
//		if (StringUtils.isEmpty(rqcLinesDTO.getRcvHeaderId())) {
//			throw new ParameterException("收货单ID不能为空");
//		}
//		if (StringUtils.isEmpty(rqcLinesDTO.getRcvLineId())) {
//			throw new ParameterException("收货行ID不能为空");
//		}
//		if (StringUtils.isEmpty(rqcLinesDTO.getItemId())) {
//			throw new ParameterException("收货行物料ID不能为空");
//		}
//
//		String rcvHeaderId = rqcLinesDTO.getRcvHeaderId();
//		String rcvLineId = rqcLinesDTO.getRcvLineId();
//		//查询对应监管码表未上传的记录
//		List<SupervisionCode> supervisionCodes = MapperCustom.builder(supervisionCodeMapper,SupervisionCode.class)
//				.andEq(SupervisionCode::getRefBillId,rcvHeaderId)
//				.andEq(SupervisionCode::getRefBillLineId,rcvLineId)
//				.andIn(SupervisionCode::getUploadFlag,Arrays.asList("0","2"))
//				.findByCriteria();
//		if(ToolKits.isEmpty(supervisionCodes)){
//			throw new ParameterException("未查询到监管码数据");
//		}
//		//查询监管码对应的上传类型和上传客户或者供应商ID
//		List<Integer> uploadTypes = supervisionCodes.stream().filter(o ->ToolKits.isNotEmpty(o.getUploadType())).map(SupervisionCode :: getUploadType).collect(Collectors.toList());
//		List<String> uploadShippIds = supervisionCodes.stream().filter(o ->ToolKits.isNotEmpty(o.getUploadShippId())).map(SupervisionCode :: getUploadShippId).collect(Collectors.toList());
//		if(ToolKits.isEmpty(uploadTypes)){
//			throw new ParameterException("rcvHeaderId ="+rcvHeaderId + ",rcvLineId ="+ rcvLineId  +",对应的监管码上传类型为空");
//		}
//		if(ToolKits.isEmpty(uploadShippIds)){
//			throw new ParameterException("rcvHeaderId ="+rcvHeaderId + ",rcvLineId ="+ rcvLineId  +",对应的监管码上传客户或者供应商为空");
//		}
//		Integer uploadType =uploadTypes.get(0);// 0-入库 1-出库
//		String uploadShippId =uploadShippIds.get(0);
//		String eleccode= "";
//		//根据客户ID或者供应商ID查询对应的企业ID
//		RestMessage<BaseCustomerMst> customerResult = chainRemoteCaller.findCustomerMstOne(uploadShippId);
//		if (customerResult.isSuccess() && customerResult.getData() != null) {
//			if(ToolKits.isNotEmpty(customerResult.getData().getEleccode())){
//				eleccode = customerResult.getData().getEleccode();
//			}
//		}else {
//			RestMessage<BaseSupplierMst> supplierResult = chainRemoteCaller.findOne(uploadShippId);
//			if (supplierResult.isSuccess() && supplierResult.getData() != null) {
//				if(ToolKits.isNotEmpty(supplierResult.getData().getEleccode())){
//					eleccode = supplierResult.getData().getEleccode();
//				}
//			}
//		}
//		if(StringUtils.isEmpty(eleccode)){
//			logger.info("未查询到客户或者供应商ID"+uploadShippId+"对应的码上放心平台ID");
//			throw new ParameterException("未查询到客户或者供应商ID"+uploadShippId+"对应的码上放心平台ID");
//		}
//
//
//		RcvHeaders rcvHeaders =rcvMapper.findById(rcvHeaderId,RcvHeaders.class);
//
//
//		//查询系统配置的参数
//		RestMessage<SysRegistry> restMessage = commonCaller.getRegistryInfo("refEntId",rcvHeaders.getEnterpriseId());
//		if (!restMessage.isSuccess()) {
//			throw new RuntimeException("未查询到 refEntId 的系统配置参数:" + restMessage.getMessage());
//		}
//		SysRegistry data1 = restMessage.getData();
//		String refEntId = data1.getRegValue();
//
//
//		RestMessage<SysRegistry> restMessage3 = commonCaller.getRegistryInfo("serverUrl",rcvHeaders.getEnterpriseId());
//		if (!restMessage3.isSuccess()) {
//			throw new RuntimeException("未查询到 serverUrl 的系统配置参数:" + restMessage.getMessage());
//		}
//		SysRegistry data3 = restMessage3.getData();
//		String serverUrl = data3.getRegValue();
//
//		RestMessage<SysRegistry> restMessage4 = commonCaller.getRegistryInfo("appKey",rcvHeaders.getEnterpriseId());
//		if (!restMessage4.isSuccess()) {
//			throw new RuntimeException("未查询到 appKey 的系统配置参数:" + restMessage.getMessage());
//		}
//		SysRegistry data4 = restMessage4.getData();
//		String appKey = data4.getRegValue();
//
//		RestMessage<SysRegistry> restMessage5 = commonCaller.getRegistryInfo("appSecret",rcvHeaders.getEnterpriseId());
//		if (!restMessage5.isSuccess()) {
//			throw new RuntimeException("未查询到 appSecret 的系统配置参数:" + restMessage.getMessage());
//		}
//		SysRegistry data5 = restMessage5.getData();
//		String appSecret = data5.getRegValue();
//
//
//		Map returnMap = UploadCircubillUtil.uploadCircubillMsc(supervisionCodes, rcvLineId, rcvHeaders.getRcvType(),"", userDTO.getUsername(),refEntId,eleccode,serverUrl,appKey,appSecret,uploadType);
//		Boolean isSuccess = (Boolean) returnMap.get("isSuccess");
//		String message = (String) returnMap.get("message");
//
//		String uploadFlag;
//		if(isSuccess){
//			uploadFlag = "1";
//		}else {
//			uploadFlag = "2";
//		}
//		//更新对应的监管码上传信息
//		rcvMapper.updateUploadFlag(rcvHeaderId,rcvLineId,uploadFlag,message);
//
//		return true;
//	}
	@Override
	public Object uploadCircubillRcvDetails(RqcLinesDTO rqcLinesDTO) {
		if (StringUtils.isEmpty(rqcLinesDTO.getAsnHeaderId())) {
			throw new ParameterException("入库单ID不能为空");
		}

		List<SupervisionCode> supervisionCodeList = rcvMapper.findInSupervisionCode(rqcLinesDTO.getAsnHeaderId());


		if(ToolKits.isEmpty(supervisionCodeList)){
			logger.info("未查询到可上传的监管码数据asnHeaderId=" + rqcLinesDTO.getAsnHeaderId());
			return false;
		}
		if(ToolKits.isNotEmpty(supervisionCodeList) && supervisionCodeList.size()> 0){
			String enterpriseId = supervisionCodeList.get(0).getEnterpriseId();
			//查询系统配置的参数
			RestMessage<SysRegistry> restMessage = commonCaller.getRegistryInfo("refEntId",enterpriseId);
			if (!restMessage.isSuccess()) {
				logger.info("未查询到 refEntId 的系统配置参数:" + restMessage.getMessage());
				return false;
			}
			SysRegistry data1 = restMessage.getData();
			String refEntId = data1.getRegValue();

			RestMessage<SysRegistry> restMessage3 = commonCaller.getRegistryInfo("serverUrl",enterpriseId);
			if (!restMessage3.isSuccess()) {
				logger.info("未查询到 serverUrl 的系统配置参数:" + restMessage.getMessage());
				return false;
			}
			SysRegistry data3 = restMessage3.getData();
			String serverUrl = data3.getRegValue();

			RestMessage<SysRegistry> restMessage4 = commonCaller.getRegistryInfo("appKey",enterpriseId);
			if (!restMessage4.isSuccess()) {
				logger.info("未查询到 appKey 的系统配置参数:" + restMessage.getMessage());
				return false;
			}
			SysRegistry data4 = restMessage4.getData();
			String appKey = data4.getRegValue();

			RestMessage<SysRegistry> restMessage5 = commonCaller.getRegistryInfo("appSecret",enterpriseId);
			if (!restMessage5.isSuccess()) {
				logger.info("未查询到 appSecret 的系统配置参数:" + restMessage.getMessage());
				return false;
			}
			SysRegistry data5 = restMessage5.getData();
			String appSecret = data5.getRegValue();

			//根据上传类型uploadType分组 0-入库 1-出库
			Map<Integer, List<SupervisionCode>> uploadTypeMap = supervisionCodeList.stream().collect(Collectors.groupingBy(SupervisionCode::getUploadType));
			for (Integer uploadType : uploadTypeMap.keySet()) {
				List<SupervisionCode> codeList = uploadTypeMap.get(uploadType);
				//根据asnh的billno分组
				Map<String, List<SupervisionCode>> codeListByBillnoMap = codeList.stream().collect(Collectors.groupingBy(SupervisionCode::getSrcCode));
				for (String billno : codeListByBillnoMap.keySet()) {
					List<SupervisionCode> supervisionCodes = codeListByBillnoMap.get(billno);
					//获取企业ID
					String eleccode =supervisionCodes.get(0).getEntId();

					if(ToolKits.isEmpty(eleccode)){
						logger.info("入库单号billno"+ billno+"对应的eleccode为空");
						continue;
					}

					//入库单需要校验整单上架完成再上传
					//出库单再调用这个接口之前就已经校验是否整单完成了，因此可以直接上传
					logger.info("uploadType =" +uploadType+"billno="+billno);
					if(uploadType == 0) {
						OmsAsnBillH asnBillH = MapperCustom.builder(omsAsnBillHMapper, OmsAsnBillH.class)
								.andEq(OmsAsnBillH::getBillno, billno)
								.findFirst();
						if (ToolKits.isEmpty(asnBillH)) {
							logger.info("入库单号billno"+ billno+"未查询到对应的入库单");
							continue;
						}

						//检查billno对应的所有入库单明细是否全部上架完成，只有整单完成时才能进行上传
						Boolean flag = this.checkIsFinish(asnBillH);
						if(!flag){
							continue;
						}
					}

					List<SupervisionCode> newSupervisionCodes = new ArrayList<>();
					Set<String> parentSupervisionCodes = new HashSet<>();
					//检查对应的上传监管码是否已经上传过，并且已经返回了失败
					supervisionCodes.forEach(x -> {
						if(x.getUploadFlag().equals("2") && ToolKits.isNotEmpty(x.getMessage()) && x.getMessage().contains("有上下级关联码")){
							String[] split = x.getMessage().split("（上级）");
							for (String s : split) {
								String parentSupervisionCode  =  s.substring((s.length()-20));
								//监管码都是20位，并且以8开头
								if(parentSupervisionCode.length() == 20 && parentSupervisionCode.startsWith("8")){
									parentSupervisionCodes.add(parentSupervisionCode);
								}
							}
						}
					});

					if(!parentSupervisionCodes.isEmpty() && parentSupervisionCodes.size()>0){
						supervisionCodes.forEach(x -> {
							if(parentSupervisionCodes.contains(x.getSupervisionCode())){
								newSupervisionCodes.add(x);
							}
						});
					}

					if(!newSupervisionCodes.isEmpty() && newSupervisionCodes.size()>0){
						logger.info("上传的监管码中存在有上下级关联码"+JSON.toJSONString(newSupervisionCodes));
						supervisionCodes.clear();
						supervisionCodes = newSupervisionCodes;
					}

					Map returnMap = UploadCircubillUtil.uploadCircubillMsc(supervisionCodes,billno,"1","1","TaskTimer",refEntId,eleccode,serverUrl,appKey,appSecret,uploadType);
					Boolean isSuccess = (Boolean) returnMap.get("isSuccess");
					String message = (String) returnMap.get("message");

					if(isSuccess){
						//更新对应的监管码状态为 已上传成功
						rcvMapper.updateUploadFlagV3(billno,"1",message);
						logger.info("上传成功!");
					}else {
						//更新对应的监管码状态为 已上传失败，同时更新remark
						rcvMapper.updateUploadFlagV3(billno,"2",message);
						logger.info("上传失败!");
					}
				}
			}
		}

		return true;
	}

	@Override
	public void outBoundUploadCircubill(OutBoundUploadCircubParamVO vo) {
		if(StringUtils.isEmpty(vo.getAcceptEnterpriseId())){
			logger.info("出库单上传时对应的供应商ID或者客户ID为空");
			return;
		}
		List<String> refbilllineids = vo.getRefbilllineids();
		// 0-入库 1-出库
		Integer uploadType= 1; //从出库服务调用过来，默认为出库
		//更新监管码对应的类型为出库，同时保存供应商ID或者客户ID到监管码表中
		rcvMapper.updateSupervisionCodeType(refbilllineids,vo.getAcceptEnterpriseId(),uploadType);
	}

//	@Override
//	public void uploadCircubillTimer() {
//		//查询所有监管码中，未上传且已经保存了客户或者供应商id的数据
//		List<SupervisionCode> supervisionCodeList = rcvMapper.findSupervisionCodes();
//		if(ToolKits.isEmpty(supervisionCodeList)){
//			logger.info("未查询到可上传的监管码数据");
//			return;
//		}
//		if(ToolKits.isNotEmpty(supervisionCodeList) && supervisionCodeList.size()> 0){
//			String enterpriseId = supervisionCodeList.get(0).getEnterpriseId();
//			//查询系统配置的参数
//			RestMessage<SysRegistry> restMessage = commonCaller.getRegistryInfo("refEntId",enterpriseId);
//			if (!restMessage.isSuccess()) {
//				logger.info("未查询到 refEntId 的系统配置参数:" + restMessage.getMessage());
//				return;
//			}
//			SysRegistry data1 = restMessage.getData();
//			String refEntId = data1.getRegValue();
//
//			RestMessage<SysRegistry> restMessage3 = commonCaller.getRegistryInfo("serverUrl",enterpriseId);
//			if (!restMessage3.isSuccess()) {
//				logger.info("未查询到 serverUrl 的系统配置参数:" + restMessage.getMessage());
//				return;
//			}
//			SysRegistry data3 = restMessage3.getData();
//			String serverUrl = data3.getRegValue();
//
//			RestMessage<SysRegistry> restMessage4 = commonCaller.getRegistryInfo("appKey",enterpriseId);
//			if (!restMessage4.isSuccess()) {
//				logger.info("未查询到 appKey 的系统配置参数:" + restMessage.getMessage());
//				return;
//			}
//			SysRegistry data4 = restMessage4.getData();
//			String appKey = data4.getRegValue();
//
//			RestMessage<SysRegistry> restMessage5 = commonCaller.getRegistryInfo("appSecret",enterpriseId);
//			if (!restMessage5.isSuccess()) {
//				logger.info("未查询到 appSecret 的系统配置参数:" + restMessage.getMessage());
//				return;
//			}
//			SysRegistry data5 = restMessage5.getData();
//			String appSecret = data5.getRegValue();
//
//			Map<String, List<SupervisionCode>> map = supervisionCodeList.stream().collect(Collectors.groupingBy(SupervisionCode::getRefBillLineId));
//			for (Map.Entry<String, List<SupervisionCode>> entry : map.entrySet()) {
//				String key = entry.getKey();
//				List<SupervisionCode> value = entry.getValue();
//				Integer uploadType = value.get(0).getUploadType();
//				String uploadShippId = value.get(0).getUploadShippId();
//				String eleccode ="";
//				//根据客户ID或者供应商ID查询对应的企业ID
//				RestMessage<BaseCustomerMst> customerResult = chainRemoteCaller.findCustomerMstOne(uploadShippId);
//				if (customerResult.isSuccess() && customerResult.getData() != null) {
//					if(ToolKits.isNotEmpty(customerResult.getData().getEleccode())){
//						eleccode = customerResult.getData().getEleccode();
//					}
//				}else {
//					RestMessage<BaseSupplierMst> supplierResult = chainRemoteCaller.findOne(uploadShippId);
//					if (supplierResult.isSuccess() && supplierResult.getData() != null) {
//						if(ToolKits.isNotEmpty(supplierResult.getData().getEleccode())){
//							eleccode = supplierResult.getData().getEleccode();
//						}
//					}
//				}
//
//				if(ToolKits.isEmpty(eleccode)){
//					logger.info("rcvLineId"+ key+"对应的eleccode为空");
//					continue;
//				}
//
//				List<SupervisionCode> newSupervisionCodes = new ArrayList<>();
//				Set<String> parentSupervisionCodes = new HashSet<>();
//				//检查对应的上传监管码是否已经上传过，并且已经返回了失败
//				value.forEach(x -> {
//					if(x.getUploadFlag().equals("2") && ToolKits.isNotEmpty(x.getMessage()) && x.getMessage().contains("有上下级关联码")){
//						String[] split = x.getMessage().split("（上级）");
//						for (String s : split) {
//							String parentSupervisionCode  =  s.substring((s.length()-20));
//							//监管码都是20位，并且以8开头
//							if(parentSupervisionCode.length() == 20 && parentSupervisionCode.startsWith("8")){
//								parentSupervisionCodes.add(parentSupervisionCode);
//							}
//						}
//					}
//				});
//
//				if(!parentSupervisionCodes.isEmpty() && parentSupervisionCodes.size()>0){
//					value.forEach(x -> {
//						if(parentSupervisionCodes.contains(x.getSupervisionCode())){
//							newSupervisionCodes.add(x);
//						}
//					});
//				}
//
//				if(!newSupervisionCodes.isEmpty() && newSupervisionCodes.size()>0){
//					logger.info("上传的监管码中存在有上下级关联码"+JSON.toJSONString(newSupervisionCodes));
//					value.clear();
//					value = newSupervisionCodes;
//					key = newSupervisionCodes.get(0).getRefBillLineId();
//				}
//
//
//				Map returnMap = UploadCircubillUtil.uploadCircubillMsc(value,key,"1","1","TaskTimer",refEntId,eleccode,serverUrl,appKey,appSecret,uploadType);
//				Boolean isSuccess = (Boolean) returnMap.get("isSuccess");
//				String message = (String) returnMap.get("message");
//
//				if(isSuccess){
//					//更新对应的监管码状态为 已上传成功
//					rcvMapper.updateUploadFlagV2(key,"1",message);
//					logger.info("上传成功!");
//				}else {
//					//更新对应的监管码状态为 已上传失败，同时更新remark
//					rcvMapper.updateUploadFlagV2(key,"2",message);
//					logger.info("上传失败!");
//				}
//			}
//		}
//
//
//	}

    @Override
    public void uploadCircubillTimer() {
		//查询src_code中所有ent_id不为空的数据，ent_id是在另外一个定时任务saveCusEntIdTimer中保存进去的，是从码上放心平台获取的客户或者供应商的企业ID
		//一次上传10条，多了可能会影响性能
		List<String>  srcCodes= rcvMapper.findUnUploadSrcCode();
		if(ToolKits.isEmpty(srcCodes)){
			logger.info("未查询到可上传的监管码数据");
			return;
		}
        //以srcCode的维度查询监管码进行上传
		logger.info("srcCodes="+JSON.toJSONString(srcCodes));
        List<SupervisionCode> supervisionCodeList = rcvMapper.findSupervisionCodes(srcCodes);
        if(ToolKits.isEmpty(supervisionCodeList)){
            logger.info("未查询到可上传的监管码数据");
            return;
        }
        if(ToolKits.isNotEmpty(supervisionCodeList) && supervisionCodeList.size()> 0){
            String enterpriseId = supervisionCodeList.get(0).getEnterpriseId();
            //查询系统配置的参数
            RestMessage<SysRegistry> restMessage = commonCaller.getRegistryInfo("refEntId",enterpriseId);
            if (!restMessage.isSuccess()) {
                logger.info("未查询到 refEntId 的系统配置参数:" + restMessage.getMessage());
                return;
            }
            SysRegistry data1 = restMessage.getData();
            String refEntId = data1.getRegValue();

            RestMessage<SysRegistry> restMessage3 = commonCaller.getRegistryInfo("serverUrl",enterpriseId);
            if (!restMessage3.isSuccess()) {
                logger.info("未查询到 serverUrl 的系统配置参数:" + restMessage.getMessage());
                return;
            }
            SysRegistry data3 = restMessage3.getData();
            String serverUrl = data3.getRegValue();

            RestMessage<SysRegistry> restMessage4 = commonCaller.getRegistryInfo("appKey",enterpriseId);
            if (!restMessage4.isSuccess()) {
                logger.info("未查询到 appKey 的系统配置参数:" + restMessage.getMessage());
                return;
            }
            SysRegistry data4 = restMessage4.getData();
            String appKey = data4.getRegValue();

            RestMessage<SysRegistry> restMessage5 = commonCaller.getRegistryInfo("appSecret",enterpriseId);
            if (!restMessage5.isSuccess()) {
                logger.info("未查询到 appSecret 的系统配置参数:" + restMessage.getMessage());
                return;
            }
            SysRegistry data5 = restMessage5.getData();
            String appSecret = data5.getRegValue();

            //根据上传类型uploadType分组 0-入库 1-出库
            Map<Integer, List<SupervisionCode>> uploadTypeMap = supervisionCodeList.stream().collect(Collectors.groupingBy(SupervisionCode::getUploadType));
            for (Integer uploadType : uploadTypeMap.keySet()) {
				List<SupervisionCode> codeList = uploadTypeMap.get(uploadType);
				//根据srcCode分组,因为监管码平台是以billno为维度上传的，同一个billno只能上传一次
				Map<String, List<SupervisionCode>> codeListByBillnoMap = codeList.stream().collect(Collectors.groupingBy(SupervisionCode::getSrcCode));
				for (String billno : codeListByBillnoMap.keySet()) {

					List<SupervisionCode> supervisionCodes = codeListByBillnoMap.get(billno);
					String eleccode = supervisionCodes.get(0).getEntId();

					//入库单需要校验整单上架完成再上传
					//出库单再调用这个接口之前就已经校验是否整单完成了，因此可以直接上传
					logger.info("uploadType =" +uploadType+"billno="+billno);
					if(uploadType == 0) {
						OmsAsnBillH asnBillH = MapperCustom.builder(omsAsnBillHMapper, OmsAsnBillH.class)
								.andEq(OmsAsnBillH::getBillno, billno)
								.findFirst();
						if (ToolKits.isEmpty(asnBillH)) {
							logger.info("入库单号billno"+ billno+"未查询到对应的入库单");
							continue;
						}

						//检查billno对应的所有入库单明细是否全部上架完成，只有整单完成时才能进行上传
						Boolean flag = this.checkIsFinish(asnBillH);
						if(!flag){
							continue;
						}
					}

					List<SupervisionCode> newSupervisionCodes = new ArrayList<>();
					Set<String> parentSupervisionCodes = new HashSet<>();
					//检查对应的上传监管码是否已经上传过，并且已经返回了失败
					supervisionCodes.forEach(x -> {
						if(x.getUploadFlag().equals("2") && ToolKits.isNotEmpty(x.getMessage()) && x.getMessage().contains("有上下级关联码")){
							String[] split = x.getMessage().split("（上级）");
							for (String s : split) {
								String parentSupervisionCode  =  s.substring((s.length()-20));
								//监管码都是20位，并且以8开头
								if(parentSupervisionCode.length() == 20 && parentSupervisionCode.startsWith("8")){
									parentSupervisionCodes.add(parentSupervisionCode);
								}
							}
						}
					});

					if(!parentSupervisionCodes.isEmpty() && parentSupervisionCodes.size()>0){
						supervisionCodes.forEach(x -> {
							if(parentSupervisionCodes.contains(x.getSupervisionCode())){
								newSupervisionCodes.add(x);
							}
						});
					}

					if(!newSupervisionCodes.isEmpty() && newSupervisionCodes.size()>0){
						logger.info("上传的监管码中存在有上下级关联码"+JSON.toJSONString(newSupervisionCodes));
						supervisionCodes.clear();
						supervisionCodes = newSupervisionCodes;
					}

					Map returnMap = UploadCircubillUtil.uploadCircubillMsc(supervisionCodes,billno,"1","1","TaskTimer",refEntId,eleccode,serverUrl,appKey,appSecret,uploadType);
					Boolean isSuccess = (Boolean) returnMap.get("isSuccess");
					String message = (String) returnMap.get("message");

					if(isSuccess){
						//更新对应的监管码状态为 已上传成功
						rcvMapper.updateUploadFlagV3(billno,"1",message);
						logger.info("上传成功!");
					}else {
						//更新对应的监管码状态为 已上传失败，同时更新remark
						rcvMapper.updateUploadFlagV3(billno,"2",message);
						logger.info("上传失败!");
					}
				}
            }
        }


    }

    private Boolean checkIsFinish(OmsAsnBillH asnBillH) {
        Boolean flag = true;
        Criteria crt = Criteria.forClass(OmsAsnBillD.class);
        crt.setRestriction(Restrictions.eq("billid", asnBillH.getBillid()));
        List<OmsAsnBillD> asnBillDList = omsAsnBillDMapper.findByCriteria(crt);
        for (OmsAsnBillD omsAsnBillD : asnBillDList) {
            //查询入库单明细ID是否存在对应数量的上架单
			BigDecimal qty = rcvMapper.findFinishDetalQty(omsAsnBillD.getLineid());
			if(omsAsnBillD.getItemQty().compareTo(qty) != 0 ){
				//任意一条明细没有对应的上架单则返回false
				logger.info("入库单lineid = "+omsAsnBillD.getLineid()+"对应的入库单明细数量="+ omsAsnBillD.getItemQty() +"和对应的上架数量="+qty+"不相等");
				return false;
			}

        }

        return flag;
    }

	@Override
	public void saveSupervisionCodeSmallTimer() {
		//查询所有监管码中，未保存子码的数据，只查保存类型是入库的，每次处理20条
		List<SupervisionCode> supervisionCodeList = rcvMapper.findUnDownLoadSupervisionCode();
		if(ToolKits.isEmpty(supervisionCodeList)){
			logger.info("未查询到需要保存子码的监管码数据");
			return;
		}
        String message="保存小码成功";
        Integer downFlag = 1;
        List<String>  supervisionCodes = new ArrayList<>();
		List<RelationCodeResultDTO> failDtos =new ArrayList<>();
		try{
            List<SupervisionCodeSmall> codeSmallList = new ArrayList<>();
            //大包装或者中包装监管码集合
            List<SupervisionCode> bigCodeList = supervisionCodeList.stream().filter(o ->o.getPackLevel().equals("0") || o.getPackLevel().equals("1")).collect(Collectors.toList());
            List<RelationCodeResultVO> resultVOS =new ArrayList<>();
            if(ToolKits.isNotEmpty(bigCodeList) && bigCodeList.size()>0){
                for (SupervisionCode supervisionCode : bigCodeList) {
                    RelationCodeResultVO resultVO =new RelationCodeResultVO();
                    resultVO.setEnterpriseId(supervisionCode.getEnterpriseId());
                    resultVO.setPackLevel(Integer.valueOf(supervisionCode.getPackLevel()));
                    resultVO.setSupervisionCode(supervisionCode.getSupervisionCode());
                    resultVOS.add(resultVO);
                }
                //组装参数查询所有大包装或者中包装对应的子码
                logger.info("resultVOS = "+ JSON.toJSONString(resultVOS));
                RestMessage<List<RelationCodeResultDTO>> listRestMessage = outboundCaller.relationSupervisionCode(resultVOS);
                if (listRestMessage.isSuccess() && listRestMessage.getData() != null) {
                    if(ToolKits.isNotEmpty(listRestMessage.getData()) && listRestMessage.getData().size()>0){
                        List<RelationCodeResultDTO> resultDTOS = listRestMessage.getData();
						//过滤出所有查询成功的监管码数据
						List<RelationCodeResultDTO> successDtos = resultDTOS.stream().filter(t -> t.getFlag() == 1).collect(Collectors.toList());
						if(successDtos.size() > 0){
							for (RelationCodeResultDTO resultDTO : successDtos) {
								String supervisionCode = resultDTO.getSupervisionCode();
								SupervisionCode bigSupervisionCode= bigCodeList.stream().filter(o ->o.getSupervisionCode().equals(supervisionCode)).findFirst().orElse(null);
								List<RelationCodeResult> relationCodeResults = resultDTO.getRelationCodeResults();
								//查询对应的批次ID
								RelationCodeResult relationCodeResultBatch = relationCodeResults.get(0);
								SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
								String productionDateString = formatter.format(relationCodeResultBatch.getProduceDate());
								String expiredDateString = formatter.format(relationCodeResultBatch.getExpireDate());
								String batchId =rcvMapper.findBatchId(bigSupervisionCode.getItemId(),relationCodeResultBatch.getBatchNo(),productionDateString,expiredDateString);
								if(ToolKits.isEmpty(batchId)){
									String downMessage = "未查询到该条监管码对应的批次ID! 上级监管码="+supervisionCode+",批号="+relationCodeResultBatch.getBatchNo()+",商品ID="+bigSupervisionCode.getItemId()+",生产日期="+ productionDateString +",有效期至="+expiredDateString;
									supervisionCodes.add(supervisionCode);
									throw new BizException(downMessage);
								}
								for (RelationCodeResult relationCodeResult : relationCodeResults) {
									SupervisionCodeSmall codeSmall = new SupervisionCodeSmall();
									codeSmall.setEnterpriseId(bigSupervisionCode.getEnterpriseId());
									codeSmall.setWarehouseCode(bigSupervisionCode.getWarehouseCode());
									codeSmall.setSupervisionCode(relationCodeResult.getCode());
									codeSmall.setItemId(bigSupervisionCode.getItemId());
									codeSmall.setItemCode(bigSupervisionCode.getItemCode());
									codeSmall.setItemName(bigSupervisionCode.getItemName());
									codeSmall.setStatus("0");
									codeSmall.setManufacturerLotNum(relationCodeResult.getBatchNo());
									codeSmall.setProductionDate(relationCodeResult.getProduceDate());
									codeSmall.setExpiredDate(relationCodeResult.getExpireDate());
									codeSmall.setPackSize(bigSupervisionCode.getPackSize());
									codeSmall.setCodeType(bigSupervisionCode.getCodeType());
									codeSmall.setPackLevel(bigSupervisionCode.getPackLevel());
									codeSmall.setParentCode(relationCodeResult.getParentCode());
									codeSmall.setGmtCreate(new Date());
									codeSmall.setBatchId(batchId);
									codeSmallList.add(codeSmall);
								}
							}
						}

						//过滤出所有查询失败的监管码数据
						failDtos = resultDTOS.stream().filter(t -> t.getFlag() == 2).collect(Collectors.toList());
                    }
                }else {
					supervisionCodes = supervisionCodeList.stream().map(SupervisionCode::getSupervisionCode).collect(Collectors.toList());
					throw new BizException(listRestMessage.getMessage());
				}
            }

            //小包装监管码集合
            List<SupervisionCode> smallCodeList = supervisionCodeList.stream().filter(o ->o.getPackLevel().equals("2")).collect(Collectors.toList());
            if(ToolKits.isNotEmpty(smallCodeList) && smallCodeList.size()>0){
                List<String> rcvLineIds = smallCodeList.stream().map(SupervisionCode::getRefBillLineId).distinct().collect(Collectors.toList());
                List<RcvLines> rcvLinesList = MapperCustom.builder(rcvLinesMapper,RcvLines.class)
                        .andIn(RcvLines::getRcvLineId,rcvLineIds).findByCriteria();

                for (SupervisionCode supervisionCode : smallCodeList) {
                    RcvLines rcvLines = rcvLinesList.stream().filter(o -> o.getRcvLineId().equals(supervisionCode.getRefBillLineId())).findFirst().orElse(null);
                    if(ToolKits.isEmpty(rcvLines)){
                        supervisionCodes.add(supervisionCode.getSupervisionCode());
                        throw new BizException("未查询到该条监管码对应的收货单明细数据!"+supervisionCode);
                    }
                    SupervisionCodeSmall codeSmall = new SupervisionCodeSmall();
                    codeSmall.setEnterpriseId(supervisionCode.getEnterpriseId());
                    codeSmall.setWarehouseCode(supervisionCode.getWarehouseCode());
                    codeSmall.setSupervisionCode(supervisionCode.getSupervisionCode());
                    codeSmall.setItemId(supervisionCode.getItemId());
                    codeSmall.setItemCode(supervisionCode.getItemCode());
                    codeSmall.setItemName(supervisionCode.getItemName());
                    codeSmall.setStatus("0");
                    codeSmall.setManufacturerLotNum(rcvLines.getManufacturerLotNum());
                    codeSmall.setProductionDate(rcvLines.getBatchProductionDate());
                    codeSmall.setExpiredDate(rcvLines.getBatchExpiredDate());
                    codeSmall.setPackSize(supervisionCode.getPackSize());
                    codeSmall.setCodeType(supervisionCode.getCodeType());
                    codeSmall.setPackLevel(supervisionCode.getPackLevel());
                    codeSmall.setParentCode(supervisionCode.getSupervisionCode());
                    codeSmall.setGmtCreate(new Date());
                    //查询对应的批次ID
                    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String productionDateString = formatter.format(codeSmall.getProductionDate());
                    String expiredDateString = formatter.format(codeSmall.getExpiredDate());
                    String batchId =rcvMapper.findBatchId(codeSmall.getItemId(),codeSmall.getManufacturerLotNum(),productionDateString,expiredDateString);
                    if(ToolKits.isEmpty(batchId)){
                        supervisionCodes.add(supervisionCode.getSupervisionCode());
                        throw new BizException("未查询到该条监管码对应的批次ID! 监管码="+codeSmall.getSupervisionCode()+",商品ID="+codeSmall.getItemId()+",批号="+codeSmall.getManufacturerLotNum()+",生产日期="+ productionDateString +",有效期至="+ expiredDateString);
                    }
                    codeSmall.setBatchId(batchId);
                    codeSmallList.add(codeSmall);
                }
            }

            //保存小码同时更新监管码的保存状态
            if(ToolKits.isNotEmpty(codeSmallList) && codeSmallList.size() >0){
                //分批保存，一次保存500条数据
                if(codeSmallList.size() > 500 ){
                    List<List<SupervisionCodeSmall>> listArray = new ArrayList<>();
                    for (int i = 0; i < codeSmallList.size(); i+=500) {
                        int toIndex = i + 500>codeSmallList.size()?codeSmallList.size():i+500;
                        listArray.add(codeSmallList.subList(i, toIndex));
                    }
                    for (List<SupervisionCodeSmall> codeSmallListbatch : listArray) {
                        codeSmallMapper.saveBatch(codeSmallListbatch);
                    }

                }else {
                    codeSmallMapper.saveBatch(codeSmallList);
                }
            }

            if(failDtos.size()>0){
            	//存在查询失败的数据
				for (RelationCodeResultDTO failDto : failDtos) {
					rcvMapper.updateDownFlag(failDto.getMessage(),2, Collections.singletonList(failDto.getSupervisionCode()));
				}
				//排除查询失败的数据
				List<String> failCodes = failDtos.stream().map(RelationCodeResultDTO :: getSupervisionCode).collect(Collectors.toList());
				supervisionCodes = supervisionCodeList.stream().map(SupervisionCode::getSupervisionCode).filter(o ->!failCodes.contains(o)).collect(Collectors.toList());
			}else {
				supervisionCodes = supervisionCodeList.stream().map(SupervisionCode::getSupervisionCode).collect(Collectors.toList());
			}

        }catch (Exception e) {

		    if(supervisionCodes.size() == 0){
                supervisionCodes = supervisionCodeList.stream().map(SupervisionCode::getSupervisionCode).collect(Collectors.toList());
            }
            downFlag = 2;
            e.printStackTrace();
            logger.info("保存小码报错catch:" + e.getMessage());
            if(e.getMessage().length() >2000){
                message = e.getMessage().substring(1,2000);
            }else {
                message = e.getMessage();
            }
            message = "保存小码失败" + e.getMessage();

        }finally {
			if(supervisionCodes.size() > 0){
				rcvMapper.updateDownFlag(message,downFlag,supervisionCodes);
			}
        }

	}

	@Override
	@Transactional
	public void toHisSupervisionCodeSmallTimer() {
		//查询所有监管码子码表中，保存时间超过15天的数据转历史
		List<SupervisionCodeSmall> supervisionCodeSmallList = rcvMapper.findUnToHisSupervisionCode();
		if(ToolKits.isEmpty(supervisionCodeSmallList)){
			logger.info("未查询到超过15天的监管码子码数据");
			return;
		}
		Set<String> targetIds = new HashSet<>();

		//如果是大包装或者中包装，则查询监管码表中是否做过出库
		List<SupervisionCodeSmall> bigCodeList = supervisionCodeSmallList.stream().filter(o -> o.getPackLevel().equals("0") || o.getPackLevel().equals("1")).collect(Collectors.toList());
		if(ToolKits.isNotEmpty(bigCodeList) && bigCodeList.size()> 0){
			List<String> bigSupervisionCodes = bigCodeList.stream().map(SupervisionCodeSmall::getParentCode).distinct().collect(Collectors.toList());
			List<SupervisionCode> supervisionCodes = MapperCustom.builder(supervisionCodeMapper,SupervisionCode.class)
					.andIn(SupervisionCode::getSupervisionCode,bigSupervisionCodes)
					.andEq(SupervisionCode::getSaveType,2)
					.findByCriteria();

			//如果大包装能在监管码表中查询到出库记录，则大包装对应的所有子码全部转历史
			if(ToolKits.isNotEmpty(supervisionCodes) && supervisionCodes.size()> 0){
				List<String> targetCodes = supervisionCodes.stream().map(SupervisionCode::getSupervisionCode).distinct().collect(Collectors.toList());
				//从数据库查询所有的大包装或者中包装对应的子码数据
				List<SupervisionCodeSmall> targetCodeSmalls = MapperCustom.builder(codeSmallMapper,SupervisionCodeSmall.class)
						.andIn(SupervisionCodeSmall::getParentCode,targetCodes)
						.andIn(SupervisionCodeSmall::getPackLevel,Arrays.asList("0", "1"))
						.findByCriteria();
				Set<String> targetIds1 = targetCodeSmalls.stream().map(SupervisionCodeSmall::getId).collect(Collectors.toSet());
				targetIds.addAll(targetIds1);

				//过滤出剩余的没有在监管码表中查询到出库记录的数据
				List<String> unExistBigCodes = bigSupervisionCodes.stream().filter(o -> !targetCodes.contains(o)).collect(Collectors.toList());
				if(ToolKits.isNotEmpty(unExistBigCodes) && unExistBigCodes.size()> 0){
					//大包装对应的所有的子码集合
					List<SupervisionCodeSmall> allSupervisionCodeSmalls = MapperCustom.builder(codeSmallMapper,SupervisionCodeSmall.class)
							.andIn(SupervisionCodeSmall::getParentCode,unExistBigCodes)
							.andIn(SupervisionCodeSmall::getPackLevel,Arrays.asList("0", "1"))
							.findByCriteria();

					List<String> allCodeSmalls= allSupervisionCodeSmalls.stream().map(SupervisionCodeSmall::getSupervisionCode).distinct().collect(Collectors.toList());

					//根据子码去查询是否在监管码表进行过出库
					List<SupervisionCode> allSupervisionCodes = MapperCustom.builder(supervisionCodeMapper,SupervisionCode.class)
							.andIn(SupervisionCode::getSupervisionCode,allCodeSmalls)
							.andEq(SupervisionCode::getSaveType,2)
							.findByCriteria();

					//如果子码能查询到记录则子码进行转历史
					if(ToolKits.isNotEmpty(allSupervisionCodes) && allSupervisionCodes.size()> 0){
						List<String> smallTargetCodes = allSupervisionCodes.stream().map(SupervisionCode::getSupervisionCode).collect(Collectors.toList());
						Set<String> targetIds2 = allSupervisionCodeSmalls.stream().filter(o -> smallTargetCodes.contains(o.getSupervisionCode())).map(SupervisionCodeSmall::getId).collect(Collectors.toSet());
						targetIds.addAll(targetIds2);
					}
				}
			}else {
				//如果大包装查询不到记录，则查询所有大包装对应的子码是否存在出库记录
				//从数据库查询大包装对应的所有的子码集合
				List<SupervisionCodeSmall> allSupervisionCodeSmalls = MapperCustom.builder(codeSmallMapper,SupervisionCodeSmall.class)
						.andIn(SupervisionCodeSmall::getParentCode,bigSupervisionCodes)
						.andIn(SupervisionCodeSmall::getPackLevel,Arrays.asList("0", "1"))
						.findByCriteria();

				List<String> allCodeSmalls= allSupervisionCodeSmalls.stream().map(SupervisionCodeSmall::getSupervisionCode).distinct().collect(Collectors.toList());

				//根据子码去查询是否在监管码表进行过出库
				List<SupervisionCode> allSupervisionCodes = MapperCustom.builder(supervisionCodeMapper,SupervisionCode.class)
						.andIn(SupervisionCode::getSupervisionCode,allCodeSmalls)
						.andEq(SupervisionCode::getSaveType,2)
						.findByCriteria();

				//如果子码能查询到记录则子码进行转历史
				if(ToolKits.isNotEmpty(allSupervisionCodes) && allSupervisionCodes.size()> 0){
					List<String> smallTargetCodes = allSupervisionCodes.stream().map(SupervisionCode::getSupervisionCode).distinct().collect(Collectors.toList());
					Set<String> targetIds3 = allSupervisionCodeSmalls.stream().filter(o -> smallTargetCodes.contains(o.getSupervisionCode())).map(SupervisionCodeSmall::getId).collect(Collectors.toSet());
					targetIds.addAll(targetIds3);
				}

			}
		}

		//如果是小包装，则查询监管码表中是否做过出库
		List<SupervisionCodeSmall> smallCodeList = supervisionCodeSmallList.stream().filter(o -> o.getPackLevel().equals("2") || o.getPackLevel().equals("1")).collect(Collectors.toList());
		if(ToolKits.isNotEmpty(smallCodeList) && smallCodeList.size()> 0){

			List<String> needCheckCodes = smallCodeList.stream().map(SupervisionCodeSmall::getSupervisionCode).distinct().collect(Collectors.toList());
			//根据子码去查询是否在监管码表进行过出库
			List<SupervisionCode> supervisionCodes = MapperCustom.builder(supervisionCodeMapper,SupervisionCode.class)
					.andIn(SupervisionCode::getSupervisionCode,needCheckCodes)
					.andEq(SupervisionCode::getSaveType,2)
					.findByCriteria();


			if(ToolKits.isNotEmpty(supervisionCodes) && supervisionCodes.size()> 0){
				List<String> smallTargetCodes = supervisionCodes.stream().map(SupervisionCode::getSupervisionCode).distinct().collect(Collectors.toList());
				Set<String> targetIds4 = smallCodeList.stream().filter(o -> smallTargetCodes.contains(o.getSupervisionCode())).map(SupervisionCodeSmall::getId).collect(Collectors.toSet());
				targetIds.addAll(targetIds4);
			}
		}

		//进行转历史处理
		if(ToolKits.isNotEmpty(targetIds) && targetIds.size()>0 ){
			//查询出对应的子码数据
			List<SupervisionCodeSmall> codeSmalls = codeSmallMapper.findByIds(SupervisionCodeSmall.class, targetIds.toArray(), null);

			//删除所有的监管码子码数据
			codeSmallMapper.deleteByIds(targetIds.toArray(),SupervisionCodeSmall.class);

			//保存监管码子码数据到历史表中
			List<SupervisionCodeSmallHis>  supervisionCodeSmallHis = new ArrayList<>();
			for (SupervisionCodeSmall targetCodeSmall : codeSmalls) {
				SupervisionCodeSmallHis codeSmallHis =new SupervisionCodeSmallHis();
				BeanUtil.copyProperties(targetCodeSmall, codeSmallHis);
				supervisionCodeSmallHis.add(codeSmallHis);
			}
			codeSmallHisMapper.saveBatch(supervisionCodeSmallHis);
		}
	}

	@Override
	@Transactional
	public void saveCusEntIdTimer() {
		//查询eleccode为空的客户数据
		List<BaseCustomerMst> customerMsts = rcvMapper.findUnSaveCusEntId();
		List<String> customerList = new ArrayList<>();
		List<String> supplierList = new ArrayList<>();
		//查询保存了uploadShippid，但是endId为空的数据，并且uploadType=1(出库订单对应客户表)时，关联查询客户表的eleccode不能为空的数据，以srcCode的维度分组
		List<String> srcCodeForCustomer = rcvMapper.findUnSaveEntIdSrcCodeForCustomer();
		if(ToolKits.isNotEmpty(srcCodeForCustomer) && srcCodeForCustomer.size() > 0){
			logger.info("srcCodeForCustomer="+ JSON.toJSONString(srcCodeForCustomer));
			customerList = rcvMapper.findUnSaveEntIdSupCode(srcCodeForCustomer);
		}

		//查询保存了uploadShippid，但是endId为空的数据，并且uploadType=0时(入库订单对应供应商表)，关联查询供应商表的eleccode不能为空的数据，以srcCode的维度分组
		List<String> srcCodeForSupplier = rcvMapper.findUnSaveEntIdSrcCodeForSupplier();
		if(ToolKits.isNotEmpty(srcCodeForSupplier) && srcCodeForSupplier.size() > 0){
			logger.info("srcCodeForSupplier="+ JSON.toJSONString(srcCodeForSupplier));
			supplierList = rcvMapper.findUnSaveEntIdSupCode(srcCodeForSupplier);
		}


		if(ToolKits.isEmpty(customerMsts) && ToolKits.isEmpty(customerList)  && ToolKits.isEmpty(supplierList)){
			logger.info("未查询到客户eleccode为空或者监管码表endId为空的的客户数据");
			return;
		}

		if(customerMsts.size() > 0){
			String enterpriseid = customerMsts.get(0).getEnterpriseId();
			//查询系统配置的参数
			RestMessage<SysRegistry> restMessage = commonCaller.getRegistryInfo("refEntId",enterpriseid);
			if (!restMessage.isSuccess()) {
				throw new RuntimeException("未查询到 refEntId 的系统配置参数:" + restMessage.getMessage());
			}
			SysRegistry data1 = restMessage.getData();
			String refEntId = data1.getRegValue();

			RestMessage<SysRegistry> restMessage3 = commonCaller.getRegistryInfo("serverUrl",enterpriseid);
			if (!restMessage3.isSuccess()) {
				throw new RuntimeException("未查询到 serverUrl 的系统配置参数:" + restMessage.getMessage());
			}
			SysRegistry data3 = restMessage3.getData();
			String serverUrl = data3.getRegValue();

			RestMessage<SysRegistry> restMessage4 = commonCaller.getRegistryInfo("appKey",enterpriseid);
			if (!restMessage4.isSuccess()) {
				throw new RuntimeException("未查询到 appKey 的系统配置参数:" + restMessage.getMessage());
			}
			SysRegistry data4 = restMessage4.getData();
			String appKey = data4.getRegValue();

			RestMessage<SysRegistry> restMessage5 = commonCaller.getRegistryInfo("appSecret",enterpriseid);
			if (!restMessage5.isSuccess()) {
				throw new RuntimeException("未查询到 appSecret 的系统配置参数:" + restMessage.getMessage());
			}
			SysRegistry data5 = restMessage5.getData();
			String appSecret = data5.getRegValue();

			for (BaseCustomerMst customerMst : customerMsts) {
				String entId =  taobaoUtil.getentinfoV2(customerMst.getCustomerName(),refEntId,serverUrl,appKey,appSecret);
				if(ToolKits.isNotEmpty(entId)){
					rcvMapper.saveCusEntId(entId,customerMst.getCustomerId());
				}
			}
		}

		if(customerList.size()> 0 ){
			logger.info("customerList="+ JSON.toJSONString(customerList));
			List<BaseCustomerMst> customerMstList = rcvMapper.findCustomerMstByIds(customerList);
			if(customerMstList.size() > 0){
				//更新eleccode到监管码表中的entId中
				for (BaseCustomerMst customerMst : customerMstList) {
					rcvMapper.saveEntIdSupCode(customerMst.getEleccode(),customerMst.getCustomerId(),1,srcCodeForCustomer);
				}
			}
		}

		if(supplierList.size()> 0 ){
			logger.info("supplierList="+ JSON.toJSONString(supplierList));
			List<BaseSupplierMst> supplierMstList = rcvMapper.findSupplierMstByIds(supplierList);
			if(supplierMstList.size() > 0){
				//更新eleccode到监管码表中的entId中
				for (BaseSupplierMst supplierMst : supplierMstList) {
					rcvMapper.saveEntIdSupCode(supplierMst.getEleccode(),supplierMst.getSupplierId(),0,srcCodeForSupplier);
				}
			}
		}
	}
}
