ProcessSpecServiceImpl.java
package com.mycim.server.spec.service;
import com.alipay.sofa.runtime.api.annotation.SofaService;
import com.alipay.sofa.runtime.api.annotation.SofaServiceBinding;
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.jdbc.Page;
import com.mycim.framework.utils.beans.BeanUtils;
import com.mycim.framework.utils.lang.BooleanUtils;
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.server.base.manager.NamedObjectManager;
import com.mycim.server.base.manager.TransactionLogManager;
import com.mycim.server.edc.manager.EcnManager;
import com.mycim.server.edc.manager.ParameterSetManager;
import com.mycim.server.prp.manager.*;
import com.mycim.server.rcp.manager.RecipeManager;
import com.mycim.server.reticle.manager.ReticleFamilyManager;
import com.mycim.server.spec.manager.*;
import com.mycim.server.system.manager.ReferenceFileManager;
import com.mycim.utils.FieldValidateUtils;
import com.mycim.utils.WflLinkContextSetupAttributeUtil;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.Pair;
import com.mycim.valueobject.SystemConstant;
import com.mycim.valueobject.bas.TransactionLog;
import com.mycim.valueobject.consts.StepTypeConst;
import com.mycim.valueobject.consts.TransactionNames;
import com.mycim.valueobject.consts.VersionStatus;
import com.mycim.valueobject.prp.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.lang.Override;
import java.sql.Timestamp;
import java.util.*;
/**
* @author Qiansheng.Wang
* @version 1.0
* @since 2021-03-15
**/
@Service
@Transactional
@SofaService(interfaceType = ProcessSpecService.class, bindings = {@SofaServiceBinding(bindingType = "bolt")})
public class ProcessSpecServiceImpl implements ProcessSpecService {
private static final String KEY_INSERT_SPEC_ITEMS = "insertSpecItems";
private static final String KEY_UPDATE_SPEC_ITEMS = "updateSpecItems";
private static final String KEY_DELETE_SPEC_ITEMS = "deleteSpecItems";
@Autowired
NamedObjectManager namedObjectManager;
@Autowired
TransactionLogManager transactionLogManager;
@Autowired
ReferenceFileManager referenceFileManager;
@Autowired
EcnManager ecnManager;
@Autowired
ProcessSpecInfoManager processSpecInfoManager;
@Autowired
ProcessSpecItemManager processSpecItemManager;
@Autowired
ProductAttributeInfoManager productAttributeInfoManager;
@Autowired
ProductAttributeItemManager productAttributeItemManager;
@Autowired
ProductSpecInfoManager productSpecInfoManager;
@Autowired
AttributeSetupManager attributeSetupManager;
@Autowired
AttributeQueryManager attributeQueryManager;
@Autowired
AttributeConvertManager attributeConvertManager;
@Autowired
SpecManager specManager;
@Autowired
ProcessManager processManager;
@Autowired
OperationManager operationManager;
@Autowired
ProductVersionManager productVersionManager;
@Autowired
ProductProcessManager productProcessManager;
@Autowired
RecipeManager recipeManager;
@Autowired
TimeLimitSetUpManager timeLimitSetupManager;
@Autowired
ProcessReworkManager processReworkManager;
@Autowired
ProductManager productManager;
@Autowired
ParameterSetManager parameterSetManager;
@Autowired
ReticleFamilyManager reticleFamilyManager;
@Autowired
WorkflowManager workflowManager;
@Override
public void saveProcessSpecItems(ProcessSpecFormDto processSpecForm) {
Assert.isFalse(CollectionUtils.isEmpty(processSpecForm.getSpecItems()),
Errors.create().content("no data to save").build());
processSpecForm.setProcessRrn(
namedObjectManager.getNamedObjectRrn(processSpecForm.getProcessId(), LocalContext.getFacilityRrn(),
ObjectList.WFL_KEY));
Assert.isFalse(processSpecForm.getProcessRrn() <= 0,
Errors.create().content("Process ID does not exist.").build());
Assert.isFalse(isEditableProcessSpec(processSpecForm.getProcessRrn(), processSpecForm.getProcessVersion()),
Errors.create()
.content("Process Version does not exist or status is UNFROZEN, cannot save spec.")
.build());
List<ProcessSpecItem> willSaveProcessSpecItems = buildSaveProcessSpecItemList(LocalContext.getFacilityRrn(),
processSpecForm.getSpecItems());
Assert.state(CollectionUtils.isNotEmpty(willSaveProcessSpecItems),Errors.create().key(MessageIdList.NOT_EXIST_WET_LIST).content("list is empty!").build());
List<ProcessSpecItem> processSpecItemsInDb = processSpecItemManager.getProcessSpecItems(
processSpecForm.getProcessRrn(), processSpecForm.getProcessVersion());
ProcessSpecInfo processSpecInfo = getProcessSpecInfoForSave(processSpecForm);
Map<String, List<ProcessSpecItem>> saveProcessSpecItemMap = new HashMap<>();
boolean isAlreadyActivated = BooleanUtils.toBoolean(processSpecInfo.getActiveFlag());
if (isAlreadyActivated) {
checkIfTheAttributeTypeHasBeenModified(willSaveProcessSpecItems, processSpecItemsInDb);
saveProcessSpecItemMap.put(KEY_UPDATE_SPEC_ITEMS, willSaveProcessSpecItems);
} else {
/*
If the spec has never been activated, all items need to be inserted/updated/deleted. Because the process
steps (workflow) may have been modified.
*/
saveProcessSpecItemMap = buildProcessSpecItemSaveMap(processSpecItemsInDb, willSaveProcessSpecItems);
}
TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),
TransactionNames.SAVE_KEY);
// Save Process Spec Base Info (Table Status)
processSpecInfoManager.saveProcessSpecItemInfo(transactionLog, processSpecInfo);
// Save Process Spec Items.
processSpecItemManager.saveProcessSpecItems(transactionLog, saveProcessSpecItemMap);
if (isAlreadyActivated) {
// If the process spec table is "active". No other operations are required.
return;
}
checkIfFlowSequencesIsValid(willSaveProcessSpecItems);
List<ProductVersion> allProductVersions = getProductVersions(processSpecInfo.getProcessRrn());
// Save Product Attribute
productAttributeItemManager.saveProductAttributeWithReset(transactionLog, processSpecInfo,
willSaveProcessSpecItems, allProductVersions);
// Save Flow Sequence to context value
Ecn ecn = ecnManager.generateUnFrozenEcnForContext(LocalContext.getUserRrn());
attributeSetupManager.saveFlowSequenceToContextValue(LocalContext.getFacilityRrn(), ecn,
willSaveProcessSpecItems);
}
@Override
public void restoreProcessSpecItems(ProcessSpecFormDto processSpecForm) {
// processSpecForm.setSpecItems(); TODO 重写该方法
saveProcessSpecItems(processSpecForm);
}
@Override
public List<ProcessSpecItemDto> queryProcessSpecItems(ProcessSpecFormDto processSpecForm) {
String processId = processSpecForm.getProcessId();
Integer processVersion = processSpecForm.getProcessVersion();
String productId = processSpecForm.getProductId();
long productRrn = productManager.getProductRrnById(productId);
Long processRrn = namedObjectManager.getNamedObjectRrn(processId, LocalContext.getFacilityRrn(),
ObjectList.WFL_KEY);
// TODO 优化查询流程的方法
List<Map<String, Object>> processFlow = processManager.getProcessAllStepInfo(processRrn, processVersion, null,
null, 99999L, null, null, 0);
ProcessSpecInfo processSpecInfo = processSpecInfoManager.getProcessSpecInfoByPrimaryKey(processRrn,
processVersion);
Map<String, ProcessAttributeDto> attributes;
Integer highestProcessVersion = processVersion;
if (processSpecInfo == null && processVersion > 1) {
highestProcessVersion = processSpecInfoManager.getHighestActivatedProcessVersion(processRrn);
attributes = attributeQueryManager.getProcessAttributesFromTargetVersion(processRrn, processVersion,
highestProcessVersion);
} else {
attributes = attributeQueryManager.getProcessAttributesWithSetup(processRrn, processVersion);
}
if (processSpecInfo == null) {
processSpecInfo = new ProcessSpecInfo();
processSpecInfo.setProcessRrn(processRrn);
processSpecInfo.setProcessId(processId);
processSpecInfo.setProcessVersion(processVersion);
}
// 构建FlipTypeMap
Map<String, String> flipTypeMap = attributeConvertManager.getFlipTypeKeyMap();
ProcessSpecItemBuildParameterDto processSpecItemBuildParameterDto = new ProcessSpecItemBuildParameterDto(
processSpecInfo).setAttributes(attributes).setStageIdKeyMap(attributeConvertManager.getStageIdKeyMap())
.setOperationTypeKeyMap(attributeConvertManager.getOperationTypeKeyMap())
.setWorkAreaKeyMap(attributeConvertManager.getWorkAreaKeyMap())
.setFlipTypeMap(flipTypeMap);
return buildProcessSpecItems(processSpecItemBuildParameterDto, highestProcessVersion, processFlow, productRrn);
}
@Override
public ProcessSpecInfo getProcessSpecInfo(ProcessSpecFormDto processSpecForm) {
Long processRrn = namedObjectManager.getNamedObjectRrn(processSpecForm.getProcessId(),
LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);
return processSpecInfoManager.getProcessSpecInfoByPrimaryKey(processRrn, processSpecForm.getProcessVersion());
}
@Override
public void freezeProcessSpecItems(ProcessSpecFormDto processSpecForm) {
String processId = processSpecForm.getProcessId();
Integer processVersion = processSpecForm.getProcessVersion();
Long processRrn = namedObjectManager.getNamedObjectRrn(processId, LocalContext.getFacilityRrn(),
ObjectList.WFL_KEY);
ProcessSpecInfo processSpecInfo = processSpecInfoManager.getProcessSpecInfoByPrimaryKey(processRrn,
processVersion);
Assert.isFalse(
processSpecInfo == null || !VersionStatus.UNFROZEN_KEY.equals(processSpecInfo.getCurrentStatus()),
Errors.create().content(
"This spec table has never been saved or the status of this spec table is not UNFROZEN. " +
"Unable to perform freeze operation.").build());
Assert.isFalse(isEditableProcessSpec(processRrn, processVersion), Errors.create().content(
"Process Version does not exist or status is UNFROZEN, cannot freeze spec.").build());
List<ProcessSpecItem> processSpecItems = processSpecItemManager.getProcessSpecItems(processRrn, processVersion,
VersionStatus.UNFROZEN_KEY);
StringBuilder errorMsg = new StringBuilder();
checkIfProcessSpecItemsCanDoFreeze(processSpecItems, errorMsg);
this.checkFlipType(null, errorMsg, processSpecItemManager.checkFlipSetTogether(processRrn, processVersion));
Assert.isFalse(errorMsg.length() > 0, Errors.create().content(errorMsg.toString()).build());
TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),
TransactionNames.FROZEN_KEY);
transactionLog.setTransSequence(0L);
updateStatusOfProcessSpec(transactionLog, processSpecInfo, processSpecItems, null, VersionStatus.FROZEN_KEY);
}
@Override
public void unfreezeProcessSpecItems(ProcessSpecFormDto processSpecForm) {
String processId = processSpecForm.getProcessId();
Integer processVersion = processSpecForm.getProcessVersion();
Long processRrn = namedObjectManager.getNamedObjectRrn(processId, LocalContext.getFacilityRrn(),
ObjectList.WFL_KEY);
ProcessSpecInfo processSpecInfo = processSpecInfoManager.getProcessSpecInfoByPrimaryKey(processRrn,
processVersion);
Assert.isFalse(processSpecInfo == null || !VersionStatus.FROZEN_KEY.equals(processSpecInfo.getCurrentStatus()),
Errors.create().content(
"This spec table has never been saved or the status of this spec table is not FROZEN. " +
"Unable to perform unfreeze operation.").build());
List<ProcessSpecItem> processSpecItems = processSpecItemManager.getProcessSpecItems(processRrn, processVersion,
VersionStatus.FROZEN_KEY);
TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),
TransactionNames.UNFROZEN_KEY);
updateStatusOfProcessSpec(transactionLog, processSpecInfo, processSpecItems, null, VersionStatus.UNFROZEN_KEY);
}
@Override
public void activateProcessSpecItems(ProcessSpecFormDto processSpecForm) {
String processId = processSpecForm.getProcessId();
Integer processVersion = processSpecForm.getProcessVersion();
long facilityRrn = LocalContext.getFacilityRrn();
Long processRrn = namedObjectManager.getNamedObjectRrn(processId, facilityRrn, ObjectList.WFL_KEY);
ProcessSpecInfo processSpecInfo = processSpecInfoManager.getProcessSpecInfoByPrimaryKey(processRrn,
processVersion);
Assert.isFalse(processSpecInfo == null || !VersionStatus.FROZEN_KEY.equals(processSpecInfo.getCurrentStatus()),
Errors.create().content(
"This spec table has never been saved or the status of this spec table is not FROZEN. " +
"Unable to perform activate operation.").build());
//校验数据完整性
validationActiveProcessSpecItems(processSpecForm);
// 若 VERSION_LAST_UPDATED_TIME < LAST_UPDATE_TIME,则表示流程版本被修改过,需重新做 Save 操作。
if (processSpecInfo != null && processSpecInfo.getVersionLastUpdateTime() != null) {
ProcessVersion processVersionInfo = processManager.getProcessVersionInfo(processRrn, processVersion);
Assert.isFalse(
processSpecInfo.getVersionLastUpdateTime().before(processVersionInfo.getLastUpdateTimestamp()),
Errors.create().key(MessageIdList.SPEC_CHECK_UPDATE_TIME)
.content("The process has been modified and needs to be saved again!").build());
}
checkIfHasUnfrozenDataInProductAttribute(processRrn, processVersion);
List<ProcessSpecItem> processSpecItems = processSpecItemManager.getProcessSpecItems(processRrn, processVersion,
VersionStatus.FROZEN_KEY);
this.checkFlipType(null, null, processSpecItemManager.checkFlipSetTogether(processRrn, processVersion));
checkIfHasUnfrozenTimeLimit(processSpecItems, processId, processVersion);
//check Multipath 是否已设定
Assert.isFalse(specManager.checkMultipath(processId, processRrn, processVersion, null),
Errors.create().key(MessageIdList.MULTIPATH_PROCESS_SET)
.content("Multipath is not set for this process!").build());
Ecn ecn = ecnManager.generateActiveEcnForContext(LocalContext.getUserRrn());
TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),
TransactionNames.ACTIVE_KEY);
updateStatusOfProcessSpec(transactionLog, processSpecInfo, processSpecItems, ecn, VersionStatus.ACTIVE_KEY);
attributeSetupManager.saveProcessAttributeToContextValue(facilityRrn, ecn, processSpecItems);
if (processSpecInfo != null) {
//每次535激活都需要更新PRO_CONTEXT_ACTIVE_DTL
activateProduct(transactionLog, processSpecInfo);
}
}
@Override
public Page queryProcessSpecItemHistories(Page page, String processId, Integer processVersion, Date queryStartTime,
Date queryEndTime) {
return processSpecItemManager.queryProcessSpecItemHistories(page, processId, processVersion, queryStartTime,
queryEndTime);
}
@Override
public Map<String, Object> checkImportProcessSpecItems(String processId, Integer processVer,
List<ProcessSpecItemDto> importList) {
long facilityRrn = LocalContext.getFacilityRrn();
Map<String, String> stageIdDescKeyMap = attributeConvertManager.getStageIdDescKeyMap();
Map<String, String> operationTypeDescKeyMap = attributeConvertManager.getOperationTypeDescKeyMap();
Map<String, String> workAreaDescKeyMap = attributeConvertManager.getWorkAreaDescKeyMap();
Map<String, String> bankFlagDescKeyMap = attributeConvertManager.getBankFlagDescKeyMap();
Map<String, String> processLocationKeyMap = attributeConvertManager.getProcessLocationKeyMap();
Map<String, String> contaminationKeyMap = attributeConvertManager.getContaminationKeyDescMap();
Map<String, String> flipTypeValueMapMap = attributeConvertManager.getFlipTypeValueMap();
// List<String> flipTypeArr = ListUtils.newArrayList("A", "B");//, "A To B", "B To A"
Long processRrn = namedObjectManager.getNamedObjectRrn(processId, facilityRrn, ObjectList.WFL_KEY);
Map<String, String> allFlowSeq = attributeQueryManager.getAllFlowSeqMap(processRrn, processVer);
StringBuilder errorMsg = new StringBuilder();
Map<String, ProcessSpecItemDto> validData = new LinkedHashMap<>();
Set<String> keySet = new HashSet<>();
for (int i = 0; i < importList.size(); i++) {
Integer rowNum = i;
ProcessSpecItemDto processSpecItem = importList.get(i);
Assert.isTrue(StringUtils.equalsIgnoreCase(processId, processSpecItem.getProcessId()),
Errors.create().content("The process ID is different from the process spec table.").build());
Assert.isTrue(processVer != null && processVer.equals(processSpecItem.getProcessVersion()),
Errors.create().content("The process version is different from the process spec table.")
.build());
StringBuilder rowErrorMsg = new StringBuilder();
long routeRrn = namedObjectManager.getNamedObjectRrn(processSpecItem.getRouteId(), facilityRrn,
ObjectList.WFL_KEY);
if (routeRrn <= 0) {
rowErrorMsg.append("Sub Plan dose not existed.<br>");
}
long operationRrn = namedObjectManager.getNamedObjectRrn(processSpecItem.getOperationId(), facilityRrn,
ObjectList.OPERATION_KEY);
if (operationRrn <= 0) {
rowErrorMsg.append("Step dose not existed.<br>");
}
if (routeRrn > 0 && operationRrn > 0 && StringUtils.isNotBlank(processSpecItem.getFlowSeq())) {
if (!FlowSeqGenerator.isValid(processSpecItem.getFlowSeq())) {
errorMsg.append("Flow Seq: ").append(processSpecItem.getFlowSeq())
.append(" is not valid! it is must be six digits!<br>");
} else {
String flowSeq = FlowSeqGenerator.generate(processSpecItem.getFlowSeq());
String oldFlowSeq = allFlowSeq.get(
ContextValueUtils.buildKeyByProcess(processRrn, processVer, routeRrn, operationRrn));
if (StringUtils.isNotEmpty(oldFlowSeq) && !StringUtils.equals(oldFlowSeq, flowSeq)) {
rowErrorMsg.append("Flow Seq: ").append(oldFlowSeq).append(" cannot be modified.<br>");
}
if (StringUtils.isEmpty(oldFlowSeq) && allFlowSeq.containsValue(flowSeq)) {
rowErrorMsg.append("Flow seq: ").append(processSpecItem.getFlowSeq())
.append(" already exists on another step.<br>");
}
}
} else if (StringUtils.isBlank(processSpecItem.getFlowSeq())) {
rowErrorMsg.append("Flow seq cannot be empty. <br>");
}
String recipeId = processSpecItem.getRecipeId();
if (StringUtils.isNotBlank(recipeId)) {
long recipeRrn = namedObjectManager.getNamedObjectRrn(recipeId, facilityRrn, ObjectList.RECIPE_KEY);
if (recipeRrn <= 0) {
rowErrorMsg.append(recipeManager.checkRecipeAndCreate(recipeId));
} else if (recipeManager.isMainRecipe(recipeRrn) != recipeRrn) {
rowErrorMsg.append("Recipe: ").append(recipeId).append(" is chamber recipe!<br>");
}
}
String reticleGroupId = processSpecItem.getReticleFamilyId();
if (StringUtils.isNotBlank(reticleGroupId)) {
long reticleGroupRrn = namedObjectManager.getNamedObjectRrn(reticleGroupId, facilityRrn,
ObjectList.RETICLEFAMILY_KEY);
if (reticleGroupRrn <= 0 && ProductVariableEnum.isReticleGroupVariable(reticleGroupId)) {
rowErrorMsg.append(reticleFamilyManager.checkReticleFamilyAndCreate(reticleGroupId));
} else if (reticleGroupRrn <= 0) {
rowErrorMsg.append("Reticle Group: ").append(reticleGroupId).append(" dose not existed.<br>");
}
}
String parameterSetId = processSpecItem.getParameterSetId();
if (StringUtils.isNotBlank(parameterSetId)) {
long parameterSetRrn = namedObjectManager.getNamedObjectRrn(parameterSetId, facilityRrn,
ObjectList.PARAMETERSET_KEY);
if (parameterSetRrn <= 0 && ProductVariableEnum.isEdcPlanVariable(parameterSetId)) {
rowErrorMsg.append(parameterSetManager.checkParameterSetAndCreate(parameterSetId));
} else if (parameterSetRrn <= 0) {
rowErrorMsg.append("EDC Plan: ").append(parameterSetId).append(" dose not existed.<br>");
}
}
if (StringUtils.isNotBlank(processSpecItem.getOperationDesc()) &&
processSpecItem.getOperationDesc().getBytes().length > 200) {
rowErrorMsg.append("Operation Description should smaller than 200.<br>");
}
if (StringUtils.isNotEmpty(processSpecItem.getPollutionLevel()) &&
(!NumberUtils.isCreatable(processSpecItem.getPollutionLevel()) ||
StringUtils.isEmpty(contaminationKeyMap.get(processSpecItem.getPollutionLevel())))) {
rowErrorMsg.append("Contamination is not a number or contamination does not existed.<br>");
}
if (StringUtils.isNotBlank(processSpecItem.getStageId()) &&
StringUtils.isBlank(stageIdDescKeyMap.get(processSpecItem.getStageId()))) {
rowErrorMsg.append("Stage ID: ").append(processSpecItem.getStageId()).append(" not exists.<br> ");
}
if (StringUtils.isNotBlank(processSpecItem.getWorkArea()) &&
StringUtils.isBlank(workAreaDescKeyMap.get(processSpecItem.getWorkArea()))) {
rowErrorMsg.append("Work area: ").append(processSpecItem.getWorkArea()).append(" not exists.<br> ");
}
if (StringUtils.isNotBlank(processSpecItem.getBankFlag()) &&
StringUtils.isBlank(bankFlagDescKeyMap.get(processSpecItem.getBankFlag()))) {
rowErrorMsg.append("Bank flag: ").append(processSpecItem.getBankFlag()).append(" not exists!<br>");
}
if (StringUtils.isNotBlank(processSpecItem.getFlipTypeDesc())) {
String flipTypeCode = flipTypeValueMapMap.get(processSpecItem.getFlipTypeDesc());
if (StringUtils.isEmpty(flipTypeCode)) {
rowErrorMsg.append("Flip Type: ").append(processSpecItem.getFlipTypeDesc())
.append(" not exists!<br>");
} else {
processSpecItem.setFlipType(flipTypeCode);
}
}
if (StringUtils.isNotBlank(processSpecItem.getOperationType()) &&
StringUtils.isBlank(operationTypeDescKeyMap.get(processSpecItem.getOperationType()))) {
rowErrorMsg.append("Operation type: ").append(processSpecItem.getOperationType())
.append(" not exists!<br>");
}
if (StringUtils.isNotBlank(processSpecItem.getProcessLocation()) &&
StringUtils.isBlank(processLocationKeyMap.get(processSpecItem.getProcessLocation()))) {
rowErrorMsg.append("Process location: ").append(processSpecItem.getProcessLocation())
.append(" not exists!<br>");
}
if (StringUtils.isNotBlank(processSpecItem.getEquipmentGroupId())) {
String eqptGroupRrns = "";
String[] eqptGroupIdArr = processSpecItem.getEquipmentGroupId().split(",");
for (String eqptGroupId : eqptGroupIdArr) {
Long eqptGroupRrn = namedObjectManager.getNamedObjectRrn(eqptGroupId, facilityRrn,
ObjectList.ENTITYGROUP_KEY);
eqptGroupRrns += eqptGroupRrn + ",";
if (eqptGroupRrn <= 0) {
rowErrorMsg.append("Eqpt Group: ").append(eqptGroupId).append(" not exists!<br>");
}
}
eqptGroupRrns = eqptGroupRrns.substring(0, eqptGroupRrns.length() - 1);
processSpecItem.setEquipmentGroupRrns(eqptGroupRrns);
}
String key = processSpecItem.getRouteId() + "#$#" + processSpecItem.getOperationId();
if (keySet.add(key)) {
validData.put(key, processSpecItem);
} else {
rowErrorMsg.append("The current row (Route and Operation) is duplicated with other rows! <br>");
}
if (rowErrorMsg.length() > 0) {
errorMsg.append(" Row Num: ").append(rowNum).append(" <br>").append(rowErrorMsg);
}
}
this.checkFlipType(importList, errorMsg, false);
Map<String, Object> map = new HashMap<>();
map.put("errorMsg", errorMsg.toString());
map.put("data", validData);
return map;
}
@Override
public Boolean canRestore(ProcessSpecFormDto processSpecForm) {
return false;
}
@Override
public ProcessSpecItemDto queryProcessSpecItem(ProcessSpecItemDto processSpecItemDto) {
ProcessSpecItem psi = processSpecItemManager.getProcessSpecItemForActive(processSpecItemDto);
ProcessSpecItemDto psid = new ProcessSpecItemDto();
if (!Objects.isNull(psi)) {
BeanUtils.copyProperties(psi, psid);
}
return psid;
}
@Override
public Map<String, String> getFlipTypeKeyMap() {
return attributeConvertManager.getFlipTypeKeyMap();
}
private boolean isEditableProcessSpec(Long processRrn, Integer processVersion) {
ProcessVersion processVersionObj = processManager.getProcessVersion(processRrn, processVersion);
return processVersionObj == null || VersionStatus.UNFROZEN_KEY.equals(processVersionObj.getVersionStatus());
}
private List<ProductVersion> getProductVersions(Long processRrn) {
List<ProductVersion> allProductVersions = new ArrayList<>();
for (Item product : processManager.getUsedByProducts(processRrn)) {
List<ProductVersion> allVersions = productVersionManager.getAllVersions(product.getInstanceRrn());
for (ProductVersion productVersion : allVersions) {
productVersion.setProductId(product.getInstanceId());
}
allProductVersions.addAll(allVersions);
}
return allProductVersions;
}
private ProcessSpecInfo getProcessSpecInfoForSave(ProcessSpecFormDto processSpecForm) {
ProcessSpecInfo processSpecInfo = processSpecInfoManager.getProcessSpecInfoByPrimaryKey(
processSpecForm.getProcessRrn(), processSpecForm.getProcessVersion());
if (processSpecInfo == null) {
processSpecInfo = new ProcessSpecInfo();
processSpecInfo.setProcessRrn(processSpecForm.getProcessRrn());
processSpecInfo.setProcessId(processSpecForm.getProcessId());
processSpecInfo.setProcessVersion(processSpecForm.getProcessVersion());
processSpecInfo.setActiveFlag(false);
}
processSpecInfo.setCurrentStatus(VersionStatus.UNFROZEN_KEY);
return processSpecInfo;
}
private void activateProduct(TransactionLog transactionLog, ProcessSpecInfo processSpecInfo) {
//如果不存在变量,更新 ProductSpecInfo 状态为ACTIVE(所有当前绑定产品的所有版本)
if (canActivateProducts(processSpecInfo)) {
List<ProductVersion> allProductVersions = getProductVersions(processSpecInfo.getProcessRrn());
productSpecInfoManager.activateProductSpecInfos(transactionLog, processSpecInfo, allProductVersions);
}
specManager.activateProduct(transactionLog, processSpecInfo.getProcessRrn(),
processSpecInfo.getProcessVersion());
}
private boolean canActivateProducts(ProcessSpecInfo processSpecInfo) {
// isNoAnyVariable
return CollectionUtils.isEmpty(
productAttributeInfoManager.getProductAttributeInfosByProcess(processSpecInfo.getProcessRrn(),
processSpecInfo.getProcessVersion()));
}
private void updateStatusOfProcessSpec(TransactionLog transactionLog, ProcessSpecInfo processSpecInfo,
List<ProcessSpecItem> processSpecItems, Ecn ecn, String status) {
processSpecInfoManager.updateStatusOfProcessSpecInfo(transactionLog, processSpecInfo, status);
processSpecItemManager.updateStatusOfProcessSpecItems(transactionLog, processSpecItems, ecn, status);
}
/**
* Check whether the product attributes have unfreeze data. If so, the activation operation cannot be performed
* and an exception is thrown.
*
* @param processRrn Checked process
* @param processVersion Checked process version
*/
private void checkIfHasUnfrozenDataInProductAttribute(Long processRrn, Integer processVersion) {
List<ProductAttributeItem> productAttributeItems = productAttributeItemManager.getProductAttributeItems(
processRrn, processVersion);
boolean hasUnfrozenData = false;
for (ProductAttributeItem productAttributeItem : productAttributeItems) {
if (VersionStatus.UNFROZEN_KEY.equals(productAttributeItem.getStatus())) {
hasUnfrozenData = true;
break;
}
}
Assert.isFalse(hasUnfrozenData,
Errors.create().content("The product attribute has unfrozen data and cannot be activated.")
.build());
}
private void checkIfFlowSequencesIsValid(List<ProcessSpecItem> processSpecItems) {
StringBuilder errorMsg = new StringBuilder();
Set<Integer> flowSeqSet = new LinkedHashSet<>();
List<String> invalidFlowSeqs = new ArrayList<>();
List<String> duplicatedFlowSeqs = new ArrayList<>();
for (ProcessSpecItem processSpecItem : processSpecItems) {
if (!FlowSeqGenerator.isValid(processSpecItem.getFlowSeq())) {
invalidFlowSeqs.add(processSpecItem.getFlowSeq());
}
if (!flowSeqSet.add(NumberUtils.toInt(processSpecItem.getFlowSeq()))) {
duplicatedFlowSeqs.add(processSpecItem.getFlowSeq());
}
}
if (invalidFlowSeqs.size() > 0) {
errorMsg.append("Flow Seq: ");
errorMsg.append(StringUtils.join(", ", invalidFlowSeqs));
errorMsg.append(" is not valid! it is must be six digits!<br>");
}
if (duplicatedFlowSeqs.size() > 0) {
errorMsg.append("Flow Seq: ");
errorMsg.append(StringUtils.join(", ", duplicatedFlowSeqs));
errorMsg.append(" can not be duplicated!<br>");
}
List<String> outOfOrderFlowSeqs = new ArrayList<>();
Integer[] flowSeqArray = flowSeqSet.toArray(new Integer[0]);
for (int i = 1; i < flowSeqArray.length - 1; i++) {
Integer flowSeq = flowSeqArray[i];
Integer lastFlowSeq = flowSeqArray[i - 1];
Integer nextFlowSeq = flowSeqArray[i + 1];
if (flowSeq - lastFlowSeq < 0 || flowSeq - nextFlowSeq > 0) {
outOfOrderFlowSeqs.add(FlowSeqGenerator.generate(flowSeq));
}
}
if (outOfOrderFlowSeqs.size() > 0) {
errorMsg.append("Reseq should be between the previous step and next step Reseq! the unqualified Reseq:");
errorMsg.append(StringUtils.join(", ", outOfOrderFlowSeqs)).append("<br>");
}
Assert.isFalse(errorMsg.length() > 0, Errors.create().content(errorMsg.toString()).build());
}
private void checkIfTheAttributeTypeHasBeenModified(List<ProcessSpecItem> processSpecItemsInDb,
List<ProcessSpecItem> willSaveProcessSpecItems) {
StringBuilder errorMsg = new StringBuilder();
for (ProcessSpecItem processSpecItemTemp : willSaveProcessSpecItems) {
int index = processSpecItemsInDb.indexOf(processSpecItemTemp);
if (index < 0) {
continue;
}
ProcessSpecItem processSpecItem = processSpecItemsInDb.get(index);
errorMsg.append(
checkIfAttributeCanBeModified(processSpecItem.getFlowSeq(), processSpecItemTemp.getRecipeId(),
processSpecItem.getRecipeId(), "Recipe"));
errorMsg.append(
checkIfAttributeCanBeModified(processSpecItem.getFlowSeq(), processSpecItemTemp.getParameterSetId(),
processSpecItem.getParameterSetId(), "EDC Plan"));
errorMsg.append(checkIfAttributeCanBeModified(processSpecItem.getFlowSeq(),
processSpecItemTemp.getReticleFamilyId(),
processSpecItem.getReticleFamilyId(), "Reticle Group"));
}
Assert.isFalse(errorMsg.length() > 0, Errors.create().content(errorMsg.toString()).build());
}
private String checkIfAttributeCanBeModified(String flowSeq, String sourceValue, String targetValue, String type) {
if (!StringUtils.equals(sourceValue, targetValue)) {
boolean oldIsVariable = ProductVariableEnum.isVariable(sourceValue);
boolean newIsVariable = ProductVariableEnum.isVariable(targetValue);
if (oldIsVariable && !newIsVariable) {
return "Cannot modify the variable of the " + type + " (flow seq " + flowSeq + ") into a constant!<br>";
}
if (!oldIsVariable && newIsVariable) {
return "Cannot modify the constant of the " + type + " (flow seq " + flowSeq + ") into a variable!<br>";
}
}
return StringUtils.EMPTY;
}
private Map<String, List<ProcessSpecItem>> buildProcessSpecItemSaveMap(List<ProcessSpecItem> processSpecItemsInDb,
List<ProcessSpecItem> willSaveProcessSpecItems) {
Map<String, List<ProcessSpecItem>> saveProcessSpecItems = new HashMap<>();
saveProcessSpecItems.put(KEY_INSERT_SPEC_ITEMS, new ArrayList<>());
saveProcessSpecItems.put(KEY_UPDATE_SPEC_ITEMS, new ArrayList<>());
saveProcessSpecItems.put(KEY_DELETE_SPEC_ITEMS, new ArrayList<>());
for (ProcessSpecItem processSpecItemTemp : willSaveProcessSpecItems) {
if (processSpecItemsInDb.contains(processSpecItemTemp)) {
// If the spec item already exists, it will be updated
saveProcessSpecItems.get(KEY_UPDATE_SPEC_ITEMS).add(processSpecItemTemp);
} else {
// If the spec item does not exists, it will be inserted
saveProcessSpecItems.get(KEY_INSERT_SPEC_ITEMS).add(processSpecItemTemp);
}
}
for (ProcessSpecItem processSpecItemTemp : processSpecItemsInDb) {
if (!willSaveProcessSpecItems.contains(processSpecItemTemp)) {
// If the spec item already exists but is not in the willSave list, delete it
saveProcessSpecItems.get(KEY_DELETE_SPEC_ITEMS).add(processSpecItemTemp);
}
}
return saveProcessSpecItems;
}
private List<ProcessSpecItem> buildSaveProcessSpecItemList(Long facilityRrn,
List<ProcessSpecItemDto> processSpecItems) {
Map<String, String> stageIdDescKeyMap = attributeConvertManager.getStageIdDescKeyMap();
Map<String, String> operationTypeDescKeyMap = attributeConvertManager.getOperationTypeDescKeyMap();
Map<String, String> workAreaDescKeyMap = attributeConvertManager.getWorkAreaDescKeyMap();
Map<String, String> processLocationKeyMap = attributeConvertManager.getProcessLocationKeyMap();
Map<String, String> contaminationKeyMap = attributeConvertManager.getContaminationKeyDescMap();
StringBuilder errorMsg = new StringBuilder();
int rowNum = 1;
List<ProcessSpecItem> willSaveProcessSpecItems = new ArrayList<>();
for (ProcessSpecItemDto processSpecItemTemp : processSpecItems) {
ProcessSpecItem processSpecItem = new ProcessSpecItem();
BeanUtils.copyProperties(processSpecItemTemp, processSpecItem);
if (processSpecItemTemp.getCreatedTime() != null) {
processSpecItem.setCreatedTime(new Timestamp(processSpecItemTemp.getCreatedTime().getTime()));
}
StringBuilder rowErrorMsg = new StringBuilder();
if (StringUtils.isEmpty(processSpecItem.getFlowSeq())) {
rowErrorMsg.append("Flow Seq can not be empty.<br>");
}
checkIfRecipeIsValidAndSet(facilityRrn, processSpecItem, rowErrorMsg);
checkIfReticleFamilyIsValidAndSet(facilityRrn, processSpecItem, rowErrorMsg);
checkIfParameterSetIsValidAndSet(facilityRrn, processSpecItem, rowErrorMsg);
if (StringUtils.isBlank(processSpecItem.getEquipmentGroupId())) {
Long equipmentGroupRrn = operationManager.getOperationEquipmentGroupRrn(
processSpecItem.getOperationRrn());
if (equipmentGroupRrn != null) {
processSpecItem.setEquipmentGroupId(namedObjectManager.getInstanceId(equipmentGroupRrn));
processSpecItem.setEquipmentGroupRrns(StringUtils.toString(equipmentGroupRrn));
}
} else if (processSpecItem.getEquipmentGroupId().length() > 512) {
rowErrorMsg.append("Equipment Group ID should smaller than 512.<br>");
}
if (StringUtils.isNotEmpty(processSpecItem.getStageId())) {
String stageId = stageIdDescKeyMap.get(processSpecItem.getStageId());
if (StringUtils.isEmpty(stageId)) {
rowErrorMsg.append("Stage ID does not existed.<br>");
}
processSpecItem.setStageId(stageId);
}
if (StringUtils.isNotEmpty(processSpecItem.getWorkArea())) {
String workArea = workAreaDescKeyMap.get(processSpecItem.getWorkArea());
if (StringUtils.isEmpty(workArea)) {
rowErrorMsg.append("Work Area does not existed.<br>");
}
processSpecItem.setWorkArea(workArea);
}
if (StringUtils.isNotEmpty(processSpecItem.getOperationType())) {
String operationType = operationTypeDescKeyMap.get(processSpecItem.getOperationType());
if (StringUtils.isEmpty(operationType)) {
rowErrorMsg.append("Operation Type does not existed.<br>");
}
processSpecItem.setOperationType(operationType);
}
if (StringUtils.isNotEmpty(processSpecItem.getOperationDesc()) &&
processSpecItem.getOperationDesc().getBytes().length > 200) {
rowErrorMsg.append("Operation Description should smaller than 200.<br>");
}
processSpecItem.setPollutionLevel(StringUtils.trimToEmpty(processSpecItem.getPollutionLevel()));
if (StringUtils.isNotEmpty(processSpecItem.getPollutionLevel()) &&
(!NumberUtils.isCreatable(processSpecItem.getPollutionLevel()) ||
StringUtils.isEmpty(contaminationKeyMap.get(processSpecItem.getPollutionLevel())))) {
rowErrorMsg.append("Contamination is not a number or contamination does not existed.<br>");
}
if (StringUtils.isNotEmpty(processSpecItem.getProcessLocation()) &&
StringUtils.isEmpty(processLocationKeyMap.get(processSpecItem.getProcessLocation()))) {
rowErrorMsg.append("Process Location does not existed.<br>");
}
/* 优化 #45306 新增EDC PLAN验证,长度128位以内。字符必须为字母 或 数字 或 英文半角减号- 或 英文半角下划线_ 或者 英文半角@ 或 英文半角$ 或 英文半角% */
if(StringUtils.isNotBlank(processSpecItem.getParameterSetId())){
if (StringUtils.length(processSpecItem.getParameterSetId()) < 128) {
String result = FieldValidateUtils.validateSpecialChar(processSpecItem.getParameterSetId());
if(StringUtils.isNotBlank(result)){
rowErrorMsg.append("EdcPlan "+result);
}
} else {
rowErrorMsg.append("EDCPLAN ID length cannot more than 128!.<br />");
}
}
/*优化 #45305 新增Reticle Group验证,长度128位以内。字符必须为字母 或 数字 或 英文半角减号- 或 英文半角下划线_ 或者 英文半角@ 或 英文半角$ 或 英文半角% */
if(StringUtils.isNotEmpty(processSpecItem.getReticleFamilyId())){
if (StringUtils.length(processSpecItem.getReticleFamilyId()) < 128) {
String result = FieldValidateUtils.validateSpecialChar(processSpecItem.getReticleFamilyId());
if(StringUtils.isNotBlank(result)){
rowErrorMsg.append("Recticle Group "+result);
// break;
}
} else {
rowErrorMsg.append("Recticle Group ID length cannot more than 128!.<br />");
}
}
if (StringUtils.isNotEmpty(processSpecItem.getRecipeId())) {
//错误 #45489 允许$R 创建 与 Recipe setup 一致 删除循环式判断
String msg = FieldValidateUtils.validateRecipeId(processSpecItem.getRecipeId());
if(StringUtils.isNotEmpty(msg)) {
rowErrorMsg.append(msg);
}
}
if (rowErrorMsg.length() > 0) {
errorMsg.append(" Row Num: ").append(rowNum).append("<br>").append(rowErrorMsg);
}
willSaveProcessSpecItems.add(processSpecItem);
rowNum++;
}
Assert.isFalse(errorMsg.length() > 0, Errors.create().content(errorMsg.toString()).build());
return willSaveProcessSpecItems;
}
private void checkIfParameterSetIsValidAndSet(Long facilityRrn, ProcessSpecItem processSpecItem,
StringBuilder rowErrorMsg) {
processSpecItem.setParameterSetId(StringUtils.trimToUpperCase(processSpecItem.getParameterSetId()));
if (StringUtils.isNotEmptyTrim(processSpecItem.getParameterSetId())) {
processSpecItem.setParameterSetRrn(
namedObjectManager.getNamedObjectRrn(processSpecItem.getParameterSetId(), facilityRrn,
ObjectList.PARAMETERSET_KEY));
if (processSpecItem.getParameterSetRrn() == null || processSpecItem.getParameterSetRrn() <= 0) {
if (ProductVariableEnum.isEdcPlanVariable(processSpecItem.getParameterSetId())) {
rowErrorMsg.append(
parameterSetManager.checkParameterSetAndCreate(processSpecItem.getParameterSetId()));
processSpecItem.setParameterSetRrn(
namedObjectManager.getNamedObjectRrn(processSpecItem.getParameterSetId(), facilityRrn,
ObjectList.PARAMETERSET_KEY));
} else {
rowErrorMsg.append("EDC Plan dose not existed.<br>");
}
}
processSpecItem.setVariableFlag(StringUtils.startsWith(processSpecItem.getParameterSetId(),
ProductVariableEnum.EDCPLAN_VARIABLE_PREFIX.getValue()));
}
}
private void checkIfReticleFamilyIsValidAndSet(Long facilityRrn, ProcessSpecItem processSpecItem,
StringBuilder rowErrorMsg) {
processSpecItem.setReticleFamilyId(StringUtils.trimToUpperCase(processSpecItem.getReticleFamilyId()));
if (StringUtils.isNotEmptyTrim(processSpecItem.getReticleFamilyId())) {
processSpecItem.setReticleFamilyRrn(
namedObjectManager.getNamedObjectRrn(processSpecItem.getReticleFamilyId(), facilityRrn,
ObjectList.RETICLEFAMILY_KEY));
if (processSpecItem.getReticleFamilyRrn() == null || processSpecItem.getReticleFamilyRrn() <= 0) {
if (ProductVariableEnum.isReticleGroupVariable(processSpecItem.getReticleFamilyId())) {
rowErrorMsg.append(
reticleFamilyManager.checkReticleFamilyAndCreate(processSpecItem.getReticleFamilyId()));
processSpecItem.setReticleFamilyRrn(
namedObjectManager.getNamedObjectRrn(processSpecItem.getReticleFamilyId(), facilityRrn,
ObjectList.RETICLEFAMILY_KEY));
} else {
rowErrorMsg.append("Reticle Group dose not existed.<br>");
}
}
processSpecItem.setVariableFlag(StringUtils.startsWith(processSpecItem.getReticleFamilyId(),
ProductVariableEnum.RTL_VARIABLE_PREFIX.getValue()));
}
}
private void checkIfRecipeIsValidAndSet(Long facilityRrn, ProcessSpecItem processSpecItem,
StringBuilder rowErrorMsg) {
processSpecItem.setRecipeId(StringUtils.trimToUpperCase(processSpecItem.getRecipeId()));
if (StringUtils.isNotEmptyTrim(processSpecItem.getRecipeId())) {
processSpecItem.setRecipeRrn(
namedObjectManager.getNamedObjectRrn(processSpecItem.getRecipeId(), facilityRrn,
ObjectList.RECIPE_KEY));
if (processSpecItem.getRecipeRrn() == null || processSpecItem.getRecipeRrn() <= 0) {
rowErrorMsg.append(recipeManager.checkRecipeAndCreate(processSpecItem.getRecipeId()));
processSpecItem.setRecipeRrn(
namedObjectManager.getNamedObjectRrn(processSpecItem.getRecipeId(), facilityRrn,
ObjectList.RECIPE_KEY));
} else if (recipeManager.isMainRecipe(processSpecItem.getRecipeRrn()) != processSpecItem.getRecipeRrn()) {
rowErrorMsg.append("Recipe: ").append(processSpecItem.getRecipeId()).append(" is chamber recipe!<br>");
}
processSpecItem.setVariableFlag(StringUtils.startsWith(processSpecItem.getRecipeId(),
ProductVariableEnum.RECIPE_VARIABLE_PREFIX.getValue()));
} else {
processSpecItem.setRecipeId("");
}
}
private List<ProcessSpecItemDto> buildProcessSpecItems(ProcessSpecItemBuildParameterDto parameter,
Integer highestProcessVersion,
List<Map<String, Object>> processFlow, Long productRrn) {
Long processRrn = parameter.getProcessSpecInfo().getProcessRrn();
Integer processVersion = parameter.getProcessSpecInfo().getProcessVersion();
String processId = parameter.getProcessSpecInfo().getProcessId();
List<Pair<Long, Integer>> reworkRoutes = new ArrayList<>();
List<ProcessSpecItemDto> processSpecItems = new ArrayList<>();
for (Map<String, Object> map : processFlow) {
ProcessSpecItemDto processSpecItem = new ProcessSpecItemDto();
processSpecItem.setProcessRrn(processRrn);
processSpecItem.setProcessId(processId);
processSpecItem.setProcessVersion(processVersion);
processSpecItem.setRouteRrn(MapUtils.getLong(map, "routeRrn"));
processSpecItem.setRouteId(MapUtils.getString(map, "routeId", StringUtils.EMPTY));
processSpecItem.setRouteVersion(MapUtils.getInteger(map, "routeVersion"));
processSpecItem.setRouteSeq(MapUtils.getString(map, "routeProcessSeq", StringUtils.EMPTY));
processSpecItem.setOperationRrn(MapUtils.getLong(map, "operationRrn"));
processSpecItem.setOperationId(MapUtils.getString(map, "operationId", StringUtils.EMPTY));
processSpecItem.setOperationSeq(MapUtils.getString(map, "operationRouteSeq", StringUtils.EMPTY));
// Default Value
processSpecItem.setOperationType(
parameter.getOperationTypeDesc(MapUtils.getString(map, "operationType", StringUtils.EMPTY)));
processSpecItem.setWorkArea(
parameter.getWorkAreaDesc(MapUtils.getString(map, "workArea", StringUtils.EMPTY)));
processSpecItem.setIsCopyFromLastVer(!processVersion.equals(highestProcessVersion));
ProcessAttributeDto attribute = parameter.getAttribute(
ContextValueUtils.buildKeyByProcess(processSpecItem.getProcessRrn(),
processSpecItem.getProcessVersion(),
processSpecItem.getRouteRrn(),
processSpecItem.getOperationRrn()));
if (attribute != null) {
if (StringUtils.isBlank(attribute.getProcessSpecItem().getEquipmentGroupRrns())) {
Long equipmentGroupRrn = operationManager.getOperationEquipmentGroupRrn(
processSpecItem.getOperationRrn());
if (equipmentGroupRrn != null) {
processSpecItem.setEquipmentGroupId(namedObjectManager.getInstanceId(equipmentGroupRrn));
processSpecItem.setEquipmentGroupRrns(StringUtils.toString(equipmentGroupRrn));
}
} else {
processSpecItem.setEquipmentGroupRrns(attribute.getProcessSpecItem().getEquipmentGroupRrns());
processSpecItem.setEquipmentGroupId(attribute.getProcessSpecItem().getEquipmentGroupId());
}
processSpecItem.setOperationDesc(attribute.getProcessSpecItem().getOperationDesc());
if (StringUtils.isNotBlank(attribute.getProcessSpecItem().getOperationType())) {
processSpecItem.setOperationType(
parameter.getOperationTypeDesc(attribute.getProcessSpecItem().getOperationType()));
}
processSpecItem.setFlowSeq(attribute.getProcessSpecItem().getFlowSeq());
if (StringUtils.isNotBlank(attribute.getProcessSpecItem().getWorkArea())) {
processSpecItem.setWorkArea(
parameter.getWorkAreaDesc(attribute.getProcessSpecItem().getWorkArea()));
if (StringUtils.isBlank(processSpecItem.getWorkArea())) {
// 兼容老数据
processSpecItem.setWorkArea(attribute.getProcessSpecItem().getWorkArea());
}
}
processSpecItem.setStageId(parameter.getStageIdDesc(attribute.getProcessSpecItem().getStageId()));
processSpecItem.setRecipeId(attribute.getProcessSpecItem().getRecipeId());
processSpecItem.setReticleFamilyId(attribute.getProcessSpecItem().getReticleFamilyId());
processSpecItem.setParameterSetId(attribute.getProcessSpecItem().getParameterSetId());
processSpecItem.setPollutionLevel(attribute.getProcessSpecItem().getPollutionLevel());
processSpecItem.setProcessLocation(attribute.getProcessSpecItem().getProcessLocation());
processSpecItem.setBankFlag(attribute.getProcessSpecItem().getBankFlag());
processSpecItem.setFlipType(attribute.getProcessSpecItem().getFlipType());
processSpecItem.setFlipTypeDesc(parameter.getFlipTypeDesc(processSpecItem.getFlipType()));
if (!processSpecItem.getIsCopyFromLastVer()) {
processSpecItem.setEcnRrn(attribute.getProcessSpecItem().getEcnRrn());
processSpecItem.setStatus(attribute.getProcessSpecItem().getStatus());
processSpecItem.setEffectiveTime(attribute.getProcessSpecItem().getEffectiveTime());
processSpecItem.setTerminatedTime(attribute.getProcessSpecItem().getTerminatedTime());
processSpecItem.setCreatedUser(attribute.getProcessSpecItem().getCreatedUser());
processSpecItem.setCreatedTime(attribute.getProcessSpecItem().getCreatedTime());
processSpecItem.setUpdatedUser(attribute.getProcessSpecItem().getUpdatedUser());
processSpecItem.setUpdatedTime(attribute.getProcessSpecItem().getUpdatedTime());
}
}
processSpecItem.setTimeLimitInfo(getOperationQueueTimeFilterProduct(processSpecItem, productRrn));
processSpecItem.setIsMain(BooleanUtils.toBoolean(MapUtils.getIntValue(map, "isMain")));
processSpecItem.setIsRework(BooleanUtils.toBoolean(MapUtils.getIntValue(map, "isRework")));
if (attribute != null && attribute.getProcessRework() != null) {
ProcessReworkDto processReworkDTO = attribute.getProcessRework();
processSpecItem.setReworkRouteId(
namedObjectManager.getInstanceId(processReworkDTO.getReworkRouteRrn()));
processSpecItem.setReworkRouteVersion(processReworkDTO.getReworkRouteVersion());
processSpecItem.setMaxReworkTimes(StringUtils.toString(processReworkDTO.getMaxReworkTimes()));
reworkRoutes.add(
new Pair<>(processReworkDTO.getReworkRouteRrn(), processReworkDTO.getReworkRouteVersion()));
}
processSpecItems.add(processSpecItem);
}
if (CollectionUtils.isNotEmpty(reworkRoutes)) {
for (Pair<Long, Integer> reworkRoute : reworkRoutes) {
Long reworkRouteRrn = reworkRoute.getKey();
Integer reworkRouteVersion = reworkRoute.getValue();
if (parameter.getReworkRrnInProcessSet().add(reworkRouteRrn)) {
List<Map<String, Object>> reworkRouteFlow = getReworkRouteFlow(reworkRouteRrn, reworkRouteVersion);
processSpecItems.addAll(
buildProcessSpecItems(parameter, highestProcessVersion, reworkRouteFlow, productRrn));
}
}
}
//将multipath step对应的default step做上标记
return setMultipathAndDefaultStepFlag(processSpecItems);
}
/**
* 将process对应的multipath和default step都做上标记
**/
public List<ProcessSpecItemDto> setMultipathAndDefaultStepFlag(List<ProcessSpecItemDto> nodes) {
if(CollectionUtils.isEmpty(nodes)){
return new ArrayList<>();
}
List<Map<String,Object>> multipathAndDefultWfls = new ArrayList<>();
List<Map<String,Object>> multipathAndDefultWflByOperation = specManager.getMultipathAndDefaultSteps(nodes.get(0).getProcessRrn(), nodes.get(0).getProcessVersion(), WflLinkContextSetupAttributeUtil.OPERATION_FLAG);
multipathAndDefultWfls.addAll(multipathAndDefultWflByOperation);
List<Map<String,Object>> multipathAndDefultWflByRoute = specManager.getMultipathAndDefaultSteps(nodes.get(0).getProcessRrn(), nodes.get(0).getProcessVersion(), WflLinkContextSetupAttributeUtil.ROUTE_FLAG);
multipathAndDefultWfls.addAll(multipathAndDefultWflByRoute);
if(CollectionUtils.isNotEmpty(multipathAndDefultWfls)){
for(ProcessSpecItemDto node : nodes){
for(Map<String,Object> multipathAndDefultWfl : multipathAndDefultWfls){
Long operationRrn = MapUtils.getLong(multipathAndDefultWfl,"operationRrn");
Long routeRrn = MapUtils.getLong(multipathAndDefultWfl,"routeRrn");
if(operationRrn.equals(node.getOperationRrn()) && routeRrn.equals(node.getRouteRrn())){
node.setMultipathAndDefaultStepFlag("1");
break;
}
}
}
}
return nodes;
}
private List<Map<String, Object>> getReworkRouteFlow(Long reworkRouteRrn, Integer reworkRouteVersion) {
// 兼容 Rework 加 Rework Route Version
List<Map<String, Object>> reworkRouteFlow;
if (reworkRouteVersion == null || reworkRouteVersion <= 0) {
reworkRouteFlow = processReworkManager.getReworkWorkflow(reworkRouteRrn);
} else {
reworkRouteFlow = processReworkManager.getReworkWorkflow(reworkRouteRrn, reworkRouteVersion);
}
return reworkRouteFlow;
}
private String getOperationQueueTimeFilterProduct(ProcessSpecItemDto processSpecItem, Long productRrn) {
TimeLimitSetup timeLimitSetup = new TimeLimitSetup();
timeLimitSetup.setStartProductRrn(productRrn);
timeLimitSetup.setStartProcessRrn(processSpecItem.getProcessRrn());
timeLimitSetup.setStartProcessVersion(processSpecItem.getProcessVersion());
timeLimitSetup.setStartRouteRrn(processSpecItem.getRouteRrn());
timeLimitSetup.setStartOperationRrn(processSpecItem.getOperationRrn());
List<TimeLimitSetup> timeLimitSetups = timeLimitSetupManager.getTimeLimitSetupsByStartInfo(timeLimitSetup);
List<TimeLimitSetup> realTimeLimitSetups = new ArrayList<>();
//若没有productRrn则显示公共设置
if (productRrn == null || productRrn.longValue() <= 0) {
for (TimeLimitSetup limitSetup : timeLimitSetups) {
if (limitSetup.getStartProductRrn().longValue() == 0) {
realTimeLimitSetups.add(limitSetup);
}
}
}
//否则只显示该product的设置
else {
for (TimeLimitSetup limitSetup : timeLimitSetups) {
if (limitSetup.getStartProductRrn().longValue() > 0) {
realTimeLimitSetups.add(limitSetup);
}
}
}
StringBuilder sb = new StringBuilder();
if (CollectionUtils.isNotEmpty(realTimeLimitSetups)) {
for (TimeLimitSetup temp : realTimeLimitSetups) {
sb.append(temp.getInstanceId()).append(" ").append(temp.getTimeLimit()).append(";");
}
}
return sb.toString();
}
private void checkIfProcessSpecItemsCanDoFreeze(List<ProcessSpecItem> processSpecItems, StringBuilder errorMsg) {
for (ProcessSpecItem processSpecItem : processSpecItems) {
StringBuilder rowErrorMsg = new StringBuilder();
if (StepTypeConst.isMeasurementStep(processSpecItem.getOperationType()) &&
processSpecItem.getParameterSetRrn() == 0) {
rowErrorMsg.append("Operation Type is M must be set EDC Plan ");
}
if (rowErrorMsg.length() > 0) {
errorMsg.append(" Flow Seq: ").append(processSpecItem.getFlowSeq()).append("<br>").append(rowErrorMsg);
}
}
}
private void checkIfHasUnfrozenTimeLimit(List<ProcessSpecItem> processSpecItems, String processId,
Integer processVersion) {
Page page = new Page(1, Integer.MAX_VALUE);
page = timeLimitSetupManager.getTimeLimitSetupForTemp(page, StringUtils.EMPTY, processId, processVersion);
/**
* 从TIMELIMIT_SETUP_TMP表能查询出数据,当前流程版本下有未激活的Q-Timne
* 因为当Q-Time激活时,会删除TIMELIMIT_SETUP_TMP表中对应的数据
*/
Assert.isFalse(CollectionUtils.isNotEmpty(page.getResults()),
Errors.create().key(MessageIdList.SPEC_PROCESS_TIMELIMIT_NO_ACTION)
.content("The process has unfrozen Q-Time and cannot be activated.").build());
}
private void checkFlipType(List<ProcessSpecItemDto> processSpecItems, StringBuilder errorMsg,
boolean confirmNotTogether) {
boolean flag;
if (confirmNotTogether) {
flag = true;
} else {
if (CollectionUtils.isNotEmpty(processSpecItems)) {
int size = processSpecItems.size();
int count = 0;
for (ProcessSpecItemDto psi : processSpecItems) {
if (StringUtils.isNotBlank(psi.getFlipType())) {
count++;
}
}
flag = count != 0 && size != count;
} else {
flag = false;
}
}
if (flag) {
if (errorMsg == null) {
throw new SystemIllegalArgumentException(Errors.create().key(MessageIdList.FLIP_SET_TOGETHER)
.content("Flip properties need to be set together!")
.build());
} else {
errorMsg.append(I18nUtils.getMessage(MessageIdList.FLIP_SET_TOGETHER,
"Flip properties need to be set together!")).append("<br>");
}
}
}
private void validationActiveProcessSpecItems(ProcessSpecFormDto processSpecForm) {
//验证active数据完整性,防止有新增的step但未刷新的情况
List<ProcessSpecItemDto> processSpecItemDtos = queryProcessSpecItems(processSpecForm);
boolean validation = true;
for (ProcessSpecItemDto processSpecItemDto : processSpecItemDtos) {
if (!validation) {
break;
}
if (StringUtils.isBlank(processSpecItemDto.getFlowSeq()) ||
StringUtils.isBlank(processSpecItemDto.getWorkArea()) ||
StringUtils.isBlank(processSpecItemDto.getOperationDesc()) ||
StringUtils.isBlank(processSpecItemDto.getStageId()) ||
StringUtils.isBlank(processSpecItemDto.getRecipeId()) ||
StringUtils.isBlank(processSpecItemDto.getProcessLocation()) ||
StringUtils.isBlank(processSpecItemDto.getEquipmentGroupId())) {
validation = false;
}
}
//提示用户点击查询刷新数据并填写必填的数据
Assert.isTrue(validation, Errors.create().key(MessageIdList.PRODSPEC_INCOMPLETE_DATA).content(
"The data is incomplete, please click the query button to refresh the data and supplement the data")
.build());
}
}