DummyLotReassignAction.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.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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Luopeng.Wang
 * @version 6.0.0
 * @date 2019/9/26
 **/
public class DummyLotReassignAction 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");

        Assert.isFalse(StringUtils.isEmpty(lotId) && StringUtils.isEmpty(productId),
                       Errors.create().content("Product ID cannot" + " be empty!").build());

        boolean isNeedHold = ReassignTypeEnum.isProcessReassign(reassignType);
        Integer latestActivatedProcessVersion = NumberUtils.INTEGER_MINUS_ONE;
        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
        checkLotisRework(reassignRequestDto.getReassignLotRrns());

        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(true);
        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().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().content("Can not find Lot").build());
                lotRrns.add( lot.getLotRrn());
            }
            reassignRequestDto.setReassignLotRrns(lotRrns);
        }
        lotReassignService.reassign(reassignRequestDto, responsibilityUser);
    }

    private void checkLot(Boolean holdFlag, Lot lot) {
        boolean isDummyLot = StringUtils.equals("C", lot.getCreateCategory());
        Assert.isFalse(!isDummyLot,
                       Errors.create().content("Lot ID: {} is not 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());
    }

    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 checkLotisRework(List<Long> lotRrns) {
        for (long lotRrn : lotRrns) {
            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());
        }
    }

}