ScrapLotEditAction.java

package com.mycim.webapp.actions.lot.lotscrapunscrap;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.i18n.I18nUtils;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.consts.*;
import com.mycim.valueobject.ems.Carrier;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.LotStatus;
import com.mycim.valueobject.wip.TransReason;
import com.mycim.webapp.Constants;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.WipSetupAction;
import com.mycim.webapp.forms.lot.ScrapLotInfoForm;
import org.apache.commons.compress.utils.Sets;
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.io.*;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liuji.li
 * @version 6.0.0
 * @date 2019/9/20
 **/
public class ScrapLotEditAction extends WipSetupAction {

    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e'
            , 'f'};

    private static byte[] toBytes(String str) {
        if (str == null || str.trim().equals("")) {
            return new byte[0];
        }
        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }
        return bytes;
    }

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        ScrapLotInfoForm theform = (ScrapLotInfoForm) form;
        long facilityRrn = LocalContext.getFacilityRrn();
        Lot lot = new Lot();
        String lotId = StringUtils.trimToUpperCase(WebUtils.getParameter("lotId", request));
        String transId = WebUtils.getParameter("transId", request);
        if (StringUtils.isNotBlank(lotId)) {
            lot = lotQueryService.getLot(lotId, facilityRrn);
            long lotRrn = lot.getLotRrn();
            Assert.isFalse(lotRrn <= 0,
                           Errors.create().key(MessageIdList.SCRAPLOT_NOT_FIND_LOT).content("Cannot Find Lot!")
                                 .build());
            // Assert.isTrue(StringUtils.equalsIgnoreCase("P", lot.getLotType()), Errors.create().content("The lot type should be P!").build());

            //卡控post future hold被hold住的lot
            checkPostFutureHold(lot.getLotRrn());

            if (transId.equalsIgnoreCase(Constants.SCRAP_KEY)) {
                Assert.isTrue(lot.getLotStatus().equals(LotStatus.HOLD),
                              Errors.create().key(MessageIdList.SCRAPLOT_STATUS_NOT_ALLOW)
                                    .content("Lot status must be Hold!").build());
                theform.setTransId(Constants.SCRAP_KEY);
            } else if (transId.equalsIgnoreCase(Constants.UNSCRAP_KEY)) {
                Assert.isTrue(lot.getLotStatus().equals(LotStatus.SCRAPPED),
                              Errors.create().key(MessageIdList.UNSCRAP_INVALID_LOT_STATUS)
                                    .content("Invalid Lot status!").build());
                Assert.isFalse(workOrderService.getErpPackageCount(lot.getLotRrn()) > 0,
                               Errors.create().key(MessageIdList.UNSCRAP_EXIST_LOT_PACKAGE)
                                     .content("Lot package info exists!").build());
                theform.setQty1(lot.getInputQty1());
                theform.setTransId(Constants.UNSCRAP_KEY);

                List<Map> scrapReasons = lotQueryService.getScrapReasons(lot.getLotRrn());
                Carrier carrier = carrierService.getCarrier(lot.getCarrierRrn());
                if (carrier != null && carrier.getInstanceRrn() > 0) {
                    if (StringUtils.equalsIgnoreCase(carrier.getObjectSubtype(), CarrierType.DUMMY)) {
                        request.setAttribute("carrierType", carrier.getDmmType());
                        request.setAttribute("carrierCategory", carrier.getFlagType());
                    } else {
                        request.setAttribute("carrierType", carrier.getObjectSubtype());
                        request.setAttribute("carrierCategory", carrier.getFlagType());
                    }
                }
                request.setAttribute("unscrapCollection", scrapReasons);
                theform.setTransId(Constants.UNSCRAP_KEY);
            }
            wipQueryService.checkActiveInlineOcapId(lot.getLotRrn());
            //check sortJob
            checkWaitJobs(lot.getCarrierRrn(), 0L, 0L, null);
        }
        super.checkCstRemoved(Sets.newHashSet(lot.getLotRrn()));
        Assert.isFalse(diffBatchQueryService.checkLotInBatch(lot.getLotRrn()),
                       Errors.create().key(MessageIdList.SCRAPLOT_LOT_BATCH).content("Lot in batch!").build());
        request.setAttribute("lotId", lotId);
        theform.setCacheLot(getCacheObj2String(lot));
        request.setAttribute("collection", new ArrayList<>());
        initLotBaseInfoForJsp(request, true, "", "");
        return mapping.getInputForward();
    }

    public ActionForward scrapLot(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                  HttpServletResponse response) throws Exception {
        ScrapLotInfoForm theform = (ScrapLotInfoForm) form;
        long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();
        String language = I18nUtils.getCurrentLanguage().toString();
        List<Map> transReasons = new ArrayList<Map>();
        Lot lot = (Lot) getCacheString2Obj(theform.getCacheLot());
        checkLotInfo(request, lot, WebUtils.getParameter("lotId", request),
                     WebUtils.getParameter("carrierId", request));
        // get units in string array
        Map transInfo = new HashMap();
        // List<Lot> lockLots = new ArrayList<Lot>();
        transInfo.put("lotComments", theform.getLotComments());
        transInfo.put("lot", lot);
        // lockLots.add(lot);
        transInfo.put("transPerformedBy", user);
        Assert.isFalse(StringUtils.isBlank(theform.getDepartment()),
                       Errors.create().key(MessageIdList.SCRAPLOT_DEPT_NOT_EMPTY)
                             .content("Department id cannot be Empty!").build());
        Assert.isFalse(StringUtils.isBlank(theform.getReasonCode()),
                       Errors.create().key(MessageIdList.SCRAPLOT_RESON_NOT_EMPTY)
                             .content("ReasonCode cannot be Empty!").build());
        Assert.isFalse(StringUtils.isEmpty((request.getParameter("exceptionId"))),
                       Errors.create().key(MessageIdList.SCRAPLOT_BILL_NUMBER_NOT_EMPTY)
                             .content("Abnormal Bill" + " " + "number can" + " not be " + "empty!").build());
        Map transReason = new HashMap();
        transReason.put("reasonCode", theform.getReasonCode());
        transReason.put("reasonCategory", theform.getTransId().toUpperCase());

        transReason.put("transQty1", lot.getQty1());
        transReason.put("transQty2", lot.getQty2());
        String reasonDesc = this.getReasonDesc(theform.getTransId(), theform.getReasonCode(), facilityRrn);
        transReason.put("reasonDesc", reasonDesc);
        long userRrn = WebUtils.getParameterLong("userId", request);
        String lotOwner = securityService.getUser(userRrn).getUserName();
        String reason = "";
        if (StringUtils.equalsIgnoreCase("CN", language)) {
            reason =
                    reasonDesc + " " + " " + theform.getDepartment() + " " + theform.getDeptExt().trim().toUpperCase() +
                            " " + lotOwner.toUpperCase() + " " + theform.getReason() + " 异常单号:" +
                            request.getParameter("exceptionId");
        } else {
            reason =
                    reasonDesc + " " + " " + theform.getDepartment() + " " + theform.getDeptExt().trim().toUpperCase() +
                            " " + lotOwner.toUpperCase() + " " + theform.getReason() + " Abnormal Bill number:" +
                            request.getParameter("exceptionId");
        }

        transReason.put("reason", reason);
        String userName = securityService.getUser(LocalContext.getUserRrn()).getUserName();
        if (StringUtils.isNotBlank(userName)) {
            transReason.put("responsibility", user + " " + userName);
        } else {
            transReason.put("responsibility", user);
        }
        transReasons.add(transReason);
        transInfo.put("transReasons", transReasons);
        transInfo.put("transQty1", lot.getQty1());
        transInfo.put("areaDepartment", theform.getAreaDepartment());
        transInfo.put("transQty2", lot.getQty2());
        transInfo.put("facilityRrn", facilityRrn);

        // checkAndCreateLotsTransLock(LocalContext.getUserRrn(), TransactionNames.LOCK_SCRAP, lockLots,
        //                             "Scrap lot in " + "ScrapLotEditAction by:" + user);
        lotService.scrapLot(transInfo);
        /**
         * List<LotRunCard> runcardList = wipQueryService.getEffectiveLotRuncardByLot(lot.getLotRrn());
         for(LotRunCard runcard : runcardList) {
         lotRuncardService.forceWithdrawRunCard(facilityRrn, user, userRrn, runcard.getRunCardRrn());
         }*/

        return mapping.findForward(Constants.LOTLOCATION_KEY);
    }

    public ActionForward unScrapLot(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                    HttpServletResponse response) throws Exception {
        ScrapLotInfoForm theform = (ScrapLotInfoForm) form;
        long facilityRrn = LocalContext.getFacilityRrn();
        Lot lot = (Lot) getCacheString2Obj(theform.getCacheLot());
        long userRRN = WebUtils.getParameterLong("userId", request);
        this.checkLotInfo(request, lot, theform.getLotId(), theform.getCarrierId());
        Map transInfo = new HashMap();
        // List<Lot> lockLots = new ArrayList<>();
        String userName = userRRN > 0 ? securityService.getUser(userRRN).getUserName() : "";
        String userId = LocalContext.getUserId();
        String reasonDesc = this.getReasonDesc(theform.getTransId(), theform.getReasonCode(), facilityRrn);
        String reason =
                reasonDesc + " " + theform.getDepartment() + " " + StringUtils.upperCase(theform.getDeptExt()) + " " +
                        StringUtils.upperCase(StringUtils.trim(userName)) + " " + theform.getReason();
        TransReason transReason = new TransReason();
        transReason.setReasonCode(theform.getReasonCode());
        transReason.setReason(reason);
        transReason.setReasonCategory(theform.getTransId().toUpperCase());

        Map qty = lotQueryService.getQtyForUnscrap(lot.getLotRrn());
        Double qty1 = null;
        Double qty2 = null;
        if (qty != null) {
            qty1 = MapUtils.getDouble(qty, "TRANS_QTY1");
            qty2 = MapUtils.getDouble(qty, "TRANS_QTY2");
        }
        transReason.setTransQty1(qty1);
        transReason.setTransQty2(qty2);
        transReason.setResponsibility(theform.getResponsibility());
        transInfo.put("lotComments", theform.getLotComments());
        transInfo.put("lot", lot);
        // transInfo.put("lotRrn",new Long(lot.getLotRrn()).toString());
        // transInfo.put("lotStepSeq",lot.getStepSequence());
        transInfo.put("transPerformedBy", userId);
        transInfo.put("transReason", transReason);
        transInfo.put("wholeLotFlag", new String("1"));
        transInfo.put("transQty1", qty1);
        transInfo.put("transQty2", qty2);
        String targetCarrierId = StringUtils.trimToUpperCase(theform.getTargetCarrierId());
        Assert.isFalse(StringUtils.isEmpty(targetCarrierId),
                       Errors.create().key(MessageIdList.UNSCRAP_NOT_CARRIER).content("Target carrier Not Specified!")
                             .build());
        // 批次复活后的真实晶舟id
        carrierService.compareRealAndDummyCarrierAndCheckRealCarrierAvailabile(facilityRrn, lot.getCarrierId(),
                                                                               targetCarrierId);
        long targetCarrierRrn = this.getCarrierRrnForLot(facilityRrn, lot.getQty1(), targetCarrierId);

        transInfo.put("targetCarrierRrn", targetCarrierRrn);
        transInfo.put("areaDepartment", theform.getAreaDepartment());
        // lockLots.add(lot);
        // checkAndCreateLotsTransLock(LocalContext.getUserRrn(), TransactionNames.LOCK_UNSCRAP, lockLots,
        //                             "UnScrap lot in ScrapLotEditAction by:" + LocalContext.getUserId());
        lotService.unscrapLot(transInfo);
        return mapping.findForward(Constants.LOTLOCATION_KEY);
    }

    public long getCarrierRrnForLot(long facilityRrn, Double lotQty, String carrierId) {
        carrierId = StringUtils.trimToUpperCase(carrierId);
        Assert.isFalse(StringUtils.isEmpty(carrierId),
                       Errors.create().key(MessageIdList.UNSCRAP_CARRIER_REQUIRED).content("carrier is required!")
                             .build());
        Carrier carrier = carrierService.getCarrier(facilityRrn, carrierId);

        Assert.isFalse(StringUtils.equalsIgnoreCase(carrier.getObjectSubtype(), Carrier.CarrierType.DUMMY.toString()),
                       Errors.create().key(MessageIdList.UNSCRAP_DUMMY_CARRIER)
                             .content("The carrier: {} is a  dummy carrier!").args(carrier.getInstanceId()).build());
        Assert.isFalse(carrier.getAvailableSlotCount() < lotQty,
                       Errors.create().key(MessageIdList.UNSCRAP_SLOT_NOT_ENOUGH)
                             .content("The AvailableSlot is not enough!").build());

        Assert.isFalse(!StringUtils.equalsIgnoreCase(carrier.getCarrierStatus(), PcdStatus.FREE_KEY) &&
                               !StringUtils.equalsIgnoreCase(carrier.getCarrierStatus(), PcdStatus.ASSEMBLY_KEY),
                       Errors.create().key(MessageIdList.UNSCRAP_CARRIER_STATUS).content("Invalid carrier status!")
                             .build());
        Assert.isFalse((carrierService.isAssseblyNeed(carrier.getObjectSubtype())) &&
                               !StringUtils.equalsIgnoreCase(carrier.getCarrierStatus(), PcdStatus.ASSEMBLY_KEY),
                       Errors.create().key(MessageIdList.UNSCRAP_NEED_ASSEMBLED)
                             .content("{} type carrier needed " + "assembled first!").args(carrier.getObjectSubtype())
                             .build());
        carrierService.checkPcdIsValid(carrier.getInstanceRrn(), facilityRrn);

        return carrierService.getAvailableCarrierRrnById(facilityRrn, carrierId);
    }

    protected String getCacheObj2String(Object obj) throws Exception {
        if (obj == null) {
            return "";
        }
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(byteStream);
        oo.writeObject(obj);
        String string = bytesToHexFun2(byteStream.toByteArray());
        return string;
    }

    private String bytesToHexFun2(byte[] bytes) {
        char[] buf = new char[bytes.length * 2];
        int index = 0;
        // 利用位运算进行转换,可以看作方法一的变种
        for (byte b : bytes) {
            buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
            buf[index++] = HEX_CHAR[b & 0xf];
        }
        return new String(buf);
    }

    private Object getCacheString2Obj(String pageDataString) throws Exception {
        if (pageDataString != null && !"".equals(pageDataString)) {
            String string = URLDecoder.decode(pageDataString);
            BufferedInputStream bff = new BufferedInputStream(new ByteArrayInputStream(toBytes(string)));
            ObjectInputStream objectInputStream;
            objectInputStream = new ObjectInputStream(bff);
            return objectInputStream.readObject();
        }
        return null;
    }

    private void checkLotInfo(HttpServletRequest request, Lot lot, String formLotId, String formCarrierId) {
        String lotInfoFlag = WebUtils.getParameter("lotInfoFlag", request);
        String formCarrierIdTemp = StringUtils.equals(lotInfoFlag, "1") ? WebUtils
                .getParameter("baseCarrierId", request) : StringUtils.trimToUpperCase(formCarrierId);
        Assert.isFalse(!StringUtils.equals(lot.getLotId(), StringUtils.trimToUpperCase(formLotId)) ||
                               !StringUtils.equals(StringUtils.defaultString(lot.getCarrierId()), formCarrierIdTemp),
                       Errors.create().key(MessageIdList.SCRAPLOT_LOTID_ERROR).content("Invalid ID!").build());
        //check sortJob
        checkWaitJobs(lot.getCarrierRrn(), 0L, 0L, null);
    }

    /**
     * 根据transId判断类表号,默认查询类表号$REASON_CODE的reasonDesc
     */
    private String getReasonDesc(String transId, String reasonCode, long facilityRrn) {
        Assert.isFalse(StringUtils.isEmpty(StringUtils.trim(transId)),
                       Errors.create().key(MessageIdList.SCRAPLOT_TRANSID_ERROR).content("TransId can't be Empty!")
                             .build());
        String reasonDesc = "";
        if (StringUtils.isEmpty(StringUtils.trim(reasonCode))) {
            return reasonDesc;
        }
        long rrn = getInstanceRrn(ReferenceDetailNames.SCRAP_CODE, facilityRrn, ObjectList.REFERENCE_FILE_KEY);
        reasonDesc = sysService
                .referenceDetailExchangeNull(ReferenceDetailNames.SCRAP_CODE, reasonCode, "DATA_1_VALUE");
        return reasonDesc;
    }

}