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

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.prolog.cs.biz.inbound.constant.BizConstant;
import com.prolog.cs.biz.inbound.dao.rcv.RcvHeadersMapper;
import com.prolog.cs.biz.inbound.dao.rcv.RcvHeadersProfilesMapper;
import com.prolog.cs.biz.inbound.dao.rcv.RcvLinesProfilesMapper;
import com.prolog.cs.biz.inbound.dao.rqc.WmsInRqcSampleMapper;
import com.prolog.cs.biz.inbound.dao.task.TaskQcDetailMapper;
import com.prolog.cs.biz.inbound.dto.CargoChangeIn;
import com.prolog.cs.biz.inbound.dto.CargoChangeInDetails;
import com.prolog.cs.biz.inbound.dto.rqc.RqcLinesDTO;
import com.prolog.cs.biz.inbound.dto.rqc.RqcStDTO;
import com.prolog.cs.biz.inbound.dto.rqc.WmsInRqcSampleDTO;
import com.prolog.cs.biz.inbound.dto.rqc.WmsInRqcStRuleDTO;
import com.prolog.cs.biz.inbound.model.rcv.RcvHeaders;
import com.prolog.cs.biz.inbound.model.rcv.RcvHeadersProfiles;
import com.prolog.cs.biz.inbound.model.rcv.RcvLinesProfiles;
import com.prolog.cs.biz.inbound.model.rqc.WmsInRqcSample;
import com.prolog.cs.biz.inbound.model.task.TaskQcDetail;
import com.prolog.cs.biz.inbound.service.impl.processor.Helper.TaskHelper;
import com.prolog.cs.biz.inbound.service.rqc.RqcStService;
import com.prolog.cs.biz.inbound.service.rqc.WmsInRqcSampleService;
import com.prolog.cs.biz.inbound.service.rqc.WmsInRqcStRuleService;
import com.prolog.cs.biz.inbound.utils.ObjectUtils;
import com.prolog.cs.biz.inbound.utils.UserUtils;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.beans.BeanUtils;
import com.prolog.framework.bz.core.model.PageParam;
import com.prolog.framework.bz.core.service.BaseServiceImpl;
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.utils.AssertUtils;
import com.prolog.framework.utils.MapUtils;
import com.prolog.framework.utils.StringUtils;
import io.swagger.annotations.ApiModelProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.util.*;
import java.util.stream.Collectors;

@Service
public class WmsInRqcSampleServiceImpl extends BaseServiceImpl<WmsInRqcSample> implements WmsInRqcSampleService {

	@Resource
	private WmsInRqcSampleMapper mapper;

	@Resource
	private UserUtils userUtils;

	@Resource
	private Validator validator;

	@Resource
	private TaskQcDetailMapper taskQcDetailMapper;

	@Resource
	private RcvHeadersProfilesMapper rcvProfilemapper;

	@Resource
	private RcvLinesProfilesMapper rcvLinesProfilesMapper;

	@Resource
	private RcvHeadersMapper rcvHeadersMapper;

	@Resource
	private RqcStService rqcStService;

	@Resource
	private WmsInRqcStRuleService rqcStRuleService;

	@Resource
	private TaskHelper taskHelper;

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

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

	@Override
	public List<WmsInRqcSampleDTO> getPreList(List<RqcLinesDTO> rqcLinesDTOList) {
		// 获取待抽检的列表
		AssertUtils.isNotEmpty(rqcLinesDTOList, "抽检集合为空!");
		boolean withCargoOwner = true;
		return this.getPreSample(rqcLinesDTOList, withCargoOwner, null);
	}

	private List<WmsInRqcSampleDTO> getPreSample(List<RqcLinesDTO> rqcLinesDTOList, boolean withCargoOwner,
			CargoChangeIn cargoChangeIn) {
		// TODO 调用策略服务获取抽检策略
		List<WmsInRqcSampleDTO> resultList = new ArrayList<>();
		String rcvHeaderId = rqcLinesDTOList.get(0).getRcvHeaderId();
		// 获取货主名称加code
		RcvHeadersProfiles hp = null;
		if (withCargoOwner) {
			hp = rcvProfilemapper.findById(rcvHeaderId, RcvHeadersProfiles.class);
		}
		RqcLinesDTO rqcLinesDTO2 = rqcLinesDTOList.get(0);
		String mtlOwnerId = rqcLinesDTO2.getMtlOwnerId();
		String warehouseId2 = rqcLinesDTO2.getWarehouseId();
		String rcvType = rqcLinesDTO2.getRcvType();

		// 0否1是
		String businessControlValue = taskHelper.getBusinessControlValue(warehouseId2, mtlOwnerId, "0",
				BizConstant.ENABLE_USE_SAMPLE_STRATEGY);

		// 获取通用策略
		RqcStDTO st = new RqcStDTO();
		st.setMtlOwnerId(mtlOwnerId);
		st.setWarehouseId(warehouseId2);
		st.setStatus("1");
		st.setStType("0");
		st.setBillType(rcvType);
		List<RqcStDTO> RqcStDTOList = rqcStService.findAll(st);

		int row = 0;
		for (RqcLinesDTO rqcLinesDTO : rqcLinesDTOList) {
			row++;
			WmsInRqcSampleDTO sampleDTO = new WmsInRqcSampleDTO();
			if (enableUseSampleStrategy || businessControlValue.equals("1")) {
				String itemId = rqcLinesDTO.getItemId();
				String categoryId = rqcLinesDTO.getCategoryId();
				st.setMtlOwnerId(mtlOwnerId);
				st.setWarehouseId(warehouseId2);
				st.setStatus("1");
				st.setStType("1");
				st.setItemId(itemId);
				st.setBillType(rcvType);
				List<RqcStDTO> findAll = rqcStService.findAll(st);
				if (ObjectUtils.isNull(findAll)) {
					st.setItemCategoryCode(categoryId);
					findAll = rqcStService.findAll(st);
				}
				if (ObjectUtils.isNull(findAll)) {
					findAll = RqcStDTOList;
				}
				if (!ObjectUtils.isNull(findAll)) {
					RqcStDTO rqcStDTO = findAll.get(0);
					if (rqcStDTO == null) {
						findAll = null;
					}
					String rqcStId = rqcStDTO.getRqcStId();
					List<WmsInRqcStRuleDTO> ruleList = rqcStRuleService.findByRelatedId(rqcStId);
					AssertUtils.isNotEmpty(ruleList, String.format("第[%d]行,策略对应的规则为空,请检查!", row));
					excuteSampleMatchRule(ruleList, sampleDTO, rqcLinesDTO, resultList, hp);
				}

				if (ObjectUtils.isNull(findAll)) {
					excuteDefaultSample(sampleDTO, rqcLinesDTO, resultList, hp);
				}
			} else {
				excuteDefaultSample(sampleDTO, rqcLinesDTO, resultList, hp);
			}
			if (cargoChangeIn != null) {// 货主转换指定抽检数量，则按指定的操作
				CargoChangeInDetails changeInDetails = cargoChangeIn.getDetails().stream()
						.filter(t -> !StringUtils.isBlank(t.getRefLineId())
								&& t.getRefLineId().equals(rqcLinesDTO.getRqcLineId()))
						.findFirst().orElse(null);
				if (changeInDetails != null) {
					if (changeInDetails.getQcOddCaseQty() != null) {
						sampleDTO.setQcOddCaseQty(changeInDetails.getQcOddCaseQty());
					}
					if (changeInDetails.getQcOddPieceQty() != null) {
						sampleDTO.setQcOddPieceQty(changeInDetails.getQcOddPieceQty());
					}
					if (changeInDetails.getQcOddCaseActQty() != null) {
						sampleDTO.setQcOddCaseActQty(changeInDetails.getQcOddCaseActQty());
					}
					if (changeInDetails.getQcOddPieceActQty() != null) {
						sampleDTO.setQcOddPieceActQty(changeInDetails.getQcOddPieceActQty());
					}
				}

			}
			sampleDTO.setAllowDecimal(rqcLinesDTO.getAllowDecimal());
		}
		return resultList;
	}

	private void excuteSampleMatchRule(List<WmsInRqcStRuleDTO> ruleList, WmsInRqcSampleDTO sampleDTO,
			RqcLinesDTO rqcLinesDTO, List<WmsInRqcSampleDTO> resultList, RcvHeadersProfiles hp) {
		// 匹配抽检策略规则
		BigDecimal oddCaseQty = rqcLinesDTO.getOddCaseQty();
		AssertUtils.notNull(oddCaseQty, "整件数不可为空");
		sampleDTO.setOddCaseQty(oddCaseQty);
		BigDecimal conversionRate = rqcLinesDTO.getConversionRate();
		BigDecimal oddPieceQty = rqcLinesDTO.getOddPieceQty();
		BigDecimal pieceQty = rqcLinesDTO.getPieceQty();
		String warehouseId = rqcLinesDTO.getWarehouseId();
		BeanUtils.copyProperties(rqcLinesDTO, sampleDTO);
		String itemNum = rqcLinesDTO.getItemNum();
		sampleDTO.setItemCode(itemNum);
		if (hp != null) {
			sampleDTO.setMtlOwnerCode(hp.getMtlOwnerNum());
			sampleDTO.setMtlOwnerName(hp.getMtlOwnerName());
		}
		sampleDTO.setQcOddPieceQty(oddPieceQty);
		sampleDTO.setQcOddPieceActQty(oddPieceQty);
		for (WmsInRqcStRuleDTO rule : ruleList) {
			String searchRegexp = rule.getSearchRegexp();
			String matchRegexp = rule.getMatchRegexp();
			logger.info("查询规则->" + searchRegexp);
			Expression compiledExp = AviatorEvaluator.compile(searchRegexp);
			Map<String, Object> env = new HashMap<String, Object>();
			env.put("x", pieceQty);
			env.put("c", conversionRate);
			Boolean s = (Boolean) compiledExp.execute(env);
			if (s) {
				Expression compiledExp2 = AviatorEvaluator.compile(matchRegexp);
				Double resultd = (Double) compiledExp2.execute(env);
				BigDecimal result = BigDecimal.valueOf(resultd);
				BigDecimal divide = result.divide(conversionRate, 0, RoundingMode.DOWN);
				BigDecimal multiply = divide.multiply(divide);
				BigDecimal subtract = result.subtract(multiply);
				sampleDTO.setQcOddPieceQty(subtract);
				sampleDTO.setQcOddPieceActQty(subtract);
				sampleDTO.setQcOddCaseQty(divide);
				sampleDTO.setQcOddCaseActQty(divide);
				resultList.add(sampleDTO);
				break;
			}
		}
	}

	/**
	 * 默认抽检策略
	 * 
	 * @param sampleDTO
	 * @param rqcLinesDTO
	 * @param resultList
	 * @param hp
	 */
//	private void excuteDefaultSample(WmsInRqcSampleDTO sampleDTO, RqcLinesDTO rqcLinesDTO,
//			List<WmsInRqcSampleDTO> resultList, RcvHeadersProfiles hp) {
//		String rcvType = rqcLinesDTO.getRcvType();
//		// 组装因子并执行策略获取结果
//		BigDecimal oddCaseQty = rqcLinesDTO.getOddCaseQty();
//		AssertUtils.notNull(oddCaseQty, "整件数不可为空");
//		sampleDTO.setOddCaseQty(oddCaseQty);
//		BigDecimal conversionRate = rqcLinesDTO.getConversionRate();
//		BigDecimal oddPieceQty = rqcLinesDTO.getOddPieceQty();
//		BigDecimal pieceQty = rqcLinesDTO.getPieceQty();
//		String warehouseId = rqcLinesDTO.getWarehouseId();
//		BeanUtils.copyProperties(rqcLinesDTO, sampleDTO);
//		String itemNum = rqcLinesDTO.getItemNum();
//		sampleDTO.setItemCode(itemNum);
//		// 这里先用假的默认代替,需要在策略中实现
//		if (hp != null) {
//			sampleDTO.setMtlOwnerCode(hp.getMtlOwnerNum());
//			sampleDTO.setMtlOwnerName(hp.getMtlOwnerName());
//		}
//
//		// 非销退
//		BigDecimal b1 = new BigDecimal(3);
//		BigDecimal b2 = new BigDecimal(50);
//		BigDecimal b3 = new BigDecimal(1);
//		if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.SALE_RETURN_IN)) {
//			// 销退,6件以内抽全部,不足6件加增数2,8件也抽全部,8件到50件抽检6+2件,50件以上没多50多抽2件,比如60,100件抽6+2+2,10件,101件抽12件
//			// 公式: 基数b1,抽检范围数b2,抽检增数b3,b为待抽检数,
//			b1 = new BigDecimal(6); // 抽检基数
//			b2 = new BigDecimal(50); // 抽检范围数
//			b3 = new BigDecimal(2); // 抽检增数
//		} else {
//		}
//
//		// 整件小于等于抽检基数,抽检全部
//		if (oddCaseQty.compareTo(b1) < 1) {
//			// 抽检全部的整件加零散
//			sampleDTO.setQcOddPieceQty(oddPieceQty);
//			sampleDTO.setQcOddPieceActQty(oddPieceQty);
//			sampleDTO.setQcOddCaseQty(oddCaseQty);
//			sampleDTO.setQcOddCaseActQty(oddCaseQty);
//			resultList.add(sampleDTO);
//			return;
//		}
//		// 整件大于抽检基数加增数小于等于范围数 抽检结果为抽检基数
//		if (oddCaseQty.compareTo(b1) == 1 && oddCaseQty.compareTo(b2) < 1) {
//			sampleDTO.setQcOddPieceQty(BigDecimal.ZERO);
//			sampleDTO.setQcOddPieceActQty(BigDecimal.ZERO);
//			sampleDTO.setQcOddCaseQty(b1);
//			sampleDTO.setQcOddCaseActQty(b1);
//			resultList.add(sampleDTO);
//			return;
//		}
//		// 整件大于范围数 不足范围数按范围数计算 抽检基数+抽检增数*(up(验收件-范围数/范围数))
//		if (oddCaseQty.compareTo(b2) == 1) {
//			BigDecimal divide = BigDecimal.ZERO;
//			if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.SALE_RETURN_IN)) {
//				divide = oddCaseQty.divide(b2, 0, RoundingMode.UP);
//			} else {
//				divide = (oddCaseQty.subtract(b2)).divide(b2, 0, RoundingMode.UP);
//			}
//			BigDecimal add = b1.add(divide.multiply(b3));
//			sampleDTO.setQcOddPieceQty(BigDecimal.ZERO);
//			sampleDTO.setQcOddPieceActQty(BigDecimal.ZERO);
//			sampleDTO.setQcOddCaseQty(add);
//			sampleDTO.setQcOddCaseActQty(add);
//			resultList.add(sampleDTO);
//			return;
//		}
//	}

	private void excuteDefaultSample(WmsInRqcSampleDTO sampleDTO, RqcLinesDTO rqcLinesDTO,
									 List<WmsInRqcSampleDTO> resultList, RcvHeadersProfiles hp) {
		String rcvType = rqcLinesDTO.getRcvType();
		//查询当前品批的已验收数量和当前收货单对应的到货数量和到货件数和到货零散数
		WmsInRqcSampleDTO sampleDhQty = taskQcDetailMapper.findSampleDhDTO(rqcLinesDTO.getRcvLineId());

		WmsInRqcSampleDTO sampleCjQty = taskQcDetailMapper.findSampleCjDTO(rqcLinesDTO.getAsnHeaderId(),rqcLinesDTO.getItemId(),rqcLinesDTO.getManufacturerLotNum());

		BigDecimal isDhCaseQty = sampleDhQty.getIsDhCaseQty();//到货件数
		BigDecimal isDhPieceQty = sampleDhQty.getIsDhPieceQty();//到货零散数
		BigDecimal isDhQty = sampleDhQty.getIsDhQty();//到货数量
		BigDecimal isRqcQty = sampleCjQty.getIsRqcQty();//已验收数量
		BigDecimal isCjCaseQty = sampleCjQty.getIsCjCaseQty(); //已抽检的质检件数
		BigDecimal isCjPieceQty = sampleCjQty.getIsCjPieceQty();//已抽检的质检零散数


		sampleDTO.setIsDhQty(isDhQty);
		sampleDTO.setIsDhCaseQty(isDhCaseQty);
		sampleDTO.setIsDhPieceQty(isDhPieceQty);
		sampleDTO.setIsRqcQty(isRqcQty);
		sampleDTO.setIsCjCaseQty(isCjCaseQty);
		sampleDTO.setIsCjPieceQty(isCjPieceQty);

		// 组装因子并执行策略获取结果
		BigDecimal oddCaseQty = rqcLinesDTO.getOddCaseQty();// 入库整件数
		AssertUtils.notNull(oddCaseQty, "整件数不可为空");
		sampleDTO.setOddCaseQty(oddCaseQty);
		BigDecimal oddPieceQty = rqcLinesDTO.getOddPieceQty();// 入库零散数
		sampleDTO.setOddPieceQty(oddPieceQty);
		BeanUtils.copyProperties(rqcLinesDTO, sampleDTO);
		String itemNum = rqcLinesDTO.getItemNum();
		sampleDTO.setItemCode(itemNum);


		// 这里先用假的默认代替,需要在策略中实现
		if (hp != null) {
			sampleDTO.setMtlOwnerCode(hp.getMtlOwnerNum());
			sampleDTO.setMtlOwnerName(hp.getMtlOwnerName());
		}

		// 非销退
		BigDecimal b1 = new BigDecimal(3);
		BigDecimal b2 = new BigDecimal(50);
		BigDecimal b3 = new BigDecimal(1);
		if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.SALE_RETURN_IN)) {
			// 销退,6件以内抽全部,不足6件加增数2,8件也抽全部,8件到50件抽检6+2件,50件以上没多50多抽2件,比如60,100件抽6+2+2,10件,101件抽12件
			// 公式: 基数b1,抽检范围数b2,抽检增数b3,b为待抽检数,
			b1 = new BigDecimal(6); // 抽检基数
			b2 = new BigDecimal(50); // 抽检范围数
			b3 = new BigDecimal(2); // 抽检增数
		} else {
		}

		// 整件小于等于抽检基数,抽检全部---根据到货的件数来计算
		if (isDhCaseQty.compareTo(b1) < 1) {
			// 抽检全部的整件加零散
			sampleDTO.setQcOddPieceQty(isDhPieceQty);//计划抽样零散数
			sampleDTO.setQcOddCaseQty(isDhCaseQty);//计划抽样整件数
			sampleDTO.setQcOddPieceActQty(oddPieceQty);//实际抽样零散数

			BigDecimal plantQcActQty = isDhCaseQty.subtract(isCjCaseQty);//总体实际抽样整件数=计划抽样整件数-已抽检的质检件数

			if(oddCaseQty.compareTo(b1) < 1){
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(oddCaseQty) >= 0 ){
						sampleDTO.setQcOddCaseActQty(oddCaseQty);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}
			if (oddCaseQty.compareTo(b1) == 1 && oddCaseQty.compareTo(b2) < 1) {
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(b1) >= 0 ){
						sampleDTO.setQcOddCaseActQty(b1);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}
			if (oddCaseQty.compareTo(b2) == 1) {
				BigDecimal divide1 = BigDecimal.ZERO;
				if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.SALE_RETURN_IN)) {
					divide1 = oddCaseQty.divide(b2, 0, RoundingMode.UP);
				} else {
					divide1 = (oddCaseQty.subtract(b2)).divide(b2, 0, RoundingMode.UP);
				}
				BigDecimal add1 = b1.add(divide1.multiply(b3));
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(add1) >= 0 ){
						sampleDTO.setQcOddCaseActQty(add1);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}

			resultList.add(sampleDTO);
			return;
		}
		// 整件大于抽检基数加增数小于等于范围数 抽检结果为抽检基数
		if (isDhCaseQty.compareTo(b1) == 1 && isDhCaseQty.compareTo(b2) < 1) {
			sampleDTO.setQcOddPieceQty(BigDecimal.ZERO);//计划抽样零散数
			sampleDTO.setQcOddCaseQty(b1);//计划抽样整件数

			sampleDTO.setQcOddPieceActQty(oddPieceQty);//实际抽样零散数
//			sampleDTO.setQcOddCaseActQty(b1.subtract(isCjCaseQty));//实际抽样整件数=计划抽样整件数-已抽检的质检件数
			BigDecimal plantQcActQty = b1.subtract(isCjCaseQty);//总体实际抽样整件数=计划抽样整件数-已抽检的质检件数

			if(oddCaseQty.compareTo(b1) < 1){
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(oddCaseQty) >= 0 ){
						sampleDTO.setQcOddCaseActQty(oddCaseQty);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}
			if (oddCaseQty.compareTo(b1) == 1 && oddCaseQty.compareTo(b2) < 1) {
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(b1) >= 0 ){
						sampleDTO.setQcOddCaseActQty(b1);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}
			if (oddCaseQty.compareTo(b2) == 1) {
				BigDecimal divide1 = BigDecimal.ZERO;
				if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.SALE_RETURN_IN)) {
					divide1 = oddCaseQty.divide(b2, 0, RoundingMode.UP);
				} else {
					divide1 = (oddCaseQty.subtract(b2)).divide(b2, 0, RoundingMode.UP);
				}
				BigDecimal add1 = b1.add(divide1.multiply(b3));
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(add1) >= 0 ){
						sampleDTO.setQcOddCaseActQty(add1);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}
			resultList.add(sampleDTO);
			return;
		}
		// 整件大于范围数 不足范围数按范围数计算 抽检基数+抽检增数*(up(验收件-范围数/范围数))
		if (isDhCaseQty.compareTo(b2) == 1) {
			BigDecimal divide = BigDecimal.ZERO;
			if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.SALE_RETURN_IN)) {
				divide = isDhCaseQty.divide(b2, 0, RoundingMode.UP);
			} else {
				divide = (isDhCaseQty.subtract(b2)).divide(b2, 0, RoundingMode.UP);
			}
			BigDecimal add = b1.add(divide.multiply(b3));
			sampleDTO.setQcOddPieceQty(BigDecimal.ZERO);//计划抽样零散数
			sampleDTO.setQcOddCaseQty(add);//计划抽样整件数

			sampleDTO.setQcOddPieceActQty(oddPieceQty);//实际抽样零散数

			BigDecimal plantQcActQty = add.subtract(isCjCaseQty);//总体实际抽样整件数=计划抽样整件数-已抽检的质检件数
			if(oddCaseQty.compareTo(b1) < 1){
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(oddCaseQty) >= 0 ){
						sampleDTO.setQcOddCaseActQty(oddCaseQty);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}
			if (oddCaseQty.compareTo(b1) == 1 && oddCaseQty.compareTo(b2) < 1) {
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(b1) >= 0 ){
						sampleDTO.setQcOddCaseActQty(b1);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}
			if (oddCaseQty.compareTo(b2) == 1) {
				BigDecimal divide1 = BigDecimal.ZERO;
				if (!StringUtils.isBlank(rcvType) && rcvType.equals(BizConstant.SALE_RETURN_IN)) {
					divide1 = oddCaseQty.divide(b2, 0, RoundingMode.UP);
				} else {
					divide1 = (oddCaseQty.subtract(b2)).divide(b2, 0, RoundingMode.UP);
				}
				BigDecimal add1 = b1.add(divide1.multiply(b3));
				if(plantQcActQty.compareTo(BigDecimal.ZERO) > 0){
					if(plantQcActQty.compareTo(add1) >= 0 ){
						sampleDTO.setQcOddCaseActQty(add1);
					}else {
						sampleDTO.setQcOddCaseActQty(plantQcActQty);
					}
				}else {
					sampleDTO.setQcOddCaseActQty(BigDecimal.ZERO);
				}
			}
			resultList.add(sampleDTO);
			return;
		}
	}

	@Override
	@Transactional
	public Object batchAdd(List<WmsInRqcSampleDTO> wmsInRqcSampleDTOList,String type) {
		AssertUtils.isNotEmpty(wmsInRqcSampleDTOList, "抽检的数据不可为空!");
		// 批量添加
		UserDTO userDTO = userUtils.getUserDTO();
		int row = 0;
		boolean editFlag = Boolean.FALSE;
		Date now = new Date();
		List<WmsInRqcSample> result = new ArrayList<>();
		List<Map<String, Object>> mapList = new ArrayList<>();
		WmsInRqcSampleDTO wmsInRqcSampleDTO2 = wmsInRqcSampleDTOList.get(0);
		String rcvHeaderId = wmsInRqcSampleDTO2.getRcvHeaderId();
		RcvHeaders rcvHead = rcvHeadersMapper.findById(rcvHeaderId, RcvHeaders.class);
		String rcvType = rcvHead.getRcvType();

		for (WmsInRqcSampleDTO wmsInRqcSampleDTO : wmsInRqcSampleDTOList) {
			row++;
			this.buildDefaultField(wmsInRqcSampleDTO, editFlag, userDTO, now, row);
			this.vaildateModel(wmsInRqcSampleDTO, editFlag, userDTO, row, validator, "抽检批量保存");
			BigDecimal pieceQty = wmsInRqcSampleDTO.getPieceQty();
			BigDecimal conversionRate = wmsInRqcSampleDTO.getConversionRate();
			// 计算qty,保证准确性
			if (pieceQty == null)
				pieceQty = BigDecimal.ZERO;
			if (conversionRate == null || BigDecimal.ZERO.compareTo(conversionRate) == 0)
				conversionRate = BigDecimal.ONE;
			BigDecimal oddCaseQty = pieceQty.divide(conversionRate, 0, RoundingMode.DOWN); // 整件
			BigDecimal multiply = oddCaseQty.multiply(conversionRate);
			BigDecimal oddPieceQty = pieceQty.subtract(multiply); // 零散
			wmsInRqcSampleDTO.setPieceQty(pieceQty);
			wmsInRqcSampleDTO.setConversionRate(conversionRate);
			wmsInRqcSampleDTO.setOddPieceQty(oddPieceQty);
			wmsInRqcSampleDTO.setOddPieceQty(oddPieceQty);
			// 校验不能为小数
			BigDecimal qcOddPieceActQty = wmsInRqcSampleDTO.getQcOddPieceActQty();
			BigDecimal qcOddCaseActQty = wmsInRqcSampleDTO.getQcOddCaseActQty();
			if (new BigDecimal(qcOddPieceActQty.intValue()).compareTo(qcOddPieceActQty) != 0
					|| new BigDecimal(qcOddCaseActQty.intValue()).compareTo(qcOddCaseActQty) != 0) {
				// TOOD 需要根据大类来判断
				String allowDecimal = wmsInRqcSampleDTO.getAllowDecimal();
				if (StringUtils.isBlank(allowDecimal)) {
					RcvLinesProfiles findById = rcvLinesProfilesMapper.findById(wmsInRqcSampleDTO.getRcvLineId(),
							RcvLinesProfiles.class);
					if (findById != null) {
						allowDecimal = findById.getAllowDecimal();
					}
				}

				// 为采购入库并且不允许小数拆分才可拆 其它应该都可拆
				if (!StringUtils.isBlank(rcvType) && "1".equals(rcvType)
						&& (StringUtils.isBlank(allowDecimal) || !"Y".equalsIgnoreCase(allowDecimal.trim()))) {
					throw new ParameterException(String.format("第[%d]行,实际抽检整件数和实际抽检零散不能为小数!", row));
				}
				if(StringUtils.isBlank(rcvType) && "2".equals(rcvType)){
					if(qcOddCaseActQty.compareTo(oddCaseQty)<=0||qcOddPieceActQty.compareTo(oddPieceQty)<=0){
						throw new BizException(String.format("第[%d]行,实际抽检整件数和实际抽检零散数不能小于推荐数值!", row));
					}
				}

//				if (!StringUtils.isBlank(allowDecimal) && "Y".equalsIgnoreCase(allowDecimal.trim())) {
//					// 其他物品可小数
//				} else {
//					// 为小数抛错
//					throw new ParameterException(String.format("第[%d]行,实际抽检整件数和实际抽检零散不能为小数!", row));
//				}
			}
//			if (qcOddPieceActQty.compareTo(conversionRate) == 1) {
//				throw new ParameterException(String.format("第[%d]行,实际抽检零散不能大于包装含量!", row));
//			}
			// 质检保存出错 TODO
			//直通的不用校验
			if(!"straight".equals(type)){
				if (qcOddCaseActQty.compareTo(oddCaseQty) == 1) {
					throw new ParameterException(String.format("第[%d]行,实际抽检整件不能大于质检的整件数!", row));
				}
				BigDecimal add = qcOddCaseActQty.multiply(conversionRate).add(qcOddPieceActQty);
				if (add.compareTo(pieceQty) == 1) {
					throw new ParameterException(String.format("第[%d]行,实际抽检总数不能大于质检的总数!", row));
				}
			}


			WmsInRqcSample wmsInRqcSample = new WmsInRqcSample();
			BeanUtils.copyProperties(wmsInRqcSampleDTO, wmsInRqcSample);
			this.vaildateModelRepeated(wmsInRqcSample, editFlag, userDTO);
			this.setBaseSysField(wmsInRqcSample, editFlag, userDTO, now);
			this.mapper.save(wmsInRqcSample);
			result.add(wmsInRqcSample);

			Map<String, Object> map = new HashMap<>();
			String taskRqcId = wmsInRqcSampleDTO.getTaskRqcId();
			map.put("taskRqcId", taskRqcId);
			map.put("isSpotCheck", 1);
			mapList.add(map);

		}
		List<String> collect = wmsInRqcSampleDTOList.stream().filter(p -> !StringUtils.isBlank(p.getTaskRqcId()))
				.map(p -> p.getTaskRqcId()).collect(Collectors.toList());

		if (ObjectUtils.isNotNull(collect)) {
			// 更新质检任务池已抽检
			Criteria crt = Criteria.forClass(TaskQcDetail.class);
			crt.setRestriction(Restrictions.in("taskRqcId", collect.toArray(new String[collect.size()])));
			this.taskQcDetailMapper.updateMapByCriteria(MapUtils.put("is_spot_check", 1).getMap(), crt);
		}
		return mapList;
//		return result;
	}

	private void buildDefaultField(WmsInRqcSampleDTO wmsInRqcSampleDTO, boolean editFlag, UserDTO userDTO, Date now,
			int row) {
		// 构建默认字段
		Date sampleDate = wmsInRqcSampleDTO.getSampleDate();
		if (ObjectUtils.isNull(sampleDate)) {
			wmsInRqcSampleDTO.setSampleDate(now);
		}
		String sampleBy = wmsInRqcSampleDTO.getSampleBy();
		if (StringUtils.isBlank(sampleBy)) {
			wmsInRqcSampleDTO.setSampleBy(userDTO.getUsername());
		}
	}

	@Override
	public Object add(WmsInRqcSampleDTO wmsInRqcSampleDTO) {
		// TODO vaildate
		UserDTO userDTO = userUtils.getUserDTO();
		WmsInRqcSample wmsInRqcSample = new WmsInRqcSample();
		BeanUtils.copyProperties(wmsInRqcSampleDTO, wmsInRqcSample);
		this.vaildateModel(wmsInRqcSample, false, userDTO);
		this.buildField(wmsInRqcSample, false, userDTO);
		this.mapper.save(wmsInRqcSample);
		return "";
	}

	@Override
	public Object edit(String pkId, WmsInRqcSampleDTO wmsInRqcSampleDTO) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		WmsInRqcSample wmsInRqcSample = new WmsInRqcSample();
		BeanUtils.copyProperties(wmsInRqcSampleDTO, wmsInRqcSample);
		this.vaildateModel(wmsInRqcSample, true, userDTO);
		this.buildField(wmsInRqcSample, true, userDTO);
		this.mapper.updateWithValidate(wmsInRqcSample,
				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, WmsInRqcSample.class));
		return "";
	}

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

	@Override
	public Page<WmsInRqcSampleDTO> findList(WmsInRqcSampleDTO wmsInRqcSampleDTO, PageParam pageParam) {
		Criteria criteria = Criteria.forClass(WmsInRqcSample.class);
		Integer pageNum = null;
		Integer pageSize = null;
		Restriction r = null;
		if (pageParam == null) {
			pageNum = PageParam.DEFAULT_PAGE_NUM;
			pageSize = PageParam.DEFAULT_PAGE_SIZE;
		} else {
			pageNum = pageParam.getPageNum();
			pageSize = pageParam.getPageSize();
			WmsInRqcSampleDTO condition = wmsInRqcSampleDTO;
			r = buildCondition(condition);
		}
		if (pageNum == null || pageNum == 0) {
			pageNum = PageParam.DEFAULT_PAGE_NUM;
		}
		if (pageSize == null || pageSize == 0) {
			pageSize = PageParam.DEFAULT_PAGE_SIZE;
		}
		criteria.setRestriction(r);
		Order order = Order.newInstance().desc("gmtModified");
		criteria.setOrder(order);
		PageUtils.startPage(pageNum, pageSize);
		List<WmsInRqcSample> list = this.mapper.findByCriteria(criteria);
		List<WmsInRqcSampleDTO> collect = Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(p -> {
			WmsInRqcSampleDTO target = new WmsInRqcSampleDTO();
			BeanUtils.copyProperties(p, target);
			return target;
		}).collect(Collectors.toList());
		Page<WmsInRqcSample> page = PageUtils.getPage(list);
		Page<WmsInRqcSampleDTO> page2 = new Page<>();
		page2.setStartRow(page.getStartRow());
		page2.setEndRow(page.getEndRow());
		page2.setPageCount(page.getPageCount());
		page2.setPageNum(page.getPageNum());
		page2.setPageSize(page.getPageSize());
		page2.setTotalCount(page.getTotalCount());
		page2.setList(collect);
		return page2;
	}

	@Override
	@Transactional
	public Object batchEdit(List<WmsInRqcSampleDTO> wmsInRqcSampleDTOList) {
		// TODO
		UserDTO userDTO = userUtils.getUserDTO();
		for (WmsInRqcSampleDTO wmsInRqcSampleDTO : wmsInRqcSampleDTOList) {
			WmsInRqcSample wmsInRqcSample = new WmsInRqcSample();
			BeanUtils.copyProperties(wmsInRqcSampleDTO, wmsInRqcSample);
			this.vaildateModel(wmsInRqcSample, true, userDTO);
			this.buildField(wmsInRqcSample, true, userDTO);
			this.mapper.updateWithValidate(wmsInRqcSample,
					p -> ObjectUtils.isNotNull(p) && ObjectUtils.isNotNull(p.getValue()));
		}
		return "";
	}

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

	@Override
	public WmsInRqcSampleDTO findByPkId(String pkId) {
		// TODO
		WmsInRqcSample wmsInRqcSample = this.findById(pkId);
		AssertUtils.notNull(wmsInRqcSample, "model empty!");
		WmsInRqcSampleDTO wmsInRqcSampleDTO = new WmsInRqcSampleDTO();
		BeanUtils.copyProperties(wmsInRqcSample, wmsInRqcSampleDTO);
		return wmsInRqcSampleDTO;
	}

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

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

	private void buildField(WmsInRqcSample wmsInRqcSample, Boolean editFlag, UserDTO userDTO) {
		if (!editFlag) {
			// TODO add
		} else {
			// TODO edit
		}
		vaildateModelRepeated(wmsInRqcSample, editFlag, userDTO);
	}

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

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

	private Restriction buildCondition(WmsInRqcSampleDTO wmsInRqcSampleDTO) {
		// TODO
		return null;
	}

	@Transactional
	@Override
	public Object autoGen(List<RqcLinesDTO> lineList, String rcvType, CargoChangeIn cargoChangeIn, UserDTO userDTO) {
		// 获取待抽检的列表
		AssertUtils.isNotEmpty(lineList, "抽检集合为空!");
		List<WmsInRqcSampleDTO> preSample = getPreSample(lineList, false, cargoChangeIn);
		String type ="normal";
		this.batchAdd(preSample,type);
		return null;
	}

	@Override
	public List<WmsInRqcSampleDTO> getPreListByPad(List<RqcLinesDTO> rqcLinesDTOList) {
		return this.getPreList(rqcLinesDTOList);
	}

	@Override
	@Transactional
	public Object batchAddByPad(List<WmsInRqcSampleDTO> wmsInRqcSampleDTOList) {
		String type ="normal";
		return this.batchAdd(wmsInRqcSampleDTOList,type);
	}

}
