CreateJobAtEquipmentExtAction.java
package com.mycim.webapp.actions.operation;
import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
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.MapUtils;
import com.mycim.framework.utils.lang.time.DateUtils;
import com.mycim.utils.WetBatchUtils;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.SystemConstant;
import com.mycim.valueobject.bas.ErrorMsg;
import com.mycim.valueobject.consts.JobStatus;
import com.mycim.valueobject.consts.LinkTypeList;
import com.mycim.valueobject.consts.SessionNames;
import com.mycim.valueobject.ems.Entity;
import com.mycim.valueobject.ems.Equipment;
import com.mycim.valueobject.ems.SpcResultEquipment;
import com.mycim.valueobject.prp.Operation;
import com.mycim.valueobject.prp.RecipeVersion;
import com.mycim.valueobject.security.Station;
import com.mycim.valueobject.wip.*;
import com.mycim.webapp.Constants;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.WipSetupAction;
import com.mycim.webapp.forms.JobOfEquipmentInfoForm;
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.*;
/**
* CreateJobAtEquipmentExt
*
* @author pinyan.song
* @version 6.0.0
* @date 2019-10-24
**/
public class CreateJobAtEquipmentExtAction extends WipSetupAction {
@Override
public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
// Create方法抛出异常时, 通过init转到error.jsp
return mapping.findForward(Constants.ERROR_KEY);
}
public ActionForward create(ActionMapping mapping, JobOfEquipmentInfoForm theform, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String user = LocalContext.getUserId();
long userRrn = LocalContext.getUserRrn();
Long facilityRrn = LocalContext.getFacilityRrn();
request.setAttribute("automovein", "automovein");
List<Lot> s_lots = new ArrayList<>();
Station station = new Station(getInstanceId(new Long(request.getParameter("stationRrn"))),
getNamedSpace(ObjectList.STATION_KEY, facilityRrn), ObjectList.STATION_KEY);
station = securityService.getStation(station);
station.setUsers(securityService.getUserOfStation(station.getInstanceRrn()));
String lotList = request.getParameter("lotList");
String cou = request.getParameter("cou");
String cou1 = request.getParameter("cou1");
String stationRrn = request.getParameter("stationRrn");
Long eqptRrn = WebUtils.getParameterLong("eqptRrn", request);
Equipment equipment = new Equipment();
equipment.setInstanceRrn(eqptRrn);
Equipment e = emsService.getEquipment(equipment);
equipment = e == null ? equipment : e;
Equipment _eqt = emsService.getEquipment(eqptRrn);
String operationMode = _eqt.getOperationMode();
Map entityExtMap = this.emsService.getEquipmentExtMap(equipment.getInstanceRrn());
Entity entity = new Entity(baseService.getNamedObject(equipment).getInstanceId(),
getNamedSpace(ObjectList.ENTITY_KEY, facilityRrn), ObjectList.ENTITY_KEY);
entity = emsService.getEntity(entity);
String diffFlag = MapUtils.getString(entityExtMap, "diffFlag");
// Check special dispatch rule, added by yichao, 20130723
if ("on".equals(station.getDispatchRuleFlag())) {
// 在批次track in时候,对此时该设备下的waitting批次判断,是否有和该批次使用菜单相同批次,
// 如果没有,正常track in,如果有,弹出提示框,让选择是继续,还是cancel。
// 说明:在JS页面中做检查
// 在按机台作业设备下,看到的批次只对waitting状态的批次进行判断,有大于其优先等级两个等级的批次,该批次不能track in作业。
// 如果由于机台设置一次可以track in多个批次,其中如有1个批次是上面规则判断可以track in的,那允许track in。
// 除非多批次中每个批次都无法track in,才禁止此次操作。
String passLots = "";
String forbidLots = "";
String highLevelLots = "";
for (int j = 0; j < new Long(cou).intValue(); j++) { // Lots to be move in
String lId = request.getParameter("lotId" + j);
Lot sLot = getLot(lId);
for (int i = 0; i < new Long(cou1).intValue(); i++) { // Lots at waiting
String lIdA = request.getParameter("lotIdA" + i);
Lot sLotA = getLot(lIdA);
if ("WAITING".equalsIgnoreCase(sLotA.getLotStatus())) {
if (sLotA.getPriority() <= sLot.getPriority() - 2) {
if (!(forbidLots.indexOf(lId) > 0)) {
forbidLots += ":" + lId;
}
if (!(highLevelLots.indexOf(lIdA) > 0)) {
highLevelLots += "," + lIdA;
}
}
}
}
if (!(forbidLots.indexOf(lId) > 0)) {
passLots += ":" + lId;
}
}
Assert.isFalse("".equals(passLots), Errors.create().content(
"The priority of {} is two grades higher than the " + "current lot.The current lot " +
"cannot be " + "MoveIn!").args(highLevelLots).build());
}
Map holdPMMap = wipCheckService.validateEquipPMStatus(entity);
String msg = "";
String msgPMInfo = wipCheckService.validateEquipPMStatusReturnMsg(holdPMMap);
if (Boolean.parseBoolean(MapUtils.getString(holdPMMap, "pmHold"))) {
if (holdPMMap.get("checklistSize") != null) {
msg = I18nUtils.getMessage(MessageIdList.EQUIPMENT_PM_SUSPENDED,
"The EQP is suspended by PM and cannot be processed.!", msgPMInfo,
(MapUtils.getString(holdPMMap, "checklistJobIds")));
}
throw new SystemIllegalArgumentException(Errors.create().content(msg).build());
}
List list = emsService.getEquipmentHoldInfo(equipment.getInstanceRrn());
for (int i = 0; i < new Long(cou).intValue(); i++) {
String id = request.getParameter("lotId" + i);
Lot lot = getLot(id);
Assert.isFalse(!list.isEmpty() && lot.getLotStatus().equals("WAITING"),
Errors.create().content("EQP suspended,lot {} Can't send " + "out work {}")
.args(lot.getLotId(), SpcResultEquipment.getReasonInfo(list)).build());
// Recipe超时提醒.
List<Map> lots = new ArrayList<>();
Map item = new HashMap();
item.put("lotRrn", lot.getLotRrn() + "");
lots.add(item);
String recipeTimeOutMsg = checkRecipeTimeOutMsg(lots);
if (StringUtils.isNotBlank(recipeTimeOutMsg)) {
int index = recipeTimeOutMsg.indexOf("|");
if (index >= 0) {
String timeOutAction = recipeTimeOutMsg.substring(0, index);
recipeTimeOutMsg = recipeTimeOutMsg.substring(index + 1);
Assert.isFalse(timeOutAction.equalsIgnoreCase("HOLD"),
Errors.create().content(recipeTimeOutMsg).build());
}
request.setAttribute("TIMEOUT_INFO", recipeTimeOutMsg);
}
}
if (holdPMMap.get("checklistSize") != null) {
msg = msgPMInfo;
if (holdPMMap.get("checklistSize") != null) {
msg += "\n" + ((String) holdPMMap.get("checklistJobIds")).replaceAll("<br>", "\n");
}
request.setAttribute("PM_CHECKLIST_INFO", msg);
}
//session.setAttribute(SessionNames.ENTITY_KEY, equipment);
request.setAttribute(SessionNames.ENTITY_KEY, equipment);
theform.setTransId("nomal");
String eqptId = getInstanceId(eqptRrn);
// 检查设备上recipe失效间隔限制
emsService.checkEquipmentRecipeInvalid(equipment.getInstanceRrn());
List<Map> recipes = recipeService.getRelation4Recipe(equipment.getInstanceRrn(), LinkTypeList.ENTITY_TO_RECIPE);
// check product constrain
Lot firstNDlot = null;
// boolean dummyBatch = false;
// boolean isAllDummy = true;
Long recipeRrn = null;
for (int i = 0; i < new Long(cou).intValue(); i++) {
String lId = request.getParameter("lotId" + i);
Lot sLot = getLot(lId);
// sLot = getLot(sLot);
if (firstNDlot == null && (!"".equals(sLot.getRecipeId()))) {
firstNDlot = sLot;
}
String recipePhysicalId = sLot.getRecipePhysicalId();
if (StringUtils.isBlank(recipePhysicalId) || recipePhysicalId.contains("*")) {
sLot.setEqptID(getInstanceId(equipment.getInstanceRrn()));
RecipeVersion version = recipeService.getLotRecipe(sLot);
Assert.isFalse(version == null || StringUtils.isBlank(version.getPpid()),
Errors.create().content("Do not get the Recipe ID, please confirm!").build());
recipePhysicalId = version.getPpid();
}
boolean isRecipeOk = false;
/*// dummy lot check
if (new Long(cou).intValue() > 1) {
isAllDummy = false;
}
if (new Long(cou).intValue() > 1) {
dummyBatch = true;
}*/
long physicalRecipeRrn = getInstanceRrn(recipePhysicalId, facilityRrn, ObjectList.RECIPE_KEY);
Assert.isFalse(physicalRecipeRrn <= 0,
Errors.create().content("The recipe is not defined in the system!").build());
// dummy lot不验证recipe
// if ("D".equals(sLot.getLotType()) || recipes.isEmpty()) {
// isRecipeOk = true;
// } else {
for (Object o : recipes) {
Map recipe = (Map) o;
String status = MapUtils.getString(recipe, "status");
if (StringUtils.equalsIgnoreCase(recipePhysicalId, MapUtils.getString(recipe, "recipeId")) &&
(StringUtils.equals("ON", status) || StringUtils.equals("EXIST", status))) {
isRecipeOk = true;
break;
}
}
// }
Assert.isTrue(isRecipeOk, Errors.create().content(
"The available recipe and lot on the EQP. Recipe does not " + "match!").build());
if (recipeRrn == null) {
recipeRrn = physicalRecipeRrn;
} else {
Assert.isFalse(recipeRrn != physicalRecipeRrn, Errors.create().content("Not the same recipe!").build());
}
ErrorMsg errorMsg = constrainService.checkLotConstrain(equipment, sLot);
Assert.isFalse(errorMsg.getError(), Errors.create().content(errorMsg.getErrorMsg()).build());
Assert.isFalse(diffBatchQueryService.checkLotInBatch(sLot.getLotRrn()),
Errors.create().key(MessageIdList.LOT_IN_BATCH).content("The Lot in batch!")
.build());
}
/*
* if (dummyBatch) { for (int i = 0; i < new Long(cou).intValue(); i++) { String lId =
* request.getParameter("lotId" + i); log.info("lId" + i + "===" + lId); Lot sLot = getLot
* (lId); sLot =
* getLot(sLot); if (sLot.getOperationRrn().longValue() != firstNDlot.getOperationRrn()
* .longValue()) {
* if(StringUtils.equalsIgnoreCase("CN", language)){ // request.setAttribute(ErrorDef
* .MYCIM_ERR_KEY, new
* ValidateFailureException("作业列表中的批次步骤不相同")); }else{ // request.setAttribute(ErrorDef
* .MYCIM_ERR_KEY, new
* ValidateFailureException("The lot steps in the job list are different.")); } // return
* (mapping.findForward("error")); } if (!firstNDlot.getRecipeId().equals(sLot.getRecipeId()) &&
* !isAllDummy) { request.setAttribute(ErrorDef.MYCIM_ERR_KEY, new
* ValidateFailureException("作业列表中的批次recipe不相同")); return (mapping.findForward("error")); } } }
*/
// end
for (int i = 0; i < new Long(cou).intValue(); i++) {
String lId = request.getParameter("lotId" + i);
Lot sLot = getLot(lId);
s_lots.add(sLot);
}
Lot slot = s_lots.iterator().next();
String operationId = slot.getOperationId();
Operation operation = new Operation();
operation.setInstanceId(operationId);
operation.setNamedSpace(getNamedSpace(ObjectList.OPERATION_KEY, facilityRrn));
operation = prpService.getOperation(operation.getInstanceId(), operation.getNamedSpace());
for (Lot lotInfo : s_lots) {
lotInfo = lotQueryService.getLot(lotInfo.getLotRrn());
String lotOperationId = lotInfo.getOperationId();
Operation lotOperation = new Operation();
lotOperation.setInstanceId(lotOperationId);
lotOperation.setNamedSpace(getNamedSpace(ObjectList.OPERATION_KEY, facilityRrn));
lotOperation = prpService.getOperation(lotOperation.getInstanceId(), lotOperation.getNamedSpace());
Assert.isTrue(StringUtils.equals(operation.getMvinWflId(), lotOperation.getMvinWflId()), Errors.create()
.content(
"The Lot's Start Routine not same,please re-select Lots with same " +
"Start Routine!")
.build());
Assert.isTrue(StringUtils.equals(operation.getMvouWflId(), lotOperation.getMvouWflId()), Errors.create()
.content(
"The Lot's End Routine not same, please re-select Lots with same End " +
"Routine!")
.build());
}
List<Long> jobLots = new ArrayList<>();
List<Lot> lockLots = new ArrayList<>();
List<Map> lotInfos = new ArrayList<>();
Lot tLot = new Lot();
Job job = (Job) request.getAttribute(SessionNames.JOB_KEY);
if (s_lots.size() < 1) {
Assert.isFalse(request.getParameter(Constants.CREATE_KEY) != null,
Errors.create().content("No lot selected to be " + "created !").build());
Assert.isTrue(request.getParameter(Constants.CREATE_KEY) != null,
Errors.create().content("Use cancel job to delete" + " all lots in job" + " list").build());
}
long total_slots_qty = 0;
for (Lot s_lot : s_lots) {
long qty = s_lot.getQty1().longValue();
total_slots_qty = total_slots_qty + qty;
}
Assert.isTrue(wipCheckService.isValidJobSize(eqptRrn, s_lots.size(), total_slots_qty),
Errors.create().key(MessageIdList.LOT_INVALID_JOB_SIZE).content("Invalid Job Size!").build());
boolean createFlag = true;
if (createFlag) {
job = new Job();
job.setTransPerformedby(user);
job.setJobComments(theform.getJobComments());
job.setEqptRrn(eqptRrn);
equipment.setInstanceRrn(job.getEqptRrn().longValue());
// get operation and recipe,recipeParameter
Iterator _temp = s_lots.iterator();
if (_temp.hasNext()) {
tLot = (Lot) _temp.next();
}
Long operationRrn = tLot.getOperationRrn();
job.setOperationRrn(operationRrn);
job.setJobStatus(JobStatus.WAITING);
}
for (Lot _tlot : s_lots) {
Lot lot = lotQueryService.getLot(_tlot.getLotRrn());
Assert.isFalse(lot.getExecutionRrn() == null || lot.getExecutionRrn() == 0,
Errors.create().content("Lot's " + "executionRrn is null, and can not be dispatched.")
.build());
Assert.isFalse(diffBatchQueryService.checkLotInBatch(_tlot.getLotRrn()),
Errors.create().content("Lot:{} had batch").args(_tlot.getLotId()).build());
long lotJobRrn = lot.getJobRrn();
/*if (StringUtils.equalsIgnoreCase(LotStatus.DISPATCH, lot.getLotStatus()) && lotJobRrn > 0 &&
StringUtils.isBlank(lot.getRecipePhysicalId())) {
autoCancelMoveIn(user, facilityRrn, lot);
}*/
String category = lot.getCreateCategory();
String lotType = lot.getLotType();
wipCheckService.validateLotOverQueueTime(lot);
jobLots.add(_tlot.getLotRrn());
lockLots.add(_tlot);
checkLotAndSetParameters(_tlot,lot,equipment,lotInfos);
}
if (createFlag) {
if (theform.getTransId().equals("nomal")) {
// prepare recipe string according to context values
Map context = new HashMap();
context.put("operationRrn", job.getOperationRrn());
context.put("facilityRrn", facilityRrn);
// get first lot
Lot firstLot = new Lot();
Iterator _it = s_lots.iterator();
if (_it.hasNext()) {
firstLot = (Lot) _it.next();
}
context.put("lotRrn", firstLot.getLotRrn());
Assert.isTrue(wipCheckService.validJobSize(job),
Errors.create().content("Equipment currently busy.").build());
validLotInEqp(eqptRrn, lockLots);
job.setEqptId(equipment.getInstanceId());
job.setExecutionRrn(0L);
job.setUOM1(firstLot.getUOM1());
job.setUOM2(firstLot.getUOM2());
// checkAndCreateLotsTransLock(userRrn, TransactionNames.LOCK_MOVEIN, lockLots,
// " movein-createJob in
// CreateJobAtEquipmentExtAction by: "
// + LocalContext.getUserId());
// job = wipService.createJob(job, jobLots);
request.setAttribute(SessionNames.JOB_KEY, job);
request.setAttribute(SessionNames.COLLECTION_KEY, lotInfos);
request.setAttribute("automovein", "automovein");
request.setAttribute("transId", theform.getTransId());
return mapping.findForward("jobservice");
}
}
if (theform.getTransId().equals("future")) {
return new ActionForward(mapping.getInput());
} else if (theform.getTransId().equals("nomal")) {
return mapping.findForward("jobmanagement");
} else {
// session.setAttribute(SessionNames.COLLECTION_KEY, s_lots);
request.setAttribute(SessionNames.COLLECTION_KEY, s_lots);
// session.setAttribute(SessionNames.OBJECT_KEY, "equipment");
request.setAttribute(SessionNames.OBJECT_KEY, "equipment");
return mapping.findForward("jobservice");
}
}
public String validateEqptPMCounterStatus(Map params) {
long eqptRrn = MapUtils.getLong(params, "eqptRrn");
List<String> lotIds = (List<String>) MapUtils.getObject(params, "lotIds");
if (lotIds.size()>=2){//判断lot的当前step id是否一致
for (int i = 0; i < lotIds.size()-1; i++) {
Assert.isTrue(StringUtils.equalsIgnoreCase(lotQueryService.getLot(lotIds.get(i), LocalContext.getFacilityRrn()).getOperationId(),
lotQueryService.getLot(lotIds.get(i+1), LocalContext.getFacilityRrn()).getOperationId()),
Errors.create().content("The current step ID of main and by-products is inconsistent").build());
}
}
Equipment equipment = new Equipment();
equipment.setInstanceRrn(eqptRrn);
Entity entity = emsService.getEntity(equipment);
Long recipeRrn = null;
List<Lot> lotsTempForCheckEqpt = new ArrayList<>();
for (String lotId : lotIds) {
Lot lot = lotQueryService.getLot(lotId, LocalContext.getFacilityRrn());
Assert.isFalse(lot == null || lot.getLotRrn() <= 0,
Errors.create().key(MessageIdList.LOT_MISSING_ID).content("Lot id does not exist!").build());
// 目前PMCounter不支持多工艺菜单的判断数量扣减,故与PMCounterAction一致,指定第一个批次的recipeRrn。
recipeRrn = recipeRrn == null ? lot.getRecipeLogicalRrn() : recipeRrn;
lotsTempForCheckEqpt.add(lot);
}
Equipment checkEqpt = emsService.getEquipment(equipment);
if (lotsTempForCheckEqpt.size() > 1
&& SystemConstant.Str.NUM_TRUE.equalsIgnoreCase(checkEqpt.getWetFlag())
&& !checkEqpt.getWetMap().isEmpty()){
String message = WetBatchUtils.checkWetBatchList(lotsTempForCheckEqpt, checkEqpt);
Assert.isFalse(StringUtils.isNotBlank(message),
Errors.create().key(MessageIdList.NOT_EXIST_WET_LIST).content("ProductID of {} is not in the list of Wet Batch!").args(message).build());
}
return wipCheckService.validateEqptPMCounterStatus(entity, recipeRrn, lotsTempForCheckEqpt);
}
private void fillRecipeInfo(List<Map> lots) {
for (Map map : lots) {
long lotRrn = MapUtils.getLongValue(map, "lotRrn");
Lot lot = lotQueryService.getLot(lotRrn);
map.put("recipePhysicalId", lot.getRecipePhysicalId());
map.put("recipeId", lot.getRecipeId());
map.put("recipeRrn", baseService.getNamedObjectRrn(lot.getRecipeId(), baseService
.getNamedSpace(LocalContext.getFacilityRrn(), ObjectList.RECIPE_KEY), ObjectList.RECIPE_KEY));
}
}
private void autoCancelMoveIn(String user, Long facilityRrn, Lot lot) throws Exception {
String reason = "SYSTEM 0 SYSTEM AutoCancelMoveIn";
TransReason transReason = new TransReason();
transReason.setReasonCode("SYSTEM");
transReason.setReason(reason);
transReason.setResponsibility(user);
transReason.setTransQty1(lot.getQty1());
transReason.setTransQty2(lot.getQty2());
lotService
.autoCancelMoveIn(lot.getLotRrn(), lot.getLotStatus(), lot.getJobRrn(), user, "System AutoCancelMoveIn",
transReason);
}
private Lot getLot(String id) {
Lot l = lotQueryService.getLot(id);
return l == null ? new Lot() : l;
}
private void checkLotAndSetParameters(Lot _tlot,Lot lot,Equipment equipment,List<Map> lotInfos) {
Map lotInfo = BeanUtils.copyBeanToMap(_tlot);
long spent = DateUtils.getDistanceTime4Now(lot.getQueueTimestamp());
lotInfo.put("queueTimestamp", new Long(spent / 60).toString());
lotInfo.put("recipeId", baseService.getNamedObjectId(MapUtils.getLongValue(lotInfo, "recipeRrn", 0)));
lotInfo.put("processId", baseService.getNamedObjectId(MapUtils.getLongValue(lotInfo, "processRrn", 0)));
lotInfo.put("productId", baseService.getNamedObjectId(MapUtils.getLongValue(lotInfo, "productRrn", 0)));
lotInfo.put("operationDesc", lot.getOperationDesc());
lotInfo.put("reticleId", baseService.getNamedObjectId(MapUtils.getLong(lotInfo, "reticleRrn")));
lotInfo.put("equipmentRrn", equipment.getInstanceRrn());
lotInfo.put("eqptId", equipment.getInstanceId());
lotInfo.put("executionRrn", "0");
lotInfo.put("isUniqueCarrierFlag", "1");
lotInfo.put("isUniqueJobFlag", "0");
lotInfo.put("facilityRrn", LocalContext.getFacilityRrn());
lotInfo.put("recipePhysicalId", lot.getRecipePhysicalId());
lotInfo.put("recipeId", lot.getRecipeId());
lotInfo.put("recipeRrn", baseService.getNamedObjectRrn(lot.getRecipeId(), baseService
.getNamedSpace(LocalContext.getFacilityRrn(), ObjectList.RECIPE_KEY), ObjectList.RECIPE_KEY));
lotInfos.add(lotInfo);
}
}