EdcSpcManagerImpl.java

package com.mycim.server.edcchart.manager.impl;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.jdbc.Page;
import com.mycim.framework.logging.Logger;
import com.mycim.framework.logging.LoggerFactory;
import com.mycim.framework.utils.beans.BeanUtils;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.framework.utils.lang.time.DateUtils;
import com.mycim.framework.utils.msg.JsonUtils;
import com.mycim.server.base.manager.NamedObjectManager;
import com.mycim.server.base.manager.ObjectVersionManager;
import com.mycim.server.base.manager.TransactionLogManager;
import com.mycim.server.edc.manager.DataCollectionRuleManager;
import com.mycim.server.edc.manager.EcnManager;
import com.mycim.server.edc.manager.ParameterManager;
import com.mycim.server.edc.manager.ParameterSetManager;
import com.mycim.server.edcchart.dao.EdcSpcDAO;
import com.mycim.server.edcchart.manager.EdcSpcManager;
import com.mycim.server.edcchart.manager.EquipmentChartManager;
import com.mycim.server.emas.manager.EmasEventManager;
import com.mycim.server.emas.manager.EmasManager;
import com.mycim.server.ems.manager.EntityManager;
import com.mycim.server.ems.manager.EquipmentManager;
import com.mycim.server.ocap.manager.OcapManager;
import com.mycim.server.spc.Edc2SpcContainer;
import com.mycim.server.spc.manager.SpcManager;
import com.mycim.server.system.manager.ReferenceFileManager;
import com.mycim.server.wip.manager.LotQueryManager;
import com.mycim.server.wip.manager.OcapQueryManager;
import com.mycim.server.wip.manager.UnitQueryManager;
import com.mycim.utils.NonRTMathUtil;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.automonitor.util.AutoMonitorUtils;
import com.mycim.valueobject.bas.ObjectVersion;
import com.mycim.valueobject.bas.TransactionLog;
import com.mycim.valueobject.consts.ObjectStatus;
import com.mycim.valueobject.consts.SpecifiedActionEnum;
import com.mycim.valueobject.consts.TransactionNames;
import com.mycim.valueobject.consts.VersionStatus;
import com.mycim.valueobject.edcspc.*;
import com.mycim.valueobject.edcspc.dto.nonrt.*;
import com.mycim.valueobject.ems.Entity;
import com.mycim.valueobject.ocap.dto.OcapChartInfoDTO;
import com.mycim.valueobject.ocap.dto.OcapProcessingResultDTO;
import com.mycim.valueobject.prp.Ecn;
import com.mycim.valueobject.security.User;
import com.mycim.valueobject.spc.RunCardRawDataInfo;
import com.mycim.valueobject.sys.Facility;
import com.mycim.valueobject.sys.ReferenceFileDetail;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.Unit;
import com.mycim.webservice.nonrtservice.client.stub.NonRTUploadData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;

/**
 * @author zhi.cai
 * @version 6.0.0
 * @date 2019/12/14
 **/
@Service
@Transactional
public class EdcSpcManagerImpl implements EdcSpcManager {

    private final Logger logger = LoggerFactory.getLogger(EdcSpcManagerImpl.class);

    @Autowired
    EdcSpcDAO edcSpcDAO;

    @Autowired
    EquipmentChartManager equipmentChartManager;

    @Autowired
    TransactionLogManager transactionLogManager;

    @Autowired
    ObjectVersionManager objectVersionManager;

    @Autowired
    NamedObjectManager namedObjectManager;

    @Autowired
    ParameterSetManager parameterSetManager;

    @Autowired
    EcnManager ecnManager;

    @Autowired
    SpcManager spcManager;

    @Autowired
    ParameterManager parameterManager;

    @Autowired
    LotQueryManager lotQueryManager;

    @Autowired
    DataCollectionRuleManager dataCollectionRuleManager;

    @Autowired
    UnitQueryManager unitQueryManager;

    @Autowired
    ReferenceFileManager referenceFileManager;

    @Autowired
    Edc2SpcContainer edc2SpcContainer;

    @Autowired
    EntityManager entityManager;

    @Autowired
    OcapManager ocapManager;

    @Autowired
    OcapQueryManager ocapQueryManager;

    @Autowired
    EdcSpcManager edcSpcManager;

    @Autowired
    EmasEventManager emasEventManager;

    @Autowired
    EmasManager emasManager;

    @Autowired
    EquipmentManager equipmentManager;

    @Override
    public Long insertNonRTUploadHistory(List<NonRTUploadDataInfo> list, String user) {
        TransactionLog transactionLog = transactionLogManager.startTransactionLog(user, TransactionNames.NON_RT_UPLOAD);
        edcSpcDAO.insertNonRTUploadHistory(list, transactionLog.getTransRrn());
        transactionLogManager.markTransactionLog(transactionLog);
        return transactionLog.getTransRrn();
    }

    @Override
    public List getActiveParameterSetVersion(long instanceRrn) {
        int activeVersion = 0;
        activeVersion = objectVersionManager.getActiveVersion(instanceRrn);
        edcSpcDAO.getActiveParameterSetVersion(instanceRrn, activeVersion);
        return null;
    }

    @Override
    public String getParameterSetUseForumla(long parameterSetRrn) {
        return edcSpcDAO.getParameterSetUseForumla(parameterSetRrn);
    }

    @Override
    public String getParameterSetMultiEqptMonitor(long parameterSetRrn) {
        return edcSpcDAO.getParameterSetMultiEqptMonitor(parameterSetRrn);
    }

    @Override
    public List<NonRTUploadDataInfo> getNonRTDataValues(String spcJobName, Long lotRrn, List<String> unitList) {
        return edcSpcDAO.getNonRTDataValues(spcJobName, lotRrn, unitList);
    }

    @Override
    public Page getNonRTUploadHistory(Page page) {
        return edcSpcDAO.getNonRTUploadHistory(page);
    }

    @Override
    public Page getEdcPlanImportHistory(Page page) {
        return edcSpcDAO.getEdcPlanImportHistory(page);
    }

    @Override
    public void insertEdcPlanImportHistory(List<EDCPlanExcelData> list, String impType) {
        TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(), impType);
        edcSpcDAO.insertEdcPlanImportHistory(list, transactionLog.getTransRrn());
        transactionLogManager.markTransactionLog(transactionLog);
    }

    @Override
    public void addEDCPlanByExcel(Map<String, List<ParameterSetVersion>> parameterSetList) {
        long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();

        long parameterSetRrn;
        long parameterRrn;
        String parameterId;
        ParameterSetVersion parameterSetVersion = new ParameterSetVersion();
        ObjectVersion ob;
        ParameterSet parameterSet;
        Parameter parameter;
        List<ParameterSetVersion> psvList;
        for (String parameterSetId : parameterSetList.keySet()) {// 获取所有导入的参数集Id

            psvList = parameterSetList.get(parameterSetId);
            // 参数集
            ParameterSet tempParamSet = new ParameterSet(parameterSetId, namedObjectManager.getNamedSpace(facilityRrn,
                                                                                                          ObjectList.PARAMETERSET_KEY),
                                                         ObjectList.PARAMETERSET_KEY);
            parameterSet = parameterSetManager.getParameterSet(tempParamSet);
            if (parameterSet == null || parameterSet.getInstanceRrn() <= 0) {// 新建parameterSet
                parameterSet = buildParameterSetForInsert(parameterSetId);
                parameterSet.setObjectType(psvList.iterator().next().getObjectType());
                parameterSetManager.insertParameterSet(parameterSet);
                parameterSet = parameterSetManager.getParameterSet(parameterSet);
            }
            parameterSetRrn = parameterSet.getInstanceRrn();
            ob = getNewestParameterSetVersion(parameterSet);
            parameterSetVersion.setInstanceRrn(parameterSetRrn);
            parameterSetVersion.setInstanceVersion(ob.getInstanceVersion());
            if (StringUtils.equalsIgnoreCase(ob.getVersionStatus(), ObjectStatus.UNFROZEN_KEY)) {
                // 删除 样点 参数采集规则信息
                this.deleteParameterSetVersion(parameterSetVersion.getInstanceRrn(),
                                               parameterSetVersion.getInstanceVersion());
            }

            if (StringUtils.equalsIgnoreCase(ob.getVersionStatus(), ObjectStatus.ACTIVE_KEY)) {
                // 直接升级版本
                buildParameterSetVersion(parameterSet, ob.getInstanceVersion() + 1);
                ob = getNewestParameterSetVersion(parameterSet);
            }


            parameterSetManager.activeParameterSetVersion(ob, user);

            parameterSetVersion.setInstanceVersion(ob.getInstanceVersion());
            parameterSetVersion.setVersionId(String.valueOf(ob.getInstanceVersion()));

            // 开始添加参数信息
            for (ParameterSetVersion tmp : psvList) {
                parameterId = tmp.getParameterId();
                Parameter tempParam = new Parameter();
                tempParam.setInstanceRrn(namedObjectManager.getNamedObjectRrn(parameterId,
                                                                              namedObjectManager.getNamedSpace(
                                                                                      facilityRrn,
                                                                                      ObjectList.PARAMETER_KEY),
                                                                              ObjectList.PARAMETER_KEY));
                parameter = parameterManager.getParameter(tempParam);

                if (parameter == null || parameter.getInstanceRrn() <= 0) {// 新建parameter
                    parameter = buildParameterForInsert(parameterId);
                    parameter.setInstanceDesc(tmp.getParameterDesc());
                    parameter.setObjectType(tmp.getParameterType());
                    parameterManager.insertParameter(parameter);
                    parameter = parameterManager.getParameter(parameter);
                }
                parameterRrn = parameter.getInstanceRrn();

                tmp.setInstanceRrn(parameterSetRrn);
                tmp.setParameterRrn(parameterRrn);
                tmp.setInstanceVersion(ob.getInstanceVersion());
                parameterSetVersion.setParameterRrn(parameterRrn);
                parameterSetVersion.setCollectionLevel(tmp.getCollectionLevel());
                parameterSetVersion.setRuleType(tmp.getRuleType());
                parameterSetVersion.setTransPerformedby(user);
                parameterSetVersion.setEffectiveDateFrom(DateUtils.stringToTimestamp(DateUtils.formatDate(new Date())));
                parameterSetVersion.setEffectiveDateTo(DateUtils.stringToTimestamp(getEffectiveDateTo()));
                Double lowerLimit = tmp.getLowerSpecificationLimit();
                Double upperLimit = tmp.getUpperSpecificationLimit();
                if (StringUtils.isNotBlank(tmp.getLowerSpecificationLimitStr())) {
                    parameterSetVersion.setLowerSpecificationLimit(lowerLimit);
                }
                if (StringUtils.isNotBlank(tmp.getUpperSpecificationLimitStr())) {
                    parameterSetVersion.setUpperSpecificationLimit(upperLimit);
                }
                parameterSetVersion.setCheckLowerLimitFlag(lowerLimit == 0 || lowerLimit == null ? "0" : "1");
                parameterSetVersion.setCheckUpperLimitFlag(upperLimit == 0 || upperLimit == null ? "0" : "1");
                parameterSetVersion.setOptionalFlag(tmp.getOptionalFlag());

                // 绑定到参数集
                // 绑定参数集、参数、规则关系到DATA_COLLECTION_RULE表中
                //parameterSetManager.addParameterToSet(parameterSetVersion);
                handleEdcPlanRelation(parameterSetVersion, parameterRrn);
            }
        }
    }


    @Override
    public void addEDCPlanByExcel(String parameterSetId, List<ParameterSetVersion> versionList) {
        long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();

        long parameterRrn;
        ParameterSetVersion parameterSetVersion = new ParameterSetVersion();
        String parameterId;
        Parameter parameter;
        boolean newParameterFlag = false;

        ParameterSet tempParamSet = new ParameterSet(parameterSetId, namedObjectManager.getNamedSpace(facilityRrn,
                                                                                                      ObjectList.PARAMETERSET_KEY),
                                                     ObjectList.PARAMETERSET_KEY);
        ParameterSet parameterSet = parameterSetManager.getParameterSet(tempParamSet);
        if (parameterSet == null || parameterSet.getInstanceRrn() <= 0) {// 新建parameterSet
            parameterSet = buildParameterSetForInsert(parameterSetId);
            parameterSet.setObjectType(versionList.iterator().next().getObjectType());
            parameterSetManager.insertParameterSet(parameterSet);
            parameterSet = parameterSetManager.getParameterSet(parameterSet);
        }
        long parameterSetRrn = parameterSet.getInstanceRrn();
        ObjectVersion ob = getNewestParameterSetVersion(parameterSet);
        parameterSetVersion.setInstanceRrn(parameterSetRrn);
        parameterSetVersion.setInstanceVersion(ob.getInstanceVersion());
        if (StringUtils.equalsIgnoreCase(ob.getVersionStatus(), ObjectStatus.UNFROZEN_KEY)) {
            // 删除 样点 参数采集规则信息
            this.deleteParameterSetVersion(parameterSetVersion.getInstanceRrn(),
                                           parameterSetVersion.getInstanceVersion());
        }

        if (StringUtils.equalsIgnoreCase(ob.getVersionStatus(), ObjectStatus.ACTIVE_KEY)) {
            // 直接升级版本
            buildParameterSetVersion(parameterSet, ob.getInstanceVersion() + 1);
            ob = getNewestParameterSetVersion(parameterSet);
        }


        parameterSetManager.activeParameterSetVersion(ob, user);

        parameterSetVersion.setInstanceVersion(ob.getInstanceVersion());
        parameterSetVersion.setVersionId(String.valueOf(ob.getInstanceVersion()));

        // 开始添加参数信息
        for (ParameterSetVersion tmp : versionList) {
            parameterId = tmp.getParameterId();
            Parameter tempParam = new Parameter();
            tempParam.setInstanceRrn(namedObjectManager.getNamedObjectRrn(parameterId,
                                                                          namedObjectManager.getNamedSpace(facilityRrn,
                                                                                                           ObjectList.PARAMETER_KEY),
                                                                          ObjectList.PARAMETER_KEY));
            parameter = parameterManager.getParameter(tempParam);

            if (parameter == null || parameter.getInstanceRrn() <= 0) {// 新建parameter
                parameter = buildParameterForInsert(parameterId);
                parameter.setInstanceDesc(tmp.getParameterDesc());
                parameter.setObjectType(tmp.getParameterType());
                parameterManager.insertParameter(parameter);
                parameter = parameterManager.getParameter(parameter);
                newParameterFlag = true;
            }
            parameterRrn = parameter.getInstanceRrn();

            tmp.setInstanceRrn(parameterSetRrn);
            tmp.setParameterRrn(parameterRrn);
            tmp.setInstanceVersion(ob.getInstanceVersion());
            parameterSetVersion.setParameterRrn(parameterRrn);
            parameterSetVersion.setCollectionLevel(tmp.getCollectionLevel());
            parameterSetVersion.setRuleType(tmp.getRuleType());
            parameterSetVersion.setTransPerformedby(user);
            parameterSetVersion.setEffectiveDateFrom(DateUtils.stringToTimestamp(DateUtils.formatDate(new Date())));
            parameterSetVersion.setEffectiveDateTo(DateUtils.stringToTimestamp(getEffectiveDateTo()));
            Double lowerLimit = tmp.getLowerSpecificationLimit();
            Double upperLimit = tmp.getUpperSpecificationLimit();
            if (StringUtils.isNotBlank(tmp.getLowerSpecificationLimitStr())) {
                parameterSetVersion.setLowerSpecificationLimit(lowerLimit);
            }
            if (StringUtils.isNotBlank(tmp.getUpperSpecificationLimitStr())) {
                parameterSetVersion.setUpperSpecificationLimit(upperLimit);
            }
            parameterSetVersion.setCheckLowerLimitFlag(lowerLimit == 0 || lowerLimit == null ? "0" : "1");
            parameterSetVersion.setCheckUpperLimitFlag(upperLimit == 0 || upperLimit == null ? "0" : "1");
            parameterSetVersion.setOptionalFlag(tmp.getOptionalFlag());

            // 绑定到参数集
            // 绑定参数集、参数、规则关系到DATA_COLLECTION_RULE表中
            //parameterSetManager.addParameterToSet(parameterSetVersion);
            handleEdcPlanRelation(parameterSetVersion, parameterRrn);
        }

    }

    @Override
    public void addParameterByExcel(List<Parameter> parameterList) {
        String user = LocalContext.getUserId();

        for (Parameter parameter : parameterList) {
            if (parameter.getInstanceRrn() <= 0) {// 新建parameter
                String dataType = "VARIABLE";
                parameter.setTransPerformedby(user);
                parameter.setDataType(dataType);
                parameterManager.insertParameter(parameter);
                parameter = parameterManager.getParameter(parameter);
            } else {
                // 修改 parameter参数
                String cpPara = parameter.getCpPara();
                String keyChartFlag = parameter.getKeyChartFlag();
                Integer sampleNum = parameter.getSampleNum();
                String parameterUnit = parameter.getParameterUnit();
                String actionPoint = parameter.getActionPoint();
                parameter = parameterManager.getParameter(parameter);
                //if (!StringUtils.equals(parameter.getCpPara(), cpPara) || !StringUtils.equals(
                //        parameter.getKeyChartFlag(), keyChartFlag)) {
                parameter.setCpPara(cpPara);
                parameter.setKeyChartFlag(keyChartFlag);
                parameter.setSampleNum(sampleNum);
                parameter.setParameterUnit(parameterUnit);
                parameter.setActionPoint(actionPoint);
                parameterManager.updateParameter(parameter);
                //}
                dataCollectionRuleManager.deleteDataCollectionRuleForAll(0L, 0, parameter.getInstanceRrn());
                parameterSetManager.deleteReadingPromptsForParameterAll(0L, 0, parameter.getInstanceRrn());
            }

            Collection<DataCollectionRule> rules = parameter.getCollectionRules();
            int i = 0;

            for (DataCollectionRule rule : rules) {
                rule.setParameterSetRrn(0L);
                rule.setParameterSetVersion(0);
                rule.setParameterRrn(parameter.getInstanceRrn());
                rule.setCollectionRuleSequence(++i);
                dataCollectionRuleManager.insertDataCollectionRule(rule);
            }

            Collection readings = parameter.getReadingPrompts();
            i = 0;
            for (Object obj : readings) {
                ReadingPrompts reading = (ReadingPrompts) obj;
                reading.setParameterSetRrn(0L);
                reading.setParameterSetVersion(0L);
                reading.setParameterRrn(parameter.getInstanceRrn());
                reading.setReadingSequence(++i);
                parameterManager.insertReadingPrompt(reading);
            }
        }
    }

    @Override
    public List<RunCardRawDataInfo> getRunCardRawDataInfoList(Long lotRrn, Long stepSequence) {
        return edcSpcDAO.getRunCardRawDataInfoList(lotRrn, stepSequence);
    }

    @Override
    public void insertSrcSampleRawdata(List<RunCardRawDataInfo> rawDataInfoList) {
        edcSpcDAO.insertSrcSampleRawdata(rawDataInfoList);
    }

    @Override
    public void handleEdcPlanRelation(ParameterSetVersion parameterSetVersion, long parameterRrn) {
        parameterSetManager.addParameterToSet(parameterSetVersion);
        List<DataCollectionRule> dataCollectionRules = dataCollectionRuleManager.getDataCollectionRules(parameterRrn);
        int i = 0;
        for (DataCollectionRule rule : dataCollectionRules) {
            rule.setParameterSetRrn(parameterSetVersion.getInstanceRrn());
            rule.setParameterSetVersion(parameterSetVersion.getInstanceVersion());
            rule.setParameterRrn(parameterSetVersion.getParameterRrn());
            rule.setCollectionRuleSequence(++i);
            dataCollectionRuleManager.insertDataCollectionRule(rule);
        }

    }

    @Override
    public NonRTReturnInfoDTO importUploadData(List<NonRTUploadDTO> uploadDataInfos, Facility facility, User user,
                                               String importType, Map dataInfo) {
        boolean isOcapSend = StringUtils.isNotBlank(MapUtils.getStringCheckNull(dataInfo, "ocapId"));
        NonRTReturnInfoDTO returnInfo = importUploadData(uploadDataInfos, facility, user, importType, isOcapSend);

        boolean needHold = NonRTMathUtil.isNeedHoldEqptImportType(importType) ||
                checkAutoMoitorTypeNeedCreateOcap(importType, dataInfo, returnInfo);

        if (needHold && !isOcapSend) {
            if (returnInfo.getUploadSpc() && returnInfo.getHadViolation()) {
                for (Long eqptRrn : returnInfo.getVioEqptRrnList()) {
                    entityManager.logEventToWaitEng(facility.getInstanceRrn(), user.getInstanceId(), eqptRrn,
                                                    "NonRT value out of range");
                }
            }
            if (!checkOcapIsAlreadyExists(returnInfo)) {
                // ocap 处理
                if (MapUtils.isNotEmpty(returnInfo.getVioInfos())) {
                    Long measuringEqptRrn = MapUtils.getLong(dataInfo, "edcEqptRrn", 0L);
                    String measuringEqptId = MapUtils.getString(dataInfo, "edcEqptId", "");
                    List<OcapProcessingResultDTO> ocaplist = ocapManager.createOcapByOffLine(facility.getInstanceRrn(),
                                                                                             user.getInstanceRrn(),
                                                                                             user.getInstanceId(),
                                                                                             returnInfo.getTransRrn(),
                                                                                             returnInfo.getVioInfos(),
                                                                                             measuringEqptId,
                                                                                             measuringEqptRrn);
                    if (CollectionUtils.isNotEmpty(ocaplist)) {
                        insertOcapChartInfo(facility.getInstanceRrn(), user.getInstanceId(), returnInfo, ocaplist);
                    }
                }
            }
        } else if (isOcapSend) {
            String offlineFlag = MapUtils.getString(dataInfo, "offlineFlag");
            String remark = StringUtils.EMPTY;
            if (StringUtils.equals(offlineFlag, SpecifiedActionEnum.RE_KEYIN_DATA.toString())) {
                remark = "offline Re-key-in upload data";
            } else if (StringUtils.equals(offlineFlag, SpecifiedActionEnum.REMEASURE.toString())) {
                remark = "offline Re-measure upload data";
            }
            Long ocapRrn = MapUtils.getLongValue(dataInfo, "ocapRrn");
            String ocapId = MapUtils.getStringCheckNull(dataInfo, "ocapId");
            if (returnInfo.getUploadDetails().size() > 0) {
                if (!returnInfo.getHadViolation()) { // 上传成功
                    insertNonRTUploadHistory(returnInfo.getUploadDetails(), user, StringUtils.EMPTY);
                } else {// 返回 OOS或OOC
                    insertNonRTUploadHistory(returnInfo.getUploadDetails(), user, ocapId);
                }
            }
            ocapManager.handleOcapSend(facility, user, ocapRrn, returnInfo.getHadViolation(), remark);
        }
        return returnInfo;
    }

    @Override
    public void handleEdcPlanByChart(List<Parameter> parameterList, List<EDCPlanExcelData> list, String impType) {
        edcSpcManager.addParameterByExcel(parameterList);

        edcSpcManager.insertEdcPlanImportHistory(list, impType);
    }

    @Override
    public void handleEdcPlanByExcel(Map<String, List<ParameterSetVersion>> parameterSetList,
                                     List<EDCPlanExcelData> list, String impType) {
        edcSpcManager.addEDCPlanByExcel(parameterSetList);

        edcSpcManager.insertEdcPlanImportHistory(list, impType);
    }

    @Override
    public void handleEdcPlanByExcel(String parameterSetId, List<ParameterSetVersion> versionList,
                                     EDCPlanExcelData data, String impType) {
        edcSpcManager.addEDCPlanByExcel(parameterSetId, versionList);
        edcSpcManager.insertEdcPlanImportHistory(Collections.singletonList(data), impType);
    }

    @Override
    public String queryOfflineUnitList(String jobId, String lotId, String ocapId) {
        return edcSpcDAO.queryOfflineUnitList(jobId, lotId, ocapId);
    }

    @Override
    public NonRTUploadCheckResult impNonRTUploadData(NonRTUploadDataInfo reqData, String userId) {
        NonRTUploadData data = new NonRTUploadData();
        BeanUtils.copyProperties(reqData, data);
        NonRTUploadCheckResult result = edc2SpcContainer.impNonRTUploadData(data, userId);
        equipmentChartManager.updateLastUploadTimestampWhenUpload(userId, reqData.getEqptRrn(), reqData.getJobId());
        emasManager.updateEmasChartLastUpLoadTime(reqData.getEqptRrn(), reqData.getJobName());
        return result;
    }

    @Override
    public List<Map> getMainEqpNonRTJobList(Long eqptRrn) {
        List<String> jobIds = new ArrayList<>();
        List<Map> jobList = new ArrayList<>();

        String eqptId = namedObjectManager.getInstanceId(eqptRrn);
        String spcResult = edc2SpcContainer.getNonRTJob(eqptId);
        List<Map> nonRTJobList = JsonUtils.toList(spcResult, Map.class);
        jobList.addAll(buildJobList(jobIds, nonRTJobList, eqptId, eqptRrn));

        List<Entity> childEqptList = equipmentManager.getChildChamberEquip(eqptRrn);
        for (Entity entity : childEqptList) {
            String childSpcResult = edc2SpcContainer.getNonRTJob(entity.getInstanceId());
            if (StringUtils.isBlank(childSpcResult)) {
                continue;
            }
            List<Map> childNonRTJobList = JsonUtils.toList(childSpcResult, Map.class);
            jobList.addAll(buildJobList(jobIds, childNonRTJobList, entity.getInstanceId(), entity.getInstanceRrn()));
        }
        return jobList;
    }

    public Timestamp timestampPlusHours(Timestamp timestamp, Float hours) {
        if (timestamp == null) {
            return null;
        }
        if (hours == null) {
            return timestamp;
        }
        return new Timestamp(timestamp.getTime() + (long) (hours * 60 * 60 * 1000));
    }

    private boolean checkOcapIsAlreadyExists(NonRTReturnInfoDTO returnInfo) {
        List<Map<String, Object>> ocapChartInfos = returnInfo.getOcapChartInfos();

        if (Objects.isNull(ocapChartInfos)) {
            return true;
        }

        for (Map<String, Object> ocapChartInfo : ocapChartInfos) {
            String jobName = MapUtils.getString(ocapChartInfo, "jobName");
            Long eqptRrn = MapUtils.getLong(ocapChartInfo, "eqptRrn");
            String ocapId = ocapQueryManager.getActiveOfflineOcapId(eqptRrn, jobName);

            if (StringUtils.isNotBlank(ocapId)) {
                return true;
            }
        }
        return false;
    }

    private boolean checkAutoMoitorTypeNeedCreateOcap(String importType, Map ocapinfo, NonRTReturnInfoDTO returnInfo) {
        if (StringUtils.equals(NonRTMathUtil.NONRT_IMPORT_TYPE_AUTO_MONITOR, importType)) {
            String eqptType = MapUtils.getString(ocapinfo, "eqptType");
            if (AutoMonitorUtils.checkStepIsPreEdcStep(eqptType)) {
                return false;
            }

            if (checkOcapIsAlreadyExists(returnInfo)) {
                return false;
            }
        }
        return true;
    }

    private List<Map> buildJobList(List<String> jobIds, List<Map> nonRTJobList, String eqptId, Long eqptRrn) {
        List<Map> jobList = new ArrayList<>();
        for (Map nonRTJob : nonRTJobList) {
            String jobId = MapUtils.getString(nonRTJob, "JobID");
            String formula = MapUtils.getString(nonRTJob, "Formula");

            if (!jobIds.contains(jobId)) {
                jobIds.add(jobId);
                if (NonRTMathUtil.isBasicFormula(formula)) {
                    nonRTJob.put("eqptId", eqptId);
                    nonRTJob.put("eqptRrn", eqptRrn);
                    jobList.add(nonRTJob);
                }
            }
        }
        return jobList;
    }

    private long insertNonRTUploadHistory(List<NonRTUploadDetailDTO> uploadDetails, User user, String ocapId) {
        TransactionLog transactionLog = transactionLogManager.startTransactionLog(user.getInstanceId(),
                                                                                  TransactionNames.NON_RT_UPLOAD_WITH_OCAP);
        edcSpcDAO.insertNonRTUploadHistory(uploadDetails, transactionLog.getTransRrn(), ocapId);
        transactionLogManager.markTransactionLog(transactionLog);
        return transactionLog.getTransRrn();
    }

    private NonRTReturnInfoDTO importUploadData(List<NonRTUploadDTO> uploadDataInfos, Facility facility, User user,
                                                String importType, boolean isOcapSend) {
        List<NonRTUploadDataInfo> saveList = new ArrayList<NonRTUploadDataInfo>();
        List<NonRTUploadDataInfo> postList = new ArrayList<NonRTUploadDataInfo>();
        for (NonRTUploadDTO uploadDataInfoDTO : uploadDataInfos) {
            NonRTUploadDataInfo baseInfo = buildUploadDataBaseInfo(facility, user, importType, uploadDataInfoDTO);

            String lotId = uploadDataInfoDTO.getJobBaseInfo().getLotId();
            Lot lot = lotQueryManager.getLot(lotId, facility.getInstanceRrn());
            Assert.isFalse(StringUtils.isNotBlank(lotId) && lot.getLotRrn() <= 0,
                           Errors.create().content("Incorrect lot information!").build());

            for (NonRTUnitInfoDTO unitInfo : uploadDataInfoDTO.getUnitList()) {
                Assert.isFalse(unitInfo.getValueList() == null || unitInfo.getValueList().length !=
                                       uploadDataInfoDTO.getJobBaseInfo().getSubgroupSize(),
                               Errors.create().content("Value list size unequal the subgroup size!").build());

                NonRTUploadDataInfo dataValueInfo = buildUploadDataValueInfo(lot, baseInfo, unitInfo);
                saveList.add(dataValueInfo);

                if (StringUtils.equalsIgnoreCase(NonRTMathUtil.NONRT_FORMULA_POST_KEY, baseInfo.getValueType())) {
                    postList.add(dataValueInfo);
                }
            }
        }

        List<NonRTUploadDataInfo> uploadDataList = new ArrayList<NonRTUploadDataInfo>();
        if (postList.size() > 0) {
            preAndDeriveChartDataHandle(facility, importType, saveList, postList, uploadDataList);
        }

        // vio flag
        boolean hadViolation = false;
        List<String> violitionIds = new ArrayList<String>();
        List<Long> vioEqptRrns = new ArrayList<>();

        // ocap info
        Map<NonRTUploadDataInfo, NonRTUploadCheckResult> nonRTDataInfos = new HashMap<>();
        List<NonRTUploadDetailDTO> detailDTOList = new ArrayList<>();
        List<Map<String, Object>> ocapChartInfoList = new ArrayList<>();


        // upload data
        for (NonRTUploadDataInfo uploadDataInfo : uploadDataList) {
            String lotId = uploadDataInfo.getLotId();
            Lot tempLot = lotQueryManager.getLot(lotId, LocalContext.getFacilityRrn());
            if (tempLot != null && tempLot.getLotRrn() > 0) {
                uploadDataInfo.setProcessId(tempLot.getProcessId());
            }
            NonRTUploadCheckResult result = impNonRTUploadData(uploadDataInfo, user.getInstanceId());

            if (validateSpcResultsHadViolate(result, uploadDataInfo, saveList, nonRTDataInfos)) {
                hadViolation = true;
            }

            Map<String, Object> jobInfoMap = new HashMap<String, Object>();
            jobInfoMap.put("jobId", uploadDataInfo.getJobId());
            jobInfoMap.put("jobName", uploadDataInfo.getJobName());
            jobInfoMap.put("url", result.getUrl());
            jobInfoMap.put("eqptRrn", uploadDataInfo.getEqptRrn());

            ocapChartInfoList.add(jobInfoMap);
            detailDTOList.add(new NonRTUploadDetailDTO(uploadDataInfo, result));

            if (hadViolation && (!violitionIds.contains(uploadDataInfo.getLotId()))) {
                violitionIds.add(uploadDataInfo.getLotId());
            }
            if (hadViolation && (!vioEqptRrns.contains(uploadDataInfo.getEqptRrn()))) {
                vioEqptRrns.add(uploadDataInfo.getEqptRrn());
            }

        }

        // build return info
        NonRTReturnInfoDTO returnInfo = new NonRTReturnInfoDTO();

        if (saveList.size() > 0 && !isOcapSend) {
            returnInfo.setTransRrn(insertNonRTUploadHistory(saveList, user.getInstanceId()));
        }

        if (uploadDataList.size() > 0) {
            returnInfo.setUploadSpc(true);
            returnInfo.setHadViolation(hadViolation);

            returnInfo.setVioLotIds(violitionIds);
            returnInfo.setVioEqptRrnList(vioEqptRrns);
            returnInfo.setVioInfos(nonRTDataInfos);

            returnInfo.setUploadDetails(detailDTOList);
            returnInfo.setOcapChartInfos(ocapChartInfoList);

            // 对 list 根据 eqpId 以及 jobName 进行去重,保证相同 eqpId、jobName、checkType只close一条
            Set<NonRTUploadDetailDTO> set = new TreeSet<>(new Comparator<NonRTUploadDetailDTO>() {
                @Override
                public int compare(NonRTUploadDetailDTO n1, NonRTUploadDetailDTO n2) {
                    int compareToResult = 1;//==0表示重复
                    if(StringUtils.equals(n1.getUploadData().getEqptId(), n2.getUploadData().getEqptId()) &&
                            StringUtils.equals(n1.getUploadData().getJobName(), n2.getUploadData().getJobName())) {
                        compareToResult = 0;
                    }
                    return compareToResult;
                }
            });
            set.addAll(detailDTOList);
            List<NonRTUploadDetailDTO> nonRTUploadDetailDTOS = new ArrayList<>(set);
            // new Emas 处理 去重后的数据
            for (NonRTUploadDetailDTO detailDTO : nonRTUploadDetailDTOS) {
                String eqpId = detailDTO.getUploadData().getEqptId();
                String chartId = detailDTO.getUploadData().getJobName();
                emasEventManager.closeEmasEvent(eqpId, chartId);
            }
        }
        return returnInfo;
    }

    private void preAndDeriveChartDataHandle(Facility facility, String importType, List<NonRTUploadDataInfo> saveList,
                                             List<NonRTUploadDataInfo> postList,
                                             List<NonRTUploadDataInfo> uploadDataList) {
        for (NonRTUploadDataInfo postInfo : postList) {
            NonRTUploadDataInfo uploadDataInfo = new NonRTUploadDataInfo();
            BeanUtils.copyProperties(postInfo, uploadDataInfo);

            if (NonRTMathUtil.isNeedPreValue(uploadDataInfo.getFormulaType())) {

                NonRTUploadDataInfo preInfo = getPreDataInfoByPostInfo(importType, saveList, uploadDataInfo);

                Assert.isFalse(preInfo == null, Errors.create().content(
                                                              "The NonRT chart:{} wafer:{} need pre value," + "please"
                                                                      + " check the transData or history")
                                                      .args(uploadDataInfo.getJobName(), uploadDataInfo.getUnitId())
                                                      .build());

                double[] values = new double[uploadDataInfo.getValueList().length];
                for (int i = 0; i < values.length; i++) {
                    double pre = preInfo.getValueList()[i];
                    double post = postInfo.getValueList()[i];
                    String time = uploadDataInfo.getFormulaPara();
                    String formulaType = uploadDataInfo.getFormulaType();
                    double value = formatDataValue(NonRTMathUtil.mathDataValue(formulaType, pre, post, time),
                                                   facility.getInstanceRrn());
                    if (StringUtils.contains(formulaType, "C") && value < 0) {
                        value = 0;
                    }
                    values[i] = value;
                }

                uploadDataInfo.setValueList(values);
            } else {
                for (int i = 0; i < uploadDataInfo.getValueList().length; i++) {
                    uploadDataInfo.getValueList()[i] = formatDataValue(uploadDataInfo.getValueList()[i],
                                                                       facility.getInstanceRrn());
                }
            }

            uploadDataList.add(uploadDataInfo);

            if (NonRTMathUtil.isNeedDeriveChart(uploadDataInfo.getFormulaType())) {
                String deriveFormulaType = StringUtils.split(uploadDataInfo.getFormulaType(), ",")[1];
                if (NonRTMathUtil.isAvaliableFormula(deriveFormulaType)) {
                    NonRTUploadDataInfo deriveDataInfo = buildDeriveChartUploadInfo(facility, uploadDataInfo,
                                                                                    deriveFormulaType);
                    saveList.add(deriveDataInfo);
                    uploadDataList.add(deriveDataInfo);
                }
            }
        }
    }

    private void insertOcapChartInfo(Long facilityRrn, String userId, NonRTReturnInfoDTO returnDTO,
                                     List<OcapProcessingResultDTO> ocaplist) {
        for (OcapProcessingResultDTO ocapDTO : ocaplist) {
            String jobId = "";
            String jobName = "";
            String url = "";

            for (NonRTUploadDetailDTO detail : returnDTO.getUploadDetails()) {
                if (StringUtils.isEmpty(detail.getUploadData().getViolationInfo())) {
                    continue;
                }
                if (StringUtils.equals(ocapDTO.getChartName(), detail.getUploadData().getJobName())) {
                    jobId = detail.getUploadData().getJobId();
                    jobName = detail.getUploadData().getJobName();
                    url = detail.getResultInfo().getUrl();
                    if (ocapDTO.getCreationFlag()) {
                        StringBuilder msg = new StringBuilder(detail.getUploadData().getViolationInfo());
                        msg.append(":" + ocapDTO.getOcapId());
                        detail.getUploadData().setViolationInfo(msg.toString());
                    }
                    break;
                }
            }

            String newOcapId = ocapDTO.getOcapId();
            // 在NON_RT_DATA_HISTORY的数据上标识ocap_Id
            updateNonRTUploadHistoryWithOcapId(newOcapId, userId, returnDTO.getTransRrn());

            // 记录chart info
            Long planRrn = ocapQueryManager.getOcapCardRrnByUniqueKey(facilityRrn, newOcapId, null);
            OcapChartInfoDTO dto = new OcapChartInfoDTO(planRrn, jobId, jobName, url);

            ocapManager.insertOcapChartInfo(dto);
        }
    }

    private void updateNonRTUploadHistoryWithOcapId(String newOcapId, String userId, Long transRrn) {
        TransactionLog transactionLog = transactionLogManager.startTransactionLog(userId,
                                                                                  TransactionNames.NON_RT_UPLOAD_UPDATE);
        edcSpcDAO.updateNonRTUploadHistoryWithOcapId(newOcapId, transRrn);
        transactionLogManager.markTransactionLog(transactionLog);
    }

    private boolean validateSpcResultsHadViolate(NonRTUploadCheckResult result, NonRTUploadDataInfo valueInfo,
                                                 List<NonRTUploadDataInfo> saveList,
                                                 Map<NonRTUploadDataInfo, NonRTUploadCheckResult> nonRTDataInfos) {
        boolean hadViolation = false;
        if (result != null) {
            Assert.isFalse(StringUtils.equalsIgnoreCase("1", result.getReturnCode()),
                           Errors.create().content(result.getReturnMessage()).build());

            String rm = result.getReturnMessage();
            if (StringUtils.contains(result.getReturnMessage(), "Violate Rule")) {
                String violate = rm.substring(StringUtils.indexOf(rm, "Violate Rule") + "Violate Rule".length() + 1,
                                              StringUtils.indexOf(rm, "||", StringUtils.indexOf(rm, "Violate Rule")));

                hadViolation = true;
                for (NonRTUploadDataInfo saveInfo : saveList) {
                    if (StringUtils.equalsIgnoreCase(saveInfo.getJobId(), valueInfo.getJobId()) &&
                            StringUtils.equalsIgnoreCase(saveInfo.getLotId(), valueInfo.getLotId()) &&
                            StringUtils.equalsIgnoreCase(saveInfo.getUnitId(), valueInfo.getUnitId())) {
                        saveInfo.setViolationInfo(violate);
                        valueInfo.setViolationInfo(violate);
                        result.setHoldFlag(true);
                        nonRTDataInfos.put(saveInfo, result);
                    }
                }
            }
        }
        return hadViolation;
    }

    private double formatDataValue(double value, long facilityRrn) {

        // 查询上下限值
        List<ReferenceFileDetail> refFileValues = referenceFileManager.getRefFileValues("$$EDC_DATAVALUE_LIMIT",
                                                                                        namedObjectManager.getNamedSpace(
                                                                                                facilityRrn,
                                                                                                ObjectList.REFERENCE_FILE_KEY));

        double upperLimit = 0.0;
        double lowerLimit = 0.0;
        boolean checkUpperFLag = false;
        boolean checkLowerFLag = false;
        if (CollectionUtils.isNotEmpty(refFileValues)) {
            for (Iterator<ReferenceFileDetail> it = refFileValues.iterator(); it.hasNext(); ) {
                ReferenceFileDetail ref = it.next();
                if (StringUtils.isNotBlank(ref.getData1Value()) && NumberUtils.isNumber(ref.getData1Value()) &&
                        StringUtils.equals(ref.getKey1Value(), "LOWER LIMIT VALUE")) {
                    lowerLimit = NumberUtils.toDouble(ref.getData1Value(), lowerLimit);
                    checkLowerFLag = true;
                    continue;
                } else if (StringUtils.isNotBlank(ref.getData1Value()) && NumberUtils.isNumber(ref.getData1Value()) &&
                        StringUtils.equals(ref.getKey1Value(), "UPPER LIMIT VALUE")) {
                    upperLimit = NumberUtils.toDouble(ref.getData1Value(), upperLimit);
                    checkUpperFLag = true;
                }
            }

            /**
             * 判断dataValue是否大于上限upperLimit或者小于下限lowerLimit
             */
            if (checkUpperFLag && value >= upperLimit) {
                value = upperLimit;
            } else if (checkLowerFLag && value <= lowerLimit) {
                value = lowerLimit;
            }
        }

        if (new Double(value).toString().length() > 15) {
            value = NumberUtils.toDouble(StringUtils.substring(new Double(value).toString(), 0, 15));
        }

        return value;
    }

    private NonRTUploadDataInfo buildDeriveChartUploadInfo(Facility facility, NonRTUploadDataInfo uploadDataInfo,
                                                           String deriveFormulaType) {
        NonRTUploadDataInfo deriveInfo = new NonRTUploadDataInfo();
        BeanUtils.copyProperties(uploadDataInfo, deriveInfo);

        deriveInfo.setJobId(deriveInfo.getDeriveJobId());
        deriveInfo.setJobName(deriveInfo.getDeriveJobName());
        deriveInfo.setNonRTKey(deriveInfo.getDeriveNonRTKey());
        deriveInfo.setValueType("DERIVE");

        double value = formatDataValue(NonRTMathUtil.mathDataValue(deriveFormulaType, uploadDataInfo.getValueList()),
                                       facility.getInstanceRrn());
        deriveInfo.setValueList(new double[]{value});
        deriveInfo.setFormula(NonRTMathUtil.getNonRTFormula(deriveFormulaType));
        deriveInfo.setFormulaType(deriveFormulaType);

        return deriveInfo;
    }

    private NonRTUploadDataInfo getPreDataInfoByPostInfo(String importType, List<NonRTUploadDataInfo> saveList,
                                                         NonRTUploadDataInfo postInfo) {
        NonRTUploadDataInfo preInfo = null;
        for (NonRTUploadDataInfo saveInfo : saveList) {
            if (StringUtils.equalsIgnoreCase(saveInfo.getJobId(), postInfo.getJobId()) &&
                    StringUtils.equalsIgnoreCase(saveInfo.getLotId(), postInfo.getLotId()) &&
                    StringUtils.equalsIgnoreCase(saveInfo.getUnitId(), postInfo.getUnitId()) &&
                    StringUtils.equalsIgnoreCase(NonRTMathUtil.NONRT_FORMULA_PRE_KEY, saveInfo.getValueType())) {
                preInfo = saveInfo;
                break;
            }
        }

        if (preInfo == null) {
            List<String> unitList = new ArrayList<String>();
            unitList.add(postInfo.getUnitId());
            List<NonRTUploadDataInfo> list = getNonRTDataValues(postInfo.getJobName(), postInfo.getLotRrn(), unitList);
            for (NonRTUploadDataInfo dataInfo : list) {
                if (StringUtils.equalsIgnoreCase(NonRTMathUtil.NONRT_FORMULA_PRE_KEY, dataInfo.getValueType())) {
                    preInfo = dataInfo;
                    preInfo.setImportType(importType);
                    saveList.add(preInfo);
                    break;
                }
            }
        }
        return preInfo;
    }

    private NonRTUploadDataInfo buildUploadDataValueInfo(Lot lot, NonRTUploadDataInfo baseInfo,
                                                         NonRTUnitInfoDTO unitInfo) {
        NonRTUploadDataInfo valueInfo = new NonRTUploadDataInfo();
        BeanUtils.copyProperties(baseInfo, valueInfo);

        if (lot != null && lot.getLotRrn() > 0) {
            Assert.isTrue(StringUtils.equalsIgnoreCase("C", lot.getCreateCategory()),
                          Errors.create().content("Error Lot Type").build());

            valueInfo.setLotId(lot.getLotId());
            valueInfo.setLotRrn(lot.getLotRrn());

            Unit unit = unitQueryManager.getUnit(lot.getFacilityRrn(), unitInfo.getUnitId());
            Assert.isFalse(unit == null || unit.getUnitRrn() <= 0,
                           Errors.create().content("Incorrect unit information!").build());
            valueInfo.setUnitId(unitInfo.getUnitId());
            valueInfo.setUnitRrn(unit.getUnitRrn());

            valueInfo.setPro1(lot.getLotId());
            valueInfo.setPro2(unitInfo.getUnitId());
        }
        valueInfo.setValueList(unitInfo.getValueList());

        return valueInfo;
    }

    private NonRTUploadDataInfo buildUploadDataBaseInfo(Facility facility, User user, String importType,
                                                        NonRTUploadDTO dataInfo) {
        NonRTUploadDataInfo info = new NonRTUploadDataInfo();
        info.setImportType(importType);
        info.setFabId(facility.getInstanceId());
        info.setFacilityRrn(facility.getInstanceRrn());

        info.setEqptId(dataInfo.getJobBaseInfo().getEqptId());
        info.setEqptRrn(dataInfo.getJobBaseInfo().getEqptRrn());
        info.setArea(dataInfo.getJobBaseInfo().getArea());
        info.setJobId(dataInfo.getJobBaseInfo().getJobId());
        info.setJobName(dataInfo.getJobBaseInfo().getJobName());
        info.setNonRTKey(dataInfo.getJobBaseInfo().getNonRTKey());
        info.setFormulaType(dataInfo.getJobBaseInfo().getFormulaType());
        info.setFormulaPara(dataInfo.getJobBaseInfo().getFormulaPara());
        info.setTime(dataInfo.getJobBaseInfo().getFormulaPara());
        info.setCreateUser(user.getInstanceId());
        info.setValueType(dataInfo.getJobBaseInfo().getValueType());
        info.setDeriveJobId(dataInfo.getJobBaseInfo().getDeriveChartID());
        info.setDeriveJobName(dataInfo.getJobBaseInfo().getDeriveChartName());
        info.setDeriveNonRTKey(dataInfo.getJobBaseInfo().getDeriveNonRTKey());
        info.setSubgroupSizeFlag(StringUtils.toString(dataInfo.getJobBaseInfo().getSubgroupSize()));

        info.setFormula(NonRTMathUtil.getNonRTFormula(info.getFormulaType()));
        return info;
    }

    private ParameterSet buildParameterSetForInsert(String parameterSetId) {
        long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();
        ParameterSet parameterSet = new ParameterSet(parameterSetId, namedObjectManager.getNamedSpace(facilityRrn,
                                                                                                      ObjectList.PARAMETERSET_KEY),
                                                     ObjectList.PARAMETERSET_KEY);
        parameterSet.setTransPerformedby(user);
        return parameterSet;
    }

    private ObjectVersion getNewestParameterSetVersion(ParameterSet parameterSet) {
        List<ObjectVersion> versions = parameterSetManager.getBaseVersions(parameterSet);
        if (versions == null || versions.isEmpty()) {
            buildParameterSetVersion(parameterSet, 1);
            versions = parameterSetManager.getBaseVersions(parameterSet);
        }

        return versions.iterator().next();
    }

    private void buildParameterSetVersion(ParameterSet parameterSet, Integer version) {

        String user = LocalContext.getUserId();

        ParameterSetVersion parameterSetVersion = new ParameterSetVersion();
        parameterSetVersion.setInstanceRrn(parameterSet.getInstanceRrn());
        parameterSetVersion.setInstanceVersion(version);
        parameterSetVersion.setVersionId(version.toString());

        parameterSetVersion.setVersionDesc("Automatic schema generation");
        parameterSetVersion.setTransId("create");
        parameterSetVersion.setTransPerformedby(user);

        Ecn ecn;
        try {
            ecn = generateUnFrozenECNForParameterSetVersion();
        } catch (SystemIllegalArgumentException e) {
            throw new SystemIllegalArgumentException(Errors.create().key(MessageIdList.SYSTEM_UPDATE_VERSION_ERROR)
                                                           .content("导入至 {},系统今日导入的版本已达最大值,请明日再试! ")
                                                           .args(parameterSet.getInstanceId()).build());
        }

        parameterSetVersion.setEffectiveDateFrom(DateUtils.stringToTimestamp(ecn.getEffectiveDateFrom()));
        parameterSetVersion.setEffectiveDateTo(DateUtils.stringToTimestamp(ecn.getEffectiveDateTo()));
        parameterSetVersion.setEcnRrn(ecn.getInstanceRrn());

        parameterSetManager.insertParameterSetVersion(parameterSetVersion);
    }

    private Ecn generateUnFrozenECNForParameterSetVersion() {

        long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();

        Long userRrn = LocalContext.getUserRrn();
        String defaultType = "PROCESSPLAN";

        String ecnId = ecnManager.generateECNID();

        Ecn ecn = new Ecn(ecnId, namedObjectManager.getNamedSpace(facilityRrn, ObjectList.ECN_KEY), ObjectList.ECN_KEY);

        ecn.setInstanceDesc("Automatic schema generation");

        ecn.setEffectiveDateFrom(DateUtils.formatDate(new Date()));
        ecn.setEffectiveDateTo(getEffectiveDateTo());

        ecn.setEcnStatus(VersionStatus.UNFROZEN_KEY);

        ecn.setObject(ObjectList.ECN_KEY);

        ecn.setTransId(TransactionNames.CREATE_KEY);

        ecn.setObjectType(defaultType);
        ecn.setObjectSubtype(defaultType);
        ecn.setRequestBy(userRrn);
        ecn.setTransPerformedby(user);

        ecn.setInstanceRrn(ecnManager.insertEcn(ecn));

        return ecn;
    }

    private String getEffectiveDateTo() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 100);
        return DateUtils.formatDate(cal.getTime());
    }

    private void deleteParameterSetVersion(Long parameterSetRrn, Integer parameterSetVersion) {
        edcSpcDAO.deleteParameterSetVersion(parameterSetRrn, parameterSetVersion);
        edcSpcDAO.deleteSamplePromptsForAll(parameterSetRrn, parameterSetVersion);
        edcSpcDAO.deleteReadingPromptsForAll(parameterSetRrn, parameterSetVersion);
        edcSpcDAO.deleteDataCollectionRuleForAll(parameterSetRrn, parameterSetVersion);
        parameterSetManager.adjustParameterSetVersion(parameterSetRrn, null);
    }

    private Parameter buildParameterForInsert(String parameterId) {
        String dataType = "VARIABLE";
        long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();
        Parameter parameter = new Parameter(parameterId,
                                            namedObjectManager.getNamedSpace(facilityRrn, ObjectList.PARAMETER_KEY),
                                            ObjectList.PARAMETER_KEY);
        parameter.setTransPerformedby(user);
        parameter.setDataType(dataType);

        return parameter;
    }

}