# FutureHoldManagerImpl.java

    package com.mycim.server.ctx.exec.manager.impl;

    import com.fa.sesa.threadlocal.LocalContext;
    import com.mycim.framework.oid.IDGenerators;
    import com.mycim.framework.oid.type.IDNames;
    import com.mycim.framework.oid.type.SequenceNames;
    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.server.base.manager.TransactionLogManager;
    import com.mycim.server.ctx.exec.dao.FutureHoldDAO;
    import com.mycim.server.ctx.exec.manager.FutureHoldManager;
    import com.mycim.server.wip.dao.LotDAO;
    import com.mycim.server.wip.manager.LotQueryManager;
    import com.mycim.valueobject.bas.TransactionLog;
    import com.mycim.valueobject.consts.EenActionType;
    import com.mycim.valueobject.consts.TransactionNames;
    import com.mycim.valueobject.prp.FutureHold;
    import com.mycim.valueobject.prp.FutureHoldHistory;
    import com.mycim.valueobject.prp.FutureHoldLot;
    import com.mycim.valueobject.prp.FutureHoldLotHistory;
    import com.mycim.valueobject.wip.Lot;
    import com.mycim.valueobject.wip.TransReason;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.sql.Timestamp;
    import java.util.*;

    /**
     * @author Sola
     * @date 2021/7/19
     **/
    @Service
    @Transactional
    public class FutureHoldManagerImpl implements FutureHoldManager {
        @Autowired
        private FutureHoldDAO futureHoldDAO;
        @Autowired
        private TransactionLogManager transactionLogManager;

        @Autowired
        private LotDAO lotDAO;

        @Autowired
        private LotQueryManager lotQueryManager;

        @Override
        public void addFutureHold(FutureHold futureHoldInfo) {
            //插入futureHold
            futureHoldInfo.setSysRrn(Long.valueOf(IDGenerators.get(IDNames.SEQUENCE).generateId(SequenceNames.MODULE_SEQ_OBJECT_RRN)));
            if(EenActionType.FUTURE_HOLD_BY_PRODUCT.equals(futureHoldInfo.getHoldCategory())){
                //查询by product已经设置了几条post future hold(通过max()获取最大值)
                List<String> maxSeqNumByProduct = futureHoldDAO
                        .getMaxSeqNumByProduct(futureHoldInfo.getFacilityRrn(), futureHoldInfo.getProductRrn(),
                                            futureHoldInfo.getHoldType(), futureHoldInfo.getHoldCategory());
                long count = 1;
                if(maxSeqNumByProduct.get(0)!=null){
                    count = Long.valueOf(maxSeqNumByProduct.get(0)) + 1;
                }
                futureHoldInfo.setAttributeData1(String.valueOf(count));
            } else if (EenActionType.FUTURE_HOLD_BY_LOT.equals(futureHoldInfo.getHoldCategory())){
                //查询by lot已经设置了几条post future hold(通过max()获取最大值)
                List<String> maxSeqNumByLot = futureHoldDAO
                        .getMaxSeqNumByLot(futureHoldInfo.getFacilityRrn(), futureHoldInfo.getLotRrn(),
                                        futureHoldInfo.getHoldType(), futureHoldInfo.getHoldCategory());
                long count = 1;
                if(maxSeqNumByLot.get(0)!=null) {
                    count = Long.valueOf(maxSeqNumByLot.get(0)) + 1;
                }
                futureHoldInfo.setAttributeData1(String.valueOf(count));
            }
            futureHoldDAO.insertFutureHold(futureHoldInfo);

            String transactionName = TransactionNames.BY_LOT_CREATE_FUTURE_HOLD;
            if(EenActionType.POST_FUTURE_HOLD.equals(futureHoldInfo.getHoldType())){
                transactionName = TransactionNames.BY_LOT_CREATE_POST_FUTURE_HOLD;
            }
            //插入futureHoldH
            TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(), transactionName);
            long transRrn = transactionLog.getTransRrn();
            FutureHoldHistory futureHoldHInfo = new FutureHoldHistory();
            BeanUtils.copyProperties(futureHoldInfo,futureHoldHInfo);
            futureHoldHInfo.setTransRrn(transRrn);
            futureHoldHInfo.setTransId(transactionName);
            futureHoldHInfo.setTransUserId(LocalContext.getUserId());
            futureHoldHInfo.setTransTime(new Timestamp(System.currentTimeMillis()));
            futureHoldDAO.insertFutureHoldH(futureHoldHInfo);

            if (StringUtils.equalsIgnoreCase(futureHoldInfo.getFlag(), "addFutureHold")) {
                Map _transInfo = new HashMap(10);
                Lot lot = lotQueryManager.getLot(futureHoldInfo.getLotRrn());
                _transInfo.put("transRrn", transactionLog.getTransRrn());
                _transInfo.put("transSequence", NumberUtils.BYTE_ONE);
                _transInfo.put("transId", transactionName);
                _transInfo.put("lotRrn", lot.getLotRrn());
                _transInfo.put("facilityRrn", lot.getFacilityRrn());
                _transInfo.put("stepSequence", lot.getStepSequence());
                _transInfo.put("carrierRrn", lot.getCarrierRrn());
                _transInfo.put("carrierMapRrn", lot.getCarrierMapRrn());
                _transInfo.put("qty1", lot.getQty1());
                _transInfo.put("qty2", lot.getQty2());
                _transInfo.put("transComments", futureHoldHInfo.getHoldReason());
                _transInfo.put("hotFlag", lot.getHotFlag());
                _transInfo.put("priority", lot.getPriority());
                _transInfo.put("eqptRrn", lot.getEqptRrn());
                _transInfo.put("recipeId", lot.getRecipeId());
                Long lotRrn = lot.getLotRrn();
                Lot lotExt = new Lot();
                lotExt.setLotRrn(lotRrn);
                lotExt = lotQueryManager.getLotExt(lotExt);
                _transInfo.put("customerId", StringUtils.isNotBlank(lotExt.getCustomerId()) ? lotExt.getCustomerId() : "");
                _transInfo
                        .put("shippingCode", StringUtils.isNotBlank(lotExt.getShippingCode()) ? lotExt.getShippingCode() : "");
                _transInfo
                        .put("outerOrderNo", StringUtils.isNotBlank(lotExt.getOuterOrderNO()) ? lotExt.getOuterOrderNO() : "");
                _transInfo
                        .put("outOrderType", StringUtils.isNotBlank(lotExt.getOutOrderType()) ? lotExt.getOutOrderType() : "");
                _transInfo.put("location", lotExt.getLocation());
                _transInfo.put("prevLocation", lotExt.getpLocation());
                _transInfo.put("locationRrn", lotExt.getLocationRrn());
                _transInfo.put("prevLocationRrn", lotExt.getpLocationRrn());
                _transInfo.put("splitMergeFlag", lotExt.getSplitMergeFlag());

                lotDAO.createLotTrans(_transInfo);
                TransReason transReason = new TransReason();
                transReason.setReasonCode(futureHoldHInfo.getHoldCode());
                transReason.setReason(futureHoldHInfo.getHoldReason());
                transReason.setTransQty1(lot.getQty1());
                transReason.setTransQty2(lot.getQty2());
                transReason.setResponsibility(LocalContext.getUserId());

                lotDAO.insertTransReason(transRrn, futureHoldInfo.getLotRrn(), transReason, NumberUtils.BYTE_ONE);
                lotDAO.insertTransReasonH(transRrn, transRrn, futureHoldInfo.getLotRrn());
            }

            transactionLogManager.markTransactionLog(transactionLog);
        }

        @Override
        public List<FutureHold> getFutureHoldBySysRrn(Long futureHoldSysRrn) {
            return futureHoldDAO.getFutureHoldBySysRrn(futureHoldSysRrn);
        }

        @Override
        public List<FutureHold> getFutureHold(FutureHold futureHold) {
            return futureHoldDAO.getFutureHold(futureHold);
        }

        @Override
        public List<FutureHold> getFHListByProduct(Long facilityRrn,long lotRrn,long productRrn, String holdType, String holdCategory) {
            List<FutureHold> futureHoldListByProduct = futureHoldDAO.getFHListByProduct(facilityRrn,productRrn,holdType,holdCategory);
            for (FutureHold futureHold : futureHoldListByProduct) {
                if(getFHLHistoryListByFutureHold(futureHold.getSysRrn(),lotRrn).size()>0){
                    futureHold.setExecutedFlag("EXECUTED");
                }else{
                    futureHold.setExecutedFlag("");
                }
            }
            return futureHoldListByProduct;
        }

        @Override
        public List<FutureHold> getFHListByLot(Long facilityRrn, long lotRrn, String holdType,
                                                        String holdCategory) {
            List<FutureHold> futureHoldListByLot = futureHoldDAO.getFHListByLot(facilityRrn,lotRrn,holdType,holdCategory);
            for (FutureHold futureHold : futureHoldListByLot) {
                if(getFHLHistoryListByFutureHold(futureHold.getSysRrn(),lotRrn).size()>0){
                    futureHold.setExecutedFlag("EXECUTED");
                }else{
                    futureHold.setExecutedFlag("");
                }
            }
            return futureHoldListByLot;
        }

        @Override
        public void deleteFutureHold(FutureHold futureHold) {
            List<FutureHold> futureHoldInfos = new ArrayList<>();
            //判断删除的是by lot or by product的设置
            if(EenActionType.FUTURE_HOLD_BY_LOT.equals(futureHold.getHoldCategory())){
                futureHoldInfos = futureHoldDAO.getFHListByLot(futureHold.getFacilityRrn(),futureHold.getLotRrn(),
                                                               futureHold.getHoldType(),futureHold.getHoldCategory());
            } else {
                futureHoldInfos = futureHoldDAO.getFHListByProduct(futureHold.getFacilityRrn(),futureHold.getProductRrn(),
                                                                   futureHold.getHoldType(),futureHold.getHoldCategory());
            }
            String seqNum = futureHold.getAttributeData1();
            if (CollectionUtils.isNotEmpty(futureHoldInfos)) {
                for (FutureHold futureHoldInfo : futureHoldInfos) {
                    if(StringUtils.isNotBlank(seqNum)) {
                        //若指定删除某条hold信息
                        if(seqNum.equals(futureHoldInfo.getAttributeData1())){
                            deleteFutureHoldBySysRrn(futureHoldInfo);
                        }
                    } else {
                        //若未指定删除某条hold信息
                        deleteFutureHoldBySysRrn(futureHoldInfo);
                    }
                }
            }
        }

        @Override
        public void deleteFutureHoldBySysRrn(FutureHold futureHoldInfo){
            long sysRrn = futureHoldInfo.getSysRrn();
            futureHoldDAO.deleteFutureHold(sysRrn);

            String transactionName = TransactionNames.BY_LOT_DELETE_FUTURE_HOLD;
            if (EenActionType.POST_FUTURE_HOLD.equals(futureHoldInfo.getHoldType())) {
                transactionName = TransactionNames.BY_LOT_DELETE_POST_FUTURE_HOLD;
            }
            //插入futureHoldH
            TransactionLog transactionLog = transactionLogManager
                    .startTransactionLog(LocalContext.getUserId(), transactionName);
            long transRrn = transactionLog.getTransRrn();
            FutureHoldHistory futureHoldHInfo = new FutureHoldHistory();
            BeanUtils.copyProperties(futureHoldInfo,futureHoldHInfo);
            futureHoldHInfo.setTransRrn(transRrn);
            futureHoldHInfo.setTransId(transactionName);
            futureHoldHInfo.setTransUserId(LocalContext.getUserId());
            futureHoldHInfo.setTransTime(new Timestamp(System.currentTimeMillis()));
            futureHoldDAO.insertFutureHoldH(futureHoldHInfo);
            transactionLogManager.markTransactionLog(transactionLog);
        }

        @Override
        public void addFutureHoldLot(FutureHoldLot futureHoldLot) {
            //添加future_hold_lot表数据
            futureHoldDAO.insertFutureHoldLot(futureHoldLot);
            //添加future_hold_lot_h表数据
            String transactionName = TransactionNames.HOLD_KEY;
            TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(),transactionName);
            long transRrn = transactionLog.getTransRrn();
            FutureHoldLotHistory futureHoldLotHistory = new FutureHoldLotHistory();
            BeanUtils.copyProperties(futureHoldLot,futureHoldLotHistory);
            futureHoldLotHistory.setTransRrn(transRrn);
            futureHoldLotHistory.setTransId(transactionName);
            futureHoldLotHistory.setTransUserId(LocalContext.getUserId());
            futureHoldLotHistory.setTransTime(new Timestamp(System.currentTimeMillis()));
            futureHoldDAO.insertFutureHoldLotH(futureHoldLotHistory);
            transactionLogManager.markTransactionLog(transactionLog);
        }

        @Override
        public List<FutureHoldLot> getFHLotListByLot(long lotRrn,String holdType) {
            return futureHoldDAO.getFHLotListByLot(lotRrn,holdType);
        }

        @Override
        public void releaseFutureHoldLot(long lotRrn, String holdType,Map releaseInfo) {
            List<FutureHoldLot> fhLotListByLots = getFHLotListByLot(lotRrn, holdType);
            Collection releaseReasons = (Collection) MapUtils.getObject(releaseInfo, "releaseReasons");
            Object[] releaseReasonArray = releaseReasons.toArray();

            for (int i = 0; i < releaseReasonArray.length; i++) {
                HashMap releaseReason = (HashMap) releaseReasonArray[i];
                String holdCode = MapUtils.getString(releaseReason, "reasonCode");
                String sequenceNumber = MapUtils.getString(releaseReason,"sequenceNumber");
                for (FutureHoldLot fhLotListByLot : fhLotListByLots) {
                    if (sequenceNumber.equals(fhLotListByLot.getAttributeData1())) {
                        //删除future_hold_lot表数据
                        futureHoldDAO.deleteFutureHoldLot(fhLotListByLot.getFutureHoldSysRrn(), lotRrn);
                        //添加future_hold_lot_h表数据
                        String transactionName = TransactionNames.RELEASE_KEY;
                        TransactionLog transactionLog = transactionLogManager
                                .startTransactionLog(MapUtils.getString(releaseReason, "transPerformedBy"),
                                                     transactionName);
                        long transRrn = transactionLog.getTransRrn();

                        FutureHoldLotHistory futureHoldLotHistory = new FutureHoldLotHistory();
                        BeanUtils.copyProperties(fhLotListByLot,futureHoldLotHistory);
                        futureHoldLotHistory.setTransRrn(transRrn);
                        futureHoldLotHistory.setTransId(transactionName);
                        futureHoldLotHistory.setTransUserId(MapUtils.getString(releaseReason, "transPerformedBy"));
                        futureHoldLotHistory.setTransTime(new Timestamp(System.currentTimeMillis()));
                        futureHoldDAO.insertFutureHoldLotH(futureHoldLotHistory);
                        transactionLogManager.markTransactionLog(transactionLog);
                    }
                }
            }
        }

        @Override
        public void addFutureHoldLotHistory(FutureHoldLotHistory fhlHistory) {
            String transactionName = fhlHistory.getTransId();
            TransactionLog transactionLog = transactionLogManager.startTransactionLog(fhlHistory.getTransUserId(), transactionName);
            long transRrn = transactionLog.getTransRrn();
            fhlHistory.setTransRrn(transRrn);
            futureHoldDAO.insertFutureHoldLotH(fhlHistory);
            transactionLogManager.markTransactionLog(transactionLog);
        }

        @Override
        public List<FutureHoldLotHistory> getFHLHistoryListByFutureHold(Long sysRrn,long lotRrn) {
            List<FutureHoldLotHistory> futureHoldLotHList = futureHoldDAO.getFutureHoldLotHList(sysRrn, lotRrn);
            return futureHoldLotHList;
        }
    }