MonitorLotWaferStartAction.java

package com.mycim.webapp.actions.dmmlotplan;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
import com.fa.sesa.i18n.I18nUtils;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.utils.beans.BeanUtils;
import com.mycim.framework.utils.beans.PropertyUtils;
import com.mycim.framework.utils.lang.StringUtils;
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.Relation;
import com.mycim.valueobject.consts.LinkTypeList;
import com.mycim.valueobject.consts.ReferenceDetailNames;
import com.mycim.valueobject.consts.ReferenceFileConst;
import com.mycim.valueobject.consts.SessionNames;
import com.mycim.valueobject.ems.Carrier;
import com.mycim.valueobject.inv.LotInventoryDO;
import com.mycim.valueobject.prp.Operation;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.TransReason;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.NpwSetupAction;
import com.mycim.webapp.forms.MonitorLotInfoForm;
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 shijie.deng
 * @version 6.0.0
 * @date 2019/9/24
 **/
public class MonitorLotWaferStartAction extends NpwSetupAction {

    private static final int MORE = 1;

    private static final int LESS = -1;

    private static final int EQUAL = 0;

    private static final String SEPARATOR = "#";

    private static final String DEFAULT_WAFER_BANK = "WAFER_BANK";

    private static final String MATERIAL_PREFIX = "allMaterial";

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) {
        String lotId = WebUtils.getParameterUpperCase("lotId", request);
        MonitorLotInfoForm theform = (MonitorLotInfoForm) form;
        Map lotInfo = new HashMap();
        if (StringUtils.isNotBlank(lotId)) {
            String carrierId = WebUtils.getParameterUpperCase("carrierId", request);
            lotInfo = buildLotMap(lotId);
            lotInfo.put("carrierId", carrierId);
        }
        request.setAttribute("_lotInfo", lotInfo);
        return mapping.getInputForward();
    }

    public ActionForward initLotInfo(ActionMapping mapping, MonitorLotInfoForm form, HttpServletRequest request) {
        String lotId = WebUtils.getParameterUpperCase("lotId", request);
        Map lotMapInfo = new HashMap();
        lotMapInfo = buildLotMap(lotId);

        Lot lot = lotService.getLotPlan(lotId);
        List<Map> rawMaterials = new ArrayList<Map>();

        if (isRawMaterialRequired(lot.getLotType())) {
            request.setAttribute("selectedMaterial", parseMaterialInfo(lot.getMaterialinfo()));
        }

        String lotPlanType = WebUtils.getParameter("menuType", request);
        validateLotPlanType(lotPlanType, lot.getLotPlanType());
        lotMapInfo.put("lotPlanTypeMenu", lotPlanType);
        form.setCacheCollection(WebUtils.getCacheObj2String(rawMaterials));
        request.setAttribute("_lotInfo", lotMapInfo);
        return mapping.getInputForward();

    }

    public ActionForward createLot(ActionMapping mapping, MonitorLotInfoForm theform, HttpServletRequest request) {

        Long facilityRrn = LocalContext.getFacilityRrn();
        List<Map> rawMaterials = (List<Map>) WebUtils.getCacheString2Obj(theform.getCacheCollection());
        String user = LocalContext.getUserId();
        String[] units = request.getParameterValues("unitList");

        if (rawMaterials == null) {
            rawMaterials = new ArrayList();
        }

        String lotId = WebUtils.getParameterUpperCase("lotId", request);
        Map lotMapInfo;
        Lot lot;
        lotMapInfo = buildLotMap(lotId);

        lot = (Lot) lotMapInfo.get("lot");
        validateLotPlanType(theform.getLotPlanType(), lot.getLotPlanType());
        //校验 plan start date
        Assert.isFalse(lot.getPlanStartDate() != null && new Date().compareTo(lot.getPlanStartDate()) < 0,
                       Errors.create().key(MessageIdList.LOT_PLAN_DATE_EARLY)
                             .content("The lot plan start date is: {} , please waiting!").build());

        String carrierId = WebUtils.getParameterUpperCase("carrierId", request);
        if (StringUtils.isBlank(carrierId)) {
            request.setAttribute(SessionNames.COLLECTION_KEY, rawMaterials);
            throw new SystemIllegalArgumentException(
                    Errors.create().key(MessageIdList.LOT_CASSETTE_REQUIRED).content("cassette is required!").build());
        }
        Long carrrierRrn = carrierService.getCarrierRrnForLot(facilityRrn, lot, carrierId);

        lotMapInfo.put("carrierId", carrierId);
        lotMapInfo.put("lotPlanTypeMenu", theform.getLotPlanType());

        lot.setCarrierRrn(carrrierRrn);
        lot.setCarrierId(carrierId);

        // cassette与lot的绑定需要判断category
        Carrier carrier = carrierService.getCarrier(carrrierRrn);
        Assert.isTrue(StringUtils.equalsIgnoreCase(lot.getCreateCategory(), carrier.getFlagType()),
                      Errors.create().key(MessageIdList.LOT_CASSETTE_TYPE_MUST_SAME)
                            .content("Lot and cassette must be same category!").build());

        Assert.isFalse(StringUtils.isNotBlank(lot.getCustomerWaferId()) &&
                               isValidUnitId(lot.getCustomerWaferId(), facilityRrn),
                       Errors.create().key(MessageIdList.UNIT_WAFER_ID_EXISTS).content("wafer Id already exists!")
                             .build());

        Assert.isFalse(validateQty(lot.getQty1(), rawMaterials) == MORE,
                       Errors.create().key(MessageIdList.LOT_MATERIALS_TOO_MUCH)
                             .content("Too much raw materials " + "selected!").build());
        Assert.isFalse(validateQty(lot.getQty1(), rawMaterials) == LESS,
                       Errors.create().key(MessageIdList.LOT_MATERIALS_NOT_ENOUGH)
                             .content("Not enough raw materials " + "selected!").build());

        units = parseUnitListString(units, rawMaterials, lot.getLotId());

        lot.setCustomerWaferId(
                Arrays.asList(units).toString().replace('[', ' ').replace(']', ' ').trim().toUpperCase());

        lot.setInputQty1(theform.getQty1());
        lot.setInputQty2(theform.getQty2());
        lot.setReticleGroupRrn(theform.getReticleGroupRrn());

        Assert.isTrue(validateUniqueUnit(units),
                      Errors.create().key(MessageIdList.UNIT_ID_MUST_UNIQUE).content("Unit ID must be Unique!")
                            .build());

        int i = 0;
        for (Iterator it = rawMaterials.iterator(); it.hasNext(); ) {
            HashMap item = (HashMap) it.next();
            Assert.isTrue((units[i] != null) && !"".equals(units[i]),
                          Errors.create().key(MessageIdList.UNIT_ID_MUST_SPECIFIED).content("Units must be specified!")
                                .build());
            item.put("unitList", units[i++].toUpperCase());
        }

        Lot temLot = lotQueryService.getLot(lot.getLotId(), facilityRrn);
        Assert.isFalse(temLot != null && temLot.getLotRrn() > 0,
                       Errors.create().key(MessageIdList.NPWCREATELOT_LOT_ALREADY_EXISTS).content("Lot existed!")
                             .build());

        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", rawMaterials);

        transInfo.put("lotComments", theform.getLotComments());
        transInfo.put("trackUnitFlag", "1");


        Map resultsInfo = lotService.createLotAndMoveNext(transInfo);
        Lot currentLot = lotQueryService.getLot(lotId, facilityRrn);


        saveLotSeqAttribute(((Long) resultsInfo.get("lotRrn")).longValue(), currentLot.getProductRrn());
        request.setAttribute("createFlag", "1");
        request.setAttribute("sucLotId", lot.getLotId());
        request.setAttribute("_lotInfo", lotMapInfo);
        return mapping.getInputForward();


    }

    public String validCSTType(MonitorLotInfoForm theform) {
        long facilityRrn = LocalContext.getFacilityRrn();
        String lotId = theform.getLotId();
        String carrierId = theform.getCarrierId();
        Map lotMapInfo;
        Lot lot;
        lotMapInfo = buildLotMap(lotId);
        lot = (Lot) lotMapInfo.get("lot");
        carrierService.getCarrierRrnForLot(facilityRrn, lot, carrierId);
        return StringUtils.EMPTY;
    }

    public ActionForward validateAndAddMaterial(ActionMapping mapping, MonitorLotInfoForm theform,
                                                HttpServletRequest request) {
        long facilityRrn = LocalContext.getFacilityRrn();
        List<Map> rawMaterials = (List<Map>) WebUtils.getCacheString2Obj(theform.getCacheCollection());

        if (rawMaterials == null) {
            rawMaterials = new ArrayList();
        }

        String lotId = WebUtils.getParameterUpperCase("lotId", request);
        String carrierId = WebUtils.getParameterUpperCase("carrierId", request);

        Lot lot;

        LotInventoryDO lotInventory = null;

        theform.setWarehouseId(StringUtils.trimToUpperCase(theform.getWarehouseId()));
        theform.setRawMaterialId(StringUtils.trimToUpperCase(theform.getRawMaterialId()));
        theform.setLotNumber(StringUtils.trimToUpperCase(theform.getLotNumber()));
        lot = lotService.getLotPlan(lotId);
        long warehouseRrn = getInstanceRrn(theform.getWarehouseId(), facilityRrn, ObjectList.OPERATION_KEY);
        long materialRrn = getInstanceRrn(theform.getRawMaterialId(), facilityRrn, ObjectList.ITEM_KEY);

        lotInventory = warehouseService.getLotInventory(theform.getLotNumber(), materialRrn, warehouseRrn);
        Assert.notNull(lotInventory, Errors.create().key(MessageIdList.MATERIAL_LOT_INVENTORY_MISSING)
                                           .content("Lot Inventory not found!").build());

        long productRrn = WebUtils.getParameterLong("productRrn", request);
        Assert.isTrue(isProductLinkedMaterial(productRrn, lotInventory.getItemRrn()),
                      Errors.create().key(MessageIdList.MATERIAL_NOT_LINK_PRODUCT)
                            .content("The material is " + "not " + "linked " + "to the " + "product!").build());

        Assert.isFalse(theform.getSpecifiedQty().compareTo(lotInventory.getTotalQuantity()) > 0,
                       Errors.create().key(MessageIdList.MATERIAL_INVENTORY_NOT_ENOUG)
                             .content("Not enough on-hand " + "Quantity!").build());

        // 验证与预选物料设是否匹配
        if (isRawMaterialRequired(lot.getLotType()) && StringUtils.isNotBlank(lot.getMaterialinfo())) {
            Boolean existFlag = false;
            Boolean qtyMatchFlag = false;
            List<Map<String, String>> materialInfoList = this.parseMaterialInfo(lot.getMaterialinfo());
            for (Map<String, String> tmp : materialInfoList) {
                if (StringUtils.equalsIgnoreCase(theform.getWarehouseId(), tmp.get("wareHouseId")) &&
                        StringUtils.equalsIgnoreCase(theform.getRawMaterialId(), tmp.get("rawMaterialId")) &&
                        StringUtils.equalsIgnoreCase(theform.getLotNumber(), tmp.get("lotNumber"))) {
                    existFlag = true;
                    qtyMatchFlag = theform.getSpecifiedQty() == NumberUtils.toDouble(tmp.get("specifiedQty"), 0.0);
                    break;

                }
            }

            Assert.isTrue(existFlag, Errors.create().key(MessageIdList.LOTPLAN_NOT_PLAN_MATERIAL)
                                           .content("{} is not pre-selected material!").args(theform.getRawMaterialId())
                                           .build());

            Assert.isTrue(qtyMatchFlag, Errors.create().key(MessageIdList.LOTPLAN_MATERIAL_NUM_ERROR)
                                              .content("Quantity of {} not match that of pre-selected material!")
                                              .args(theform.getRawMaterialId()).build());

        }

        int i = 0;
        int offset = 0;
        String[] units = request.getParameterValues("unitList");

        boolean check = true;

        for (Iterator it = rawMaterials.iterator(); it.hasNext(); ) {
            HashMap item = (HashMap) it.next();

            offset = offset + ((Double) item.get("specifiedQty")).intValue();

            if ((units != null) && (units[i] != null) && !units[i].equals("")) {
                item.put("unitList", units[i++]);
            }

            if (lotInventory.getLotNumber().equals(MapUtils.getString(item, "lotNumber")) &&
                    lotInventory.getItemRrn().equals(MapUtils.getLong(item, "itemRrn")) &&
                    lotInventory.getWarehouseRrn().equals(MapUtils.getLong(item, "wareHouseRrn"))) {
                check = false;

                break;
            }
        }

        Assert.isFalse(theform.getSpecifiedQty().compareTo(lotInventory.getTotalQuantity()) > 0,
                       Errors.create().key(MessageIdList.MATERIAL_INVENTORY_NOT_ENOUGH)
                             .content("Not enough on-hand " + "Quantity!").build());

        if (check) {
            HashMap rawMaterial = new HashMap();

            rawMaterial.put("lotNumber", lotInventory.getLotNumber());
            rawMaterial.put("itemId", theform.getRawMaterialId());
            rawMaterial.put("itemRrn", StringUtils.toString(lotInventory.getItemRrn()));
            rawMaterial.put("wareHouseId", lotInventory.getWarehouseId());
            rawMaterial.put("wareHouseRrn", lotInventory.getWarehouseRrn());

            theform.setCustomerWaferId(lot.getCustomerWaferId());

            String unitList = "";
            if (StringUtils.isNotEmpty(lot.getCustomerLotId()) && StringUtils.isNotBlank(lot.getCustomerLotId()) &&
                    StringUtils.isNotEmpty(lot.getCustomerWaferId()) &&
                    StringUtils.isNotBlank(lot.getCustomerWaferId())) {
                String[] unitListTemp = lot.getCustomerWaferId().split("\\$");
                for (int j = offset;
                     j < offset + theform.getSpecifiedQty().intValue() && j < unitListTemp.length; j++) {
                    String unit = unitListTemp[j];
                    unitList += unit + "$";
                }
                rawMaterial.put("unitList", unitList);
            } else {
                rawMaterial.put("unitList", unitList);
            }

            rawMaterial.put("confirmFlag", "false");
            rawMaterial.put("itemRrn", StringUtils.toString(lotInventory.getItemRrn()));
            rawMaterial.put("specifiedQty", theform.getSpecifiedQty());

            String lotBox1 = theform.getLotBox1().toUpperCase().trim();
            String lotBox2 = theform.getLotBox2().toUpperCase().trim();
            String lotBox3 = theform.getLotBox3().toUpperCase().trim();
            String lotBoxQty1 = theform.getLotBoxQty1().toUpperCase().trim();
            String lotBoxQty2 = theform.getLotBoxQty2().toUpperCase().trim();
            String lotBoxQty3 = theform.getLotBoxQty3().toUpperCase().trim();
            StringBuilder lotBox = new StringBuilder();

            lotBox.append(lotBox1).append("(").append(lotBoxQty1).append(");");
            lotBox.append(lotBox2).append("(").append(lotBoxQty2).append(");");
            lotBox.append(lotBox3).append("(").append(lotBoxQty3).append(")");

            rawMaterial.put("lotBox", lotBox.toString());

            if (theform.getSpecifiedQty() != null) {
                rawMaterial.put("int_specifiedQty", StringUtils.toString(theform.getSpecifiedQty()));
            }

            rawMaterial.put("offset", new Long(offset));
            rawMaterial.put("onHandQty", new Double(lotInventory.getTotalQuantity()));
            rawMaterials.add(rawMaterial);

            if (validateQty(lot.getQty1(), rawMaterials) == MORE) {
                rawMaterials.remove(rawMaterial);
                request.setAttribute(SessionNames.COLLECTION_KEY, rawMaterials);

                throw new SystemIllegalArgumentException(Errors.create().key(MessageIdList.LOT_MATERIALS_TOO_MUCH)
                                                               .content("Too much raw materials selected!").build());
            }
        }
        request.setAttribute(SessionNames.COLLECTION_KEY, rawMaterials);
        theform.setCacheCollection(WebUtils.getCacheObj2String(rawMaterials));
        theform.setLotNumber("");
        theform.setSpecifiedQty(null);
        Map lotMapInfo = buildLotMap(lotId);
        lotMapInfo.put("carrierId", carrierId);
        lotMapInfo.put("lotPlanTypeMenu", theform.getLotPlanType());
        request.setAttribute("_lotInfo", lotMapInfo);
        if (isRawMaterialRequired(lot.getLotType())) {
            request.setAttribute("selectedMaterial", this.parseMaterialInfo(lot.getMaterialinfo()));
        }
        return mapping.getInputForward();
    }

    public ActionForward deleteMaterial(ActionMapping mapping, MonitorLotInfoForm theform, HttpServletRequest request) {
        List<Map> rawMaterials = (List<Map>) WebUtils.getCacheString2Obj(theform.getCacheCollection());

        if (rawMaterials == null) {
            rawMaterials = new ArrayList();
        }

        String lotId = WebUtils.getParameterUpperCase("lotId", request);
        String carrierId = WebUtils.getParameterUpperCase("carrierId", request);

        int i = 0;
        long offset = 0;
        String[] units = request.getParameterValues("unitList");

        for (Iterator it = rawMaterials.iterator(); it.hasNext(); ) {
            HashMap item = (HashMap) it.next();

            if ((units != null) && (units[i] != null) && !"".equals(units[i])) {
                item.put("unitList", units[i++]);
            }

            item.put("offset", new Long(offset));
            offset = offset + ((Double) item.get("specifiedQty")).longValue();

            if (MapUtils.getString(item, "lotNumber").equals(request.getParameter("delLotNumber")) &&
                    MapUtils.getString(item, "itemRrn").equals(request.getParameter("delItemRrn")) &&
                    MapUtils.getString(item, "wareHouseRrn").equals(request.getParameter("delWarehouseRrn"))) {
                it.remove();
            }
        }
        Map lotMapInfo;
        lotMapInfo = buildLotMap(lotId);

        Lot lot = (Lot) lotMapInfo.get("lot");

        lotMapInfo.put("carrierId", carrierId);
        lotMapInfo.put("lotPlanTypeMenu", theform.getLotPlanType());

        if (isRawMaterialRequired(lot.getLotType())) {
            request.setAttribute("selectedMaterial", this.parseMaterialInfo(lot.getMaterialinfo()));
        }
        request.setAttribute("_lotInfo", lotMapInfo);
        request.setAttribute(SessionNames.COLLECTION_KEY, rawMaterials);
        theform.setCacheCollection(WebUtils.getCacheObj2String(rawMaterials));
        return mapping.getInputForward();


    }

    public ActionForward updateLotPlanInit(ActionMapping mapping, HttpServletRequest request,
                                           HttpServletResponse response, MonitorLotInfoForm theform) {
        String lotId = WebUtils.getParameterUpperCase("lotId", request);
        Lot lot = null;
        if (StringUtils.isNotBlank(lotId)) {
            Map lotMapInfo = new HashMap();
            lotMapInfo = buildLotMap(lotId);
            // lotMapInfo.put("lotPlanTypeMenu", form.getLotPlanType());
            lot = wipQueryService.getLotPlan(lotId);
            PropertyUtils.copyProperties(theform, lot);
            theform.setRecipePhysicalId(getRecipePhysicalId(lot));

            if (isRawMaterialRequired(lot.getLotType())) {
                request.setAttribute("selectedMaterial", this.parseMaterialInfo(lot.getMaterialinfo()));
            }

            lotMapInfo.put("lotPlanType", lot.getLotPlanType());
            request.setAttribute("_lotInfo", lotMapInfo);
            theform.setDueDateS(DateUtils.formatDate(lot.getDueDate()));

            theform.setWaitTime(lot.getwaitTime());

            theform.setQty1toInt(theform.getQty1().intValue());

            String createType = lot.getCreateCategory().toUpperCase();
            request.setAttribute("createType", createType);
            request.setAttribute("currentLotType", lot.getLotType());
        }

        request.setAttribute(SessionNames.COLLECTION_KEY, new ArrayList());
        if (StringUtils.isNotBlank(WebUtils.getParameter("modifyFlag", request))) {
            WebUtils.setSuccessMsg(request);
        }
        return mapping.findForward("updateLotPlanInit");
    }

    public ActionForward modifyLotPlan(ActionMapping mapping, HttpServletRequest request, HttpServletResponse response,
                                       MonitorLotInfoForm theform) {
        long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();

        String lotId = request.getParameter("lotId");

        Lot lot = lotService.getLotPlan(lotId);
        Assert.isFalse(lot == null || lot.getLotRrn() == 0,
                       Errors.create().key(MessageIdList.LOT_MISSING_ID).content("No such lotId").build());
        Map<String, Object> transInfo = new HashMap<String, Object>();
        double qty1 = NumberUtils.toDouble(request.getParameter("qty1"));

        buildLotPlanInfo(mapping, request, theform, lot);

        transInfo.put("lot", lot);
        transInfo.put("lotRrn", lot.getLotRrn());
        transInfo.put("facilityRrn", facilityRrn);

        transInfo.put("user", user);
        TransReason transReason = new TransReason();
        String reason = request.getParameter("reasonCode") + " " + request.getParameter("deptExt") + " " +
                request.getParameter("reason");
        reason += " Qty1:" + lot.getQty1() + " -------> " + qty1;

        transReason.setReasonCode(request.getParameter("reasonCode"));
        transReason.setReason(reason);
        transReason.setTransQty1(lot.getQty1());
        transReason.setTransQty2(lot.getQty2());
        transReason.setResponsibility(user);
        transInfo.put("transReason", transReason);

        lotService.updateLotPlan(transInfo);
        request.setAttribute("modifyFlag", "1");
        request.setAttribute("sucLotId", lot.getLotId());

        return mapping.findForward("modifyLotPlan");
    }

    private Map buildLotMap(String lotId) {
        Lot lot = lotService.getLotPlan(lotId);
        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(), StringUtils.EMPTY);

        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", this.getMaterials4lot(lot.getProductRrn()));
        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);
        lotMapInfo.put("carrierType", carrierService.getTargetCarrierTypeByStatus(lot));

        return lotMapInfo;
    }

    private String getMaterials4lot(Long productRrn) {
        long facilityRrn = LocalContext.getFacilityRrn();
        Operation warehouse = prpService
                .getOperation(getInstanceRrn(DEFAULT_WAFER_BANK, facilityRrn, ObjectList.OPERATION_KEY));
        Assert.isFalse(warehouse == null || warehouse.getInstanceRrn() <= 0,
                       Errors.create().key(MessageIdList.ASM_MISSING_WAREHOUSE).content("Warehouse is not exist!")
                             .build());

        return asmService.getMaterials4lot(warehouse.getInstanceRrn(), productRrn);
    }

    private void validateLotPlanType(String lotPlanType, String lotSelfPlanType) {
        Assert.isFalse(StringUtils.equalsIgnoreCase(lotSelfPlanType, ObjectList.NEW_LOT),
                       Errors.create().key(MessageIdList.LOT_LOT_TYPE_CANT_START)
                             .content("The lot for " + "new " + "lot " + "cann" + "'t wafer start!").build());

        boolean isMatchType = true;
        if (StringUtils.isBlank(lotPlanType)) {
            // 如果lot type是空,则表示普通的lot plan,产品类型不能是类表值$$SPECIAL_LOT_PLAN_TYPE设置的类型
            List<String> specialTypes = sysService
                    .getRefFileKey(ReferenceDetailNames.SPECIAL_LOT_PLAN_TYPE, StringUtils.EMPTY);
            if (specialTypes != null && specialTypes.contains(lotSelfPlanType)) {
                isMatchType = false;
            }
        } else if (!StringUtils.equalsIgnoreCase(lotPlanType, lotSelfPlanType)) {
            isMatchType = false;
        }

        Assert.isTrue(isMatchType, Errors.create().key(MessageIdList.LOT_THE_PAGE_CANT_START)
                                         .content("The lot cann't wafer start in the page!").build());
    }

    private List<Map<String, String>> parseMaterialInfo(String materialInfo) {
        List<Map<String, String>> materialInfoList = new ArrayList<Map<String, String>>();

        if (StringUtils.isBlank(materialInfo)) {
            return materialInfoList;
        }

        String[] materials = materialInfo.split(";");
        Map<String, String> map = new HashMap<String, String>();
        for (String str : materials) {
            String[] tmp = str.split(":");
            map = new HashMap<String, String>();
            map.put("rawMaterialId", tmp[0]);
            map.put("lotNumber", tmp[0]);
            map.put("specifiedQty", tmp[1]);
            map.put("wareHouseId", DEFAULT_WAFER_BANK);
            materialInfoList.add(map);
        }

        return materialInfoList;

    }

    private Boolean isRawMaterialRequired(String lotType) {

        return StringUtils.equalsIgnoreCase(lotType, "S") || StringUtils.equalsIgnoreCase(lotType, "L") ||
                StringUtils.equalsIgnoreCase(lotType, "T") || StringUtils.equalsIgnoreCase(lotType, "LF");
    }

    private String[] parseUnitListString(String[] units, Collection rawMaterials, String lotId) {

        String unitListString = "";
        for (int i = 0; i < units.length; i++) {
            unitListString += units[i];
        }

        List raw = (List) rawMaterials;
        int num = 0;
        for (int i = 0; i < units.length; i++) {
            Map map = (Map) raw.get(i);
            int qty = MapUtils.getIntValue(map, "int_specifiedQty");
            if (StringUtils.isBlank(units[i]) || StringUtils.equals("$", units[i])) {
                String unitList = "";
                for (int j = 0; j < qty; j++) {
                    String unitId = "";
                    while (true) {
                        unitId = lotId + SEPARATOR + String.format("%02d", ++num);
                        if (!StringUtils.contains(unitListString, unitId)) {
                            break;
                        }
                    }
                    unitList = unitList + unitId + "|" + "0" + "$";
                }
                units[i] = unitList;
            }
        }
        return units;
    }

    private int validateQty(Double lotQty, Collection rawMaterials) {
        double qty = 0.0;
        Double itemQty;

        for (Iterator it = rawMaterials.iterator(); it.hasNext(); ) {
            HashMap rawItem = (HashMap) it.next();
            itemQty = (Double) rawItem.get("specifiedQty");

            if (itemQty == null) {
                itemQty = new Double(0.0);
            }

            qty += itemQty.doubleValue();
        }
        if (lotQty.compareTo(new Double(qty)) > 0) {
            return LESS;
        } else if (lotQty.compareTo(new Double(qty)) < 0) {
            return MORE;
        } else {
            return EQUAL;
        }
    }

    private boolean validateUniqueUnit(Object[] unitList) {
        boolean flag = true;
        Collection keys = new ArrayList();
        Collection _keys = null;
        String _tmpString = null;

        if (unitList != null) {
            for (int i = 0; i < unitList.length; i++) {
                _tmpString = (String) unitList[i];
                _keys = myParseString(_tmpString, "1");
                keys.addAll(_keys);

                Collection tmpKeys = new ArrayList();
                tmpKeys.addAll(keys);

                if (!validateKeys(tmpKeys)) {
                    flag = false;

                    break;
                }
            }
        }

        return flag;
    }

    private boolean validateKeys(Collection keys) {
        boolean flag = true;
        for (Iterator it = keys.iterator(); it.hasNext(); ) {
            String item = (String) it.next();
            it.remove();

            if (keys.contains(item)) {
                flag = false;

                break;
            }
        }
        return flag;
    }

    private Collection myParseString(String tempString, String index) {
        int pos0 = -1;
        int pos1 = 0;
        int pos2 = 0;
        String key;
        String _tempString;
        Collection _keys = new ArrayList();
        if (tempString != null) {
            while (tempString.indexOf("$") > 0) {
                pos1 = tempString.indexOf("$");
                _tempString = tempString.substring(pos0 + 1, pos1);

                if (_tempString.indexOf("|") > 0) {
                    pos2 = _tempString.indexOf("|");

                    if (index.equals("1")) {
                        key = StringUtils.trimToUpperCase(_tempString.substring(pos0 + 1, pos2));
                    } else {
                        key = StringUtils.trimToUpperCase(_tempString.substring(pos2 + 1, pos1));
                    }

                    _keys.add(key);
                    tempString = tempString.substring(pos1 + 1, tempString.length());
                }
            }
        }

        return _keys;
    }

    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 void saveLotSeqAttribute(long lotRrn, Long productRrn) {
        long facilityRrn = LocalContext.getFacilityRrn();
        List attributes = sysService
                .getAllAttributes(lotRrn, getNamedSpace("LOT", facilityRrn), "LOT", I18nUtils.getCurrentLanguage());
        List attributesResults = new ArrayList();

        HashMap attribute = null;

        if (!attributes.isEmpty()) {
            for (Iterator it = attributes.iterator(); it.hasNext(); ) {
                attribute = (HashMap) it.next();

                if (this.getInstanceRrn("FLD_PRODUCT_SERIAL_NUMBER", getNamedSpace(ObjectList.FIELD_KEY, facilityRrn),
                                        ObjectList.FIELD_KEY) == MapUtils.getLongValue(attribute, "FIELD_RRN")) {
                    attribute
                            .put("attributeValue", Long.toString(lotQueryService.getMaxOfLotByProduct(productRrn) + 1));
                    attribute.put("instanceRrn", Long.toString(lotRrn));
                    attribute.put("instanceVersion", "1");
                    attribute.put("fieldRrn", MapUtils.getLongValue(attribute, "FIELD_RRN"));
                    attributesResults.add(attribute);
                }

                sysService.maintainAttribute(attributesResults);
            }
        } else {
            Map attributeValue = new HashMap();
            attributeValue.put("attributeValue", Long.toString(lotQueryService.getMaxOfLotByProduct(productRrn) + 1));
            attributeValue.put("instanceRrn", Long.toString(lotRrn));
            attributeValue.put("instanceVersion", "1");
            attributeValue.put("fieldRrn", Long.toString(
                    this.getInstanceRrn("FLD_PRODUCT_SERIAL_NUMBER", getNamedSpace(ObjectList.FIELD_KEY, facilityRrn),
                                        ObjectList.FIELD_KEY)));
            attributesResults.add(attributeValue);
            sysService.maintainAttribute(attributesResults);
        }
    }

    private Boolean isProductLinkedMaterial(Long productRrn, Long materialRrn) {
        if (productRrn == null || materialRrn == null) {
            return false;
        }
        Relation relation = baseService.getRelation(productRrn, materialRrn, LinkTypeList.PRODUCT_TO_MATERIAL_KEY);
        if (relation == null) {
            return false;
        }

        return true;
    }

    private void buildLotPlanInfo(ActionMapping mapping, HttpServletRequest request, MonitorLotInfoForm theform,
                                  Lot lot) {


        long facilityRrn = LocalContext.getFacilityRrn();
        Long lotRrn = lot.getLotRrn();
        double qty1 = NumberUtils.toDouble(request.getParameter("qty1"));

        String dueDates = StringUtils.trim(theform.getDueDateS());

        Assert.isFalse(StringUtils.isBlank(dueDates), Errors.create().key(MessageIdList.LOTPLAN_DUEDATE_CANNOT_BE_EMPTY)
                                                            .content("Due date cannot be empty").build());

        long nowTime = System.currentTimeMillis();
        Timestamp dueDate = DateUtils.stringToTimestamp(theform.getDueDateS() + " 00:00:00");

        Assert.isTrue(dueDate != null,
                      Errors.create().key(MessageIdList.ASM_DATEFORMAT_CHECK).content("Date format is wrong!").build());
        Assert.isFalse(dueDate.getTime() < nowTime,
                       Errors.create().key(MessageIdList.LOTPLAN_DUEDATE_CURRENTDATE_INCORRECT)
                             .content("dueDate must after the current date").build());

        if (StringUtils.isEmpty(StringUtils.trim(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.ASM_DATEFORMAT_CHECK).content("Date format is wrong!")
                             .build());

        lot.setPlanStartDate(DateUtils.stringToTimestamp(theform.getPlanStartDateS() + " 00:00:00"));
        lot.setStartHold(theform.getStartHold());

        theform.setLotOwner(StringUtils.trimToUpperCase(theform.getLotOwner()));

        Assert.isFalse(StringUtils.isBlank(theform.getLotOwner()),
                       Errors.create().key(MessageIdList.LOTPLAN_LOTOWNER_CANNOT_BE_EMPTY)
                             .content("Lot owner cannot be empty").build());
        long lotOwnerRrn = this
                .getInstanceRrn(theform.getLotOwner(), this.getNamedSpace(ObjectList.USER_KEY, facilityRrn),
                                ObjectList.USER_KEY);
        Assert.isFalse(lotOwnerRrn == 0,
                       Errors.create().key(MessageIdList.LOTPLAN_INVALID_LOTOWNER_ID).content("Invalid Lot Owner id")
                             .build());
        lot.setDueDate(DateUtils.stringToTimestamp(dueDates + " 00:00:00"));
        lot.setQty1(qty1);
        lot.setCreateCategory(theform.getCreateCategory());
        lot.setLotType(theform.getLotType());
        lot.setLotOwner(theform.getLotOwner());
        lot.setShippingCode(StringUtils.trim(theform.getShippingCode()));
        lot.setOutOrderType(StringUtils.trim(theform.getOutOrderType()));
        lot.setOuterOrderNO(StringUtils.trim(theform.getOuterOrderNO()));
        lot.setCustomerId(StringUtils.trim(theform.getCustomerId()));
        lot.setHotFlag(theform.getHotFlag());
        lot.setPriority(theform.getPriority());
        lot.setLotComments(StringUtils.trim(theform.getLotComments()));
        lot.setCustomerLotId(StringUtils.trim(theform.getCustomerLotId()));
        lot.setMaterialinfo(WebUtils.getParameterUpperCase(MATERIAL_PREFIX + lot.getLotId(), request));
    }

}