TransferLotAction.java

package com.mycim.webapp.actions.unit.transfer;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
import com.fa.sesa.exception.SystemIllegalStateException;
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.beans.PropertyUtils;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.framework.utils.lang.time.DateUtils;
import com.mycim.valueobject.LocationNames;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.NamedObject;
import com.mycim.valueobject.consts.*;
import com.mycim.valueobject.ems.Carrier;
import com.mycim.valueobject.prp.Item;
import com.mycim.valueobject.prp.Operation;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.LotStatus;
import com.mycim.valueobject.wip.LotTransfer;
import com.mycim.valueobject.wip.TransReason;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.WipSetupAction;
import com.mycim.webapp.forms.lot.LotInfoForm;
import com.mycim.webapp.forms.unit.TransferLotForm;
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.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhi.cai
 * @version 6.0.0
 * @date 2020/5/11
 **/
public class TransferLotAction extends WipSetupAction {

    private static final String DEFAULT_WAFER_BANK = "WAFER_BANK";

    private static final String SEPARATOR = "#";

    private static String WAITING_KEY = "WAITING";

    private static String Material_prefix = "allMaterial";

    private static String DUMMY_OPERATION_TYPE = "D";

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        return mapping.getInputForward();
    }


    public Map transferMap(TransferLotForm theform) {
        Map resultMap = new HashMap();
        String lotId = StringUtils.trim(theform.getLotId());
        Lot lot = lotQueryService.getLot(lotId);
        long lotRrn = lot.getLotRrn();
        Carrier carrier = carrierService.getCarrier(lot.getCarrierRrn());
        Assert.isFalse(lotRrn < 1,
                       Errors.create().key(MessageIdList.LOT_LOTRRN_NOT_FOUND).content("Cannot Find Lot!").build());
        Assert.isFalse(carrier.getObjectSubtype() == "DUMMY",
                       Errors.create().key(MessageIdList.LOT_CARRIER_IS_DUMMY).content("Please assign carrier!")
                             .build());
        Assert.isFalse(lot.getInt_qty1() > 1,
                       Errors.create().content("Only lot with a quantity of 1 can be transfer!").build());

        HashMap transferLotInfo = new HashMap();
        transferLotInfo.put("lotRrn", lotRrn);
        transferLotInfo.put("comments", theform.getComments());
        transferLotInfo.put("userId", LocalContext.getUserId());

        lotService.transferLot(transferLotInfo);

        return resultMap;
    }

    public Page qryTransferLot(TransferLotForm theform, HttpServletRequest request) {
        Map condtionInfo = new HashMap();
        condtionInfo.put("type", TransactionNames.TRANSFER_KEY);
        condtionInfo.put("lotId", theform.getLotId());
        condtionInfo.put("productId", theform.getProductId());
        condtionInfo.put("processId", theform.getProcessId());
        condtionInfo.put("transferStartDate", theform.getStartDate());
        condtionInfo.put("transferEndDate", theform.getEndDate());

        Page transferPage = new Page(theform.getPage(), theform.getLimit());

        transferPage = lotService.queryTransferLot(transferPage, condtionInfo);
        return transferPage;
    }


    public Page qryReceiveLot(TransferLotForm theform, HttpServletRequest request) {
        Map condtionInfo = new HashMap();
        condtionInfo.put("type", TransactionNames.RECEIVE_KEY);
        condtionInfo.put("lotId", theform.getLotId());
        condtionInfo.put("productId", theform.getProductId());
        condtionInfo.put("processId", theform.getProcessId());
        condtionInfo.put("receiveStartDate", theform.getStartDate());
        condtionInfo.put("receiveEndDate", theform.getEndDate());

        Page transferPage = new Page(theform.getPage(), theform.getLimit());

        transferPage = lotService.queryTransferLot(transferPage, condtionInfo);
        return transferPage;
    }

    public Map getTransferLotInfo(TransferLotForm theform, HttpServletRequest request) {
        Map resultMap = new HashMap();
        Map condtionInfo = new HashMap();
        condtionInfo.put("type", TransactionNames.TRANSFER_KEY);
        condtionInfo.put("lotId", theform.getLotId());

        Page transferPage = new Page(theform.getPage(), 1);
        transferPage = lotService.queryTransferLot(transferPage, condtionInfo);
        resultMap.put("data", transferPage.getResults());

        return resultMap;
    }

    public Map cancelTransfer(TransferLotForm theform, HttpServletRequest request) {
        Map resultMap = new HashMap();
        String lotId = theform.getLotId();
        String comments = theform.getComments();
        LotTransfer lotTransferByLotId = lotService.getLotTransferByLotId(lotId, TransactionNames.TRANSFER_KEY);
        Assert.notNull(lotTransferByLotId, Errors.create().content("Not find this transfer lot!").build());

        lotService.cancelTransferLot(lotId, comments);

        return resultMap;
    }

    public Map avoidReceive(TransferLotForm theform, HttpServletRequest request) {
        Map resultMap = new HashMap();
        String lotId = theform.getLotId();
        String comments = theform.getComments();
        LotTransfer lotTransferByLotId = lotService.getLotTransferByLotId(lotId, TransactionNames.RECEIVE_KEY);
        Assert.notNull(lotTransferByLotId, Errors.create().content("Not find this lot!").build());

        lotService.avoidReceive(lotId, comments);

        return resultMap;
    }

    public Map receiveLotReposition(LotInfoForm theform) {
        long facilityRrn = LocalContext.getFacilityRrn();
        String userId = LocalContext.getUserId();
        long userRrn = LocalContext.getUserRrn();

        String lotId = theform.getLotId();
        Lot lot = lotQueryService.getLot(lotId, facilityRrn);
        Map tempInfo = getStepsInfoByLot(lot, lot.getProcessRrn(), theform.getStepNumber());
        Long targetStepRrn = MapUtils.getLongValue(tempInfo, "operationRrn");
        Long targetRouRrn = parseRouteRrn((String) tempInfo.get("processStepVersion"));
        Carrier carrier = carrierService.getCarrier(lot.getCarrierRrn());
        Assert.isFalse(carrier == null || carrier.getInstanceRrn() <= 0,
                       Errors.create().key(MessageIdList.LOT_CARRIER_MISSING)
                             .content("Can not find this carrier of " + "Lot.").build());
        Assert.isFalse(StringUtils.equalsIgnoreCase(carrier.getObjectSubtype(), CarrierType.DUMMY) &&
                               lot.getAutoSplitMergFlag() != 1, Errors.create().key(MessageIdList.LOT_CARRIER_REMOVED)
                                                                      .content(
                                                                              "This carrier of Lot is already removed.")
                                                                      .build());

        Map changeProcessInfo = new HashMap();
        changeProcessInfo.put("lotRrn", new Long(lot.getLotRrn()));
        changeProcessInfo.put("lotId", lot.getLotId());
        changeProcessInfo.put("lotStatus", lot.getLotStatus());
        changeProcessInfo.put("qty", "" + lot.getQty1());
        changeProcessInfo.put("lotOwner", lot.getLotOwner());
        changeProcessInfo.put("currOperation", lot.getOperationId());
        changeProcessInfo.put("transPerformedBy", userId);
        changeProcessInfo.put("productRrn", lot.getProductRrn());
        changeProcessInfo.put("productId", lot.getProductId());
        changeProcessInfo.put("processRrn", lot.getProcessRrn());
        // check if technology is valid for product specified
        Assert.isTrue(isProductProcessBined((Long) changeProcessInfo.get("productRrn"),
                                            (Long) changeProcessInfo.get("processRrn")),
                      Errors.create().key(MessageIdList.PRODUCT_PRODUCT_PROCESS_NOT_BOUND)
                            .content("Product" + " " + "and " + "process" + " is " + "not " + "bound!").build());
        String stepNumber = theform.getStepNumber();
        if (!stepNumber.contains("|")) {
            changeProcessInfo.put("reworkSkip", "reworkSkip");
        }
        Boolean isFirstStepInProcess = prpService
                .isFirstStepInProcess(MapUtils.getLongValue(changeProcessInfo, "productRrn"),
                                      MapUtils.getLongValue(changeProcessInfo, "processRrn"),
                                      MapUtils.getIntValue(changeProcessInfo, "processVersion"), targetRouRrn,
                                      targetStepRrn);
        Assert.isFalse(isFirstStepInProcess, Errors.create().key(MessageIdList.LOT_CANT_SKIP_TO_FIRST_STEP)
                                                   .content("Lot cannot skip to the first step in process!").build());
        changeProcessInfo.put("stageId", tempInfo.get("stageId"));
        changeProcessInfo.put("layerId", tempInfo.get("layerId"));
        changeProcessInfo.put("executionRrn", tempInfo.get("executionRrn"));
        changeProcessInfo.put("operationRrn", tempInfo.get("operationRrn"));
        Long operationRrn = (Long) tempInfo.get("operationRrn");
        Assert.isTrue(checkOperationInFacility(operationRrn, facilityRrn),
                      Errors.create().key(MessageIdList.STEP_NOT_IN_CURRENT_FACILITY)
                            .content("The new subplan/step " + "is not in current " + "facility!").build());

        changeProcessInfo.put("operationId", getInstanceId(((Long) tempInfo.get("operationRrn")).longValue()));

        changeProcessInfo.put("operationVer", tempInfo.get("operationVer"));
        changeProcessInfo.put("processStepVersion", tempInfo.get("processStepVersion"));
        //changeProcessInfo.put("processVersion", tempInfo.get("processVersion"));
        changeProcessInfo.put("processVersion", lot.getProcessVersion());
        changeProcessInfo.put("processStepIdVersion", tempInfo.get("processStepIdVersion"));
        changeProcessInfo.put("processStepVersion4wfl", tempInfo.get("processStepVersion4wfl"));
        changeProcessInfo.put("nextoperationRrn1", tempInfo.get("nextoperationRrn1"));
        changeProcessInfo.put("nextoperationRrn2", tempInfo.get("nextoperationRrn2"));
        changeProcessInfo.put("nextprocessStepVersion1", tempInfo.get("nextprocessStepVersion1"));
        changeProcessInfo.put("nextprocessStepIdVersion1", tempInfo.get("nextprocessStepIdVersion1"));
        changeProcessInfo.put("nextprocessStepVersion2", tempInfo.get("nextprocessStepVersion2"));
        changeProcessInfo.put("nextprocessStepIdVersion2", tempInfo.get("nextprocessStepIdVersion2"));

        String temp = (String) tempInfo.get("processStepVersion");
        String route = "";

        if (temp != null) {
            int i = 0;
            int j = 0;
            i = temp.indexOf("|");

            // find first '|'
            if (i != -1) {
                j = temp.indexOf("|", i + 1);

                // find se '|'
                // string is aaa|bbb|cccc
                if (j > 0) {
                    route = temp.substring(i + 1, j);
                } else if (i > 0) { // aaa|bbb
                    route = temp.substring(0, i);
                }
            }
        }
        route = route.replace(',', '.');
        changeProcessInfo.put("route", route);
        Operation operation = prpService.getOperation(MapUtils.getLong(tempInfo, "operationRrn"));
        changeProcessInfo.put("trackUnitFlag", operation.getTrackUnitFlag());
        changeProcessInfo.put("keepUnitHistoryFlag", operation.getKeepUnitHistoryFlag());
        // get Context info
        tempInfo = new HashMap();
        tempInfo.put("productRrn", changeProcessInfo.get("productRrn"));
        // tempInfo.put("routeId", null);
        tempInfo.put("routeRrn", parseRouteRrn(MapUtils.getString(changeProcessInfo, "processStepVersion")));
        tempInfo.put("recipeRrn", null);
        tempInfo.put("operationRrn", changeProcessInfo.get("operationRrn"));
        tempInfo.put("technologyRrn", changeProcessInfo.get("processRrn"));
        tempInfo.put("lotRrn", changeProcessInfo.get("lotRrn"));
        tempInfo.put("facilityRrn", lot.getFacilityRrn());
        tempInfo.put("isOverrideConstrain", theform.isTargetCheckEquipConstrain());
        tempInfo.put("userRrn", userRrn);
        tempInfo.put("processStepVersion", changeProcessInfo.get("processStepVersion"));
        changeProcessInfo.put("borRrn", ctxExecService.getBomRrn(tempInfo));
        changeProcessInfo.put("reticleRrn", tempInfo.get("reticleRrn"));
        changeProcessInfo.put("transPerformedBy", userId);
        changeProcessInfo.put("transComments", theform.getLotComments());
        //Reason
        TransReason transReason = new TransReason();
        transReason.setReasonCode("Repoistion");
        transReason.setReason("Receive Lot Repoistion");
        transReason.setTransQty1(lot.getQty1());
        transReason.setTransQty2(lot.getQty2());
        transReason.setResponsibility(userId);
        changeProcessInfo.put("transReason", transReason);
        String skipFlag = getSkipFlag(lot, targetRouRrn, targetStepRrn);
        // after the workstream
        if ("before".equals(skipFlag)) {
            changeProcessInfo.put("changeflow", "before");
        } else if ("after".equals(skipFlag)) {
            changeProcessInfo.put("changeflow", "after");
        }
        List<Lot> lockLots = new ArrayList<Lot>();
        lockLots.add(lot);
        changeProcessInfo.put("transferLotFlag", "1");
        lotService.changeLotProcess(changeProcessInfo);
        lotService.updateLotStatus(lot.getLotRrn(), lot.getBeforeStatus());
        return null;
    }

    public Map receiveLot() {
        Map resultMsg = new HashMap();

        Map transferResultMap = null;
        List<LotTransfer> queryTransferListFromLabW = lotService.queryTransferListFromLabW();
        if (CollectionUtils.isNotEmpty(queryTransferListFromLabW)) {
            try {
                lotService.receiveLotFromLabW(queryTransferListFromLabW);
            } catch (Exception e) {
                lotService.rollbackReceiveLotFromLabW(queryTransferListFromLabW);
                LOGGER.error(e);
                throw new SystemIllegalStateException(Errors.create().content(e.getMessage()).build());
            }
        }

        int transLotCount = MapUtils.getIntValue(transferResultMap, "transLotCount");
        String transLotIds = MapUtils.getString(transferResultMap, "transLotIds");
        if (transLotCount > 0) {
            resultMsg.put("successMsg", I18nUtils
                    .getMessage("tranferlot.receiveSuccessInfo", "{} lots received. They are <br>{}", transLotCount,
                                transLotIds));
        } else {
            resultMsg.put("successMsg", I18nUtils.getMessage("nothavereceiveInfo", "Lot not received!"));
        }

        return resultMsg;
    }


    public Map receiveLotWaferStart(LotInfoForm theform, HttpServletRequest request) throws Exception {
        Map resultMsg = new HashMap();

        String user = LocalContext.getUserId();
        Long facilityRrn = LocalContext.getFacilityRrn();
        String language = I18nUtils.getCurrentLanguage().toString();
        Lot lot = new Lot();
        String lotId = theform.getLotId();
        String extendLotId = theform.getExtendLotId();
        Lot extendLot = lotQueryService.getLot(extendLotId);

        Assert.isFalse(StringUtils.isNotBlank(theform.getCustomerWaferId()) &&
                               isValidUnitId(theform.getCustomerWaferId(), facilityRrn),
                       Errors.create().key(MessageIdList.LOTPLAN_CUSTOMER_NUMBER_EXISTED)
                             .content("Customer number has already existed, " + "please change customer batch number!")
                             .build());
        Assert.isFalse(StringUtils.isBlank(theform.getLotOwner()),
                       Errors.create().key(MessageIdList.LOT_OWNER_REQUIRE).content("Lot Owner is require").build());
        theform.setLotOwner(StringUtils.trimToUpperCase(theform.getLotOwner()));
        Assert.isFalse((theform.getQty1() != null) && (theform.getQty1().compareTo((double) 0) <= 0),
                       Errors.create().key(MessageIdList.LOT_QUANTITY_MUST_LARGER_0)
                             .content("LOT Quantity must be larger than 0!").build());
        Assert.isFalse(StringUtils.isBlank(theform.getProductId()),
                       Errors.create().key(MessageIdList.PRODUCT_EMPTY_ID).content("Product Id cannot be empty!")
                             .build());
        // 根据lot plan type check the product type
        theform.setProductId(StringUtils.trimToUpperCase(theform.getProductId()));
        NamedObject obj = new NamedObject(theform.getProductId(), getNamedSpace(ObjectList.PRODUCT_KEY, facilityRrn),
                                          ObjectList.PRODUCT_KEY);
        obj = baseService.getNamedObject(obj);
        if (obj != null) {
            boolean matchFlag = true;
            // 产品类型不能是类表值$$SPECIAL_LOT_PLAN_TYPE设置的类型 也不能是BOND类型
            List<String> specialTypes = sysService
                    .getRefFileKey(ReferenceDetailNames.SPECIAL_LOT_PLAN_TYPE, StringUtils.EMPTY);
            if (specialTypes != null && specialTypes.contains(obj.getObjectType()) ||
                    StringUtils.equalsIgnoreCase(obj.getObjectType(), "BOND")) {
                matchFlag = false;
            }
            Assert.isTrue(matchFlag, Errors.create().key(MessageIdList.LOT_PRODUCT_TYPE_NOT_MATCH_PLAN)
                                           .content("Product type does not match plan type!").build());
        } else {
            throw new SystemIllegalArgumentException(Errors.create().key(MessageIdList.SUBTECHNOLOGY_ENTER_CORRECT)
                                                           .content("Please enter the correct product id!").build());
        }
        // check process
        Assert.isFalse(StringUtils.isBlank(theform.getProcessId()),
                       Errors.create().key(MessageIdList.PROCESS_EMPTY_ID).content("Process cannot be empty!").build());
        theform.setProcessId(StringUtils.trimToUpperCase(theform.getProcessId()));
        Long processRrn = new Long(
                getInstanceRrn(theform.getProcessId(), getNamedSpace(ObjectList.WFL_KEY, facilityRrn),
                               ObjectList.WFL_KEY));
        Assert.isFalse(processRrn <= 0, Errors.create().key(MessageIdList.DMMLOTPLAN_PROCESSID_NOT_CORRECT)
                                              .content("Process id input error!").build());
        boolean isProductProcessBined;
        int processVersion = 0;

        isProductProcessBined = isProductProcessBined(obj.getInstanceRrn(), processRrn);
        processVersion = prpService.getLastAvaliableProcessVersion(obj.getInstanceRrn(), processRrn);
        Assert.isFalse(processVersion == 0, Errors.create().key(MessageIdList.PRODUCT_HAVA_NOT_AVALIABLE_VERSION)
                                                  .content("Have not avaliable process version, please check!")
                                                  .build());
        Assert.isTrue(isProductProcessBined,
                      Errors.create().key(MessageIdList.PRODUCT_PRODUCT_PROCESS_NOT_BOUND).content("产品流程未绑定!").build());
        theform.setProcessRrn(processRrn);
        theform.setLotOwner(StringUtils.trimToUpperCase(theform.getLotOwner()));
        long lotOwnerRrn = this
                .getInstanceRrn(theform.getLotOwner(), this.getNamedSpace(ObjectList.USER_KEY, facilityRrn),
                                ObjectList.USER_KEY);
        Assert.isFalse(lotOwnerRrn == 0,
                       Errors.create().key(MessageIdList.LOT_INVALIDA_LOT_OWNER).content("Invalida Lot Owner id!")
                             .build());

        lot = new Lot();
        PropertyUtils.copyProperties(lot, theform);

        lot.setCreateCategory(extendLot == null ? "PE" : extendLot.getCreateCategory()); //默认PE
        lot.setLotType(extendLot == null ? "P" : extendLot.getLotType());
        lot.setLotPlanType(StringUtils.isBlank(lot.getLotPlanType()) ? obj.getObjectType() : lot.getLotPlanType());
        lot.setFacilityRrn(facilityRrn);
        lot.setQty1(theform.getQty1());
        lot.setProcessRrn(theform.getProcessRrn());
        lot.setStepSequence(new Long(TRUE));
        lot.setLotStatus(WAITING_KEY);
        if (lot.getHotFlag() == null || lot.getHotFlag().trim().equals("")) {
            lot.setHotFlag(FALSE);
        }
        lot.setQueueTimestamp(new Timestamp(System.currentTimeMillis()));

        if (theform.getDueDateS() != null && !theform.getDueDateS().trim().equalsIgnoreCase("")) {
            long nowTime = System.currentTimeMillis();
            Timestamp dueDate = DateUtils.stringToTimestamp(theform.getDueDateS() + " 00:00:00");
            Assert.nonNull(dueDate, Errors.create().key(MessageIdList.DATE_DATE_FORMAT_INCORRECT)
                                          .content("Incorrect date format!").build());
            Assert.isFalse(dueDate.getTime() < nowTime,
                           Errors.create().content("dueDate must after the current date").build());
            lot.setDueDate(DateUtils.stringToTimestamp(theform.getDueDateS() + " 00:00:00"));
        }
        //handle plandate
        if (StringUtils.isEmpty(theform.getPlanStartDateS())) {
            theform.setPlanStartDateS(DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT4DAY));
        }
        Timestamp planDate = DateUtils.stringToTimestamp(theform.getPlanStartDateS() + " 00:00:00");
        Assert.notNull(planDate,
                       Errors.create().key(MessageIdList.DATE_DATE_FORMAT_INCORRECT).content("Incorrect date format!")
                             .build());
        lot.setPlanStartDate(DateUtils.stringToTimestamp(theform.getPlanStartDateS() + " 00:00:00"));
        //handle plantDate end
        lot.setProductRrn(obj.getInstanceRrn());
        lot.setProcessVersion(processVersion);
        lot.setDummyFlag(FALSE);
        lot.setTransPerformedby(user);
        //处理批次流程信息
        List<Lot> lotList = new ArrayList<Lot>();
        String allMaterial = StringUtils.EMPTY;
        buildLotProcessStepinfo(theform, request, facilityRrn, lot);
        allMaterial = WebUtils.getParameterUpperCase(Material_prefix + lot.getLotId(), request);
        if (StringUtils.isNotEmpty(allMaterial)) {
            lot.setMaterialinfo(allMaterial);
        }
        lotList.add(lot);

        theform.setPages(new Integer(1));

        request.setAttribute(SessionNames.COLLECTION_KEY, new ArrayList());
        StringBuffer lotIdSb = new StringBuffer();
        StringBuffer existLotIdSb = new StringBuffer();
        long lotRrn = lotQueryService.getLot(lotId, facilityRrn).getLotRrn();
        Lot lotTemp = lotService.getLotPlan(lotId);
        if (lotTemp != null && (lotTemp.getLotRrn() > 0 && lotTemp.getLotRrn() != theform.getLotRrn()) || lotRrn > 0) {
            existLotIdSb.append(lotId).append(",");
        } else {
            lotIdSb.append(lotId).append(",");
        }
        if (existLotIdSb != null && existLotIdSb.length() > 0) {
            throw new SystemIllegalArgumentException(Errors.create().content("Lot:{} existed!")
                                                           .args(existLotIdSb.substring(0, existLotIdSb.length() - 1)
                                                                             .toString()).build());
        }

        lot.setTransPerformedby(user);

        String carrierId = theform.getCarrierId();
        Long carrierRrn = carrierService.getCarrierRrnForLot(facilityRrn, lot, carrierId);

        //创建批次
        lotService.insertBatchLotPlan(lotList);

        //创建完成  开始投片
        Map lotMapInfo = buildLotMap(lot);

        lotMapInfo.put("carrierId", carrierId);
        lotMapInfo.put("lotPlanTypeMenu", lot.getLotPlanType());
        lot.setCarrierRrn(carrierRrn);
        lot.setCarrierId(carrierId);

        String[] units = parseUnitListString(lot.getLotId(), lot.getInt_qty1());
        lot.setCustomerWaferId(
                Arrays.asList(units).toString().replace('[', ' ').replace(']', ' ').trim().toUpperCase());
        lot.setInputQty1(lot.getQty1());
        lot.setInputQty2(lot.getQty2());
        HashMap transInfo = new HashMap();
        transInfo.put("startFlag", lot.getStartedFlag());
        lot.setSplitMergeFlag(LocationNames.initLotFlagName(lot.getProcessId()));
        transInfo.put("lot", lot);
        transInfo.put("lotid", lot.getLotId());
        transInfo.put("qty", lot.getQty1() + "");
        transInfo.put("productRrn", lot.getProductRrn());
        transInfo.put("transPerformedby", user);
        transInfo.put("keepUnitHistoryFlag", theform.getKeepUnitHistoryFlag());
        transInfo.put("unitList", units);
        transInfo.put("positionList", getPositionList(lot.getQty1()));
        transInfo.put("rawMaterials", new ArrayList<>());
        transInfo.put("lotComments", theform.getLotComments());
        transInfo.put("trackUnitFlag", "1");
        transInfo.put("transferLotFlag", "1");

        Map resultsInfo = lotService.createLot(transInfo);

        return resultMsg;
    }


    private void buildLotProcessStepinfo(LotInfoForm theform, HttpServletRequest request, Long facilityRrn,
                                         Lot lot) throws Exception {
        String trackUnitFlag = "0";
        String keepUnitHistoryFlag = "0";
        String totalProcessTime = StringUtils.EMPTY;
        String stageId = "";
        String layerId = "";
        Long borRrn = new Long(0);
        Long operationRrn = new Long(0);
        Integer operationVer = new Integer(0);
        Long executionRrn = new Long(0);
        String processStepVersion = null;
        String processStepIdVersion = null;
        String processStepVersion4wfl = null;


        String stepNumber = request.getParameter("stepNumber");
        stepNumber = StringUtils.isBlank(stepNumber) ? theform.getStepNumber() : "";
        Map tempInfo = getStepsInfoByVersion(lot, lot.getProcessRrn(), lot.getProcessVersion(), stepNumber);

        executionRrn = (Long) tempInfo.get("executionRrn");
        operationRrn = (Long) tempInfo.get("operationRrn");

        lot.setOperationRrn(operationRrn);

        NamedObject operation = baseService.getNamedObject(new NamedObject(operationRrn.longValue()));
        operation.setObjectType(lotQueryService.getOperationType(lot));
        Assert.isFalse(StringUtils.startsWith(operation.getObjectType(), DUMMY_OPERATION_TYPE),
                       Errors.create().key(MessageIdList.LOT_FIRSTSTEP_NOT_WAFERSTART_STEP)
                             .content("The first step of the process is not the material start step!").build());

        Assert.isTrue(checkOperationInFacility(operationRrn, facilityRrn),
                      Errors.create().content("The Lot's first step is not" + " in current " + "facility!").build());
        if (theform.getCarrierId() != null && !theform.getCarrierId().trim().equals("")) {
            List lotsInSameCarrier = new ArrayList();
            Lot item = null;

            for (Iterator it = lotsInSameCarrier.iterator(); it.hasNext(); ) {
                item = (Lot) it.next();

                Assert.isFalse((item.getLotStatus() == null) || !item.getLotStatus().equals(LotStatus.WAITING),
                               Errors.create().content("Carrier selected is in used, please select other carriers.")
                                     .build());

                Assert.isFalse(item.getOperationRrn().compareTo(operationRrn) != 0, Errors.create().content(
                        "Carrier " + "should not" + " be used" + " " + "for Lot" + "({}) in " + "this " + "carrier is" +
                                " in " + "different " + "operation").args(item.getLotId()).build());
            }

        }
        operationVer = (Integer) tempInfo.get("operationVer");
        stageId = (String) tempInfo.get("stageId");
        layerId = (String) tempInfo.get("layerId");
        processStepVersion = (String) tempInfo.get("processStepVersion");
        processStepIdVersion = (String) tempInfo.get("processStepIdVersion");
        processStepVersion4wfl = (String) tempInfo.get("processStepVersion4wfl");

        lot.setNextOperationRrn1((Long) tempInfo.get("nextoperationRrn1"));

        if ((lot.getNextOperationRrn1() != null) && (lot.getNextOperationRrn1().compareTo(new Long(0)) > 0)) {
            lot.setNextOperationId1(getInstanceId(lot.getNextOperationRrn1().longValue()));
        }

        lot.setNextStepVersion1((String) tempInfo.get("nextprocessStepVersion1"));
        lot.setNextStepIdVersion1((String) tempInfo.get("nextprocessStepIdVersion1"));

        lot.setNextOperationRrn2((Long) tempInfo.get("nextoperationRrn2"));

        if ((lot.getNextOperationRrn2() != null) && (lot.getNextOperationRrn2().compareTo(new Long(0)) > 0)) {
            lot.setNextOperationId2(getInstanceId(lot.getNextOperationRrn2().longValue()));
        }

        lot.setNextStepVersion2((String) tempInfo.get("nextprocessStepVersion2"));
        lot.setNextStepIdVersion2((String) tempInfo.get("nextprocessStepIdVersion2"));

        trackUnitFlag = (String) tempInfo.get("trackUnitFlag");
        keepUnitHistoryFlag = (String) tempInfo.get("keepUnitHistoryFlag");

        tempInfo = new HashMap();
        tempInfo.put("operationRrn", operationRrn);
        tempInfo.put("productRrn", lot.getProductRrn());
        tempInfo.put("technologyRrn", lot.getProcessRrn());
        tempInfo.put("recipeRrn", null);
        tempInfo.put("lotRrn", null);

        if ((lot.getScheduleDueDate() != null) && (lot.getDueDate() != null) &&
                lot.getScheduleDueDate().after(lot.getDueDate())) {
            lot.setLastScheduleFlag(TRUE);
        }

        lot.setProcessStepVersion(processStepVersion.toString());
        lot.setProcessStepIdVersion(processStepIdVersion.toString());
        lot.setWflStepPath(processStepVersion4wfl);
        lot.setExecutionRrn(executionRrn);
        lot.setOperationRrn(operationRrn);
        lot.setOperationVersion(operationVer);
        lot.setOperationId(this.getInstanceId(operationRrn.longValue()));
        lot.setStageId(stageId);
        lot.setLayerId(layerId);
        lot.setBorRrn(borRrn);
        lot.setBeforeStatus("");
        lot.setInputQty1(theform.getQty1());
        lot.setInputQty2(theform.getQty2());
        lot.setStartedFlag(TRUE);
        lot.setReticleGroupRrn(theform.getReticleGroupRrn());
        theform.setTrackUnitFlag(trackUnitFlag);
        theform.setKeepUnitHistoryFlag(keepUnitHistoryFlag);

    }


    private Map buildLotMap(Lot lot) {
        lot = lotService.getLotPlan(lot.getLotId());
        Assert.isFalse(lot == null || lot.getLotRrn() == 0, Errors.create().key(MessageIdList.LOT_ENTER_CORRECT_LOTID)
                                                                  .content("Please enter the correct lot Id!").build());
        String lotCategoryCode = lot.getCreateCategory();
        String createCategory = sysService
                .referenceDetailExchangeNull(ReferenceDetailNames.LOT_CREATE_CATEGORY, lot.getCreateCategory(), null,
                                             ReferenceFileConst.DATA_1_VALUE);

        // 得到最新的active process version---start
        int processVersion = prpService.getLastAvaliableProcessVersion(lot.getProductRrn(), lot.getProcessRrn());

        Assert.isFalse(processVersion == 0, Errors.create().key(MessageIdList.PRODUCT_HAVA_NOT_AVALIABLE_VERSION)
                                                  .content("have not avaliable process version please check!").build());

        lot.setProcessVersion(processVersion);

        Map tempInfo = getStepsInfoByVersion(lot, lot.getProcessRrn(), lot.getProcessVersion(), lot.getWflStepPath());

        long executionRrn = (Long) tempInfo.get("executionRrn");
        long operationRrn = (Long) tempInfo.get("operationRrn");

        Operation operation = prpService.getOperation(operationRrn);

        int operationVer = (Integer) tempInfo.get("operationVer");
        // String stageId = (String) tempInfo.get("stageId");
        String layerId = (String) tempInfo.get("layerId");
        String processStepVersion = (String) tempInfo.get("processStepVersion");
        String processStepIdVersion = (String) tempInfo.get("processStepIdVersion");
        String processStepVersion4wfl = (String) tempInfo.get("processStepVersion4wfl");

        lot.setNextOperationRrn1((Long) tempInfo.get("nextoperationRrn1"));

        if ((lot.getNextOperationRrn1() != null) && (lot.getNextOperationRrn1().compareTo(new Long(0)) > 0)) {
            lot.setNextOperationId1(getInstanceId(lot.getNextOperationRrn1().longValue()));
        }

        lot.setNextStepVersion1((String) tempInfo.get("nextprocessStepVersion1"));
        lot.setNextStepIdVersion1((String) tempInfo.get("nextprocessStepIdVersion1"));
        lot.setNextOperationRrn2((Long) tempInfo.get("nextoperationRrn2"));
        if ((lot.getNextOperationRrn2() != null) && (lot.getNextOperationRrn2().compareTo(new Long(0)) > 0)) {
            lot.setNextOperationId2(getInstanceId(lot.getNextOperationRrn2().longValue()));
        }
        lot.setNextStepVersion2((String) tempInfo.get("nextprocessStepVersion2"));
        lot.setNextStepIdVersion2((String) tempInfo.get("nextprocessStepIdVersion2"));
        String trackUnitFlag = operation.getTrackUnitFlag();
        String keepUnitHistoryFlag = operation.getKeepUnitHistoryFlag();

        if ((lot.getScheduleDueDate() != null) && (lot.getDueDate() != null) &&
                lot.getScheduleDueDate().after(lot.getDueDate())) {
            lot.setLastScheduleFlag(TRUE);
        }

        tempInfo = new HashMap();
        tempInfo.put("operationRrn", operationRrn);
        tempInfo.put("productRrn", lot.getProductRrn());
        tempInfo.put("routeRrn", parseRouteRrn(processStepVersion) + "");
        tempInfo.put("technologyRrn", lot.getProcessRrn());
        tempInfo.put("recipeRrn", null);
        tempInfo.put("lotRrn", null);

        //TODO :BOR_CONTEXT
        //        Map  resultInfo = getProcessManager().getBorbyContext(tempInfo);
        //        long borRrn     = MapUtils.getLongValue(resultInfo, "borRrn");

        lot.setProcessStepVersion(processStepVersion.toString());
        lot.setProcessStepIdVersion(processStepIdVersion.toString());
        lot.setWflStepPath(processStepVersion4wfl);
        lot.setExecutionRrn(executionRrn);
        lot.setOperationRrn(operationRrn);
        lot.setOperationVersion(operationVer);
        lot.setOperationId(this.getInstanceId(operationRrn));
        // lot.setStageId(stageId);
        lot.setLayerId(layerId);
        //        lot.setBorRrn(borRrn);
        lot.setBeforeStatus("");
        lot.setStartedFlag(TRUE);
        // 得到最新的active process version---end

        Map lotMapInfo = BeanUtils.copyBeanToMap(lot);
        lotMapInfo.put("lotCategoryCode", lotCategoryCode);
        lotMapInfo.put("createCategory", createCategory);
        lotMapInfo.put("workArea", lotQueryService.getWorkArea(lot));
        lotMapInfo.put("operation_rrn", MapUtils.getLong(lotMapInfo, "operationRrn"));
        String nextOperationDesc1 = getNextStepDesc(lot);
        if (nextOperationDesc1 == null) {
            lotMapInfo.put("nextOperationDesc1", "");
        } else {
            lotMapInfo.put("nextOperationDesc1", nextOperationDesc1);
        }

        lotMapInfo.put("splitMergeFlag", StringUtils.nullToStr(lot.getSplitMergeFlag()));
        lotMapInfo.put("pollutionLevel", lot.getPollutionLevel());
        String pollutionLevel = lot.getPollutionLevel();
        String pollutionLevelColor = sysService
                .getRefFileValue("$$LOT_POLUTIONLEVEL", pollutionLevel, ReferenceFileConst.DATA_2_VALUE);
        if (StringUtils.isNotBlank(pollutionLevelColor)) {
            String plBgColor = StringUtils.substringBefore(pollutionLevelColor, "$");
            String plColor = StringUtils.substringAfter(pollutionLevelColor, "$");
            lotMapInfo.put("plBgColor", plBgColor);
            lotMapInfo.put("plColor", plColor);
        }

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String duedate = df.format(lot.getDueDate());
        lotMapInfo.put("duedate", duedate);
        lotMapInfo.put("qty1", lot.getQty1().intValue());
        lotMapInfo.put("routeDesc", getInstanceDesc(lot.getRouteRrn()));
        lotMapInfo.put("carrierType", carrierService.getTargetCarrierTypeByStatus(lot));
        String hotFlagString = "";
        if (StringUtils.isNotBlank(lot.getHotFlag()) && StringUtils.isNotBlank(lot.getPriority().toString())) {
            hotFlagString = getHotflagSplicingPriority(lot);
        }
        lotMapInfo.put("hotFlagString", hotFlagString);
        lotMapInfo.put("flowSeq", ctxExecService.getFlowSeqByProcessInfo(lotMapInfo));
        lotMapInfo.put("operationDesc", ctxExecService.getOperationDescByProcessInfo(lotMapInfo));
        String stageId = ctxExecService.getStageByProcessInfo(lotMapInfo);
        lotMapInfo.put("stageId", stageId);
        lotMapInfo.put("allMaterial", StringUtils.EMPTY);
        Item item = new Item(lot.getProductRrn());
        item = (Item) getInstance(item);
        lotMapInfo.put("defaultBank", DEFAULT_WAFER_BANK);
        lotMapInfo.put("startHold", lot.getStartHold());
        lotMapInfo.put("planStartDateS", DateUtils.formatDate(lot.getPlanStartDate(), DateUtils.DATE_FORMAT4DAY));
        lotMapInfo.put("lot", lot);

        return lotMapInfo;
    }

    private String[] parseUnitListString(String lotId, int qty) {
        String[] units = new String[1];

        int num = 0;
        String unitList = "";
        for (int i = 0; i < qty; i++) {
            String unitId = "";
            unitId = lotId + SEPARATOR + String.format("%02d", ++num);
            unitList = unitList + unitId + "|" + "0" + "$";
        }
        units[0] = unitList;
        return units;
    }

    private Object[] getPositionList(Double lotQty) {
        Object[] positionList = null;
        if (lotQty != null) {
            positionList = new Object[lotQty.intValue()];

            for (int i = 0; i < lotQty.intValue(); i++) {
                positionList[i] = new Long(i + 1);
            }
        }
        return positionList;
    }

    private String getSkipFlag(Lot lot, Long targetRouRrn, Long targetStepRrn) {
        String s_flag = null;
        long facilityRrn = LocalContext.getFacilityRrn();
        Map<String, Object> processInfoMap = new HashMap<String, Object>();
        processInfoMap.put("facilityRrn", facilityRrn);
        processInfoMap.put("processRrn", lot.getProcessRrn());
        processInfoMap.put("processVersion", lot.getProcessVersion());
        processInfoMap.put("routeRrn", lot.getRouteRrn());
        processInfoMap.put("operationRrn", lot.getOperationRrn());
        String currentFlowSeqStr = ctxExecService.getFlowSeqByProcessInfo(processInfoMap);
        currentFlowSeqStr = StringUtils.join(StringUtils.split(currentFlowSeqStr, StringUtils.POINT_SIGN), "");


        processInfoMap = new HashMap<String, Object>();
        processInfoMap.put("facilityRrn", facilityRrn);
        processInfoMap.put("processRrn", lot.getProcessRrn());
        processInfoMap.put("processVersion", lot.getProcessVersion());
        processInfoMap.put("routeRrn", targetRouRrn);
        processInfoMap.put("operationRrn", targetStepRrn);
        String targetFlowSeqStr = ctxExecService.getFlowSeqByProcessInfo(processInfoMap);
        targetFlowSeqStr = StringUtils.join(StringUtils.split(targetFlowSeqStr, StringUtils.POINT_SIGN), "");

        Integer currentFlowSeq = (Integer) NumberUtils.parseNumber(currentFlowSeqStr, Integer.class);
        Integer targetFlowSeq = (Integer) NumberUtils.parseNumber(targetFlowSeqStr, Integer.class);
        if (currentFlowSeq > targetFlowSeq) {
            s_flag = "before";
        } else {
            s_flag = "after";
        }
        return s_flag;
    }

}