ReticleQueryManagerImpl.java

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

import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.server.ctx.exec.manager.ReticleFamilyContextManager;
import com.mycim.server.ems.manager.EntityManager;
import com.mycim.server.wip.dao.ReticleQueryDAO;
import com.mycim.server.wip.manager.LotQueryManager;
import com.mycim.server.wip.manager.ReticleQueryManager;
import com.mycim.valueobject.bas.Relation;
import com.mycim.valueobject.consts.EntityEnum;
import com.mycim.valueobject.ems.Entity;
import com.mycim.valueobject.wip.Lot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author Johnson.Wang
 * @version 6.0.0
 * @date 2019/9/23
 **/
@Service
@Transactional
public class ReticleQueryManagerImpl implements ReticleQueryManager {

    @Autowired
    private ReticleFamilyContextManager reticleFamilyContextManager;

    @Autowired
    private ReticleQueryDAO reticleQueryDAO;

    @Autowired
    private EntityManager entityManager;

    @Autowired
    private LotQueryManager lotQueryManager;

    /**
     * Get reticles that has already entered equipment (equipment track in)
     *
     * @param lot
     * @param equipmentRrn
     * @return
     */
    @Override
    public List<Relation> getReticlesThatHasAlreadyEnteredEquipment(Lot lot, Long equipmentRrn) {
        return getReticleInfosForMovein(lot, equipmentRrn, false);
    }

    /**
     * Get reticles by relationship with the reticle family
     *
     * @param reticleFamilyRrn if it is not {@code null}, already entered the equipment
     * @param statusFLag       if it is {@code true}, the reticle's entity status must be IDLE or RELEASE or RUN
     * @return {@code Relation} object has value: ["instanceRrn", "instanceId", "instanceDesc", "fromRrn",
     * "toRrn"]
     */
    @Override
    public List<Relation> getReticlesForMovein(Long reticleFamilyRrn, Long entityRrn, Boolean statusFLag) {
        return reticleQueryDAO.getReticlesForMovein(reticleFamilyRrn, entityRrn, statusFLag);
    }

    /**
     * Get reticles that has already entered equipment (equipment track in), it is available entity status and
     * does not exceed the maximum usage times
     *
     * @param lot
     * @param equipmentRrn
     * @return
     */
    @Override
    public List<Relation> getAvailableReticlesForTrackIn(Lot lot, Long equipmentRrn) {
        List<Relation> reticleInfos = getReticleInfosForMovein(lot, equipmentRrn, true);

        for (Iterator<Relation> iterator = reticleInfos.iterator(); iterator.hasNext(); ) {
            Relation relation = iterator.next();

            Entity reticleEntity = entityManager.getEntity(relation.getInstanceRrn());

            if (isNeedCheckUseTimes(reticleEntity.getPDFlag())) {
                Integer inuseWaferQty = lotQueryManager.getInuseWaferQtyForReticle(relation.getInstanceRrn());

                if (isOutMaxTimesOfUse(reticleEntity.getMaxUseTimes(), reticleEntity.getCurrentUseTimes(),
                                       inuseWaferQty, lot.getQty1())) {
                    iterator.remove();
                }
            }
        }
        return reticleInfos;
    }

    @Override
    public String getReticleIdsThatHasAlreadyEnteredEquipmentStr(Lot lot, Long equipmentRrn, Boolean isNeedFilter) {
        List<Relation> reticles = getReticlesThatHasAlreadyEnteredEquipment(lot, equipmentRrn);
        if (isNeedFilter) {
            reticles = filterSpecialStatus(reticles);
        }

        return buildReticleIdsStr(reticles);
    }

    @Override
    public String getAvailableReticleIdsStr(Lot lot, Long equipmentRrn) {
        return buildReticleIdsStr(getAvailableReticlesForTrackIn(lot, equipmentRrn));
    }

    @Override
    public String getAvailableReticleIdsStr(Long reticleFamilyRrn, Long equipmentRrn, Boolean statusFlag) {
        return buildReticleIdsStr(getReticlesForMovein(reticleFamilyRrn, equipmentRrn, statusFlag));
    }

    @Override
    public long getReticleFamilyRrnByLot(Lot lot) {
        return reticleFamilyContextManager
                .getReticleFamilyRrn(lot.getProductRrn(), lot.getProductVersion(), lot.getProcessRrn(),
                                     lot.getProcessVersion(), lot.getRouteRrn(), lot.getOperationRrn());
    }

    public Boolean isOutMaxTimesOfUse(Integer maxUseTimes, Integer currentUseTimes, Integer inuseWaferQty,
                                      Double lotQty) {
        return maxUseTimes < currentUseTimes + inuseWaferQty + lotQty;
    }

    public Boolean isNeedCheckUseTimes(String pdFlag) {
        return EntityEnum.isPDFlagT(pdFlag);
    }

    private String buildReticleIdsStr(List<Relation> reticles) {
        if (CollectionUtils.isEmpty(reticles)) {
            return StringUtils.EMPTY;
        }
        StringBuilder reticleIds = new StringBuilder();
        for (Relation relation : reticles) {
            if (reticleIds.length() > 0) {
                reticleIds.append(",").append(relation.getInstanceId());
            } else {
                reticleIds.append(relation.getInstanceId());
            }
        }
        return reticleIds.toString();
    }

    private List<Relation> filterSpecialStatus(List<Relation> reticles) {
        Iterator<Relation> iterator = reticles.iterator();
        while (iterator.hasNext()) {
            Relation relation = iterator.next();
            String reticleStatus = entityManager.getEntityCurrentStatus(relation.getInstanceRrn());
            if (!EntityEnum.isRelease(reticleStatus)) {
                iterator.remove();
            }
        }
        return reticles;
    }

    private List<Relation> getReticleInfosForMovein(Lot lot, Long equipmentRrn, Boolean statusFLag) {
        long reticleFamilyRrn = getReticleFamilyRrnByLot(lot);
        if (reticleFamilyRrn > 0) {
            return getReticlesForMovein(reticleFamilyRrn, equipmentRrn, statusFLag);
        }

        return Collections.emptyList();
    }

    private Map<String, Object> buildProcessInfoForContext(Lot lot) {
        Map<String, Object> processInfo = new HashMap<>();

        processInfo.put("facilityRrn", LocalContext.getFacilityRrn());
        processInfo.put("productRrn", lot.getProductRrn());
        processInfo.put("processRrn", lot.getProcessRrn());
        processInfo.put("routeRrn", lot.getRouteRrn());
        processInfo.put("operationRrn", lot.getOperationRrn());
        processInfo.put("routeSeq", lot.getRouteSeq());
        processInfo.put("operationSeq", lot.getOperationSeq());
        processInfo.put("processVersion", lot.getProcessVersion());

        return processInfo;
    }

}