AutoMonitorLotDispatchAction.java
package com.mycim.webapp.actions;
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.context.spring.SpringContext;
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.msg.JsonUtils;
import com.mycim.server.edcchart.service.EdcChartService;
import com.mycim.server.ems.service.EmsService;
import com.mycim.server.rcp.service.RecipeService;
import com.mycim.server.wip.service.LotDispatchService;
import com.mycim.utils.CheckRegexUtils;
import com.mycim.utils.RcpUtils;
import com.mycim.valueobject.LocationNames;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.automonitor.dto.ReadingPromptDTO;
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.automonitor.util.AutoMonitorUtils;
import com.mycim.valueobject.bas.InputObject;
import com.mycim.valueobject.bas.Relation;
import com.mycim.valueobject.consts.ActionPointList;
import com.mycim.valueobject.consts.TransactionNames;
import com.mycim.valueobject.ems.Equipment;
import com.mycim.valueobject.prp.Recipe;
import com.mycim.valueobject.prp.RecipeVersion;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.LotStatus;
import com.mycim.valueobject.wip.Unit;
import com.mycim.valueobject.wip.dto.*;
import com.mycim.webapp.Constants;
import com.mycim.webapp.WebUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
/**
* @author finatice.yang
* @date 2021/9/8
**/
public class AutoMonitorLotDispatchAction extends AutoMonitorAction {
protected LotDispatchService lotDispatchService = SpringContext.getBean(LotDispatchService.class);
protected EdcChartService edcChartService = SpringContext.getBean(EdcChartService.class);
@Override
public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) {
return dispatchInfo(mapping, form, request, response);
}
public ActionForward dispatchInfo(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) {
String lotId = WebUtils.getParameter("lotId", request);
Lot lot = lotInqService.getLot(lotId);
String transId = "";
if (LotStatus.isMoveInCheckStatus(lot.getLotStatus())) {
transId = TransactionNames.MOVEIN_KEY;
} else if (LotStatus.isMoveOutCheckStatus(lot.getLotStatus())) {
transId = TransactionNames.MOVEOUT_KEY;
} else {
throw new SystemIllegalArgumentException(
Errors.create().key(MessageIdList.LOT_STATUS_NOT_ALLOW).content("Lot status not alolow").build());
}
String eqptId = WebUtils.getParameter("eqptId", request);
Equipment equipment = emsService.getEquipment(eqptId, LocalContext.getFacilityRrn());
LotAutoMonitorInfo lotMonitorInfo = lotAutoMonitorInqService.getLotActiveAutoMonitorInfo(lot.getLotRrn());
Map<String, Object> lotMap = BeanUtils.copyBeanToMap(lot);
lotMap.putAll(BeanUtils.copyBeanToMap(lotMonitorInfo));
if (StringUtils.equals(TransactionNames.MOVEIN_KEY, transId)) {
List<Lot> lotColls = new ArrayList<>();
lotColls.add(lot);
List<String> reticleIdList = new ArrayList<String>();
if (lotMonitorInfo.getReticleRrn() != null && lotMonitorInfo.getReticleRrn() > 0) {
reticleIdList.add(getInstanceId(lotMonitorInfo.getReticleRrn()));
} else if (lotMonitorInfo.getReticleGroupRrn() != null && lotMonitorInfo.getReticleGroupRrn() > 0) {
Collection<Relation> reticles = wipService
.getReticlesForMovein(lotMonitorInfo.getReticleGroupRrn(), equipment.getInstanceRrn(), false);
for (Relation relation : reticles) {
String reticleCheckResult = reticleService
.checkIfReticleIsAvailable(relation.getInstanceRrn(), lot.getQty1());
if (StringUtils.isEmpty(reticleCheckResult)) {
reticleIdList.add(getInstanceId(relation.getInstanceRrn()));
}
}
}
// 校验recipe
String recipeId = lotMonitorInfo.getRecipeId();
String recipeCheckResult = StringUtils.EMPTY;
if (AutoMonitorUtils.checkStepIsMainProcessStep(lotMonitorInfo.getEqptType())) {
recipeCheckResult = wipCheckService
.checkHasAvailableDispatchRecipeByAutoMonitor(lot, equipment.getInstanceRrn(), recipeId);
} else {
recipeCheckResult = wipCheckService
.checkHasAvailableDispatchRecipe(lot, equipment.getInstanceRrn(), recipeId,
lot.getInt_qty1().doubleValue());
}
Assert.state(StringUtils.isBlank(recipeCheckResult), Errors.create().content(recipeCheckResult).build());
if (CheckRegexUtils.checkFlagOn(equipment.getIsChamberEquip())) {
if(!wipCheckService.checkSingleChamberTypeRecipeChamberExsit(recipeId,equipment.getInstanceRrn())) {
Recipe recipe = recipeService.getRecipe(recipeId, LocalContext.getFacilityRrn());
RecipeVersion recipeVersion = recipeService
.getAvailableRecipeVersion(lot, equipment.getInstanceRrn(), recipe.getInstanceRrn());
if (Objects.nonNull(recipeVersion)) {
recipeId = recipeVersion.getInstanceId();
}
}
}
lotMap.put("recipeId", recipeId);
if (CollectionUtils.isNotEmpty(reticleIdList)) {
request.setAttribute("reticleIdList", reticleIdList);
}
}
request.setAttribute("lot", lotMap);
request.setAttribute("eqptId", eqptId);
request.setAttribute("jobStatus", lot.getLotStatus());
request.setAttribute("transId", transId);
return mapping.findForward("jobservice");
}
public ActionForward dispatchLot(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) {
String eqptId = WebUtils.getParameter("eqptId", request);
Equipment equipment = emsService.getEquipment(eqptId, LocalContext.getFacilityRrn());
String lotId = WebUtils.getParameter("lotId", request);
Lot lot = lotInqService.getLot(lotId);
LotAutoMonitorInfo lotMonitorInfo = lotAutoMonitorInqService.getLotActiveAutoMonitorInfo(lot.getLotRrn());
Assert.state(!(lotAutoMonitorInqService.checkAutoMonitorLotCanCreateSortJob(lotMonitorInfo) &&
lotMonitorInfo.getCarrierRrn().longValue() != lotMonitorInfo.getMonitorCarrierRrn().longValue()),
Errors.create().content("Lot need change to monitor cassette.").build());
List<Lot> lotInfos = new ArrayList<>();
List<LotInfoDto> dispatchLotTransDatas = new ArrayList<>();
if (LotStatus.isMoveInCheckStatus(lot.getLotStatus())) {
buildMoveInTransData(request, equipment, lot, lotMonitorInfo, lotInfos, dispatchLotTransDatas);
} else if (LotStatus.isMoveOutCheckStatus(lot.getLotStatus())) {
lot.setpLocation(lot.getLocation());
lot.setpLocationRrn(lot.getLocationRrn());
lot.setpLocationType(lot.getLocationType());
lot.setLocation(StringUtils.EMPTY);
lot.setLocationRrn(NumberUtils.LONG_ZERO);
lot.setLocationType(StringUtils.EMPTY);
lotInfos.add(lot);
ParameterSetDto parameterSetDTO = null;
if (StringUtils.isNotBlank(WebUtils.getParameter("edcOver", request))) {
parameterSetDTO = buildParameterInfo(lot, lotMonitorInfo, request);
} else {
parameterSetDTO = buildParameterInfo(lot, lotMonitorInfo, null);
if (Objects.nonNull(parameterSetDTO)) {
List<Map<String, Object>> edcInfos = new ArrayList<>();
Map<String, Object> edcInfo = MapUtils.newHashMap();
edcInfo.put("lot", lot);
edcInfo.put("parameterSetInfo", parameterSetDTO);
edcInfos.add(edcInfo);
request.setAttribute("lotId", lotId);
request.setAttribute("eqptId", eqptId);
request.setAttribute("edcInfos", edcInfos);
return mapping.findForward("edcPage");
}
}
LotInfoDto transData = new LotInfoDto();
LotBaseInfoDto lotBaseInfo = new LotBaseInfoDto();
lotBaseInfo.setLotId(lot.getLotId());
lotBaseInfo.setLotRrn(lot.getLotRrn());
lotBaseInfo.setTrackFlag(ActionPointList.MOVEOUT_KEY);
lotBaseInfo.setManualFlag(Boolean.TRUE);
transData.setLotBaseInfo(lotBaseInfo);
transData.setParameterSet(parameterSetDTO);
dispatchLotTransDatas.add(transData);
} else {
// TODO: 2021/1/26
throw new SystemIllegalArgumentException(
Errors.create().content("Lot Status:{}").args(lot.getLotStatus()).build());
}
List<String> lotRrns = new ArrayList<>();
lotRrns.add(StringUtils.toString(lot.getLotRrn()));
lotDispatchService.dispatchLot(lotInfos, equipment, dispatchLotTransDatas, lotRrns);
return mapping.findForward("lotinfo");
}
private void buildMoveInTransData(HttpServletRequest request, Equipment equipment, Lot lot,
LotAutoMonitorInfo lotMonitorInfo, List<Lot> lotInfos,
List<LotInfoDto> dispatchLotTransDatas) {
lot.setEqptRrn(equipment.getInstanceRrn());
lot.setEqptID(equipment.getInstanceId());
lot.setLocation(equipment.getInstanceId());
lot.setLocationRrn(equipment.getInstanceRrn());
lot.setLocationType(ObjectList.ENTITY_KEY);
String recipeId = WebUtils.getParameterUpperCase("recipeId", request);
if (StringUtils.isNotEmpty(StringUtils.trimToUpperCase(recipeId))) {
Recipe recipe = recipeService.getRecipe(recipeId, LocalContext.getFacilityRrn());
Assert.state(Objects.nonNull(recipe) && recipe.getInstanceRrn() > 0,
Errors.create().key(MessageIdList.RECIPE_INVALID_ID).content("Recipe not exist").build());
lot.setPpid(recipe.getInstanceId());
lot.setRecipeId(recipe.getInstanceId());
lot.setRecipeRrn(recipe.getInstanceRrn());
lot.setRecipePhysicalId(recipe.getInstanceId());
lot.setRecipeLogicalRrn(recipe.getInstanceRrn());
RecipeVersion recipeVersion = recipeService.getNowActiveRecipeVersion(recipe.getInstanceRrn());
if (Objects.nonNull(recipeVersion)) {
lot.setRecipeVersion(recipeVersion.getActiveVersion());
lot.setChamberType(recipeVersion.getChamberTypes());
}
}
String reticleId = StringUtils.EMPTY;
if (StringUtils.isNotBlank(WebUtils.getParameter("needReticleFlag", request))) {
String reticleIdSelect = StringUtils.trimToUpperCase(request.getParameter("reticleIdSelect"));
String reticleIdInput = StringUtils.trimToUpperCase(request.getParameter("reticleIdInput"));
Assert.state(StringUtils.isNotBlank(reticleIdSelect) && StringUtils.isNotBlank(reticleIdInput) &&
StringUtils.equalsIgnoreCase(reticleIdSelect, reticleIdInput),
Errors.create().content("Input Reticle ID error,please check!").build());
reticleId = reticleIdInput;
long reticleRrn = baseService.getNamedObjectRrn(reticleId, baseService
.getNamedSpace(LocalContext.getFacilityRrn(),
ObjectList.ENTITY_KEY),
ObjectList.ENTITY_KEY,
ObjectList.RETICLE_KEY);
Assert.state(reticleRrn > 0, Errors.create().key(MessageIdList.RETICLE_RETICLEID_INVALID).build());
lot.setReticleId(reticleId);
lot.setReticleRrn(reticleRrn);
}
lotInfos.add(lot);
LotInfoDto transData = new LotInfoDto();
LotBaseInfoDto lotBaseInfo = new LotBaseInfoDto();
lotBaseInfo.setLotId(lot.getLotId());
lotBaseInfo.setLotRrn(lot.getLotRrn());
lotBaseInfo.setPpid(recipeId);
lotBaseInfo.setTrackFlag(ActionPointList.MOVEIN_KEY);
lotBaseInfo.setManualFlag(Boolean.TRUE);
if (StringUtils.isNotBlank(reticleId)) {
lotBaseInfo.setReticleId(reticleId);
}
transData.setLotBaseInfo(lotBaseInfo);
dispatchLotTransDatas.add(transData);
}
private ParameterSetDto buildParameterInfo(Lot lot, LotAutoMonitorInfo monitorInfo, HttpServletRequest request) {
List<AutoMonitorItemStepEdcInfo> edcInfoList = autoMonitorItemInqService
.getEdcInfoList(monitorInfo.getWorkflowRrn(), monitorInfo.getWorkflowVersion(),
monitorInfo.getWorkflowStepSequence());
if (CollectionUtils.isEmpty(edcInfoList)) {
return null;
}
if (lotAutoMonitorInqService.checkAutomonitorLotNeedSkipEdc(lot.getLotRrn(), lot.getStepSequence())) {
return null;
}
List<Map> nonRTJobList = edcChartService.getMainEqpNonRTJobList(monitorInfo.getMainEqptRrn());
if (CollectionUtils.isEmpty(nonRTJobList)) {
return null;
}
String nonRTSlotType = monitorInfo.getNonRTSlotType();
checkNonRtJobInSpc(edcInfoList, nonRTJobList, nonRTSlotType);
ParameterSetDto parameterSetDto = new ParameterSetDto();
parameterSetDto.setParameters(new ArrayList<>());
List<Unit> unitList = getUnitList(lot.getLotRrn());
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));
}
}
for (String jobName : jobUnitMapping.keySet()) {
Integer subGroupSize = getSubGroupSize(nonRTJobList, jobName);
parameterSetDto.getParameters()
.add(buildParameterDto(jobName, subGroupSize, jobUnitMapping.get(jobName), request));
}
} else {
AutoMonitorItemStepEdcInfo edcInfo = edcInfoList.iterator().next();
String[] jobNames = StringUtils.split(edcInfo.getNonRTJobNames(), StringUtils.COMMA_SIGN);
for (String jobName : jobNames) {
Integer subGroupSize = getSubGroupSize(nonRTJobList, jobName);
parameterSetDto.getParameters().add(buildParameterDto(jobName, subGroupSize, unitList, request));
}
}
parameterSetDto.setParameterSize(parameterSetDto.getParameters().size());
return parameterSetDto;
}
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 ParameterDto buildParameterDto(String jobName, Integer subGroupSize, List<Unit> unitList,
HttpServletRequest request) {
ParameterDto parameterDto = new ParameterDto();
parameterDto.setParameterId(jobName);
parameterDto.setSamplePrompts(new ArrayList<SampleDto>());
for (int j = 0; j < unitList.size(); j++) {
Unit unit = unitList.get(j);
String unitId = unit.getUnitId();
SampleDto samplePromptDTO = new SampleDto();
samplePromptDTO.setUnitId(unitId);
samplePromptDTO.setUnitRrn(unit.getUnitRrn());
samplePromptDTO.setPosition(unit.getPositionInCarrier() + "");
samplePromptDTO.setReadingPrompts(new ArrayList<ReadingDto>());
samplePromptDTO.setSampleSequence(j + 1);
for (int k = 0; k < subGroupSize; k++) {
ReadingDto readingDto = new ReadingDto();
String readingId = "Reading " + (k + 1);
readingDto.setReadingId(readingId);
readingDto.setReadingSequence(k + 1);
if (request != null) {
String requestName = jobName + unitId;
Double dataValue = NumberUtils.toDouble(request.getParameterValues(requestName)[k]);
readingDto.setDataValue(dataValue);
}
samplePromptDTO.getReadingPrompts().add(readingDto);
samplePromptDTO.setReadingPromptSize(samplePromptDTO.getReadingPrompts().size());
}
parameterDto.getSamplePrompts().add(samplePromptDTO);
parameterDto.setSamplePromptSize(parameterDto.getSamplePrompts().size());
}
return parameterDto;
}
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());
}
}