LotReassignAction.java
package com.mycim.webapp.actions.lot.reassign;
import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.threadlocal.LocalContext;
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.prp.ProcessPlanning;
import com.mycim.valueobject.prp.ProcessSpecItemDto;
import com.mycim.valueobject.prp.ProductProcess;
import com.mycim.valueobject.prp.ProductSpecInfo;
import com.mycim.valueobject.security.User;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.LotStatus;
import com.mycim.valueobject.wip.ReassignTypeEnum;
import com.mycim.valueobject.wip.dto.ReassignQueryDto;
import com.mycim.valueobject.wip.dto.ReassignRequestDto;
import com.mycim.webapp.Constants;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.WipSetupAction;
import org.apache.commons.lang3.math.NumberUtils;
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 Luopeng.Wang
* @version 6.0.0
* @date 2019/9/26
**/
public class LotReassignAction extends WipSetupAction {
@Override
public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (StringUtils.isNotEmpty(WebUtils.getParameter(Constants.INIT_KEY, request))) {
return mapping.findForward(Constants.INIT_KEY);
}
if (StringUtils.isNotEmpty(WebUtils.getParameter("initForProduct", request))) {
return mapping.findForward("initForProduct");
}
if (StringUtils.isNotEmpty(WebUtils.getParameter("initForProcessVer", request))) {
return mapping.findForward("initForProcessVer");
}
return WebUtils.NULLActionForward;
}
public Map<String, Object> queryProcessInfo(Map<String, Object> map) {
boolean cancelFlag = MapUtils.getBooleanValue(map, "cancelFlag");
String reassignType = MapUtils.getString(map, "reassignType");
String lotId = MapUtils.getString(map, "lotId");
String productId = MapUtils.getString(map, "productId");
Integer latestActivatedProcessVersion = NumberUtils.INTEGER_MINUS_ONE;
Assert.isFalse(StringUtils.isEmpty(lotId) && StringUtils.isEmpty(productId),
Errors.create().content("Product ID cannot" + " be empty!").build());
boolean isNeedHold = ReassignTypeEnum.isProcessReassign(reassignType);
String processId = null;
List<ProductSpecInfo> productSpecInfos = null;
List<ProductSpecInfo> productSpecInfosForProcessVer = new ArrayList<>();
if (StringUtils.isNotEmpty(lotId)) {
Lot lot = lotQueryService.getLot(lotId, LocalContext.getFacilityRrn());
if (!cancelFlag) {
Assert.isFalse(lot.getLotRrn() <= 0,
Errors.create().content("Lot ID: {} does not exist!").args(lotId).build());
checkLot(isNeedHold, lot);
}
productId = getInstanceId(lot.getProductRrn());
processId = getInstanceId(lot.getProcessRrn());
productSpecInfos = new ArrayList<>();
ProductSpecInfo tmp = new ProductSpecInfo();
tmp.setProductRrn(lot.getProductRrn());
tmp.setProductVersion(lot.getProductVersion());
tmp.setProcessRrn(lot.getProcessRrn());
tmp.setProcessVersion(lot.getProcessVersion());
productSpecInfos.add(tmp);
} else if (StringUtils.isNotEmpty(productId)) {
long productRrn = baseService.getNamedObjectRrn(productId, baseService
.getNamedSpace(LocalContext.getFacilityRrn(), ObjectList.PRODUCT_KEY), ObjectList.PRODUCT_KEY);
List<ProductProcess> productProcesses = productService.getProductProcesses(productRrn);
Assert.isFalse(CollectionUtils.isEmpty(productProcesses),
Errors.create().content("This product does not have any " + "process!").build());
ProductProcess productProcess = productProcesses.iterator().next();
processId = baseService.getNamedObjectId(productProcess.getProcessRrn());
productSpecInfos = specService
.getAllActivatedProductSpecItemInfo(productRrn, productProcess.getProcessRrn());
// reassignType 为PROCESS_VERSION 时,返回的processVer需要不包含当前processVer的最高版本
if (ReassignTypeEnum.isProcessVersionReassign(reassignType)) {
latestActivatedProcessVersion = specService
.getLatestActivatedProcessVersion(productRrn, productProcess.getProcessRrn());
for (ProductSpecInfo productSpecInfo : productSpecInfos) {
if (!latestActivatedProcessVersion.equals(productSpecInfo.getProcessVersion())) {
productSpecInfosForProcessVer.add(productSpecInfo);
}
}
}
}
Map<String, Object> result = new HashMap<>();
result.put("lotId", lotId);
result.put("productId", productId);
result.put("processId", processId);
if (ReassignTypeEnum.isProductReassign(reassignType) || ReassignTypeEnum.isProcessReassign(reassignType)) {
result.put("productSpecItemInfos", productSpecInfos);
}else if (ReassignTypeEnum.isProcessVersionReassign(reassignType)) {
result.put("productSpecItemInfos", productSpecInfosForProcessVer);
}
return result;
}
public Map<String, Object> queryTargetProcessInfo(Map<String, Object> map) {
String reassignType = MapUtils.getString(map, "reassignType");
String productId = MapUtils.getString(map, "productId");
String processId = MapUtils.getString(map, "processId");
int processVersion = MapUtils.getIntValue(map, "sourcessProcessVer");
//当选择ALL作为查询条件时
if(NumberUtils.compare(processVersion, -1) == 0){
processVersion = 1;
}
Assert.isFalse(StringUtils.isEmpty(productId), Errors.create().content("Product ID cannot be empty!").build());
long productRrn = baseService.getNamedObjectRrn(productId, baseService
.getNamedSpace(LocalContext.getFacilityRrn(), ObjectList.PRODUCT_KEY), ObjectList.PRODUCT_KEY);
Assert.isFalse(productRrn == 0, Errors.create().key(MessageIdList.SUBTECHNOLOGY_ENTER_CORRECT)
.content("Please enter the correct product Id!").build());
List<ProductProcess> productProcesses = productService.getProductProcesses(productRrn);
Assert.isFalse(CollectionUtils.isEmpty(productProcesses),
Errors.create().content("This product does not have any " + "process!").build());
ProductProcess processMap = productProcesses.iterator().next();
Long targetProcessRrn = processMap.getProcessRrn();
String targetProcessId = baseService.getNamedObjectId(targetProcessRrn);
Assert.isFalse(
ReassignTypeEnum.isProductReassign(reassignType) && !StringUtils.equals(processId, targetProcessId),
Errors.create().content("The product does not match the process!").build());
List<ProductSpecInfo> productSpecInfos = new ArrayList<>();
if (!ReassignTypeEnum.isProcessReassign(reassignType)) {
Assert.isFalse(processVersion <= 0,
Errors.create().content("Source process version cannot be empty!").build());
productSpecInfos.add(specService.getHighestActivatedProductSpecItemInfo(productRrn, targetProcessRrn,
processVersion));
} else {
productSpecInfos.addAll(specService.getAllActivatedProductSpecItemInfo(productRrn, targetProcessRrn));
}
Map<String, Object> result = new HashMap<>();
result.put("productId", productId);
result.put("processId", targetProcessId);
result.put("productSpecItemInfos", productSpecInfos);
return result;
}
public Map<String, Object> checkLotIsAvailable(ReassignRequestDto reassignRequestDto) {
checkBaseTargetParameter(reassignRequestDto);
Assert.isFalse(CollectionUtils.isEmpty(reassignRequestDto.getReassignLotRrns()),
Errors.create().content("Pelease select Lot first!").build());
//检查批次当前是否返工工步,返工工步不能做Reassign
//And Check Flip attribute
checkLotIsReworkAndFlip(reassignRequestDto);
return lotReassignService.checkIfSelectLotsIsReassignable(reassignRequestDto);
}
public Map<String, Object> query(ReassignQueryDto query) {
Assert.isFalse(
ReassignTypeEnum.isProcessReassign(query.getReassignType()) && StringUtils.isEmpty(query.getLotId()) &&
StringUtils.isEmpty(query.getProductId()),
Errors.create().content("Lot ID and Product " + "ID cannot be empty" + " at the same time!").build());
Assert.isFalse(StringUtils.isEmpty(query.getProductId()),
Errors.create().content("Product ID cannot be empty!").build());
long facilityRrn = LocalContext.getFacilityRrn();
long productRrn = baseService
.getNamedObjectRrn(query.getProductId(), baseService.getNamedSpace(facilityRrn, ObjectList.PRODUCT_KEY),
ObjectList.PRODUCT_KEY);
long processRrn = baseService
.getNamedObjectRrn(query.getProcessId(), baseService.getNamedSpace(facilityRrn, ObjectList.WFL_KEY),
ObjectList.WFL_KEY);
query.setProductRrn(productRrn);
query.setProcessRrn(processRrn);
query.setDummyFlag(false);
query.setLotIsHoldFlag(ReassignTypeEnum.isProcessReassign(query.getReassignType()));
query.setExactQueryProcessVersionFlag(!ReassignTypeEnum.isProcessVersionReassign(query.getReassignType()));
List<Lot> lots = lotReassignService.getLotsForReassign(facilityRrn, query);
List<Map<String, Object>> result = new ArrayList<>();
Map<String, Object> lotShowInfo;
for (Lot lot : lots) {
lot.setOperationRrn(prpService.getOperationRrnByLot(lot));
lot.setOperationId(getInstanceId(lot.getOperationRrn()));
lotShowInfo = new HashMap<>();
lotShowInfo.put("facilityRrn", facilityRrn);
lotShowInfo.put("lotRrn", lot.getLotRrn());
lotShowInfo.put("lotId", lot.getLotId());
lotShowInfo.put("lotStatus", lot.getLotStatus());
lotShowInfo.put("productRrn", lot.getProductRrn());
lotShowInfo.put("productId", getInstanceId(lot.getProductRrn()));
lotShowInfo.put("productVersion", lot.getProductVersion());
lotShowInfo.put("processRrn", lot.getProcessRrn());
lotShowInfo.put("processId", getInstanceId(lot.getProcessRrn()));
lotShowInfo.put("processVersion", lot.getProcessVersion());
lotShowInfo.put("routeRrn", lot.getRouteRrn());
lotShowInfo.put("operationRrn", lot.getOperationRrn());
lotShowInfo.put("operationId", lot.getOperationId());
lotShowInfo.put("flowSeq", lot.getFlowSeq());
lotShowInfo.put("hasLotFutureReassigns", wipCheckService.hasLotFutureReassigns(lot.getLotRrn()));
result.add(lotShowInfo);
}
Map<String, Object> resultMsg = new HashMap<>();
resultMsg.put("reassignableLots", result);
return resultMsg;
}
public void reassign(ReassignRequestDto reassignRequestDto) {
checkParameters(reassignRequestDto);
checkBaseTargetParameter(reassignRequestDto);
User responsibilityUser = securityService.getUser(reassignRequestDto.getResponsibilityUserRrn());
Assert.isFalse(responsibilityUser == null || responsibilityUser.getInstanceRrn() <= 0,
Errors.create().content("User not exist, Please check!").build());
//LotIds 不能为空
Assert.isFalse(CollectionUtils.isEmpty(reassignRequestDto.getReassignLotIds()), Errors.create().key(MessageIdList.LOT_ID_EMPTY)
.content("Lot id is Empty!").build());
if(CollectionUtils.isEmpty(reassignRequestDto.getReassignLotRrns())){
List<Long> lotRrns = new ArrayList<>();
for(String lotId :reassignRequestDto.getReassignLotIds()){
Lot lot = lotQueryService.getLot(lotId);
Assert.isFalse(lot==null, Errors.create().key(MessageIdList.LOT_LOTRRN_NOT_FOUND).content("Can not find Lot").build());
// 如果批次已经出发post Future hold导致 hold状态,则不允许做 reassign,需要卡控住
checkPostFutureHold(lot.getLotRrn());
lotRrns.add( lot.getLotRrn());
}
reassignRequestDto.setReassignLotRrns(lotRrns);
}
lotReassignService.reassign(reassignRequestDto, responsibilityUser);
for (String reassignLotId : reassignRequestDto.getReassignLotIds()) {
Lot lot = lotQueryService.getLot(reassignLotId);
splitRunCardService.doStartSplitRunCard(LocalContext.getUserId(), lot);
}
}
private void checkLot(Boolean holdFlag, Lot lot) {
boolean isDummyLot = StringUtils.equals("C", lot.getCreateCategory());
Assert.isFalse(isDummyLot, Errors.create().content("Lot ID: {} is dummy lot!").args(lot.getLotId()).build());
boolean isHoldLot = LotStatus.isWaitingOrHold(lot.getLotStatus());
Assert.isFalse(holdFlag && !isHoldLot,
Errors.create().content("Lot ID: {} must be in HOLD or WAITING status!").args(lot.getLotId())
.build());
Assert.isFalse(lotStatusCheckService.hasValidRcHold(lot),
Errors.create().content("Lot has valid RunCard!").build());
}
protected void checkBaseTargetParameter(ReassignRequestDto reassignRequestDto) {
Assert.isFalse(StringUtils.isEmpty(reassignRequestDto.getTargetProductId()),
Errors.create().content("Target Product Id can not be empty!").build());
Assert.isFalse(StringUtils.isEmpty(reassignRequestDto.getTargetProcessId()),
Errors.create().content("Target Process Id can not be empty!").build());
Assert.isFalse(reassignRequestDto.getTargetProcessVersion() <= 0,
Errors.create().content("Target Process Version is error!").build());
Assert.isFalse(ReassignTypeEnum.isProcessReassign(reassignRequestDto.getReassignType()) &&
(StringUtils.isEmpty(reassignRequestDto.getTargetFlowSeq()) ||
StringUtils.isEmpty(reassignRequestDto.getTargetStepPath())),
Errors.create().content("Target Flow Sequence can not be empty!").build());
}
protected void checkLotIsReworkAndFlip(ReassignRequestDto rqd) {
String flipType = StringUtils.EMPTY;
long processRrn = 0;
boolean checkFlip = false;
ProcessSpecItemDto psi = null;
if (ReassignTypeEnum.isProcessReassign(rqd.getReassignType()) || ReassignTypeEnum.isProcessVersionReassign(rqd.getReassignType())){
processRrn = getInstanceRrn(rqd.getTargetProcessId(), getNamedSpace(ObjectList.WFL_KEY, LocalContext.getFacilityRrn()), ObjectList.WFL_KEY);
if (StringUtils.isNotBlank(rqd.getTargetFlowSeq())){
ProcessSpecItemDto temp = new ProcessSpecItemDto(processRrn, rqd.getTargetProcessVersion(), rqd.getTargetFlowSeq());
psi = processSpecService.queryProcessSpecItem(temp);
flipType = Objects.isNull(psi)? StringUtils.EMPTY:psi.getFlipType();
}
checkFlip = true;
}
for (long lotRrn : rqd.getReassignLotRrns()) {
Lot lot = lotQueryService.getLot(lotRrn);
String routeSeq = lot.getRouteSeq();
Assert.isFalse(StringUtils.isBlank(routeSeq), Errors.create().key(MessageIdList.REASSIGN_REWORK_STEP)
.content("{} in rework step, reassign not allowed!")
.args(lot.getLotId()).build());
//check lot flip and target flow flip
if (checkFlip){
if (ReassignTypeEnum.isProcessVersionReassign(rqd.getReassignType())){
//目前Action卡控了必须WAITING和HOLD状态才能Reassign,不会出现isFeatureReassign=true的情况。
ProcessSpecItemDto temp = new ProcessSpecItemDto(processRrn, rqd.getTargetProcessVersion(), lot.getRouteRrn(), lot.getOperationRrn());
psi = processSpecService.queryProcessSpecItem(temp);
}
this.checkFlip4LotAndFlow(lot, psi);
}
}
}
}