OcapQueryManagerImpl.java

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

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.mycim.framework.jdbc.Page;
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.time.DateUtils;
import com.mycim.framework.utils.msg.JsonUtils;
import com.mycim.framework.workflow.engine.WorkflowManagerService;
import com.mycim.server.base.manager.NamedObjectManager;
import com.mycim.server.ems.manager.EntityManager;
import com.mycim.server.prp.manager.WorkflowManager;
import com.mycim.server.wip.dao.OcapQueryDAO;
import com.mycim.server.wip.manager.EquipmentQueryManager;
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.GenerateOCAPIdUtil;
import com.mycim.utils.OcapUtil;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.consts.ActionIdEnum;
import com.mycim.valueobject.consts.EventName;
import com.mycim.valueobject.consts.OcapTypeEnum;
import com.mycim.valueobject.consts.VersionStatus;
import com.mycim.valueobject.ocap.OcapCard;
import com.mycim.valueobject.ocap.OcapStepOwner;
import com.mycim.valueobject.ocap.OcapTransData;
import com.mycim.valueobject.ocap.OcapTransLog;
import com.mycim.valueobject.ocap.dto.*;
import com.mycim.valueobject.wip.Lot;
import com.mycim.workflow.valueobject.WorkflowInstance;
import com.mycim.workflow.valueobject.WorkflowPath;
import com.mycim.workflow.valueobject.WorkflowStepModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author songpy
 * @version 1.0.0
 * @date 2021/1/21
 **/
@Service
@Transactional
public class OcapQueryManagerImpl implements OcapQueryManager {

    @Autowired
    OcapQueryDAO queryDAO;

    @Autowired
    EquipmentQueryManager equipmentQueryManager;

    @Autowired
    NamedObjectManager namedObjectManager;

    @Autowired
    UnitQueryManager unitQueryManager;

    @Autowired
    WorkflowManagerService workflowManagerService;

    @Autowired
    WorkflowManager workflowManager;

    @Autowired
    LotQueryManager lotQueryManager;

    @Autowired
    EntityManager entityManager;

    @Override
    public List<Map<String, String>> getWorkflowIdOptions() {
        List<Map<String, String>> results = new ArrayList<>();

        List<String> workflowIds = queryDAO.getWorkflowIds();
        for (String workflowId : workflowIds) {
            Map<String, String> map = new HashMap<>();

            map.put("key", workflowId);
            map.put("value", workflowId);

            results.add(map);
        }
        return results;
    }

    @Override
    public Page getOcapCardPage(OcapQueryConditionDTO queryConditionDTO) {
        Page page = new Page(queryConditionDTO.getPage(), queryConditionDTO.getLimit());
        queryConditionDTO.setStartTime(DateUtils.stringToTimestamp(queryConditionDTO.getStartDate()));
        queryConditionDTO.setEndTime(DateUtils.stringToTimestamp(queryConditionDTO.getEndDate() + " 24:00:00"));
        return queryDAO.getOcapCardPage(page, queryConditionDTO);
    }

    @Override
    public void checkActiveOfflineOcapId(Long facilityRrn, String equipmentId, String chartName) {
        long equipmentRrn = namedObjectManager.getNamedObjectRrn(equipmentId, facilityRrn, ObjectList.ENTITY_KEY);
        String ocapId = getActiveOfflineOcapId(equipmentRrn, chartName);
        Assert.isFalse(StringUtils.isNotEmpty(ocapId), Errors.create().content(
                "This equipment and chart have OCAP: {}, and the" + " specified action of the current review" + " " +
                        "step is empty or not supported. " + "Check, please.").args(ocapId).build());
    }

    @Override
    public void checkActiveInlineOcapId(Long lotRrn) {
        Assert.isFalse(StringUtils.isNotEmpty(getActiveInlineOcapId(lotRrn)),
                       Errors.create().content("Lot has valid OCAP. " + "Cannot do action.").build());
    }

    @Override
    public String getActiveOfflineOcapId(Long equipmentRrn, String chartName) {
        List<String> ocapIds = queryDAO.getOcapIds(equipmentRrn, chartName, OcapTypeEnum.OFFLINE.toString(),
                                                   VersionStatus.ACTIVE_KEY);
        if (CollectionUtils.isEmpty(ocapIds)) {
            return StringUtils.EMPTY;
        }
        return ocapIds.get(0);
    }

    @Override
    public String getMaxOcapIdOfToday(String planIdPattern) {
        return queryDAO.getMaxOcapIdOfToday(planIdPattern + GenerateOCAPIdUtil.SUFFIX_PLACEHOLDER);
    }

    @Override
    public OcapCard getOcapCardByUniqueKey(Long facilityRrn, String ocapId, String lotId) {
        return queryDAO.getOcapCardByUniqueKey(facilityRrn, ocapId, lotId);
    }

    @Override
    public List<OcapCard> getOcapCardsByBatch(Long facilityRrn, OcapCard ocap) {
        List<OcapCard> ocapCards = new ArrayList<OcapCard>();
        if (StringUtils.isNotEmpty(ocap.getOcapBatchId())) {
            ocapCards = queryDAO.getOcapCardsByBatchId(facilityRrn, ocap.getOcapBatchId());
            if (CollectionUtils.isEmpty(ocapCards)) {
                return new ArrayList<OcapCard>();
            }
        } else {
            ocapCards.add(ocap);
        }

        return ocapCards;
    }

    @Override
    public boolean hasActiveOfflineOcapCardIds(Long equipmentRrn) {
        return CollectionUtils.isNotEmpty(getActiveOfflineOcapIdsByProcessEquipment(equipmentRrn));
    }

    @Override
    public String getActiveInlineOcapId(Long lotRrn) {
        List<String> planIds = queryDAO.getOcapIds(lotRrn, OcapTypeEnum.INLINE.toString(), VersionStatus.ACTIVE_KEY);
        if (CollectionUtils.isEmpty(planIds)) {
            return StringUtils.EMPTY;
        }
        return planIds.get(0);
    }

    @Override
    public Long getOcapCardRrnByUniqueKey(Long facilityRrn, String ocapId, String lotId) {
        OcapCard ocap = getOcapCardByUniqueKey(facilityRrn, ocapId, lotId);
        if (ocap == null) {
            return null;
        }
        return ocap.getOcapRrn();
    }

    @Override
    public List<String> getActiveOfflineOcapIds(Long eqptRrn) {
        return getActiveOfflineOcapIdsByProcessEquipment(eqptRrn);
    }

    @Override
    public void checkActiveOfflineOcapId(Long eqptRrn) {
        List<String> ocapIds = getActiveOfflineOcapIdsByProcessEquipment(eqptRrn);
        Assert.isFalse(CollectionUtils.isNotEmpty(ocapIds), Errors.create().content(
                "Since the equipment has some OCAP IDs, the" + " equipment status cannot be " + "modified. OCAP IDs: " +
                        "{}").args(ocapIds.toString()).build());
    }

    @Override
    public Boolean checkLogEventActiveOfflineOcap(Long eqptRrn, String eventId) {
        List<String> ocapIds = getActiveOfflineOcapIdsByProcessEquipment(eqptRrn);

        if (CollectionUtils.isNotEmpty(ocapIds)) {
            return Arrays.asList(EventName.AVAILABLE_EQP_LOG_EVENT_BY_OFFLINE).contains(eventId);
        }

        return true;
    }

    @Override
    public OcapCard getOcapCardByPrimaryKey(Long ocapRrn) {
        return queryDAO.getOcapCardByPrimaryKey(ocapRrn);
    }

    @Override
    public List<OcapChartInfoDTO> queryOcapChartInfoList(OcapChartInfoDTO dto) {
        return queryDAO.queryOcapChartInfoList(dto);
    }

    @Override
    public List<OcapCard> getOcapCardsByBatchId(Long facilityRrn, String ocapBatchId) {
        return queryDAO.getOcapCardsByBatchId(facilityRrn, ocapBatchId);
    }

    @Override
    public boolean isValidOcapHold(Long lotRrn, String oldReason) {
        String ocapId = getActiveInlineOcapId(lotRrn);
        return StringUtils.isNotEmpty(ocapId) && StringUtils.contains(oldReason, ocapId);
    }

    @Override
    public OcapTransData getTransDataByUniqueKey(Long ocapRrn, String dataName) {
        return queryDAO.getTransDataByUniqueKey(ocapRrn, dataName);
    }

    @Override
    public List<OcapTransData> getTransDatasByOcapRrn(Long ocapRrn) {
        return queryDAO.getTransDatasByOcapRrn(ocapRrn);
    }

    @Override
    public List<OcapTransLog> getTransLogsByOcapRrn(Long ocapRrn) {
        return queryDAO.getTransLogsByOcapRrn(ocapRrn);
    }

    @Override
    public OcapCardDTO getOcapInfo(long facilityRrn, Long ocapRrn) {
        return buildOcapCardDTO(facilityRrn, getOcapCardByPrimaryKey(ocapRrn));
    }

    @Override
    public OcapCardDTO getOcapInfo(Long facilityRrn, String ocapId, String lotId) {
        return buildOcapCardDTO(facilityRrn, getOcapCardByUniqueKey(facilityRrn, ocapId, lotId));
    }

    @Override
    public String getRemeasureUnitIds(Long facilityRrn, Long lotRrn, Long parameterRrn) {
        String remeasureUnitIds = null;
        OcapCardDTO ocap = getOcapInfoByLot(facilityRrn, lotRrn);
        if (ocap != null) {
            String unitIdJson = OcapUtil.getRemeasureUnitIds(ocap.getTransDatas());
            if (StringUtils.isNotEmpty(unitIdJson)) {
                List<UnitIdDTO> unitIdDTOS = JsonUtils.toList(unitIdJson, UnitIdDTO.class);
                for (UnitIdDTO unitIdDTO : unitIdDTOS) {
                    if (Objects.nonNull(unitIdDTO.getParameterRrn()) &&
                            unitIdDTO.getParameterRrn().equals(parameterRrn)) {
                        remeasureUnitIds = unitIdDTO.getUnitIds();
                        break;
                    } else if (Objects.isNull(unitIdDTO.getParameterRrn())) { //为空代表为加量
                        remeasureUnitIds = unitIdDTO.getUnitIds();
                        break;
                    }
                }
            }
        }
        return remeasureUnitIds;
    }

    @Override
    public List<String> getActiveOfflineOcapListByLot(Long lotRrn) {
        List<String> ocapIds = queryDAO.getOcapIds(lotRrn, OcapTypeEnum.OFFLINE.toString(), VersionStatus.ACTIVE_KEY);

        return ocapIds;
    }

    private OcapCardDTO buildOcapCardDTO(Long facilityRrn, OcapCard ocap) {
        OcapCardDTO ocapCardDTO = buildOcapCardDTO(ocap);

        // 构建trans data
        ocapCardDTO.setTransDatas(buildTransDatas(ocapCardDTO.getOcapRrn()));

        // 构建trans log data
        ocapCardDTO.setTransLogs(buildTransLogs(ocapCardDTO.getOcapRrn()));

        // 构建 step,btn 信息
        ocapCardDTO.setStep(buildOcapStep(ocapCardDTO));

        // 构建current step 权限信息
        buildOcapStepOwner(ocapCardDTO);

        if (StringUtils.equals(VersionStatus.ACTIVE_KEY, ocap.getStatus())) {
            List<Map> units = unitQueryManager.getUnitListByLot(ocap.getLotRrn());
            List<Map<String, Object>> ocapUnits = new ArrayList<>();
            for (Map map : units) {
                ocapUnits.add(map);
            }
            ocapCardDTO.setUnits(ocapUnits);
        }
        return ocapCardDTO;
    }

    private void buildOcapStepOwner(OcapCardDTO ocapCardDTO) {
        List<OcapStepOwner> stepOwners = queryDAO.getOcapStepOwners(ocapCardDTO);
        ocapCardDTO.setStepOwners(stepOwners);

        StringJoiner sj = new StringJoiner(",");
        for (OcapStepOwner stepOwner : stepOwners) {
            sj.add(stepOwner.getStepOwnerId());
        }
        ocapCardDTO.setSignerId(sj.toString());
    }

    private OcapCardDTO buildOcapCardDTO(OcapCard ocap) {
        Assert.isFalse(ocap == null || ocap.getOcapRrn() == null || ocap.getOcapRrn() <= 0, Errors.create().content(
                "Can't find the OCAP, please confirm that it already exists in the system.").build());
        OcapCardDTO ocapInformationDTO = new OcapCardDTO();
        BeanUtils.copyProperties(ocap, ocapInformationDTO);
        return ocapInformationDTO;
    }

    private OcapStepDTO buildOcapStep(OcapCardDTO ocapCardDTO) {
        // 根据执行RRN 获取当前step rrn
        if (Objects.isNull(ocapCardDTO.getExecutionRrn()) || ocapCardDTO.getExecutionRrn() <= 0L) {
            return null;
        }

        WorkflowInstance workflowInstance = workflowManagerService.getWorkflowInstance(ocapCardDTO.getExecutionRrn());
        WorkflowPath path = workflowInstance.getPath();
        WorkflowStepModel stepModel = workflowManagerService.getWorkflowStepModel(path.getCurrentStepRrn());

        OcapStepDTO stepDTO = new OcapStepDTO();
        stepDTO.setStepRrn(stepModel.getStepRrn());
        stepDTO.setStepId(stepModel.getStepId());
        stepDTO.setStatus(stepModel.getComments());

        // 根据step rrn 获取 link id
        List<Map<String, Object>> linkInfos = workflowManager.getWflPathsByCurNode(stepModel.getStepRrn());
        if (CollectionUtils.isNotEmpty(linkInfos)) {
            stepDTO.setActions(linkInfos.stream().map(map -> {
                OcapStepActionDTO actionDTO = new OcapStepActionDTO();
                actionDTO.setPathId(MapUtils.getString(map, "pathId"));
                actionDTO.setActionId(
                        StringUtils.substringAfterLast(MapUtils.getString(map, "pathId"), StringUtils.UNDERLINE));
                //设置按钮显示的优先级,越小越靠前
                if (StringUtils.isNotEmptyTrim(actionDTO.getActionId())) {
                    actionDTO.setShowPriority(ActionIdEnum.valueOf(actionDTO.getActionId()).getSequence());
                } else {
                    actionDTO.setShowPriority(0);
                }
                WorkflowStepModel nextStepModel = workflowManagerService.getWorkflowStepModel(
                        MapUtils.getLongValue(map, "nextStepRrn", 0));
                actionDTO.setNextStepId(nextStepModel.getStepId());

                return actionDTO;
            }).collect(Collectors.toList()));
        }
        stepDTO.getActions().sort(Comparator.comparingInt(OcapStepActionDTO::getShowPriority));
        return stepDTO;
    }

    private List<OcapTransDataDTO> buildTransDatas(Long ocapRrn) {
        List<OcapTransData> transDatas = getTransDatasByOcapRrn(ocapRrn);
        if (CollectionUtils.isEmpty(transDatas)) {
            return null;
        }
        return transDatas.stream().map(transData -> {
            OcapTransDataDTO transDataDTO = new OcapTransDataDTO();
            BeanUtils.copyProperties(transData, transDataDTO);
            return transDataDTO;
        }).collect(Collectors.toList());
    }

    private List<OcapTransLogDTO> buildTransLogs(Long ocapRrn) {
        List<OcapTransLog> transLogs = getTransLogsByOcapRrn(ocapRrn);
        if (CollectionUtils.isEmpty(transLogs)) {
            return null;
        }

        return transLogs.stream().map(transLog -> {
            OcapTransLogDTO transLogDTO = new OcapTransLogDTO();
            BeanUtils.copyProperties(transLog, transLogDTO);
            return transLogDTO;
        }).collect(Collectors.toList());
    }

    private OcapCardDTO getOcapInfoByLot(Long facilityRrn, Long lotRrn) {
        String ocapId = getActiveInlineOcapId(lotRrn);
        if (StringUtils.isEmpty(ocapId)) {
            return null;
        }
        Lot lot = lotQueryManager.getLot(lotRrn);
        return getOcapInfo(facilityRrn, ocapId, lot.getLotId());
    }

    private List<String> getActiveOfflineOcapIdsByProcessEquipment(Long equipmentRrn) {
        List<String> planIds = queryDAO.getOcapIdsByProcessEquipment(equipmentRrn, OcapTypeEnum.OFFLINE.toString(),
                                                                     VersionStatus.ACTIVE_KEY);
        if (CollectionUtils.isEmpty(planIds)) {
            planIds = Collections.emptyList();
        }
        return planIds;
    }

}