EdcInqServiceImpl.java

package com.mycim.server.wip.service;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
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.server.automonitor.manager.AutoMonitorItemInqManager;
import com.mycim.server.automonitor.manager.LotAutoMonitorInqManager;
import com.mycim.server.edc.manager.ParameterSetManager;
import com.mycim.server.edcchart.manager.EdcSpcManager;
import com.mycim.server.wip.manager.*;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.automonitor.entity.AutoMonitorItemStepEdcInfo;
import com.mycim.valueobject.automonitor.entity.LotAutoMonitorInfo;
import com.mycim.valueobject.automonitor.util.AutoMonitorOperationConstants;
import com.mycim.valueobject.consts.ActionPointList;
import com.mycim.valueobject.consts.EDCConst;
import com.mycim.valueobject.edcspc.Parameter;
import com.mycim.valueobject.edcspc.ParameterSetVersion;
import com.mycim.valueobject.edcspc.rule.CollectionRule;
import com.mycim.valueobject.ems.Equipment;
import com.mycim.valueobject.runcard.util.RunCardUtils;
import com.mycim.valueobject.wip.*;
import com.mycim.valueobject.wip.dto.ParameterDto;
import com.mycim.valueobject.wip.dto.ParameterSetDto;
import com.mycim.valueobject.wip.dto.ReadingDto;
import com.mycim.valueobject.wip.dto.SampleDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author finatice.yang
 * @date 2022/1/17
 **/
@Service
public class EdcInqServiceImpl implements EdcInqService {

    @Autowired
    LotInqManager lotInqManager;

    @Autowired
    LotStepHistoryInqManager lotStepHistoryInqManager;

    @Autowired
    DiffBatchQueryManager diffBatchQueryManager;

    @Autowired
    RunCardQueryManager runCardQueryManager;

    @Autowired
    LotAutoMonitorInqManager lotAutoMonitorInqManager;

    @Autowired
    AutoMonitorItemInqManager autoMonitorItemInqManager;

    @Autowired
    UnitQueryManager unitQueryManager;

    @Autowired
    ParameterSetManager parameterSetManager;

    @Autowired
    EdcQueryManager edcQueryManager;

    @Autowired
    EdcSpcManager edcSpcManager;

    @Override
    public ParameterSetDto getParameterSetDto(Lot lot, Equipment equipment) {
        ParameterSetDto parameterSetDto = null;

        if (diffBatchQueryManager.checkLotIsBatchMonitorLot(lot.getLotRrn(), equipment)) {
            List<Lot> batchLotList = diffBatchQueryManager.getBatchLotList(lot.getLotRrn());
            parameterSetDto = buildParameterSetInfoByBatch(batchLotList, equipment, lot);
        } else if (RunCardUtils.checkLotIdIsRunCardLot(lot.getLotId())) {
            parameterSetDto = buildParameterSetInfoByRunCard(lot, equipment);
        } else if (lotAutoMonitorInqManager.checkLotIsAutoMonitorLot(lot.getLotRrn())) {
            parameterSetDto = buildParameterSetInfoByAutoMonitor(lot);
        } else {
            parameterSetDto = buildParameterSetInfoByNormal(lot, equipment);
        }
        return parameterSetDto;
    }

    @Override
    public CollectionRule getAvailableDataCollectionRule(Lot lot, List<Unit> unitList, Long parameterRrn) {
        Map<String, Object> matchMap = MapUtils.newHashMap();
        matchMap.put(EDCConst.CollectionRuleMatchKey.FACILITY_RRN.getMatchKey(), lot.getFacilityRrn());
        matchMap.put(EDCConst.CollectionRuleMatchKey.EQPT_RRN.getMatchKey(), lot.getEqptRrn());
        matchMap.put(EDCConst.CollectionRuleMatchKey.PRODUCT_RRN.getMatchKey(), lot.getProductRrn());

        Long matcRecipeRrn = lot.getRecipeRrn();
        if (matcRecipeRrn == null || matcRecipeRrn.longValue() <= 0) {
            matcRecipeRrn = lot.getRecipeLogicalRrn();
        }
        matchMap.put(EDCConst.CollectionRuleMatchKey.RECIPE_RRN.getMatchKey(), matcRecipeRrn);

        return edcQueryManager.getAvailableDataCollectionRule(lot.getFacilityRrn(), lot.getLotRrn(), matchMap, unitList,
                                                              parameterRrn);
    }

    @Override
    public String getChartOwnerHoldCode(List<ParameterDto> parameters) {
        return edcQueryManager.getChartOwnerHoldCode(parameters);
    }

    private ParameterSetDto buildParameterSetInfoByBatch(List<Lot> batchLotList, Equipment equipment, Lot lot) {

        List<ParameterDto> allParameterList = new ArrayList<>();

        for (Lot batchLot : batchLotList) {
            ParameterSetDto parameterSetInfoDto = null;

            if (RunCardUtils.checkLotIdIsRunCardLot(batchLot.getLotId())) {
                parameterSetInfoDto = buildParameterSetInfoByRunCard(batchLot, equipment);
            } else if (lotAutoMonitorInqManager.checkLotIsAutoMonitorLot(batchLot.getLotRrn())) {
                LotAutoMonitorInfo monitorInfo = lotAutoMonitorInqManager
                        .getLotActiveAutoMonitorInfo(batchLot.getLotRrn());
                parameterSetInfoDto = buildAutoMonitorParameterInfo(batchLot, monitorInfo);
            } else {
                parameterSetInfoDto = buildParameterSetInfoByNormal(batchLot, equipment);
            }

            if (Objects.nonNull(parameterSetInfoDto) &&
                    CollectionUtils.isNotEmpty(parameterSetInfoDto.getParameters())) {
                selectParameterList(allParameterList, parameterSetInfoDto.getParameters());
            }
        }

        if (CollectionUtils.isEmpty(allParameterList)) {
            return null;
        }

        // 3. 替换量测片
        List<Unit> unitList = unitQueryManager.getUnitList(lot.getLotRrn());
        List<ParameterDto> parameterInfoDtoList = new ArrayList<>();
        for (int i = 0; i < allParameterList.size(); i++) {
            ParameterDto baseParameterInfoDto = allParameterList.get(i);
            int size = baseParameterInfoDto.getSamplePrompts().iterator().next().getReadingPrompts().size();

            String parameterId = baseParameterInfoDto.getParameterId();
            Long paramrterRrn = baseParameterInfoDto.getParameterRrn();

            ParameterDto parameterInfo = buildAllUnitParameterDto(parameterId, size, unitList);
            parameterInfo.setParameterRrn(paramrterRrn);
            parameterInfo.setParameterSequence(i + 1);
            parameterInfoDtoList.add(parameterInfo);
        }

        ParameterSetDto parameterSetDto = new ParameterSetDto();
        parameterSetDto.setParameters(parameterInfoDtoList);

        return parameterSetDto;
    }

    private void selectParameterList(List<ParameterDto> allList, List<ParameterDto> selectList) {
        for (ParameterDto select : selectList) {
            Boolean needAdd = true;
            for (ParameterDto parameterInfoDto : allList) {
                if (StringUtils.equals(parameterInfoDto.getParameterId(), select.getParameterId())) {
                    needAdd = false;
                    break;
                }
            }
            if (needAdd) {
                allList.add(select);
            }
        }
    }

    private ParameterSetDto buildParameterSetInfoByAutoMonitor(Lot lot) {
        if (lotAutoMonitorInqManager.checkAutomonitorLotNeedSkipEdc(lot.getLotRrn(), lot.getStepSequence())) {
            return null;
        }

        LotAutoMonitorInfo monitorInfo = lotAutoMonitorInqManager.getLotActiveAutoMonitorInfo(lot.getLotRrn());
        ParameterSetDto parameterSetInfoDto = buildAutoMonitorParameterInfo(lot, monitorInfo);
        return parameterSetInfoDto;
    }

    private ParameterSetDto buildParameterSetInfoByRunCard(Lot lot, Equipment equipment) {
        List<ParameterSetVersion> allParameterSetVersionList = getRunCardParameterSetVersionList(lot);
        if (CollectionUtils.isEmpty(allParameterSetVersionList)) {
            return null;
        }

        List<Unit> unitList = unitQueryManager.getUnitList(lot.getLotRrn());
        unitList.stream().forEach(unit -> {
            unit.setUnitId(RunCardUtils.getShowUnitId(unit.getUnitId()));
        });

        ParameterSetDto parameterSetDto = buildParameterSetBaseInfo(allParameterSetVersionList.iterator().next());
        for (int i = 0; i < allParameterSetVersionList.size(); i++) {
            ParameterSetVersion parameterSetVersion = allParameterSetVersionList.get(i);
            Parameter parameter = (Parameter) parameterSetVersion.getParameters().iterator().next();
            if (lot.getEqptRrn() == null || lot.getEqptRrn().longValue() <= 0) {
                lot.setEqptRrn(equipment.getInstanceRrn());
            }

            List<Unit> edcUnitList = selectEdcUnit(unitList, parameter.getSelectedUnitIds());

            ParameterDto parameterDto = buildParameterInfo(parameterSetVersion, edcUnitList, i + 1);
            parameterSetDto.getParameters().add(parameterDto);
        }
        return parameterSetDto;
    }

    private ParameterSetDto buildParameterSetInfoByNormal(Lot lot, Equipment equipment) {
        String actionPoint = ActionPointList.MOVEOUT_KEY;
        List<ParameterSetVersion> parameterSetVersionList = getParameterSetVersionList(lot, equipment, actionPoint);
        if (CollectionUtils.isEmpty(parameterSetVersionList)) {
            return null;
        }

        List<Unit> unitList = unitQueryManager.getUnitList(lot.getLotRrn());

        ParameterSetDto parameterSetInfoDto = buildParameterSetBaseInfo(parameterSetVersionList.iterator().next());
        for (int i = 0; i < parameterSetVersionList.size(); i++) {
            ParameterSetVersion parameterSetVersion = parameterSetVersionList.get(i);
            Parameter parameter = (Parameter) parameterSetVersion.getParameters().iterator().next();
            if (lot.getEqptRrn() == null || lot.getEqptRrn().longValue() <= 0) {
                lot.setEqptRrn(equipment.getInstanceRrn());
            }

            CollectionRule collectionRule = getAvailableDataCollectionRule(lot, unitList, parameter.getInstanceRrn());
            Assert.state(Objects.nonNull(collectionRule),
                         Errors.create().content("The parameter :{} not set collection rule.")
                               .args(parameter.getInstanceId()).build());
            List<Unit> edcUnitList = selectEdcUnit(unitList, collectionRule.getSelectedUnitIds());

            ParameterDto parameterDto = buildParameterInfo(parameterSetVersion, edcUnitList, i + 1);
            parameterSetInfoDto.getParameters().add(parameterDto);
        }
        return parameterSetInfoDto;
    }

    private List<ParameterSetVersion> getParameterSetVersionList(Lot lot, Equipment equipment, String actionPoint) {
        return parameterSetManager.buildParameterSetInfo(lot, equipment, actionPoint);
    }

    private List<ParameterSetVersion> getRunCardParameterSetVersionList(Lot lot) {
        List<ParameterSetVersion> allParameterSetVersionList = new ArrayList<>();

        LotRunCardStep lotRunCardStep = runCardQueryManager.getLotRunCardStep(lot.getLotRrn());

        if (Objects.nonNull(lotRunCardStep)) {
            Long parameterSetRrn = lotRunCardStep.getOutParameterSetRrn();
            List<ParameterSetVersion> parameterSetVersionList = parameterSetManager
                    .getActiveParameterSetVersion(parameterSetRrn);
            List<LotRunCardStepParameter> stepParameterList = runCardQueryManager
                    .getLotRunCardStepParameterList(lotRunCardStep.getRunCardRrn(), lotRunCardStep.getStepSerialNo(),
                                                    parameterSetRrn);

            String[] unitRrns = StringUtils.split(lotRunCardStep.getMeasurementUnitRrns(), StringUtils.COMMA_SIGN);
            List<String> unitIdList = new ArrayList<>();
            if (unitRrns != null) {
                for (String unitRrn : unitRrns) {
                    unitIdList.add(unitQueryManager.getUnitIdByRrn(NumberUtils.toLong(unitRrn)));
                }
            }

            for (LotRunCardStepParameter stepParameter : stepParameterList) {
                String parameterId = stepParameter.getParameterId();
                for (ParameterSetVersion parameterSetVersion : parameterSetVersionList) {
                    if (StringUtils.equals(parameterId, parameterSetVersion.getParameterId())) {
                        Parameter parameter = (Parameter) parameterSetVersion.getParameters().iterator().next();
                        parameter.setSelectedUnitIds(unitIdList.toArray(new String[unitIdList.size()]));
                        allParameterSetVersionList.add(parameterSetVersion);
                    }
                }
            }
        }
        return allParameterSetVersionList;
    }

    private ParameterSetDto buildAutoMonitorParameterInfo(Lot lot, LotAutoMonitorInfo monitorInfo) {
        List<Map> nonRTJobList = edcSpcManager.getMainEqpNonRTJobList(monitorInfo.getMainEqptRrn());
        if (CollectionUtils.isEmpty(nonRTJobList)) {
            return null;
        }
        ParameterSetDto parameterSetInfoDto = new ParameterSetDto();
        parameterSetInfoDto.setParameters(new ArrayList<>());

        List<Unit> unitList = unitQueryManager.getUnitList(lot.getLotRrn());
        unitList.sort(new Comparator<Unit>() {
            @Override
            public int compare(Unit o1, Unit o2) {
                return o1.getPositionInCarrier().intValue() - o2.getPositionInCarrier().intValue();
            }
        });

        List<AutoMonitorItemStepEdcInfo> edcInfoList = autoMonitorItemInqManager
                .getEdcInfoList(monitorInfo.getWorkflowRrn(), monitorInfo.getWorkflowVersion(),
                                monitorInfo.getWorkflowStepSequence());
        if (CollectionUtils.isEmpty(edcInfoList)) {
            return null;
        }

        String nonRTSlotType = monitorInfo.getNonRTSlotType();

        checkNonRtJobInSpc(edcInfoList, nonRTJobList, nonRTSlotType);

        if (StringUtils.equals(nonRTSlotType, AutoMonitorOperationConstants.STEP_SLOT_TYPE_WAFER)) {
            Map<String, List<Unit>> jobUnitMapping = MapUtils.newHashMap();

            for (AutoMonitorItemStepEdcInfo edcInfo : edcInfoList) {
                String[] jobNames = StringUtils.split(edcInfo.getNonRTJobNames(), StringUtils.COMMA_SIGN);
                for (String jobName : jobNames) {
                    if (Objects.isNull(MapUtils.getObject(jobUnitMapping, jobName))) {
                        jobUnitMapping.put(jobName, new ArrayList<>());
                    }
                    jobUnitMapping.get(jobName).add(unitList.get(edcInfo.getWaferSlot().intValue() - 1));
                }
            }

            Integer sequence = NumberUtils.INTEGER_ONE;
            for (String jobName : jobUnitMapping.keySet()) {
                List<Unit> jobUnits = jobUnitMapping.get(jobName);
                Integer subGroupSize = getSubGroupSize(nonRTJobList, jobName);
                ParameterDto parameterInfoDto = buildAllUnitParameterDto(jobName, subGroupSize, jobUnits);
                parameterInfoDto.setParameterSequence(sequence++);
                parameterSetInfoDto.getParameters().add(parameterInfoDto);
            }
        } else {
            AutoMonitorItemStepEdcInfo edcInfo = edcInfoList.iterator().next();
            String[] jobNames = StringUtils.split(edcInfo.getNonRTJobNames(), StringUtils.COMMA_SIGN);
            Integer sequence = NumberUtils.INTEGER_ONE;
            for (String jobName : jobNames) {
                Integer subGroupSize = getSubGroupSize(nonRTJobList, jobName);
                ParameterDto parameterInfoDto = buildAllUnitParameterDto(jobName, subGroupSize, unitList);
                parameterInfoDto.setParameterSequence(sequence++);
                parameterSetInfoDto.getParameters().add(parameterInfoDto);
            }
        }
        return parameterSetInfoDto;
    }

    private Integer getSubGroupSize(List<Map> nonRTJobList, String jobName) {
        Integer subGroupSize = NumberUtils.INTEGER_ZERO;
        for (Map map : nonRTJobList) {
            if (StringUtils.equals(MapUtils.getString(map, "JobName"), jobName)) {
                subGroupSize = MapUtils.getInteger(map, "SubgroupSize");
                break;
            }
        }
        return subGroupSize;
    }

    private void rebuildParameterSelectUnitId(SRCLotSpecialStep lotSpecialStep,
                                              ParameterSetVersion parameterSetVersion) {
        Parameter parameter = (Parameter) parameterSetVersion.getParameters().iterator().next();
        parameter.setSelectedUnitIds(StringUtils.split(lotSpecialStep.getMeasSlotId(), StringUtils.COMMA_SIGN));
    }

    private List<Unit> selectEdcUnit(List<Unit> unitList, String[] selectUnitId) {
        List<Unit> edcUnitList = unitList.stream().filter(unit -> {
            for (String unitId : selectUnitId) {
                if (StringUtils.equals(unit.getUnitId(), unitId)) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        return edcUnitList;
    }

    private ParameterSetDto buildParameterSetBaseInfo(ParameterSetVersion parameterSetVersion) {
        ParameterSetDto parameterSetDto = new ParameterSetDto();

        parameterSetDto.setParameterSetRrn(parameterSetVersion.getInstanceRrn());
        parameterSetDto.setParameterSetVersion(parameterSetVersion.getInstanceVersion());
        parameterSetDto.setParameterSetSpecRrn(parameterSetVersion.getParameterSetSpecRrn());
        parameterSetDto.setParameterSetDesc(parameterSetVersion.getInstanceDesc());

        parameterSetDto.setParameters(new ArrayList<>());
        return parameterSetDto;
    }


    private ParameterDto buildParameterInfo(ParameterSetVersion parameterSetVersion, List<Unit> unitList,
                                            int parameterSequence) {
        Parameter parameter = (Parameter) parameterSetVersion.getParameters().iterator().next();

        ParameterDto parameterDto = buildAllUnitParameterDto(parameter.getInstanceId(),
                                                             parameter.getReadingPrompts().size(), unitList);
        parameterDto.setParameterRrn(parameter.getInstanceRrn());
        parameterDto.setParameterId(parameter.getInstanceId());
        parameterDto.setParameterDesc(parameter.getInstanceDesc());
        parameterDto.setParameterSequence(parameterSequence);
        parameterDto.setcollectionLevel(parameterSetVersion.getCollectionLevel());
        parameterDto.setDataType(parameterSetVersion.getDataType());
        parameterDto.setMeasureType(parameterSetVersion.getMeasureType());
        return parameterDto;
    }

    private ParameterDto buildAllUnitParameterDto(String jobName, Integer subGroupSize, List<Unit> unitList) {
        ParameterDto parameterInfoDto = new ParameterDto();
        parameterInfoDto.setParameterId(jobName);
        parameterInfoDto.setSamplePrompts(new ArrayList<SampleDto>());
        for (int j = 0; j < unitList.size(); j++) {
            Unit unit = unitList.get(j);
            SampleDto sampleInfoDto = new SampleDto();
            sampleInfoDto.setUnitId(unit.getUnitId());
            sampleInfoDto.setUnitRrn(unit.getUnitRrn());
            sampleInfoDto.setPosition(unit.getPositionInCarrier() + "");
            sampleInfoDto.setReadingPrompts(new ArrayList<ReadingDto>());
            sampleInfoDto.setSampleSequence(j + 1);

            for (int k = 0; k < subGroupSize; k++) {
                ReadingDto readingInfoDto = new ReadingDto();
                String readingId = EDCConst.READING_ID_PREFIX + (k + 1);
                readingInfoDto.setReadingId(readingId);
                readingInfoDto.setReadingSequence(k + 1);
                sampleInfoDto.getReadingPrompts().add(readingInfoDto);
            }
            parameterInfoDto.getSamplePrompts().add(sampleInfoDto);
        }
        return parameterInfoDto;
    }

    private void checkNonRtJobInSpc(List<AutoMonitorItemStepEdcInfo> edcInfoList, List<Map> nonRTJobList,
                                    String slotType) {

        List<String> notInSpcJobNameList = new ArrayList<>();
        if (StringUtils.equals(slotType, AutoMonitorOperationConstants.STEP_SLOT_TYPE_WAFER)) {
            for (AutoMonitorItemStepEdcInfo edcInfo : edcInfoList) {
                String[] jobNames = StringUtils.split(edcInfo.getNonRTJobNames(), StringUtils.COMMA_SIGN);

                for (String jobName : jobNames) {
                    boolean notInSpc = true;
                    for (Map map : nonRTJobList) {
                        if (StringUtils.equals(MapUtils.getString(map, "JobName"), jobName)) {
                            notInSpc = false;
                            break;
                        }
                    }
                    if (notInSpc && !notInSpcJobNameList.contains(jobName)) {
                        notInSpcJobNameList.add(jobName);
                    }
                }
            }
        } else {
            AutoMonitorItemStepEdcInfo edcInfo = edcInfoList.iterator().next();
            String[] jobNames = StringUtils.split(edcInfo.getNonRTJobNames(), StringUtils.COMMA_SIGN);
            for (String jobName : jobNames) {
                boolean notInSpc = true;
                for (Map map : nonRTJobList) {
                    if (StringUtils.equals(MapUtils.getString(map, "JobName"), jobName)) {
                        notInSpc = false;
                        break;
                    }
                }
                if (notInSpc && !notInSpcJobNameList.contains(jobName)) {
                    notInSpcJobNameList.add(jobName);
                }
            }
        }

        Assert.state(CollectionUtils.isEmpty(notInSpcJobNameList),
                     Errors.create().key(MessageIdList.AUTOMONITOR_NONRT_NOT_IN_SPC)
                           .args(notInSpcJobNameList.toString()).build());
    }

}