LotLocationAction.java

package com.mycim.webapp.actions.lot;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.i18n.I18nUtils;
import com.fa.sesa.threadlocal.LocalContext;
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.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.Relation;
import com.mycim.valueobject.consts.EventName;
import com.mycim.valueobject.consts.ReferenceFileConst;
import com.mycim.valueobject.edcspc.Parameter;
import com.mycim.valueobject.ems.Entity;
import com.mycim.valueobject.ems.Equipment;
import com.mycim.valueobject.ems.POD;
import com.mycim.valueobject.ems.PcdAssembly;
import com.mycim.valueobject.prp.Item;
import com.mycim.valueobject.prp.Operation;
import com.mycim.valueobject.prp.SubTechnology;
import com.mycim.valueobject.runcard.util.RunCardConstants;
import com.mycim.valueobject.runcard.util.RunCardUtils;
import com.mycim.valueobject.security.UserGroup;
import com.mycim.valueobject.wip.*;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.WipSetupAction;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.springframework.util.StopWatch;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author shijie.deng
 * @version 6.0.0
 * @date 2019/9/16
 **/
public class LotLocationAction extends WipSetupAction {
    private static final String COMMENT_DOM = ".";

    private static final String WRITE_COMMA = ",";

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) {
        Map dummyMap = new HashMap();
        String value = StringUtils.EMPTY;
        dummyMap.put("lotStatus", value);
        dummyMap.put("lotpurpose", value);
        dummyMap.put("market_order_id", value);
        dummyMap.put("order_type", value);
        dummyMap.put("custduedate", value);
        dummyMap.put("custid", value);
        initLotBaseInfoForJsp(request, false, null, null);
        request.setAttribute("_lotInfo", dummyMap);
        initButton(request);
        return mapping.getInputForward();
    }

    public ActionForward lotLocation(ActionMapping mapping, ActionForm form, HttpServletRequest request) {
        StopWatch sw = new StopWatch("lotLocation-StopWatch");
        sw.start("init-initButton");
        initButton(request);
        sw.stop();
        long facilityRrn = LocalContext.getFacilityRrn();
        String userId = LocalContext.getUserId();
        long userRrn = LocalContext.getUserRrn();
        // get facility rrn from session
        sw.start("init-initLotBaseInfoForJsp");
        // 调用上层initLotBaseInfoForJsp方法,获取lot
        Lot lot = super.initLotBaseInfoForJsp(request, false, null, null);
        sw.stop();
        String lotId = lot.getLotId();
        boolean byCarrierFlag = request.getParameter("byCarrierId") != null;
        String msg = "";
        //            msg = byCarrierFlag ? "晶舟号" : "批次号";
        msg = byCarrierFlag ? "cassette Id" : "lot Id";
        if (StringUtils.isBlank(lotId)) {
            if (WebUtils.getParameterBoolean("doSearchFlag", request) != true) {
                lotId = (String) request.getAttribute("cancel_lot");
            }
        } else {
            request.setAttribute("cancel_lot", lotId);
        }
        Assert.isFalse(lot == null || lot.getLotRrn() <= 0,
                       Errors.create().content("{} does not exist!").args(msg).build());
        if ("operate_panel".equals(request.getParameter("operate_panel"))) {
            request.setAttribute("operate_panel", "operate_panel");
        }

        sw.start("lotHandle-autoCancelMoveIn");
        if (StringUtils.equals(lot.getLotStatus(), LotStatus.DISPATCH)) {
            Job job = wipQueryService.getJob(lot.getJobRrn());
            Equipment equipment = new Equipment();
            equipment.setInstanceRrn(job.getEqptRrn());
            Entity entity = emsService.getEntity(equipment);
            //TODO:cumec autoCancelMoveIn暂不区分设备操作模式
            //            if (entity != null && StringUtils.equalsIgnoreCase(Constants.SEMI_AUTO_KEY,
            //                                                               entity.getOperationMode())) {
            //                if (job.getExecutionRrn() > 0) {
            //                    String params = wipQueryService.getSemiAutoParamsInExection(job
            //                    .getExecutionRrn());
            //                    if (StringUtils.isBlank(params)) {
            //                        autoCancelMoveIn(lot);
            //                        lot = lotQueryService.getLot(lotId, LocalContext.getFacilityRrn());
            //                    }
            //                }
            //            } else {
            // autoCancelMoveIn(lot);
            lot = lotQueryService.getLot(lot.getLotRrn());
            //            }
        }
        sw.stop();
        sw.start("lotHandle-getRecipeId");
        if (StringUtils.isBlank(lot.getRecipePhysicalId())) {
            buildRecipeId(lot);
        }
        sw.stop();
        sw.start("lotHandle-getOperation");
        Map lotMapInfo = BeanUtils.copyBeanToMap(lot);
        Operation operation = null;
        if (StringUtils.equalsIgnoreCase(LotStatus.BANKED, lot.getLotStatus()) ||
                StringUtils.equalsIgnoreCase(LotStatus.OUTSOURCING, lot.getLotStatus())) {
            operation = prpService.getOperation(MapUtils.getLongValue(lotMapInfo, "prevOperationRrn"));
        } else {
            operation = prpService.getOperation(MapUtils.getLongValue(lotMapInfo, "operationRrn"));
        }
        request.setAttribute("skippableFlag", operation.getSkippableFlag());

        lotMapInfo.put("lotPurpose", lot.getLotComments());
        lotMapInfo.put("workArea", lotQueryService.getWorkArea(lot));
        lotMapInfo.put("stageId", lotQueryService.getStageId(lot));
        lotMapInfo.put("operation_rrn", MapUtils.getLong(lotMapInfo, "operationRrn"));
        String nextOperationDesc1 = getNextStepDesc(lot);
        if (nextOperationDesc1 == null) {
            lotMapInfo.put("nextOperationDesc1", "");
        } else {
            lotMapInfo.put("nextOperationDesc1", nextOperationDesc1);
        }
        sw.stop();
        sw.start("lotHandle-getPollutionLevelColor");
        lotMapInfo.put("splitMergeFlag", StringUtils.nullToStr(lot.getSplitMergeFlag()));
        lotMapInfo.put("pollutionLevel", lot.getPollutionLevel());
        String pollutionLevel = lot.getPollutionLevel();
        String pollutionLevelColor = sysService.getRefFileValue("$$LOT_POLUTIONLEVEL", pollutionLevel,
                                                                ReferenceFileConst.DATA_2_VALUE);
        if (StringUtils.isNotBlank(pollutionLevelColor)) {
            String plBgColor = StringUtils.substringBefore(pollutionLevelColor, "$");
            String plColor = StringUtils.substringAfter(pollutionLevelColor, "$");
            lotMapInfo.put("plBgColor", plBgColor);
            lotMapInfo.put("plColor", plColor);
        }
        sw.stop();

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String duedate = df.format(lot.getDueDate());
        lotMapInfo.put("duedate", duedate);
        lotMapInfo.put("qty1", lot.getQty1().intValue());
        sw.start("lotHandle-getHotflagSplicingPriority");
        String hotFlagString = "";
        if (StringUtils.isNotBlank(lot.getHotFlag()) && StringUtils.isNotBlank(lot.getPriority().toString())) {
            hotFlagString = wipQueryService.getHotflagSplicingPriority(Integer.parseInt(lot.getHotFlag()),
                                                                       lot.getPriority(), facilityRrn);
        }
        /*
         * if (StringUtils.equalsIgnoreCase("CN", language)) { hotFlagString = StringUtils.equalsIgnoreCase
         * ("1",
         * lot.getHotFlag()) ? "是" : "否"; }else{ hotFlagString = StringUtils.equalsIgnoreCase("1", lot
         * .getHotFlag()) ?
         * "YES" : "NO"; }
         */

        if (carrierService.isPcdCleaningTimeIsLessThan3Days(lot.getCarrierRrn())) {
            request.setAttribute("pcdCleanRedFlag", "1");
        }
        lotMapInfo.put("flowSeq", ctxExecService.getFlowSeqByProcessInfo(lotMapInfo));
        lotMapInfo.put("operationDesc", ctxExecService.getOperationDescByProcessInfo(lotMapInfo));
        //get lot step comments
        //TODO: 批次备注历史
        //        lotMapInfo.put("lotComments", getLotComments(lot));

        lotMapInfo.put("hotFlagString", hotFlagString);
        sw.stop();

        // get lot q-rtime buffe
        //TODO:rs
        //        if (StringUtils.isNotBlank(lot.getqTime())) {
        //            int qTBufferTime = this.getLotManager().getQTBufferTime(facilityRrn);
        //            lotMapInfo.put("qTBufferTime", qTBufferTime);
        //        }
        sw.start("lotHandle-getLotCategory");
        //get lot category
        String lotCategoryStr = sysService.getRefFileValue("$LOT_CREATE_CATEGORY", lot.getCreateCategory(),
                                                           ReferenceFileConst.DATA_1_VALUE);
        lotMapInfo.put("lotCategoryStr", lotCategoryStr);
        sw.stop();

        sw.start("lotHandle-getLotInBatch");
        lotMapInfo.put("batchId", diffBatchQueryService.getLotBatchId(lot.getLotRrn()));
        sw.stop();

        sw.start("lotHandle-getNPWBankLot");
        Map condition = new HashMap();
        condition.put("lotId", lotId);
        List<NpwBank> bankInfos = lotQueryService.getNPWBankLot(condition);
        if (CollectionUtils.isNotEmpty(bankInfos)) {
            boolean isMonitorLot = wipService.isMonitorLot(lotId);
            if (isMonitorLot) {
                request.setAttribute("monitorLot", "monitorLot");
            }
            request.setAttribute("npwLotStatus", "IN_USE");
            /*throw new WebException("dmm.lot_already_bank_monitor",
                                   "This Lot has already bank in monitor, operation is not allowed on this "
                                   + "page!");*/
        }
        sw.stop();


        sw.start("lotHandle-getSupplementData");
        request.setAttribute("_lotInfo", lotMapInfo);
        request.setAttribute("_lotId", lotId.trim().toUpperCase());
        Collection lotRecycleInfos = prpService.listRecycledInfosOfLot(lot);
        request.setAttribute("lotRecycleInfos", lotRecycleInfos);
        String consumedMaterial = wipQueryService.getConsumedMaterial(lot.getLotRrn());
        lotMapInfo.put("consumedMaterial", StringUtils.trimToEmpty(consumedMaterial));
        sw.stop();
        //        TODO:rs
        //        RecipeVersion recipe    = ctxExecService.getLotRecipe(lot);
        //        long          recipeRrn = 0L;
        //        if (recipe != null) {
        //            recipeRrn = recipe.getInstanceRrn();
        //        }
        //        lot.setRecipeLogicalRrn(recipeRrn);
        //TODO:待释放
        //        Long borRrn = borService.getBOMRrnFromBORContextValue(lot);
        //        if (borRrn != null && borRrn > 0) {
        //            BOR                       bor             = borService.getBOR(borRrn);
        //            List<Map<String, String>> consumMaterials = borService
        //            .buildBOMConsumeMaterialListForShow(bor);
        //            if (!consumMaterials.isEmpty()) {
        //                request.setAttribute("borId", bor.getInstanceId());
        //                request.setAttribute("consumeMaterials", consumMaterials);
        //            }
        //        }
        sw.start("lotHandle-getQtime");
        // TimeLimitStatus And TimeLimitSetup Info List
        boolean timeLimitsFlag = false;
        List<Map<String, String>> timelimits = wipCheckService.getLotTimeLimitInfo(lot.getLotRrn());
        if (CollectionUtils.isNotEmpty(timelimits) && checkUserGroup(userRrn, facilityRrn, "QTIME_DELETE_GROUP")) {
            timeLimitsFlag = true;
        }
        request.setAttribute("TIMELIMITS", timelimits);
        request.setAttribute("timeLimitsFlag", timeLimitsFlag);
        sw.stop();

        sw.start("lotHandle-NEXTTIMELIMIT");
        Boolean isDummyFlagLot = checkLotIsDummyFlagLot(lot.getLotRrn());

        if (!isDummyFlagLot) {
            if (!StringUtils.equals(lot.getReworkCategory(), "REWORK")) {
                List<Map<String, String>> nextTimelimit = wipCheckService.getFutureLotTimeLimitSetup(lot);
                request.setAttribute("NEXTTIMELIMIT", nextTimelimit);
            }
        }
        sw.stop();
        sw.start("lotHandle-availableEquipmentInfos");
        String lotStatus = lot.getLotStatus();
        if (!isDummyFlagLot) {
            Collection availableEquipmentInfos = new ArrayList();
            if (StringUtils.equals(lotStatus, LotStatus.WAITING) || StringUtils.equals(lotStatus, LotStatus.HOLD)) {

                //                availableEquipmentInfos = buildAvailableEquipInfosForLot(lot, userRrn);
                availableEquipmentInfos = buildBlankEquipInfosForLot(lot);

                //            TODO:rs
                //            Collection nextAvailableEquipmentInfos = buildNextAvailableEquipInfosForLot
                //            (facilityRrn, lot, userRrn);

                request.setAttribute("availableEquipmentInfos", availableEquipmentInfos);
                //            TODO:rs
                //            request.setAttribute("nextAvailableEquipmentInfos",
                //            nextAvailableEquipmentInfos);
                //            TODO:rs
                List<Map<String, Object>> availableReticleInfos = wipService.buildAvailableReticleInfoList(lot);
                if (CollectionUtils.isNotEmpty(availableReticleInfos)) {
                    request.setAttribute("availableReticleInfos", availableReticleInfos);
                }

            } else if (StringUtils.equals(lotStatus, LotStatus.RUNNING) ||
                    StringUtils.equals(lotStatus, LotStatus.RUNNINGHOLD) ||
                    StringUtils.equals(lotStatus, LotStatus.DISPATCH) ||
                    StringUtils.equals(lotStatus, LotStatus.PROCESSED)) {
                //                Map equipmentInfo = buildEquipInfoForLot(lot);
                Map equipmentInfo = buildBlankEquipInfoForLot(lot);
                availableEquipmentInfos.add(equipmentInfo);

                //            Collection nextAvailableEquipmentInfos = buildNextAvailableEquipInfosForLot
                //            (facilityRrn, lot,
                //                                                                                        userRrn);

                request.setAttribute("availableEquipmentInfos", availableEquipmentInfos);
                //            request.setAttribute("nextAvailableEquipmentInfos",
                //            nextAvailableEquipmentInfos);
                //            TODO:rs
                List<Map<String, Object>> inuseReticleInfoList = wipService.buildInuseReticleInfoList(
                        lot.getReticleRrn());
                if (CollectionUtils.isNotEmpty(inuseReticleInfoList)) {
                    request.setAttribute("availableReticleInfos", inuseReticleInfoList);
                }
            }
            if (CollectionUtils.isNotEmpty(bankInfos)) {
                request.setAttribute("availableEquipmentInfos", null);
            }

            // 判断是否是跳步过来,如果是更新设备上的批次状态
            String equipmentRrns = "";
            String skipFlag = request.getParameter("s_flag");
            if (!StringUtils.equals(lotStatus, LotStatus.WAITING)) {
                //                availableEquipmentInfos = buildAvailableEquipInfosForLot(lot, userRrn);
                //                暂未发现再次执行此方法的意义,先注释掉
            }

            for (Iterator it = availableEquipmentInfos.iterator(); it.hasNext(); ) {
                Map availableEquipmentInfo = (HashMap) it.next();
                String equipmentRrn = MapUtils.getString(availableEquipmentInfo, "equipmentRrn");
                if (!StringUtils.isEmpty(equipmentRrn)) {
                    equipmentRrns += equipmentRrn + WRITE_COMMA;// 拼接传到前段

                    // update the cacheHelper if skip the operation
                }
            }
            equipmentRrns = StringUtils.removeLastChar(equipmentRrns, WRITE_COMMA);
            request.setAttribute("equipmentRrns", equipmentRrns);
        }
        sw.stop();
        sw.start("lotHandle-getHoldReasons");
        if (StringUtils.equals(lotStatus, LotStatus.HOLD) || StringUtils.equals(lotStatus, LotStatus.RUNNINGHOLD) ||
                StringUtils.equals(lotStatus, LotStatus.RUNCARD_HOLD) || StringUtils.equals(lotStatus, LotStatus.BANKED)) {
            List<Map> holdInfos = wipQueryService.getHoldReasons(lot.getLotRrn());
            request.setAttribute("holdInfos", holdInfos);
        }
        sw.stop();
        //TODO: 暂不做
        //        PilotLotInfo pilotLotInfo = getLotManager().checkPilotLotInfo(lot);
        //        if (pilotLotInfo != null && pilotLotInfo.getEndOperation().getInstanceRrn() > 0) {
        //            if (pilotLotInfo.getEndRoute() != null) {
        //                pilotLotInfo.setEndRouteId(pilotLotInfo.getEndRoute().getInstanceId());
        //            }
        //
        //            if (pilotLotInfo.getEndOperation() != null) {
        //                pilotLotInfo.setEndOperationId(pilotLotInfo.getEndOperation().getInstanceId());
        //            }
        //            String measureOperationId = "";
        //            request.setAttribute("pilotLotInfo", pilotLotInfo);
        //            request.setAttribute("userGroup", pilotLotInfo.getSkipUserGroup());
        //            String[] measureOperations = StringUtils.split(pilotLotInfo.getMeasureOperations(),
        //            ",");
        //            if (measureOperations != null) {
        //                for (int i = 0; i < measureOperations.length; i++) {
        //                    String measureOperation = measureOperations[i];
        //                    if (StringUtils.isNotEmpty(measureOperation)) {
        //                        if (StringUtils.isNotEmpty(measureOperationId)) {
        //                            measureOperationId += ","
        //                                                  + baseService.getNamedObjectId(Long.parseLong
        //                                                  (measureOperation));
        //                        } else {
        //                            measureOperationId =baseService.getNamedObjectId(Long.parseLong
        //                            (measureOperation));
        //                        }
        //                    }
        //                }
        //            }
        //            if (StringUtils.isNotEmpty(pilotLotInfo.getPilotLotType())) {
        //                String pilotLotTypeId = "";
        ////                    pilotLotTypeId = StringUtils.equals(pilotLotInfo.getPilotLotType(), "0") ?
        // "先行片" : "测试片";
        //                    pilotLotTypeId = StringUtils.equals(pilotLotInfo.getPilotLotType(), "0") ?
        //                    "Antecedent" : "Test film";
        //                pilotLotInfo.setPilotLotTypeId(pilotLotTypeId);
        //            }
        //            if (StringUtils.isNotEmpty(pilotLotInfo.getPilotRules())) {
        //                String pilotRulesId = "";
        ////                    pilotRulesId = StringUtils.equals(pilotLotInfo.getPilotRules(), "AUTO") ?
        // "自动" : "手动";
        //                    pilotRulesId = StringUtils.equals(pilotLotInfo.getPilotRules(), "AUTO") ?
        //                    "automatic" : "Manual";
        //                pilotLotInfo.setPilotRulesId(pilotRulesId);
        //            }
        //            if (StringUtils.isNotEmpty(pilotLotInfo.getAutoReleaseSpcHold())) {
        //                String autoReleasePilotHoldId = StringUtils.equals(pilotLotInfo
        //                .getAutoReleaseSpcHold(), "0") ? "NO" : "YES";
        //                pilotLotInfo.setAutoReleasePilotHoldId(autoReleasePilotHoldId);
        //            }
        //            if (StringUtils.isNotEmpty(pilotLotInfo.getAutoReleasePilotHold())) {
        //                String autoReleasePilotHoldId = StringUtils.equals(pilotLotInfo
        //                .getAutoReleasePilotHold(), "0") ? "NO" : "YES";
        //                pilotLotInfo.setAutoReleasePilotHoldId(autoReleasePilotHoldId);
        //            }
        //
        //            pilotLotInfo.setMeasureOperationsId(measureOperationId);
        //        }
        // subcon
        sw.start("lotHandle-allowSubconIn");
        request.setAttribute("subconInFlag",
                             lotService.allowSubconIn(lot.getProductRrn(), lot.getProcessRrn(), lot.getRouteRrn(),
                                                      lot.getOperationRrn(), lot.getLotStatus(),
                                                      lot.getBeforeStatus()));
        request.setAttribute("subconOutFlag",
                             lotService.allowSubconOut(lot.getProductRrn(), lot.getProcessRrn(), lot.getRouteRrn(),
                                                       lot.getOperationRrn(), lot.getLotStatus(),
                                                       lot.getBeforeStatus()));
        sw.stop();

        sw.start("lotHandle-AutoSplitMergeLot");
        boolean cancelAutoMergeFlag = false;
        AutoSplitMergeLot autoSplitMergeLot = lotService.getAutoSplitMergeLot4Split(lot.getLotRrn());
        if (autoSplitMergeLot != null && !LotStatus.isTerminated(lot.getLotStatus()) &&
                AutoSplitMergeLot.StatusCode.SPLITED.toString()
                                                    .equalsIgnoreCase(autoSplitMergeLot.getSplitMergeStatus())) {
            cancelAutoMergeFlag = true;
        }
        request.setAttribute("cancelAutoMergeFlag", cancelAutoMergeFlag);
        sw.stop();

        sw.start("lotHandle-getLockInfo");
        //get lot lock info
        boolean manualUnlockFlag = false;
        LotTransLock lock = new LotTransLock();
        lock.setLotRrn(lot.getLotRrn());
        // List<LotTransLock> lotLocks = getLotTransLocks(lock);
        // if (lotLocks != null && lotLocks.size() > 0) {
        //     manualUnlockFlag = true;
        //     request.setAttribute("lotLocks", lotLocks);
        // }
        request.setAttribute("manualUnlockFlag", manualUnlockFlag);
        sw.stop();

        sw.start("lotHandle-getLot");
        Lot newLot = lotQueryService.getLot(lotId);

        if (StringUtils.isNotBlank(newLot.getEqptID())) {
            String runMode = wipQueryService
                    .getLatestRunModeOfMoveIn(newLot.getEqptID(), newLot.getLotId(), newLot.getLotRrn(), newLot.getStepSequence());
            if (StringUtils.isNotBlank(runMode)) {
                request.setAttribute("runMode", runMode);
            }
        }


        if (!StringUtils.equalsIgnoreCase(newLot.getLotStatus(), lotStatus)) {
            lotLocation(mapping, form, request);
        }
        sw.stop();
        //        LOGGER.info(sw.prettyPrint());
        initLotBaseInfoForJsp(request, false, null, null);
        if(checkLotIsDummyFlagLot(lot.getLotRrn())) {
            request.setAttribute("dummyFlagLot", Boolean.TRUE);
        }
        return mapping.getInputForward();
    }

    public ActionForward lotsOfSameBatchId(ActionMapping mapping, HttpServletRequest request) {
        // 几个批次同时进站时,runrrn是一样的,根据runrrn来找
        String runRrn = WebUtils.getParameter("runRrn", request);

        List lotsList = new ArrayList();
        if (StringUtils.isNotBlank(runRrn)) {
            lotsList = lotService.getLotsByRunRrn(Long.valueOf(runRrn));
        }
        request.setAttribute("lotsList", lotsList);
        return mapping.findForward("lotsofsamebatch");
    }

    public Map checkEqptAvailable(Map paramMap) {
        Long equipmentRrn = MapUtils.getLong(paramMap, "eqptRrn", 0L);
        Long lotRrn = MapUtils.getLong(paramMap, "lotRrn", 0L);
        //查询设备和批次对象
        Lot lot = lotQueryService.getLot(lotRrn);
        Entity entity = emsService.getEntity(equipmentRrn);
        Map resultMap = new HashMap();
        Map equipmentInfo = new HashMap();
        if (lot != null && entity != null) {
            if (StringUtils.isBlank(lot.getRecipePhysicalId())) {
                buildRecipeId(lot);
            }
            if (StringUtils.equals(lot.getLotStatus(), LotStatus.WAITING) ||
                    StringUtils.equals(lot.getLotStatus(), LotStatus.HOLD)) {
                Equipment equipment = new Equipment();
                equipment.setInstanceRrn(entity.getInstanceRrn());
                equipment.setInstanceId(entity.getInstanceId());
                equipment.setInstanceDesc(entity.getInstanceDesc());
                equipmentInfo = checkEquipmentAvailable(lot, LocalContext.getUserRrn(), equipment);
            } else if (StringUtils.equals(lot.getLotStatus(), LotStatus.RUNNING) ||
                    StringUtils.equals(lot.getLotStatus(), LotStatus.RUNNINGHOLD) ||
                    StringUtils.equals(lot.getLotStatus(), LotStatus.DISPATCH) ||
                    StringUtils.equals(lot.getLotStatus(), LotStatus.PROCESSED)) {
                equipmentInfo = buildEquipInfoForLot(lot);
            }

            //#44941 Manual Move Out根据Certificate卡控权限
            if(StringUtils.equals(lot.getLotStatus(), LotStatus.RUNNING)){
                Assert.state(StringUtils.isBlank(wipCheckService.checkEquipmentCertification(LocalContext.getUserId(),entity.getInstanceRrn())),
                              Errors.create().key(MessageIdList.EQPT_NO_PERMISSION).content("The current user {} has no permission to operate the EQP {}!")
                                    .args(LocalContext.getUserId(), entity.getInstanceId()).build());
            }
        }
        //这里添加手动click me 的检查,功能暂时不能下沉到通用方法
        //否则会导致eap进站 问题
        if(CollectionUtils.isNotEmpty( diffBatchQueryService.getBatchLotList(lot.getLotRrn()))){
            equipmentInfo.put("equipmentAvailable","NOT_AVAILABLE");
            equipmentInfo.put("checkEqptAvailable",false);
            String msg = I18nUtils.getMessage(MessageIdList.BATCH_CONTAIN_LOT, "The Lot in batch ,can not dispatch lot by manual mode!");
            equipmentInfo.put("checkEqptAvailableMsg",MapUtils.getString(equipmentInfo,"checkEqptAvailableMsg","").concat(msg));
        }
        if (CollectionUtils.isNotEmpty((Collection) MapUtils.getObject(equipmentInfo, "edcInfoList"))) {
            resultMap.put("edcInfoList", MapUtils.getObject(equipmentInfo, "edcInfoList"));
        }
        resultMap.put("success", true);
        resultMap.put("msg", equipmentInfo);
        return resultMap;
    }

    private void initButton(HttpServletRequest request) {
        Map<String, Object> data = securityService.getUserAuthorizationMenu(LocalContext.getUserRrn(),
                                                                            LocalContext.getFacilityRrn(),
                                                                            I18nUtils.getCurrentLanguage());
        List<String> buttonDatas = (List<String>) data.get("buttonData");
        request.setAttribute("MENU_FILTER_BUTTONS", buttonDatas);
        request.setAttribute("buttonSize", buttonDatas.size());
    }

    private void autoCancelMoveIn(Lot lot) {
        String reason = "SYSTEM 0 SYSTEM AutoCancelMoveIn";

        TransReason transReason = new TransReason();
        transReason.setReasonCode("SYSTEM");
        transReason.setReason(reason);
        transReason.setResponsibility(LocalContext.getUserId());
        transReason.setTransQty1(lot.getQty1());
        transReason.setTransQty2(lot.getQty2());

        lotService.autoCancelMoveIn(lot.getLotRrn(), lot.getLotStatus(), lot.getJobRrn(), LocalContext.getUserId(),
                                    "System AutoCancelMoveIn", transReason);
    }

    private Map buildEquipInfoForLot(Lot lot) {
        Map equipmentInfo = new HashMap();
        if (lot.getEqptRrn() != null) {
            String lotStatus = lot.getLotStatus();

            long equipmenRrn = lot.getEqptRrn();

            Entity equipment = new Equipment();
            equipment.setInstanceRrn(equipmenRrn);
            equipment = emsService.getEntity(equipment);
            String equipmentId = equipment.getInstanceId();

            equipmentInfo.put("equipmentId", equipmentId);
            equipmentInfo.put("equipmentDesc", equipment.getInstanceDesc());
            equipmentInfo.put("operationMode", equipment.getOperationMode());

            // check equipment status
            String equipmenStatus = emsService.getEntityCurrentStatus(equipmenRrn);
            equipmentInfo.put("equipmentStatus", equipmenStatus);
            if (equipmenStatus != null &&
                    (equipmenStatus.equals(EventName.DOWN) || equipmenStatus.equals(EventName.OFF) ||
                            equipmenStatus.equals(EventName.FACD)) &&
                    !((StringUtils.equals(lotStatus, LotStatus.RUNNING) ||
                            StringUtils.equals(lotStatus, LotStatus.DISPATCH) ||
                            StringUtils.equals(lotStatus, LotStatus.PROCESSED)) &&
                            StringUtils.equalsIgnoreCase(equipmenStatus, EventName.DOWN))) {
                equipmentInfo.put("equipmentAvailable", "NOT_AVAILABLE");
            } else {
                equipmentInfo.put("equipmentAvailable", "AVAILABLE");
            }

            // add edc info
            Equipment checkEquipment = new Equipment();
            checkEquipment.setInstanceRrn(equipment.getInstanceRrn());
            checkEquipment.setInstanceId(equipment.getInstanceId());
            checkEquipment.setInstanceDesc(equipment.getInstanceDesc());
            List<Parameter> edcInfoList = wipQueryService.getLotEdcInfoList(lot, checkEquipment);
            if (CollectionUtils.isNotEmpty(edcInfoList)) {
                equipmentInfo.put("edcInfoList", edcInfoList);
            }

            // start: 检查批次在当前设备是否有constrain
            equipmentInfo.put("equipmentConstrain", "USED");

            equipmentInfo.put("checkEqptAvailable", Boolean.TRUE);
        }

        return equipmentInfo;
    }

    private boolean checkUserGroup(Long userRrn, Long facilityRrn, String groupId) {
        boolean existed = false;
        UserGroup userGroup = new UserGroup(groupId, getNamedSpace(ObjectList.USERGROUP_KEY, facilityRrn),
                                            ObjectList.USERGROUP_KEY);
        userGroup = securityService.getUserGroup(userGroup);
        if (userGroup != null) {
            Relation relation = new Relation();
            relation.setFromRrn(userRrn);
            relation.setToRrn(new Long(userGroup.getInstanceRrn()));

            if (baseService.getRelation(relation) == null) {
                existed = false;
            } else {
                existed = true;
            }

        }
        return existed;
    }

    private Map buildBlankEquipInfoForLot(Lot lot) {
        Map equipmentInfo = new HashMap();
        if (lot.getEqptRrn() != null) {
            String lotStatus = lot.getLotStatus();
            Entity equipment = new Equipment();
            equipment.setInstanceRrn(lot.getEqptRrn());
            equipment = emsService.getEntity(equipment);
            String equipmentId = equipment.getInstanceId();

            equipmentInfo.put("equipmentId", equipmentId);
            equipmentInfo.put("equipmentRrn", lot.getEqptRrn());
            equipmentInfo.put("equipmentDesc", equipment.getInstanceDesc());
            equipmentInfo.put("operationMode", equipment.getOperationMode());

            // check equipment status
            String equipmenStatus = emsService.getEntityCurrentStatus(lot.getEqptRrn());
            equipmentInfo.put("equipmentStatus", equipmenStatus);
            if (equipmenStatus != null &&
                    (equipmenStatus.equals(EventName.DOWN) || equipmenStatus.equals(EventName.OFF) ||
                            equipmenStatus.equals(EventName.FACD)) &&
                    !((StringUtils.equals(lotStatus, LotStatus.RUNNING) ||
                            StringUtils.equals(lotStatus, LotStatus.DISPATCH) ||
                            StringUtils.equals(lotStatus, LotStatus.PROCESSED)) &&
                            StringUtils.equalsIgnoreCase(equipmenStatus, EventName.DOWN))) {
                equipmentInfo.put("equipmentAvailable", "NOT_AVAILABLE");
            } else {
                equipmentInfo.put("equipmentAvailable", "AVAILABLE");
            }

            // start: 检查批次在当前设备是否有constrain
            equipmentInfo.put("equipmentConstrain", "USED");
            equipmentInfo.put("checkEqptAvailable", "");
        }
        return equipmentInfo;
    }

    private Collection buildBlankEquipInfosForLot(Lot lot) {
        Collection availableEquipmentInfos = new ArrayList();
        Collection eqptRelations = getEntitiesWithLotSpecial(lot);
        // 判断批次的机限设置 并组装设备列表--->开始
        List<Relation> constrainPairEquipments = getConstrainPairEquipments(lot);
        if (constrainPairEquipments.size() > 0) {
            eqptRelations = constrainPairEquipments;
        }
        // 判断批次的机限设置 并组装设备列表--->结束
        for (Iterator it = eqptRelations.iterator(); it.hasNext(); ) {
            Relation eqptRelation = (Relation) it.next();
            Equipment equipment = new Equipment();
            equipment.setInstanceRrn(eqptRelation.getInstanceRrn());
            equipment.setInstanceId(eqptRelation.getInstanceId());
            equipment.setInstanceDesc(eqptRelation.getInstanceDesc());

            Map equipmentInfo = new HashMap();
            equipmentInfo.put("equipmentId", equipment.getInstanceId());
            equipmentInfo.put("equipmentDesc", equipment.getInstanceDesc());
            equipmentInfo.put("equipmentRrn", equipment.getInstanceRrn());
            equipmentInfo.put("equipmentConstrain", "");
            equipmentInfo.put("checkEqptAvailable", "");
            equipmentInfo.put("checkEqptAvailableMsg", "");
            // check equipment status
            String equipmenStatus = emsService.getEntityCurrentStatus(equipment.getInstanceRrn());
            equipmentInfo.put("equipmentStatus", equipmenStatus);
            if (wipCheckService.checkEqptStatusAvailable(lot, equipment)) {
                equipmentInfo.put("equipmentAvailable", "AVAILABLE");
            } else {
                equipmentInfo.put("equipmentAvailable", "NOT_AVAILABLE");
            }
            availableEquipmentInfos.add(equipmentInfo);
        }
        return availableEquipmentInfos;
    }

    /**
     * 补充JSP页面展示数据
     **/
    @Override
    protected Lot initLotBaseInfoForJsp(HttpServletRequest request, boolean readOnly, String lotSearchType,
                                        String carrierSearchType) {
        Lot lot = super.initLotBaseInfoForJsp(request, readOnly, lotSearchType, carrierSearchType);

        if (lot != null) {
            Map lotInfo = (Map) request.getAttribute("lotBaseInfo");
/*            List commentList = (List) lotQueryService.qryLotStepHistoryComment(lot.getLotRrn(),
                                                                               lot.getStepSequence(), 1,
                                                                               1000);
            Iterator      it              = commentList.iterator();
            StringBuilder commentStr      = new StringBuilder();
            Integer       commentSequence = 0;
            while (it.hasNext()) {
                Map m = (HashMap) it.next();
                //只要最新的一条。
                if (MapUtils.getInteger(m, "commentSequence") > commentSequence) {
                    commentSequence = MapUtils.getInteger(m, "commentSequence");
                    commentStr.delete(0, commentStr.length());
                    commentStr.append(MapUtils.getString(m, "commentSequence")).append(COMMENT_DOM).append(
                            MapUtils.getString(m, "stepComment")).append(";\n");
                }
            }*/
            //添加物料批次号
            // String materialLotId = warehouseService.getMaterialInfoByLot(lot.getLotRrn()).stream()
            //                                        .map(lotNumber -> lotNumber.get("lotNumber").toString())
            //                                        .collect(Collectors.joining(","));
            // lotInfo.put("materialLotId", materialLotId);

            List commentList = lotQueryService.qryLotHistoryCommentByTime(lot.getLotRrn());
            StringBuilder commentStr = new StringBuilder();
            //取commentList 第一条,即历史最新一条
            for (Object o : commentList) {
                Map m = (HashMap) o;
                commentStr.append(MapUtils.getString(m, "stepComment")).append(";\n");
                break;
            }
            //只有批次作业页面显示批次备注
            request.setAttribute("lotCommentsFlag", "true");
            request.setAttribute("lotPurposeFlag", "true");
            lotInfo.put("lotComments", commentStr.toString());

            //批次作业界面增加TechnologyId, SubTechnologyId
            Long facilityRrn = LocalContext.getFacilityRrn();
            Item item = new Item(MapUtils.getString(lotInfo, "productId"),
                                 getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn), ObjectList.PRODUCT_KEY);
            item = (Item) getInstance(item);
            lotInfo.put("subTechnologyId", item.getSubTechnologyId());

            SubTechnology subTechnology = new SubTechnology(item.getSubTechnologyId(),
                                                            getNamedSpace(ObjectList.SUB_TECHNOLOGY,
                                                                          LocalContext.getFacilityRrn()),
                                                            ObjectList.SUB_TECHNOLOGY);
            lotInfo.put("technologyId", prpService.getSubTechnology(subTechnology).getTechnologyId());

            if (StringUtils.isNotBlank((String) request.getAttribute("npwLotStatus"))) {
                lotInfo.put("lotStatus", request.getAttribute("npwLotStatus"));
            }

            //带引号的recipeId前台无法正常识别,故将recipeId中的双引号用实体编号&#34;替换
            if (StringUtils.isNotEmpty(MapUtils.getString(lotInfo, "recipeId"))) {
                String recipeId = MapUtils.getString(lotInfo, "recipeId");
                recipeId = StringUtils.replace(recipeId, "\"", "&#34;").toString();
                lotInfo.put("recipeId", recipeId);
            }

            // 添加runcardId 链接
            LotRunCardStore lotRunCardStore = null;
            if(LotStatus.isRunCardHold(lot.getLotStatus())) {
                String rcLotId = RunCardUtils.buildRunCardLotId(lot.getLotId());
                lotRunCardStore = runCardLotInqService.getLotRunCardStore(lotInqService.getLotRrn(rcLotId));
            }
            lotInfo.put("runcardId", lotRunCardStore == null ? "" : lotRunCardStore.getRuncardId());
            lotInfo.put("runcardRrn", lotRunCardStore == null ? "" : lotRunCardStore.getRuncardRrn());

            //添加ocap id
            // lotInfo.put("ocapId", wipQueryService.getActiveInlineOcapIdByLot(lot.getLotRrn()));

            //Pi-Lot
            // PiLotView piLotView = wipQueryService.getPiLotViewIdByLotRrn(lot.getLotRrn(),lot.getBasedLotRrn());
            // if (ObjectUtils.isNotEmpty(piLotView)) {
            //     lotInfo.put("piLotViewId",piLotView.getViewId());
            //     lotInfo.put("viewRrn", piLotView.getViewRrn());
            // }

            //判断当前cst是否为组合状态
            if (carrierService.isAssembledPCD(lot.getCarrierRrn())) {//如果是组合状态则需要额外增加pod的显示属性
                PcdAssembly pcdAssembly = carrierService.getPcdAssembly(lot.getCarrierRrn(), null, null);
                if (pcdAssembly != null && StringUtils.isNotBlank(pcdAssembly.getPodId())) {
                    POD pod = carrierService.getPod(pcdAssembly.getPodRrn());
                    lotInfo.put("podId", pcdAssembly.getPodId());
                    lotInfo.put("podType", pod == null ? "" : pod.getObjectSubtype());
                }
            }
            request.setAttribute("lotBaseInfo", lotInfo);
        }

        return lot;
    }

}