package com.brilliance.isc.common.sysmod.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.brilliance.isc.bo.*;
import com.brilliance.isc.common.api.bch.service.BchService;
import com.brilliance.isc.common.cache.pty.PtyCacheService;
import com.brilliance.isc.common.codetable.service.CodetableService;
import com.brilliance.isc.common.component.DyncDaoService;
import com.brilliance.isc.common.component.PtsptaToolComponent;
import com.brilliance.isc.common.contants.CommonContants;
import com.brilliance.isc.common.context.AppEnv;
import com.brilliance.isc.common.context.SettleContext;
import com.brilliance.isc.common.context.SettleSession;
import com.brilliance.isc.common.counter.service.CounterService;
import com.brilliance.isc.common.exception.CommonServiceException;
import com.brilliance.isc.common.quemod.vo.QueClaStatus;
import com.brilliance.isc.common.quemod.vo.TaskFlowStatus;
import com.brilliance.isc.common.quemod.vo.TaskStatus;
import com.brilliance.isc.common.sysmod.SysmodService;
import com.brilliance.isc.common.sysmod.objname.ObjNameBuilderManager;
import com.brilliance.isc.common.sysmod.vo.SysmodVo;
import com.brilliance.isc.common.taskdistributor.service.TaskDistService;
import com.brilliance.isc.common.tools.service.ObjectStroeToolService;
import com.brilliance.isc.common.transaction.help.TransactionHelpService;
import com.brilliance.isc.common.transaction.vo.BaseTransactionVo;
import com.brilliance.isc.common.trnmod.service.TrnmodService;
import com.brilliance.isc.common.util.SettleExceptionUtils;
import com.brilliance.isc.common.util.StringUtils;
import com.brilliance.isc.common.util.Utils;
import com.brilliance.isc.common.vo.BizInfoVo;
import com.brilliance.isc.common.vo.PtsptaVo;
import com.brilliance.isc.mda.dao.*;
import com.brilliance.mda.runtime.mda.CodetableItem;
import com.brilliance.mda.runtime.mda.IStream;
import com.brilliance.mda.runtime.mda.impl.Argument;
import com.brilliance.mda.runtime.mda.impl.StreamImpl;
import com.brilliance.mda.runtime.mda.util.*;
import com.google.common.collect.ImmutableBiMap;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.brilliance.mda.runtime.mda.Constants.*;

@Service
public class SysmodServiceImpl implements SysmodService {


    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Resource
    private TaskDistService taskDistService;

    @Autowired
    private EvtMapper evtMapper;

    @Autowired
    private PublicMapper publicMapper;

    @Autowired
    private SptMapper sptMapper;

    @Autowired
    private SprMapper sprMapper;

    @Autowired
    private QueMapper queMapper;

    @Autowired
    private SmhMapper smhMapper;
    @Autowired
    private PtyCacheService ptyCacheService;

    @Autowired
    private SweMapper sweMapper;

    @Autowired
    private MsgMapper msgMapper;

    @Autowired
    private BchService bchService;

    @Autowired
    private TrnMapper trnMapper;

    @Autowired
    private CounterService counterService;
    @Autowired
    private DyncDaoService dyncDaoService;

    @Autowired
    private CodetableService codetableService;
    @Autowired
    private TrnmodService trnmodService;
    @Autowired
    private PtsptaToolComponent ptsptaToolComponent;
    @Autowired
    private TransactionHelpService transactionHelpService;
    @Autowired
    private ObjNameBuilderManager objNameBuilderManager;
    @Autowired
    private AppEnv appEnv;

    @Autowired
    private ObjectStroeToolService objectStroeToolService;

    @Resource
    private AtpMapper atpMapper;

    @Autowired
    private OrdMapper ordMapper;

    @Resource
    private AtpbchMapper atpbchMapper;

    private SysmodVo sysmodVo;

    @Resource
    private StbMapper stbMapper;

    @Resource
    private OffcfgMapper offcfgMapper;

    @Resource
    private RouMapper rouMapper;

    public String internalSetObjNam(Object recObj, BaseTransactionVo baseTransactionVo) {
        String objTyp = Utils.recGetObj(recObj);
        String ref = Utils.getFieldValue(recObj, "ownref");
        String name = Utils.getFieldValue(recObj, "nam");
        String pntTyp = "";
        String objName = "";
        if (StringUtils.isEmpty(ref)) {
            if ("LTD".equals(objTyp)) {
                // LTD has always as Parent LED
                pntTyp = "LED";
            } else {
                pntTyp = Utils.getFieldValue(recObj, "pnttyp");
            }
            if (StringUtils.isNotEmpty(pntTyp)) {
                Object pntGrp = Utils.getFieldValue(baseTransactionVo, pntTyp + "grp");
                ref = Utils.getFieldValue(pntGrp, "rec//ownref");
                name = Utils.getFieldValue(pntGrp, "rec//nam");
                try {
                    objName = "New for " + objNameBuilderManager.getObjName(pntTyp, ref, name);
                } catch (Exception e) {
                    log.warn("没有找到对应的ObjName子类, " + pntTyp);
                    objName = "New " + "<" + objTyp + ">" + " for " + ref;
                }
            } else {
                objName = "New " + "<" + objTyp + "> / " + objNameBuilderManager.getObjName(objTyp, ref, name);
            }
        } else {
            objName = objNameBuilderManager.getObjName(objTyp, ref, name);
        }
        return objName;
    }

    /**
     * source:sysmod.0159.script
     */

    public String evtWrite(String argTyp, String argInr, String argRtn, String argTxt) {
        //! Routine used to create an event entry. The routine returns the
        //! INR of the created event for optional reference.
        //! ArgTyp should be
        //! ArgInr could optionaly hold the INR of the
        //! ArgRtn
        //! ArgTxt should be GetText ( Errorcode ) if
        Evt evt = new Evt();
        evt.setInr(counterService.dbCounterFormat("EVT"));
        // evt.setSsninr( SettleContext.getUserSession().getSsn().getInr());
        evt.setObjtyp(argTyp);
        evt.setObjinr(argInr);
        evt.setFrm(SettleContext.getTransName());
        evt.setDattim(Dates.now());
        evt.setUsr(SettleContext.getUserSession().getUsr().getExtkey());
        evt.setRtn(argRtn);
        evt.setTxt(argTxt);
        evt.setArcflg("N");
        evtMapper.insert(evt);
        // send a notify and or inform about the event via other channels
        //
//        notifyEvent();
        return evt.getInr();

    }

    public String getProcessBranch() {
        //取得上下文
//        IContext ctx = MdaEnv.getContext();
//        ctx.setErrorCode(NO_ERROR);
        //----得到实际的记账机构--------------
        //----规则:如果机构安装TC即为TID编号,否则为BCHKEY
//        if (!MdaUtils.isEmpty(SettleContext.getUserSession().getWrkbch().getTid())) {
//            return SettleContext.getUserSession().getWrkbch().getTid();
//        } else {
        if (!MdaUtils.isEmpty(SettleContext.getUserSession().getWrkbch().getBchkey())) {
            return SettleContext.getUserSession().getWrkbch().getBchkey();
        } else {
            return SettleContext.getUserSession().getBch().getBranch();
        }
//        }

    }

    public boolean sptIsAnyLoaded(String sta) {
//        //取得上下文
//        IContext ctx = MdaEnv.getContext();
//        ctx.setErrorCode(NO_ERROR);
//        //! Function to check whether any Spt-item is loaded on entry of the transaction
//        //! returns true if any spt item is loaded
        boolean rtn = false;
        if (!MdaUtils.isEmpty(sta)) {
            rtn = true;
        } else {
            rtn = false;
        }
        return rtn;
    }

    public boolean sptIsIncLoaded(String sptState) {
        if (sptIsLoaded("INC", sptState)) {
            return true;
        } else {
            return sptIsLoaded("STP", sptState);
        }

    }

    public boolean sptIsRimLoaded(String sptState) {
        //! Function to check whether an Spt-item of typ RIM (registration) is loaded on entry of the transaction.
        //! returns true if RIM item is loaded.
        return sptIsLoaded(SptWaitingRegistration, sptState);

    }


    public boolean sptIsExeLoaded(String sptState) {
        //取得上下文
//        IContext ctx = MdaEnv.getContext();
//        ctx.setErrorCode(NO_ERROR);
        //! Function to check whether an Spt-item of typ EXE (recalculation) is loaded
        //! on entry of the transaction.
        //! returns true if EXE item is loaded.
        return sptIsLoaded(SptWaitForRecalculation, sptState);

    }

    @Override
    public boolean sptIsCorLoaded(String sptState) {
        //! function to check whether a correction spt-item is loaded on entry of the transaction.
        //! returns true if an corrected spt-item is loaded.
        return sptIsLoaded(SptAfterSentToRepair, sptState);
    }


    /**
     * source:sysmod.0244.script
     */
    @Override
    public String getRef(String stRnTbl, int nLen) {
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //! 1： STrnTbl: 参考号前2位
        //! 2： $Dbjgtxt :代办机构号
        //! 3： $DatTxt1 :时间(年)
        //! 4： $Ywssjgh :业务所属机构号（5位）\\
        //! 5： Length: 流水号长度
        //!
        //!规则(14位 15位 16为)
        //
        //!1:不含进口LC     业务品种(2位) + 代办机构号(2位) + 时间(2位)+业务所属机构号（4位）+ 流水号(5)，共计15位
        //!1:含国内信用证   业务品种(2位) + 代办机构号(2位) + 时间(2位)+业务所属机构号（4位）+ 流水号(4)+到单次数(2)，共计16位
        //hnxtiaozheng
        //!2:不含进口LC     业务品种(2位) + 时间(2位)+业务所属机构号（5位）+ 流水号(5)，共计14位
        //!2:含国内信用证   业务品种(2位) + 时间(2位)+业务所属机构号（5位）+ 流水号(4)+到单次数(2)，共计15位
        //
        //!重新调整为
        //!3:不含进口LC     业务所属机构号（5位）+业务品种(2位) + 时间(2位) + 代办机构号(2位) + 流水号(5)，共计16位
        //!3:含信用证   业务所属机构号（5位）+业务品种(2位) + 时间(2位)+ 代办机构号(2位) + 流水号(3)+到单次数(2)，共计16
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        String ref = "";
        String datTxt1 = Formats.format(Dates.today(), "YY");
        String dbjgtxt = SettleContext.getUserSession().getBch().getBchflg();
        String ywssjgh = SettleContext.getUserSession().getWrkbch().getBranch();
        ref = ywssjgh + stRnTbl + datTxt1 + dbjgtxt + MdaUtils.toString(counterService.dbCounter(stRnTbl + ywssjgh + datTxt1), -nLen);
        return ref;

    }

    @Override
    public void getPtyAccMng(String ptyinr, String argPtspta, String rol, String fileds, Argument<String> accmng, Argument<String> hdbch) {
        //!获取对应的rol对象的ID数据
        //!=====================================================
        //!根据客户信息返回客户的客户经理编号及客户经理所在部门
        //!变量:
        //!accmng  客户经理编号
        //!hdbch   客户经理所属部门
        //!=====================================================
        String resusr = "";
        String vhdbch = "";
        String sql = NULLSTR;
        int err = 0;
        if (!MdaUtils.isEmpty(ptyinr)) {
//            sql = "SELECT resusr,hdbch FROM PTY WHERE INR = '" + Strings.trim(ptyinr) + "'";

            Pty pty = ptyCacheService.getPtyById(Strings.trim(ptyinr));
            if (Objects.nonNull(pty)) {
                resusr = pty.getResusr();
//                vhdbch = pty.gethdbch();
            }
        }
        accmng.value = resusr;
        hdbch.value = vhdbch;
    }

    public boolean sptIsLoaded(String arg, String sptState) {
        //! Function to check whether one of the passed SPT status is loaded
        //! Arg holds a single SPT status or a blank delimited list of multiple SPT status to be checked
        //! If any of the passed status is set the routine returns true
        //!
        //! Usually the symbolic name used to identify the SPT status should be used on call.
        //! (eg. SptIsLoaded( SptAfterDeletion + " " + SptAfterRejection ) )
        String varg = NULLSTR;
        if (MdaUtils.isEmpty(sptState)) {
            return false;
        } else {
            varg = " " + arg + " ";
            if (Strings.pos(varg, " " + sptState + " ") > 0) {
                return true;
            } else {
                return false;
            }
        }

    }

    public void getxxdfields(String xxd, String infileds, String inr, String flg, Argument<String> fields) {
        //取得上下文
//        IContext ctx = MdaEnv.getContext();
//        ctx.setErrorCode(NO_ERROR);
        //>>> ZL---大集中改造中取表字段BCHKEY BRANCH INR---------
        // FLG: 区分标志    I:表示要取BCH的INR,   Y表示取BCH的除了INR的字段
        // XXD: 要查的表的名称
        // INR: 提供查表的条件字段的值
        // FIELDS: 输出字段的值
        //<<< ZL-------------------------------------------
//        String fileds = NULLSTR;
//        Argument<String> _filedsBox = Argument.box(fileds);
        if (MdaUtils.compareTo(flg, "I") == 0) {
//            fileds = "";
//            ctx.getDaoSession().dbExecuteSQL("select " + infileds + " from " + xxd + " where inr='" + inr + "' ");
            String sql = "select " + infileds + " from " + xxd + " where inr='" + inr + "' ";
            String item = publicMapper.dyncQueryStr(ImmutableBiMap.of("sql", sql));
            if (item != null) {
//                ctx.getDaoSession().dbFetchFields("",_filedsBox);
//                fileds = _filedsBox.value;
//                if( fileds != null )
//                {
//                    fields.value = fileds;
//                }
//                else
//                {
                fields.value = item;
//                }
            } else {
                fields.value = "";
            }
//            ctx.getDaoSession().dbCloseCursor();
        }
        if (MdaUtils.compareTo(flg, "Y") == 0) {
//            fileds = "";
//            ctx.getDaoSession().dbExecuteSQL("select " + infileds + " from " + xxd + " where BRANCH='" + inr + "' ");
            String sql = "select " + infileds + " from " + xxd + " where BRANCH='" + inr + "' ";
            String item = publicMapper.dyncQueryStr(ImmutableBiMap.of("sql", sql));
            if (item != null) {
//                ctx.getDaoSession().dbFetchFields("",_filedsBox);
//                fileds = _filedsBox.value;
//                if( fileds != null )
//                {
//                    fields.value = fileds;
//                }
//                else
//                {
                fields.value = item;
//                }
            } else {
                fields.value = "";
            }
//            ctx.getDaoSession().dbCloseCursor();
        }
        if (MdaUtils.compareTo(flg, "A") == 0) {
//            fileds = "";
//            ctx.getDaoSession().dbExecuteSQL("select " + infileds + " from " + xxd + " where ACCBCH='" + inr + "' ");
            String sql = "select " + infileds + " from " + xxd + " where ACCBCH='" + inr + "' ";
            String item = publicMapper.dyncQueryStr(ImmutableBiMap.of("sql", sql));
            if (item != null) {
//                ctx.getDaoSession().dbFetchFields("",_filedsBox);
//                fileds = _filedsBox.value;
//                if( fileds != null )
//                {
//                    fields.value = fileds;
//                }
//                else
//                {
                fields.value = item;
//                }
            } else {
                fields.value = "";
            }
//            ctx.getDaoSession().dbCloseCursor();
        }

    }

    /**
     * source:sysmod.0176.script
     */
    public void sptSaveEntry(Spt argSpt, Object rec, String argSta, Object storeObj, String objName) {
        //! save ArgRec as item of passed type ArgSta
        //! if it is an module group, the whole group is stored
        //! all SaveData structure to be stored for SPT has to be set in ArgSptDatStm by caller
        //! ArgSpt holds the preloaded SPT
        //! ArgEtg holds the required entity group or blank if the current entity group shall be taken.
        //! ArgEty holds the required entity or blank if the current entity shall be taken.
        String sptLoaded = "";
        if (StringUtils.isNotEmpty(argSpt.getInr())) {
            sptLoaded = "X";
        } else {
            sptLoaded = "";
        }
        String frm = SettleContext.getTransName();
        // transaction for 4-eye`s has to be set anew
        if (StringUtils.isEmpty(argSpt.getFrm())
                || SptWaitForProcessing.equals(argSpt.getSta())) {
            if (StringUtils.isNotEmpty(argSpt.getDelflg())) {
                argSpt.setFrm(Strings.mid(frm, 1, 2) + "A" + Strings.mid(frm, 4, 5));
            } else {
                argSpt.setFrm(frm);
            }
        }
        argSpt.setCretrn(frm);
        if (!("COR".equals(argSta) || "CTR".equals(argSta) || "REJ".equals(argSta) || "HNH".equals(argSta))) {
            argSpt.setUsr(SettleContext.getUserSession().getUsr().getExtkey());
        }
        if (StringUtils.isEmpty(argSpt.getOwnusg())) {
            // Load Workgroup, if field available in USR table
            argSpt.setOwnusg(SettleContext.getUserSession().getUsr().getUsg());
        }
        argSpt.setDattim(Dates.now());
        // argSpt.setSsninr(SettleContext.getUserSession().getSsn().getInr());
        if (MdaUtils.isEmpty(argSpt.getObjtyp())) {

            if (!MdaUtils.isEmpty(rec)) {
                argSpt.setObjtyp(Utils.recGetObj(rec));
                argSpt.setObjinr(Utils.recGetInr(rec));
            }
        }
        if (StringUtils.isNotEmpty(objName)) {
            argSpt.setObjnam(objName);
        }
        if (MdaUtils.isEmpty(argSpt.getTxt())) {
//            argSpt.setTxt(getTrnnam(frm));
        }
        argSpt.setSta(argSta);
        argSpt.setEtgextkey(SettleContext.getUserEtg().getExtkey());
        argSpt.setEtyextkey(SettleContext.getUserEty().getExtkey());
        if (null != rec) {
            String ref = Utils.getFieldValue(rec, "ownref");
            argSpt.setObjref(ref);
        }
        if (MdaUtils.isEmpty(argSpt.getInr())) {
            // Use explizit coded function instead of SdbInsert to avoid
            // Setting of the current entity / entitygroup
            argSpt.setInr(counterService.dbCounterFormat("SPT"));
            sptMapper.insert(argSpt);
            sptWriteLog(argSpt, "I");
        } else {
            sptWriteLog(argSpt, "U");
            sptMapper.updateByPrimaryKeySelective(argSpt);
        }
//        Utils.setFieldValue(storeObj, "spt", argSpt); //不用存入SPT到交易BO下面，影响收单行spt更新操作
        streamSaveInSubDir(storeObj, "delete", argSpt.getInr() + ".bak");
        // update/create que before SPT is cleared
        sptQueUpdate(argSpt);
    }

    /**
     * 后台服务专用bak文件生成,不进行spt插入
     */
    public void sptSaveEntryForBgService(Spt argSpt, Object rec, String argSta, Object storeObj, String objName) {


        //后台服务已经插入spt，这里只记录日志
        sptWriteLog(argSpt, "I");

//        Utils.setFieldValue(storeObj, "spt", argSpt); //不用存入SPT到交易BO下面，影响收单行spt更新操作
        streamSaveInSubDir(storeObj, "delete", argSpt.getInr() + ".bak");
        // update/create que before SPT is cleared
        sptQueUpdate(argSpt);
    }


    /**
     * source:sysmod.0137.script
     */
    public void sptDeleteEntry(Spt argSpt) {
        //! deletes pending item including fileimage.
        String file = NULLSTR;
        int ignore = 0;
        IStream sptStm = new StreamImpl();
        String sptInr = NULLSTR;
        if (!MdaUtils.isEmpty(argSpt.getInr())) {
            sptWriteLog(argSpt, "D");
            sptMapper.deleteByPrimaryKey(argSpt);
            // delete .BAK-File if available

            file = appEnv.getDataPath("delete", argSpt.getInr() + ".bak");
            if (Files.fileExists(file)) {
                Files.fileDelete(file);
            }
            // delete it in cache if available
            Streams.streamClear(sptStm);
//            Caches.cacheDelete(sptStm,"SYSMOD","SPTDATA",argSpt.getInr());
            // Keep the SPT\\INR as trigger to issue the DbFree later, when
            // DB-Transaction gets commited
            sptInr = argSpt.getInr();
            argSpt = new Spt();
            argSpt.setInr(sptInr);
            queUpdate("SPT", sptInr, " ", "D");
        } else {
            SettleExceptionUtils.sysDump("Delete of non existing SPT-Record with empty INR");
        }
    }

    @Override
    public void sptQueUpdate(Spt argSpt) {
        Date today = new Date();
        Que que = queMapper.selectByObjTypeInrSubId("SPT", argSpt.getInr(), null);
        if (que == null) {
            que = new Que();
            que.setObjtyp("SPT");
            que.setObjinr(argSpt.getInr());
        }
        switch (argSpt.getSta()) {
            case "COR":
            case "INC":
            case "REG":
            case "PEN":
            case "CMB":
            case "PUR":
                que.setCla(argSpt.getSta());
                que.setHldflg("");
                break;
            default:
                que.setHldflg("");
        }
        if (!MdaUtils.isEmpty(argSpt.getDelflg())) {
            que.setHldflg("D");
        }
        que.setBalflg("A");
        que.setBalcla("zzz");
        Utils.sdbEtySetRec(que, "QUE", argSpt.getEtgextkey(), argSpt.getEtyextkey());
        que.setConobjtyp(argSpt.getObjtyp());
        que.setConobjinr(argSpt.getObjinr());
        que.setObjnam(argSpt.getObjnam());
        que.setObjref(argSpt.getObjref());
        que.setTxt(argSpt.getTxt());
        que.setFrm(argSpt.getFrm());
        que.setRelamt(argSpt.getRelamt());
        que.setRelcur(argSpt.getRelcur());
        que.setUsg(argSpt.getOwnusg());
        que.setTardattim(today);
        que.setBranchinr(argSpt.getBranchinr());
        que.setBchkeyinr(argSpt.getBchkeyinr());
        Bch accBch = SettleContext.getUserSession().getBch();
        que.setAccbchinr(accBch != null ? accBch.getInr() : "");
        Ord ord = ordMapper.selectByOrdInr(argSpt.getOrdinr());
        if (ord != null) {
            que.setSdhflg(ord.getSdhflg());
            que.setOrdinr(ord.getInr());
        }
        Bch bch = bchService.getByBranch("1000");//总行机构
        if (StringUtils.isEmpty(que.getBchkeyinr())) {
            que.setBchkeyinr(bch.getInr());
        }
        if (StringUtils.isEmpty(que.getBranchinr())) {
            que.setBranchinr(que.getBchkeyinr());
        }
        que.setObjref(argSpt.getObjref());
        que.setCreateTime(today);
        que.setUpdateTime(today);
        que.setUsrcon(argSpt.getUsr());
        que.setCtmnam(argSpt.getCtmnam());
        if ("Y".equals(argSpt.getHldflg())) {//隐藏
            que.setStatus(TaskStatus.NEW.getValue());
            que.setCla("RIM");  //注册中心
            que.setHldflg("D");
            que.setFlowstatus(TaskFlowStatus.HEADQUARTER_SDH_HANDLE.getValue());
        } else {
            que.setStatus(TaskStatus.PENDING.getValue());
            que.setCla("PEN");
            Bch orgBch = SettleContext.getUserSession().getOrgBch();
            if ("1000".equals(orgBch.getBranch())) {
                que.setFlowstatus(TaskFlowStatus.HEADQUARTER_HANDLE.getValue());
            } else {
                que.setFlowstatus(TaskFlowStatus.BRANCH_HANDLE.getValue());
            }
        }
        // 行内划转专用
        if ("HNH".equalsIgnoreCase(argSpt.getSta())) {
            que.setStatus(TaskStatus.INCOMING.getValue());
            que.setCla("HNH");
            que.setUsrcon("");
        }
        // 独立申报
        if ("BOP".equalsIgnoreCase(argSpt.getSta())) {
            que.setStatus(TaskStatus.PENDING_DECLARATION.getValue());
            que.setCla("BOP");
        }
        if (StringUtils.isEmpty(que.getChannel())) {
            que.setChannel(getChannelFromSta(argSpt));
        }
        if (MdaUtils.isEmpty(que.getInr())) {
            if (!(MdaUtils.compareTo(que.getHldflg(), "D") == 0)) {
                if (MdaUtils.compareTo(que.getCla(), "INC") == 0) {
                    if (!MdaUtils.isEmpty(argSpt.getSmhinr())) {
                        Smh smh = new Smh();
                        smh.setInr(argSpt.getSmhinr());
                        smh = smhMapper.selectByPrimaryKey(smh);
                        if (smh != null) {
                            que.setAddref("MT " + smh.getMsgtyp());
                           /* if (MdaUtils.isEmpty(que.getObjref())) {
                                que.setObjref(smh.getSndkey());
                            }*/
                        }
                    }
                }
            }
            que.setInr(counterService.dbCounterFormat("QUE"));
            que.setCreateTime(today);
            que.setUpdateTime(today);
            que.setCortyp(argSpt.getCortyp());
            que.setFrontchannel(argSpt.getFrontchannel());
            queMapper.insert(que);
            if (!Objects.equals(que.getHldflg(), "D") && !Objects.equals(que.getCla(), QueClaStatus.PEN.getValue())) {
                //HLDFLG为D时不需要调用
                taskDistService.handleTaskEnqueue(que);
            }
        } else {
            queMapper.updateByPrimaryKeySelective(que);
        }

    }

    public String getChannelFromSta(String sta) {
        String channel = "";
        switch (sta) {
            case "INC":
                channel = "SWT";
                break;
            case "YPT":
                channel = "YPT";
                break;
            case "EJS":
                channel = "EJS";
                break;
        }
        return channel;
    }

    public String getChannelFromSta(Spt spt) {
        String channel = "";
        switch (spt.getSta()) {
            case "INC":
                if (!"SWT".equals(spt.getChannel())) {
                    channel = spt.getChannel();
                } else {
                    channel = "SWT";
                }
                break;
            case "YPT":
                channel = "YPT";
                break;
            case "EJS":
                channel = "EJS";
                break;
        }
        if (StringUtils.isEmpty(channel) && !StringUtils.isEmpty(spt.getTxt()) && spt.getTxt().length() == 3) {
            channel = spt.getTxt();
        }
        if (StringUtils.isEmpty(channel)) {
            channel = spt.getChannel();
        }
        return channel;
    }

    public boolean isIncomingSptsta(String sta) {
        if ("-INC-EJS-YPT-FMT-HVP-HVQ-HVR-BEP-BEQ-BES-CIU-CIV-CIW".indexOf(sta) > 0) {
            return true;
        }
        return false;
    }

    public void sptWriteLog(Spt argSpt, String argFu) {
        String lin = argSpt.getObjtyp() + TAB + Strings.mid(argSpt.getObjinr(), 1, 16) + TAB + argSpt.getInr() + TAB + argFu + TAB + argSpt.getSta() + TAB + argSpt.getHldflg() + TAB + Formats.format(Dates.now(), "YY-MM-DD hh:mm:ss",/*Systems.getLang()*/"CN", tdContextTZSYSTEM) + TAB + "" + TAB + SettleContext.getTransName() + TAB + argSpt.getObjnam();
        log.info("sptWriteLog:{}", lin);
    }

    @Override
    public void streamSaveInSubDir(Object storeObj, String argDir, String argFil) {
        if ("true".equals(appEnv.getFileLocalFlag())) {
            this.streamSaveInSubDirLocal(storeObj, argDir, argFil);
            return;
        }
        argDir += "/" + getSubDirByFileName(argFil); //修改该长度时，注意argFile是带后缀的文件名xxx.dat
        String filPath = appEnv.getSubDataPath(argDir, argFil);
        // All errorcodes are exported to the caller
        //filPath = Strings.convertPrefix(filPath);
        File file = Files.mkdirs(filPath);
        String json = Utils.toPrettyJson(storeObj);
        boolean bool = objectStroeToolService.saveObjectFileByString(json, filPath, "");
        if (!bool) {
            throw new CommonServiceException("文件存储失败!");
        }
    }

    public void saveObjectJson(String argDir, String filePath, String json) {
        String filPath = appEnv.getSubDataPath(argDir, filePath);
        boolean bool = objectStroeToolService.saveObjectFileByString(json, filPath, "");
    }

    public String loadObjectJson(String argDir, String fileName) {
        String fulFileName = appEnv.getSubDataPath(argDir, fileName);
        byte[] fileByte = objectStroeToolService.readObjectFile(fulFileName);
        if (MdaUtils.isEmpty(fileByte))
            return "";
        return new String(fileByte);
    }

    @Override
    public void streamSaveInDir(Object storeObj, String argDir, String argFil) {
        if ("true".equals(appEnv.getFileLocalFlag())) {
            this.streamSaveInDirLocal(storeObj, argDir, argFil);
            return;
        }
        String filPath = appEnv.getSubDataPath(argDir, argFil);
        //filPath = Strings.convertPrefix(filPath);
        String json = "";
        if ((storeObj instanceof IStream)) {
            List<String> rows = ((IStream) storeObj).getRows();
            for (int i = 0; i < rows.size(); i += 2) {
                if (StringUtils.isEmpty(rows.get(i)))
                    continue;
                if (StringUtils.isEmpty(json)) {
                    json = rows.get(i);
                } else {
                    json = json + "\n" + rows.get(i);
                }
                json = json + "\n" + rows.get(i + 1);
            }
        } else {
            json = Utils.toPrettyJson(storeObj);
        }

        boolean bool = objectStroeToolService.saveObjectFileByString(json, filPath, "");
        if (!bool) {
            throw new CommonServiceException("文件存储失败!");
        }
    }

    /**
     * 是否存在spt文件
     *
     * @param argDir
     * @param argFil
     * @return
     */
    public boolean existSptFile(String argDir, String argFil) {
        argDir += "/" + getSubDirByFileName(argFil);
        String filPath = appEnv.getSubDataPath(argDir, argFil);
        File file = objectStroeToolService.getObjectFile(filPath);
        return file != null;
    }

    public <T> T streamLoadInSubDir(Class<T> clazz, String argDir, String argFil) {
        if ("true".equals(appEnv.getFileLocalFlag())) {
            return this.streamLoadInSubDirLocal(clazz, argDir, argFil);
        }
        try {
            argDir += "/" + getSubDirByFileName(argFil);
            String filPath = appEnv.getSubDataPath(argDir, argFil);
            File file = objectStroeToolService.getObjectFile(filPath);
            String dataString = FileUtils.readFileToString(file, "UTF-8");
            return Utils.toObject(clazz, dataString);
        } catch (IOException e) {
            throw new CommonServiceException("加载文件失败![" + e.getMessage() + "]");
        }
    }

    public <T> T streamLoadInDir(Class<T> clazz, String argDir, String argFil) {
        if ("true".equals(appEnv.getFileLocalFlag())) {
            return this.streamLoadInDirLocal(clazz, argDir, argFil);
        }

        try {
            String filPath = appEnv.getSubDataPath(argDir, argFil);
            File file = objectStroeToolService.getObjectFile(filPath);
            String dataString = FileUtils.readFileToString(file, "UTF-8");
            return Utils.toObject(clazz, dataString);
        } catch (IOException e) {
            throw new CommonServiceException("加载文件失败![" + e.getMessage() + "]");
        }
    }


    /**
     * source:sysmod.0805.script
     */
    public String getTrnnam(String transName) {
        return codetableService.getTblLabel(transName, "ATPTXT");
    }

    public String getObjnam(Object obj) {
        String objnam = "";
        Object ownrefObj = Utils.getFieldValue(obj, "ownref");
        Object namObj = Utils.getFieldValue(obj, "nam");
        if (ownrefObj != null) {
            objnam = ownrefObj.toString();
        }
        if (namObj != null) {
            if (objnam.length() == 0) {
                objnam = namObj.toString();
            } else {
                objnam += "/" + namObj.toString();
            }
        }
        return objnam;
    }

    public String getProcessBranchinr() {
        SettleSession session = SettleContext.getUserSession();
        if (session.getBch() != null) {
            return session.getBch().getInr();
        }
        return "";
        //----得到实际的记账机构--------------
        //----规则:如果机构安装TC即为TID编号,否则为BCHKEY
//        String bchkinr = "";
//        if (!MdaUtils.isEmpty(session.getWrkbch().getTid())) {
//            Argument<String> bchkinrBox = new Argument<String>("", bchkinr);
//            ctx.absGet(Sysmod.class).getxxdfields("BCH", "INR", ctx.absGet(Sysmod.class).getWrkbch().getTid(), "Y", bchkinrBox);
//            bchkinr = bchkinrBox.value;
//        } else {
//            if (!MdaUtils.isEmpty(ctx.absGet(Sysmod.class).getWrkbch().getBchkey())) {
//                Argument<String> bchkinrBox1 = new Argument<String>("", bchkinr);
//                ctx.absGet(Sysmod.class).getxxdfields("BCH", "INR", ctx.absGet(Sysmod.class).getWrkbch().getBchkey(), "Y", bchkinrBox1);
//
//                bchkinr = bchkinrBox1.value;
//
//            } else {
//                Argument<String> bchkinrBox2 = new Argument<String>("", bchkinr);
//                ctx.absGet(Sysmod.class).getxxdfields("BCH", "INR", ctx.absGet(Sysmod.class).getBch().getBranch(), "Y", bchkinrBox2);
//
//                bchkinr = bchkinrBox2.value;
//
//            }
//        }
        /*String condition = NULLSTR;
        if (StringUtils.isEmpty(condition) && !Objects.isNull(session.getWrkbch())) {
            condition = StringUtils.isEmpty(session.getWrkbch().getTid()) ? session.getWrkbch().getBchkey() : session.getWrkbch().getTid();
        }
        if(StringUtils.isEmpty(condition)){
            condition = session.getBch().getBranch();
        }
        String sql = String.format("select INR from BCH where BRANCH='%s'", condition);
        String bchkinr = publicMapper.dyncQueryStr(ImmutableBiMap.of("sql",sql));
        return bchkinr;*/
    }

    public void sdbInsert(Object argRec) {
        Utils.setFieldValue(argRec, "inr", counterService.dbCounterFormat(Utils.getBoType(argRec)));
        Utils.setFieldValue(argRec, "ver", "0000");
        Utils.setFieldValue(argRec, "etyextkey", SettleContext.getUserEty().getExtkey());
        Utils.setFieldValue(argRec, "etgextkey", SettleContext.getUserEtg().getExtkey());
        dyncDaoService.dyncInsert(argRec);
    }

    public void sdbDeleteWithLog(Object argRec) {
//        Utils.setFieldValue(argRec, "inr", counterService.dbCounterFormat(Utils.getBoType(argRec)));
//        Utils.setFieldValue(argRec, "etyextkey", SettleContext.getUserEty().getExtkey());
//        Utils.setFieldValue(argRec, "etgextkey", SettleContext.getUserEtg().getExtkey());
        log.info("准备删除的对象，{} = {}", argRec.getClass().getSimpleName(), argRec);
        dyncDaoService.dyncDeleteByPrimaryKey(argRec);
        sdbSlgWrite(argRec, "D");
    }

    public void sdbInsertWithLog(Object argRec) {
        String objType = Utils.getBoType(argRec);
        //NID用GID的Counter
        if ("NID".equalsIgnoreCase(objType)) {
            objType = "GID";
        } else if ("NCD".equalsIgnoreCase(objType)) {
            objType = "GCD";
        }
        Utils.setFieldValue(argRec, "inr", counterService.dbCounterFormat(objType));
        Utils.setFieldValue(argRec, "ver", "0000");
        Utils.setFieldValue(argRec, "etyextkey", SettleContext.getUserEty().getExtkey());
        Utils.setFieldValue(argRec, "etgextkey", SettleContext.getUserEtg().getExtkey());
        dyncDaoService.dyncInsert(argRec);
        sdbSlgWrite(argRec, "I");
    }

    public void sdbUndeleteWithLog(Object argRec) {
        String ver = Utils.getFieldValue(argRec, "ver");
        int version = 0;
        if (StringUtils.isNotEmpty(ver)) {
            version = Integer.parseInt(ver);
        }
        Utils.setFieldValue(argRec, "ver", String.format("%04d", version + 1));
        Utils.setFieldValue(argRec, "etyextkey", SettleContext.getUserEty().getExtkey());
        Utils.setFieldValue(argRec, "etgextkey", SettleContext.getUserEtg().getExtkey());
        dyncDaoService.dyncInsert(argRec);
        sdbSlgWrite(argRec, "I");
    }

    public void sdbUpdateWithLog(Object argRec) {
        String ver = Utils.getFieldValue(argRec, "ver");
        if (org.apache.commons.lang3.StringUtils.isBlank(ver))
            ver = "0000";
        int version = Integer.parseInt(ver);
        Utils.setFieldValue(argRec, "ver", String.format("%04d", version + 1));
        dyncDaoService.dyncUpdateByPrimaryKeySelective(argRec);
        sdbSlgWrite(argRec, "U");
    }

    /**
     * 用于回滚业务数据 不需要更改版本号
     *
     * @param argRec
     */
    public void sdbUpdateWithLog2(Object argRec) {
        dyncDaoService.dyncUpdateByPrimaryKey(argRec);
        sdbSlgWrite(argRec, "U");
    }

    @Override
    public void sdbUpdate(Object argRec) {
        dyncDaoService.dyncUpdateByPrimaryKeySelective(argRec);
    }

    public Object sdbRead(Object obj) {
        String inr = Utils.getFieldValue(obj, "inr");
        try {
            Class clazz = Class.forName(obj.getClass().getName());
            return dyncDaoService.dyncReadByInr(clazz, inr);
        } catch (ClassNotFoundException e) {
            throw new CommonServiceException("找不到对应的类!");
        }
    }

    public void sdbSlgWrite(Object logMod, String fct) {
        //! Internal routine to write the log record for any type of record or recordgroup.
        //! LogMod holds the record or recordgroup to be stored.
        //! The record has to include the fields INR to identify the entry and VER to count the version.
        //! Fct holds the function code used in SLG (`U`pdate, `I`nsert, `D`elete)
//        String recPath = Platform.recGetPath(logMod);
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Sysmod.class).getSlg().setLoginr( Datas.getContent(null,recPath + "\\INR"));
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Sysmod.class).getSlg().setLogtyp( MdaDriver.getModuleInfo(MdaDriver.getModule(recPath),tdModuleInfoClass));
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Sysmod.class).getSlg().setVer( Datas.getContent(null,recPath + "\\VER"));
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Sysmod.class).getSlg().setDattim( Dates.now());
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Sysmod.class).getSlg().setUsr( SettleContext.getUserSession().getUsr().getExtkey());
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Sysmod.class).getSlg().setFct( fct);
//        Platform.sdbInsert(ctx.absGet(com.ceb.gjjs.mda.manager.module.Sysmod.class).getSlg());
//        Systems.setContext("SAVEDATASKIPEMPTY",true);
//        // save the main record
//        IStream logStm = new StreamImpl();
//        Datas.saveData(logMod,logStm);
//        // try to get additional data to be saved in log as well
//        IStream tmpStm = new StreamImpl();
//        Streams.streamClear(tmpStm);
//        Caches.cacheRead(tmpStm,ctx.getTransName(),"SlgConfig",Platform.recGetPath(logMod));
//        int max = 0;
//        String lin = NULLSTR;
//        int pos = 0;
//        String recPth = NULLSTR;
//        String section = NULLSTR;
//        IModule vlogMod = null;
//        if( ctx.getErrorCode() == 0 )
//        {
//            max = Streams.streamCount(tmpStm);
//            for(int  idx = 1;idx <= max;idx++)
//            {
//                lin = Strings.getLine(tmpStm,idx);
//                pos = Strings.pos(lin,TAB);
//                recPth = Strings.mid(lin,1,pos - 1);
//                section = Strings.mid(lin,pos + 1);
//                vlogMod = MdaDriver.getModule(recPth);
//                if( ctx.getErrorCode() <= 0 )
//                {
//                    Datas.saveData(vlogMod,logStm,section);
//                }
//            }
//        }
//        // save the log file with collected data
//        Platform.streamSaveInSubDir(logStm,"LOG",ctx.absGet(com.ceb.gjjs.mda.manager.module.Sysmod.class).getSlg().getInr() + ".DAT");
//        Systems.setContext("SAVEDATASKIPEMPTY",false);

        Slg slg = new Slg();
        slg.setLoginr(Utils.getFieldValue(logMod, "inr"));
        slg.setLogtyp(Utils.getBoType(logMod));
        slg.setVer(Utils.getFieldValue(logMod, "ver"));
        slg.setDattim(Dates.now());
        slg.setUsr(SettleContext.getUserSession().getUsr().getExtkey());
        slg.setFct(fct);
        slg.setInr(counterService.dbCounterFormat("SLG"));
        dyncDaoService.dyncInsert(slg);

    }

    /**
     * source:sysmod.0209.script
     */
    public Pty getPtyobj(String rol, List<PtsptaVo> ptsList) {
        //>>> ZL---面函移植改造中取PTY表字段的值------------
        // ROL: 输入的角色如：APL表示申请人，BEN表示收益人
        // ptyfileds: 要查的PTY表的字段名称
        // ptyval: 输出该ptyfileds字段的值
        //<<< ZL-------------------------------------------
        String name = Strings.mid(SettleContext.getTransName(), 1, 2);
        //进口保函和出口保函用同一个GID表------------------
        if (MdaUtils.compareTo(name, "GE") == 0) {
            name = "GI";
        }
        //----DZTEST----
        /**
         //国内信用证
         if $name == "DI" then
         $name = "LI"
         endif
         if $name == "DE" then
         $name = "LE"
         endif
         if $name == "BD" then
         $name = "BR"
         endif
         if $name == "BF" then
         $name = "BE"
         endif
         **/
        String inr = "";
        if (MdaUtils.compareTo(Strings.mid(SettleContext.getTransName(), 4, 3), "FRE") == 0) {
            PtsptaVo ptspta = ptsptaToolComponent.getPtsFromListByRol(ptsList, "OTHCC");
            if (ptspta != null) {
                inr = ptspta.getPtyinr();
            }
        } else {
            if (!MdaUtils.isEmpty(rol)) {
                PtsptaVo ptspta = null;
                if (MdaUtils.compareTo(SettleContext.getTransName(), "LITROG") == 0) {
                    ptspta = ptsptaToolComponent.getPtsFromListByRol(ptsList, rol);
                    if (ptspta != null) {
                        inr = ptspta.getPtyinr();
                    }
                } else {
                    ptspta = ptsptaToolComponent.getPtsFromListByRol(ptsList, rol);
                    if (ptspta != null) {
                        inr = ptspta.getPtyinr();
                    }
                }
            }
        }
        if (!MdaUtils.isEmpty(inr)) {
            return ptyCacheService.getPtyById(inr);
        }
        return null;
    }

    /**
     * source:sysmod.0178.script
     */
    public void queUpdate(String argOBJTYP, String argOBJINR, String argOBJSUBID, String argHLDFLG) {
        //! Release or (logically) delete specified QUE entry / entries
        //! if argOBJSUBID ="*" entries for all OBJSUBIDs are deleted/released
        Que que = new Que();
        que.setHldflg(argHLDFLG);
        // que.setHldssninr(SettleContext.getUserSession().getSsn().getInr());
        que.setHlddattim(Dates.now());
        que.setObjtyp(argOBJTYP);
        que.setObjinr(argOBJINR);
        que.setOldstatus(que.getStatus());
        que.setStatus(CommonContants.QUE_STATUS_PENDING);
        if (MdaUtils.compareTo(argOBJSUBID, "*") == 0) {
            //Platform.dbExecuteSQL( "UPDATE QUE SET HLDFLG=?, HLDSSNINR=?, HLDDATTIM=? where OBJTYP = ? and OBJINR = ?", argHLDFLG, $\\sysmod\\ssn\\inr.getValue(), Platform.now(), argOBJTYP, argOBJINR );
            queMapper.updateHlddattimbyObjInr(que);
        } else {
            //Platform.dbExecuteSQL( "UPDATE QUE SET HLDFLG=?, HLDSSNINR=?, HLDDATTIM=? where OBJTYP = ? and OBJINR = ? and OBJSUBID = ?", argHLDFLG, $\\sysmod\\ssn\\inr.getValue(), Platform.now(), argOBJTYP, argOBJINR, argOBJSUBID );
            que.setObjsubid(argOBJSUBID);
            queMapper.updateHlddattimbyObjInr(que);
        }
    }

    /**
     * source:sysmod.0258.script
     */
    public void sweSaveEntry(Trn trn, Spt spt, String argSta, String sptinr, String trninr) {
        //break 或者 repair 或者 save时更新swe表
        //仅针对清算报文进行处理
        // ArgSta 清算报文处理状态
        // arginr SPT\\INR
        //如果读到记录说明此业务源头为清算报文
        Swe swe = null;
        if (!MdaUtils.isEmpty(trninr)) {
            swe = sweMapper.getSweByTrninr(trninr);
        } else {
            swe = sweMapper.getSweBySptinr(sptinr);
        }
        if (swe == null) {
            log.warn("读不到swe表信息");
            return;
        }
        swe.setSta(argSta);
        swe.setIniusr(SettleContext.getUserSession().getUsr().getExtkey());
        switch (argSta) {
            case "PEN":
                swe.setOwnref(spt.getOwnref());
                break;
            case "SAV":
                swe.setObjtyp(trn.getObjtyp());
                swe.setObjinr(trn.getObjinr());
                swe.setOwnref(trn.getOwnref());
                swe.setTrninr(trn.getInr());
                swe.setSptinr("");
                break;
            case "DON":
            case "REL":
                break;
            case "COR":
            case "REJ":
                swe.setTrninr("");
                swe.setSptinr(sptinr);
                break;
            case "DEL":
                break;
        }
        sweMapper.updateByPrimaryKeySelective(swe);
    }

    /**
     * source:sysmod.0304.script
     */
    public void msgSaveEntry(Trn trn, Spt spt, String argSta, String sptinr, String trninr) {

        //break 或者 repair 或者 save时更新swe表
        //仅针对清算报文进行处理
        // ArgSta 清算报文处理状态
        // arginr SPT\\INR
        //如果读到记录说明此业务源头为清算报文
        Msg msg = null;
        if (!MdaUtils.isEmpty(trninr)) {
            msg = msgMapper.getMsgByTrninr(trninr);
        } else {
            msg = msgMapper.getMsgBySptinr(sptinr);
        }
        if (msg == null) {
            log.warn("读不到msg表信息");
            return;
        }
        msg.setSta(argSta);
        switch (argSta) {
            case "PEN":
                msg.setOwnref(spt.getOwnref());
                break;
            case "SAV":
                // msg\\OBJTYP = GetContent( "\\\\TRNMOD\\\\TRN\\\\objtyp" )
                // msg\\OBJINR = GetContent( "\\\\TRNMOD\\\\TRN\\\\objinr" )
                msg.setOwnref(trn.getOwnref());
                msg.setTrninr(trn.getInr());
                msg.setSptinr("");
                break;
            case "DON":
            case "REL":
                break;
            case "COR":
            case "REJ":
                msg.setTrninr("");
                msg.setSptinr(sptinr);
                break;
            case "DEL":
                break;
        }
        msgMapper.updateByPrimaryKeySelective(msg);
    }

    /**
     * source:sysmod.0250.script
     */
    public String getOwnRef(Bch wrkBch, String businessType, String tbl) {
        if (wrkBch == null) {
            return "";
        }
        //businessType + bchref + YY + sequence(4) + bchflg
        String branch = wrkBch.getBchref();
        String ref = businessType + branch + Utils.fmtDate(Dates.today(), "yy") + counterService.dbCounterFormat((tbl + branch).toUpperCase(), 4) + wrkBch.getBchflg();
        return ref;

    }

    /**
     * source:sysmod.0174.script
     */
    public void sptUpdateInDb(Spt spt, String sta) {
        //! update ArgSpt in database and write the log entry
        //! optionally sets status of stored SPT if nonempty ArgSta is passed
        if (!MdaUtils.isEmpty(sta)) {
            spt.setSta(sta);
        }
        sptWriteLog(spt, "U");
        sptMapper.updateByPrimaryKeySelective(spt);
        // update/create que before SPT is cleared
        sptQueUpdate(spt);
    }

    /**
     * source:sysmod.0266.script
     */
    public boolean isSwtRelNov2018Active() {
        //! Function to check whether the Swift Release November 2018 is active
        //! the activation date can be entered in DNGPARA.INI (via DBITDP)
        //! Date effictive of the update is 18th November 2018
        // DO5DOS.010108
        // DNGDEV.000291 für SR2018
        String sftTxt = Utils.cacheGetIniStr(AppIniFile, "System", "SwiftRelNov2018Activation");
        Date sftRelDat = null;
        if (sftTxt != null) {
            sftRelDat = Utils.parseDate(sftTxt, "yyyy-MM-dd");
        }

        if (MdaUtils.isEmpty(sftRelDat)) {
            sftRelDat = Utils.parseDate("2018-11-18");
        }
        return Dates.diff(sftRelDat, Dates.today()) <= 0;
    }

    /**
     * source:sysmod.0200.script
     */
    public boolean isSwtRelNov2020Active() {
        //! Function to check whether the Swift Release November 2020 is active
        //! Date effictive of the update is November 16, 2020.
        // DNGDEV.001899 f眉r SR2020
        String sftTxt = Utils.cacheGetIniStr(AppIniFile, "System", "SwiftRelNov2020Activation");
        Date sftRelDat = null;
        if (sftTxt != null) {
            sftRelDat = Utils.parseDate(sftTxt, "yyyy-MM-dd");
        }
        if (MdaUtils.isEmpty(sftRelDat)) {
            sftRelDat = Utils.parseDate("2020-11-16");
        }
        return Dates.diff(sftRelDat, Dates.today()) <= 0;

    }

    public boolean isDomesticLC() {
        String frm = SettleContext.getTransName();
        if (Strings.pos("-DI-DE-BD-BF-", Strings.mid(frm, 1, 2)) > 0 || Strings.pos("-INFDID-INFDED-INFBDD-INFBFD-", frm) > 0) {
            return true;
        } else {
            return false;
        }

    }

    public boolean isRamSptLoaded() {
        if (SettleContext.getUserSession() == null || SettleContext.getUserSession().getSpt() == null) {
            return false;
        }
        String smhinr = SettleContext.getUserSession().getSpt().getSmhinr();
        if (org.apache.commons.lang3.StringUtils.isEmpty(smhinr)) {
            return false;
        }

        Smh smh = new Smh();
        smh.setInr(smhinr);
        Smh result = smhMapper.selectByPrimaryKey(smh);

        String crefrm = NULLSTR;
        if (result != null) {
            crefrm = result.getCrefrm();
        }
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(crefrm) && crefrm.length() >= 7) {
            crefrm = crefrm.substring(3, 6);
        }
        if ("RAM".equals(crefrm) || "AMR".equals(crefrm)) {
            return true;
        } else {
            return false;
        }
    }

    public String checkAllowCN(String attributeValue) {
        String errorInfo = NULLSTR;
        //!允许输入中文的栏位不允许输入双引号，否则导致发报失败 "
        String marks = "\"";
        int txtLen = Strings.len(attributeValue);
        String substr = NULLSTR;
        int pos = 0;
        for (int idx = 1; idx <= txtLen; idx++) {
            substr = Strings.mid(attributeValue, idx, 1);
            pos = Strings.pos(marks, substr);
            if (pos != 0) {
                errorInfo = MdaUtils.getI18NString("sysmod", "字符输入不合法");
                break;
            }
        }

        return errorInfo;
    }

    @Override
    public String getzmq(String branchinr) {
        //--客户所属机构的经办机构是否是自贸区来判断是否取自贸区牌价--
        String zmqflg = "";
        String bchkey = "";
        Bch bch = bchService.getByBchInr(branchinr);
        if (bch.getBchkey() != null) {
            bchkey = bch.getBchkey();
        }
//        sql = " select zmqflg FROM bch WHERE branch ='" + bchkey + "' ";
        Bch bch1 = new Bch();
        bch1.setBranch(bchkey);
        bch1 = bchService.getByBranch(bchkey);
        if (bch1 != null) {
            zmqflg = bch1.getZmqflg();
        }
        return zmqflg;
    }

    /**
     * 保存业务对应的经办机构和业务所属机构
     *
     * @Rule(target="usrcon",order=499)
     */
    public void setRecBchInfo(Object rec, Bch bch, Bch wrkbch) {
        Utils.setFieldValue(rec, "bchkeyinr", Optional.ofNullable(bch).map(bh -> bh.getInr()).orElse(""));
        Utils.setFieldValue(rec, "branchinr", Optional.ofNullable(wrkbch).map(wh -> wh.getInr()).orElse(""));
    }


    @Override
    public int callInterface(String facename, String trninr, String itfInr, Argument<String> errtxt) {
        return 0;
    }

    /**
     * source:mtabut.0028.script
     */
    public String getReferenceOfRol(List<PtsptaVo> ptsptas, String rol, Object rec) {
        String res = "";
        PtsptaVo ptsptaVo = ptsptaToolComponent.getPtsFromListByRol(ptsptas, rol);
        if (ptsptaVo != null) {
            res = ptsptaVo.getRef();
        }
        if (StringUtils.isEmpty(res)) {
            res = Utils.getFieldValue(rec, rol + "ref");
        }
        if (StringUtils.isEmpty(res)) {
            res = "NONREF";
        }
        return res;
    }

    /**
     * source:sysmod.0136.script
     */
    public <T> T sptLoadData(Class<T> clazz, String sptinr) {
        String fileName = sptinr + ".bak";
        return streamLoadInSubDir(clazz, "delete", fileName);
    }

    public <T> T streamGetNameInSubDir(Class<T> clazz, String trninr) {
        String fileName = trninr + ".dsp";
        return streamLoadInSubDir(clazz, "display", fileName);
    }

    public <T> T streamGetDataFromDir(Class<T> clazz, String prefix, String argInr) {
        String fileName = argInr + ".dat";
        return streamLoadInSubDir(clazz, prefix, fileName);
    }

    /**
     * source:sysmod.0226.script
     */
    public void saveSprData(Spt spt, BaseTransactionVo storeObj) {
        Spr spr = new Spr();
        spr.setSptinr(spt.getInr());
        spr.setObjtyp(spt.getObjtyp());
        spr.setObjinr(spt.getObjinr());
        spr.setCredat(Dates.today());
        spr.setCretim(Numerics.time(4));
        spr.setCreusr(SettleContext.getUserSession().getUsr().getExtkey());
        // spr.setCressninr(SettleContext.getUserSession().getSsn().getInr());
        // RELLEV holds the result of the last call to SprGetRelLev
        spr.setRellev("X");
        spr.setInr(counterService.dbCounterFormat("SPR"));
        sprMapper.insert(spr);
        //存储快照数据
        streamSaveInSubDir(storeObj, "sprdsp", spr.getInr() + ".dsp");
    }


    public boolean isSdhBusiness() {
        return SettleContext.getUserSession().isSdhTransaction();
    }

    public boolean isSdhBusiness(String inifrm) {
        Bch bch = SettleContext.getUserSession().getBch();
        Bch orgBch = SettleContext.getUserSession().getOrgBch();
        String branch = "";
        if ("1000".equals(orgBch.getBranch())) {
            return false;
        }
        if (bch != null) {
            branch = bch.getBranch();
        }
        Atpbch atpbch = atpbchMapper.selectByBranchAndInifrm(branch, inifrm);
        if (atpbch != null && Objects.equals(atpbch.getNegflg(), "X")) {
            return true;
        }
        return false;
    }

    public boolean isSdhBusiness(String inifrm, String branch) {
        Atpbch atpbch = atpbchMapper.selectByBranchAndInifrm(branch, inifrm);
        if (atpbch != null && Objects.equals(atpbch.getNegflg(), "X")) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isCenterTaken() {
        // 通过Registration进交易
        // 判断交易是否是单证中心Take收单行的业务
        boolean bool = false;
        Spt spt = SettleContext.getUserSession().getSpt();
        Bch bch = SettleContext.getUserSession().getBch();
        List<Trn> trnList = null;
        List<String> inrList = null;
        Trn seltrn = new Trn();
        //&& StringUtils.isNotEmpty(bch.getCorflg() )
        if ("RIM".equals(spt.getSta())) {
            Bch selbch = new Bch();
//            selbch.setUpbchkey(bch.getBranch());
//            List<Bch> bchList = bchMapper.selectByConditionList(selbch);
            selbch.setBranch(bch.getBranch());
            List<Bch> bchList = bchService.listByRecord(selbch);
            if (CollectionUtil.isNotEmpty(bchList)) {
                inrList = bchList.stream().map(Bch::getInr).collect(Collectors.toList());
            }

            seltrn.setObjinr(spt.getObjinr());
            seltrn.setObjtyp(spt.getObjtyp());
            seltrn.setInifrm(spt.getFrm());
            trnList = trnMapper.selectByConditionListBchkeyinr(seltrn, inrList);
        }

//判断满足是否为单证中心处理
        Assert.notNull(trnList);
        for (Trn item : trnList) {
            if ("A".equals(item.getRelflg())) {
                bool = true;
                break;
            }
        }
        if (bool)
            return true;
        else
            return false;
//         通过Correction进交易
//        判断是否有同样的一笔收单行上交并且Confirm的交易
//         单证中心与清算中心是同一个的情况下，有问题
//        if ("COR".equals(spt.getSta())  && !StringUtils.isEmpty( bch.getCorflg()) {
//            seltrn.setObjinr(spt.getObjinr());
//            seltrn.setObjtyp(spt.getObjtyp());
//            seltrn.getInifrm(spt.getFrm());
//            sql = "select trn1.relflg from trn trn1, trn trn2 where trn2.inr='" + spt.getObjinr()
//             + "' and trn1.objtyp=trn2.objtyp and trn1.objinr=trn2.objinr and trn1.inifrm = trn2.inifrm and trn1.bchkeyinr in (select inr from bch where upbchkey='"
//             + bch.getBranch() + "')";
//        }
    }

    /**
     * source:sysmod.0283.script
     *
     * @return
     */
    public Map<String, String> characterX(String resultKey, String argField) {
        Map<String, String> resultMap = new HashMap<>();
        //String tEXt = "";
        //int lin = Systems.getAttribute(argField,tdAttrLines);
        //int len = Systems.getAttribute(argField,tdAttrLength);
        String txt = argField;
        int len1 = Strings.len(Strings.convertBlock(txt, 11));
        int len2 = Strings.len(Strings.convertBlock(txt, 13));
        int lenChinese = (len2 - len1);
        int num = 0;
        IStream txtStm = new StreamImpl();
        String line = NULLSTR;
        int p = 0;
        if (lenChinese == 0) {
            num = 0;
            if (!MdaUtils.isEmpty(txt)) {
                Streams.streamSet(txtStm, txt);
                num = Streams.streamCount(txtStm);
            }
            if (num > 0) {
                for (int i = 1; i <= num; i++) {
                    line = Strings.getLine(txtStm, i);
                    if (!MdaUtils.isEmpty(line)) {
                        for (int j = 1; j <= Strings.len(line); j++) {
                            p = Strings.pos("[}|~$`^]#%&*=@", Strings.mid(line, j, 1));
                            if (p > 0) {
                                resultMap.put(String.valueOf(argField), MdaUtils.getI18NString("sysmod", "CT000655"));
                                //if(1==1) return resultMap;
                            }
                        }
                    } else {
                    }
                }
            }
        } else {
            resultMap.put(String.valueOf(argField), MdaUtils.getI18NString("sysmod", "CT000666"));
            MdaUtils.exitRule();
        }
        return resultMap;
    }

    public void streamSaveInSubDirLocal(Object storeObj, String argDir, String argFil) {
        argDir += File.separator + getSubDirByFileName(argFil);
        String filPath = appEnv.getDataPath(argDir, argFil);
        // All errorcodes are exported to the caller
        filPath = Strings.convertPrefix(filPath);
        File file = Files.mkdirs(filPath);
        String json = Utils.toPrettyJson(storeObj);
        try {
            FileUtils.writeStringToFile(file, json, "UTF-8");
        } catch (IOException e) {
            throw new CommonServiceException("文件存储失败![" + e.getMessage() + "]");
        }
    }

    public <T> T streamLoadInSubDirLocal(Class<T> clazz, String argDir, String argFil) {
        try {
            argDir += File.separator + getSubDirByFileName(argFil);
            String filPath = appEnv.getDataPath(argDir, argFil);
            File file = new File(filPath);
            String dataString = FileUtils.readFileToString(file, "UTF-8");
            return Utils.toObject(clazz, dataString);
        } catch (IOException e) {
            throw new CommonServiceException("加载文件失败![" + e.getMessage() + "]");
        }
    }

    public void streamSaveInDirLocal(Object storeObj, String argDir, String argFil) {
        String filPath = appEnv.getDataPath(argDir, argFil);
        filPath = Strings.convertPrefix(filPath);
        File file = Files.mkdirs(filPath);
        String json = Utils.toPrettyJson(storeObj);
        try {
            FileUtils.writeStringToFile(file, json, "UTF-8");
        } catch (IOException e) {
            throw new CommonServiceException("文件存储失败![" + e.getMessage() + "]");
        }
    }

    public <T> T streamLoadInDirLocal(Class<T> clazz, String argDir, String argFil) {
        try {
            String filPath = appEnv.getDataPath(argDir, argFil);
            File file = new File(filPath);
            String dataString = FileUtils.readFileToString(file, "UTF-8");
            return Utils.toObject(clazz, dataString);
        } catch (IOException e) {
            throw new CommonServiceException("加载文件失败![" + e.getMessage() + "]");
        }
    }

    public Bch getUpperBch(Bch argBch) {
        if (argBch == null)
            argBch = SettleContext.getUserSession().getOrgBch();
        return bchService.getDirectParentBch(argBch.getBranch());
    }

    public String getNextFrame(String inifrm) {
        Atpbch atpbch = atpbchMapper.selecDistinctByInifrm(inifrm);
        if (atpbch != null) {
            return atpbch.getFrmtyp();
        } else {
            return inifrm;
        }
    }

    public String getPreFrame(String inifrm, String branch) {
        if ("1000".equals(branch)) {
            return this.getNextFrame(inifrm);
        } else {
            Atpbch atpbch = atpbchMapper.selectByFrmtypAndBranchAndFlg(inifrm, branch, "X");
            if (atpbch == null) {
                return inifrm;
            } else {
                return atpbch.getInifrm();
            }
        }
    }

    /**
     * 通过文件名长度截取子目录,文件名为inr,in扩长为16后截取前12位
     *
     * @param argFil 文件名
     * @return 子目录 4位或12位
     */
    public String getSubDirByFileName(String argFil) {
        if (argFil.length() >= 16) {
            return argFil.substring(0, 12);
        }
        return argFil.substring(0, 4);
    }

    public String midObjinr(String objInr) {
        if (objInr.trim().length() == 16) {
            return Strings.mid(objInr, 1, 16);
        }
        return Strings.mid(objInr, 1, 8);
    }

    /**
     * 接口开关API【默认打开】
     *
     * @param srv 接口名（对应STB表的cod字段）
     * @return true表示接口开关打开
     */
    public boolean isInterfaceOpen(String srv) {
        Stb stb = stbMapper.selectByTblAndCodAndUil("INTACE", srv, "CN");
        if (stb != null) {
            return "Y".equals(stb.getTxt()) ? true : false;
        }
        return true;
    }

    /**
     * 接口上云开关API【默认打开】
     *
     * @param srv 接口名（对应STB表的cod字段）
     * @return true表示接口上云开关打开
     */
    public boolean isInterfaceSyOpen(String srv) {
        Stb stb = stbMapper.selectByTblAndCodAndUil("INTACE_SY", srv, "CN");
        if (stb != null) {
            return "Y".equals(stb.getTxt()) ? true : false;
        }
        return true;
    }

    /**
     * 交易开关API【默认打开】
     *
     * @param switchCod 开关码
     * @return true表示交易开关打开
     */
    public boolean isBusinessOpen(String switchCod) {
        Offcfg offcfg = new Offcfg();
        offcfg.setSwitchcode(switchCod);
        Offcfg result = offcfgMapper.selectBySwitchcode(offcfg);
        if (result != null) {
            return "Y".equals(result.getSwitchflg()) ? true : false;
        }
        return true;
    }

    public boolean isStartBusiness() {
        String transName = SettleContext.getTransName();
        if ("OPN".equalsIgnoreCase(transName.substring(3, transName.length()))) {
            return true;
        }
        if ("CRQ".equalsIgnoreCase(transName.substring(3, transName.length()))) {
            return true;
        }
        return false;
    }

    @Override
    public boolean checkFinStatus(String objTyp, String objInr) {
        String sql = "SELECT relflg FROM TRN WHERE INIFRM IN ('BPTOPN', 'TRTOPN', 'BPTAME', 'TRTAME', 'BPTSET', 'TRTSET', 'BRTSET', 'BRTSET1', 'BCTSET', 'BCTSET1', 'BOTSET', 'BETSET','BDTSET','BFTSET','CPTOPN','CPTATO','JSTOPN','JSTOPT','JSTOPM')" +
                " AND OBJTYP='" + objTyp + "' AND OBJINR='" + objInr + "'";
        Map<String, Object> dyncMap = new HashMap<>();
        dyncMap.put("sql", sql);
        List<Map<String, Object>> maps = publicMapper.dyncQueryMapList(dyncMap);
        if (maps.stream().anyMatch(map -> map.values().stream().anyMatch(value -> "W".equals(value)))) {
            return false;
        }
        return true;
    }

    @Override
    public String buildElcMsgDownloadPath(String instg, String msgId) {
        if (SystemUtils.IS_OS_UNIX) {
            return Strings.toLower("/sstf/data/elcdow/" + Strings.trim(Strings.mid(msgId, 1, 8)) + "/" + instg + msgId + ".txt");
        } else {
            return Strings.toLower(Strings.getAbsPath("DATA") + "\\" + "elcdow\\" + Strings.trim(Strings.mid(msgId, 1, 8)) + "\\" + instg + msgId + ".txt");
        }
    }

    @Override
    public boolean isShangYun(String tbl) {
        String languageSTB = "EN";
        String valReturn = "";
        List<CodetableItem> dbCodeTable = codetableService.selectList(tbl.toUpperCase(), languageSTB);
        if (dbCodeTable != null && !dbCodeTable.isEmpty()) {
            valReturn = dbCodeTable.get(0).getValue();
        } else {
            log.warn("找不到上云开关{}对应的码值", tbl);
        }
        return "Y".equals(valReturn) ? true : false;
    }

    @Override
    public boolean sptIsPenLoaded(String sptState) {
        return sptIsLoaded("PEN", sptState);
    }

    /**
     * source:sysmod.0223.script
     * 黑龙江版本
     */
    @Override
    public String getClientPath(String objtyp, BizInfoVo bizInfoVo) {
        if (StringUtils.isEmpty(objtyp)) {
            return NULLSTR;
        }
        String path = NULLSTR;
        switch (objtyp) {
            case "LID":
            case "BRD":
            case "GID":
            case "FXD":
            case "FUD":
                path = "APL";
                break;
            case "LED":
            case "BED":
            case "LTD":
                path = "BEN";
                break;
            case "BCD":
                path = "DRE";
                break;
            case "BOD":
                path = "DRR";
                break;
            case "BPD":
                if (MdaUtils.compareTo(Strings.mid(SettleContext.getTransName(), 1, 2), "BP") == 0) {
                    path = "FIA";
                } else {
                    //对于福费廷发票转让交易需要特殊处理,防止160错误
                    if (MdaUtils.compareTo(SettleContext.getTransName(), "FSTPSL") == 0) {
                        path = "FIA";
                    }
                }
                break;
            case "FBD":
                path = "FIA";
                break;
            case "TRD":
                if (MdaUtils.compareTo(Strings.mid(SettleContext.getTransName(), 1, 2), "TR") == 0) {
                    path = "FIP";
                } else {
//                    path = "\\TRTCRE\\" + objtyp + "GRP\\FIP";
                    path = "FIP";
                }
                break;
            case "CPD":
                // "\\CPDGRP\\REC\\PAYTYP"
                String paytyp = Utils.getFieldValue(bizInfoVo, "paytyp");
                if (MdaUtils.compareTo(paytyp, "O") == 0) {
                    path = "ORC";
                } else {
                    path = "PYE";
                }
                break;
            case "ATD":
                //"\\atdgrp\\rec\\sector"
                String sector = Utils.getFieldValue(bizInfoVo, "sector");
                if (MdaUtils.compareTo(sector, "0") == 0) {
                    path = "ORC";
                } else {
                    path = "PYE";
                }
                break;
            case "MCD":
                path = "ADE";
                break;
            case "CCD":
                path = "PRE";
                break;
            case "FMD":
            case "FPD":
                path = "SEL";
                break;
            default:
                // hoping that in future product modules the client will always be CLI
                path = "CLI";
        }
        return path;
    }


    /**
     * source:sysmod.0289.script
     */
    public void getTrnUSG(Argument<String> grp) {
        //--------根据ROU表的设置给SPT,TRN表中的OWNGRP组赋值-----
        // sec = 业务类型
        // BCHKEY = 业务经办行
        // BRANCH = 业务所属行
        // GRP = 业务分配的所属组
        // USR = 业务分配的柜员
        grp.value = "";
        //清算交易没办法分组,CL和光票
        String sec = NULLSTR;
        String transName = SettleContext.getTransName();
        if (MdaUtils.compareTo(transName, "CLIOPN") == 0 || MdaUtils.compareTo(transName, "CLOOPN") == 0
                || MdaUtils.compareTo(transName, "CPTMAN") == 0 || MdaUtils.compareTo(transName, "CPTBCK") == 0) {
            grp.value = "CL";
        } else {
            sec = Strings.mid(transName, 1, 2);
            if (!MdaUtils.isEmpty(sec)) {
                Rou rou = rouMapper.selectByBussec(sec);
                if (Objects.nonNull(rou)) {
                    grp.value = rou.getGrp();
                }
            }
        }

    }
}
