package com.brilliance.isc.common.setmod.service.impl;

import cn.hutool.core.lang.Assert;
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 org.springframework.util.ObjectUtils;
import com.brilliance.isc.bo.*;
import com.brilliance.isc.common.cache.atpbch.AtpBchCacheService;
import com.brilliance.isc.common.cache.pta.PtaCacheService;
import com.brilliance.isc.common.cache.pty.PtyCacheService;
import com.brilliance.isc.common.cbsmod.CbsRange;
import com.brilliance.isc.common.cbsmod.service.CbsmodService;
import com.brilliance.isc.common.cbsmod.service.XrtmodService;
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.context.SettleContext;
import com.brilliance.isc.common.context.SpringEnvContext;
import com.brilliance.isc.common.converter.DtoMapper;
import com.brilliance.isc.common.counter.service.CounterService;
import com.brilliance.isc.common.exception.CommonServiceException;
import com.brilliance.isc.common.glemod.service.GlemodService;
import com.brilliance.isc.common.limmod.service.LimCecmService;
import com.brilliance.isc.common.limmod.vo.LimmodVo;
import com.brilliance.isc.common.register.comm.ICommFeeRegister;
import com.brilliance.isc.common.register.fee.IFeeRegister;
import com.brilliance.isc.common.register.settle.ISettleRegister;
import com.brilliance.isc.common.setfeg.fee.FeeSet;
import com.brilliance.isc.common.setfeg.fee.Setcbs;
import com.brilliance.isc.common.setfeg.fee.Setpty;
import com.brilliance.isc.common.setfeg.fee.Wrksum;
import com.brilliance.isc.common.setfeg.service.SetfegService;
import com.brilliance.isc.common.setfeg.service.SetfelService;
import com.brilliance.isc.common.setfeg.vo.SetfelVo;
import com.brilliance.isc.common.setfog.service.SetfogService;
import com.brilliance.isc.common.setfog.service.SetfolService;
import com.brilliance.isc.common.setfog.vo.SetfolVo;
import com.brilliance.isc.common.setglg.service.SetglgService;
import com.brilliance.isc.common.setglg.vo.SetglgVo;
import com.brilliance.isc.common.setgll.service.SetgllService;
import com.brilliance.isc.common.setgll.vo.SetgllVo;
import com.brilliance.isc.common.setmod.service.SetmodService;
import com.brilliance.isc.common.setmod.vo.CommCbsLine;
import com.brilliance.isc.common.setmod.vo.CommFeeVo;
import com.brilliance.isc.common.setmod.vo.PtsFeeDetailVo;
import com.brilliance.isc.common.setmod.vo.SetmodVo;
import com.brilliance.isc.common.sysmod.SysmodService;
import com.brilliance.isc.common.transaction.help.TransactionHelpService;
import com.brilliance.isc.common.trndia.service.TrndiaService;
import com.brilliance.isc.common.trndia.vo.DiaVo;
import com.brilliance.isc.common.trndoc.service.TrndocService;
import com.brilliance.isc.common.trndoc.vo.DoceotVo;
import com.brilliance.isc.common.trnmod.vo.TrnmodVo;
import com.brilliance.isc.common.util.DocUtils;
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.FecVo;
import com.brilliance.isc.common.vo.PtsptaVo;
import com.brilliance.isc.common.vo.SimpleModuleVo;
import com.brilliance.isc.esb.newmodel.cecm.Battrn;
import com.brilliance.isc.esb.newmodel.cecm.Cecmfep;
import com.brilliance.isc.mda.dao.*;
import com.brilliance.isc.utils.BigDecimalUtils;
import com.brilliance.isc.utils.DateUtils;
import com.brilliance.isc.vo.component.dftcre.DftcreVo;
import com.brilliance.isc.vo.model.Fale01Vo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

import static com.brilliance.mda.runtime.mda.Constants.*;
import static com.brilliance.isc.common.contants.CommonContants.SETGLL_DSP_CODES;

/**
 *
 */
@Service
public class SetmodServiceImpl implements SetmodService {
    private static Logger log = LoggerFactory.getLogger(SetmodServiceImpl.class);

    @Autowired
    private SetfegService setfegService;

    @Autowired
    private SetfelService setfelService;

    @Autowired
    private SetglgService setglgService;

    @Autowired
    private SetgllService setgllService;

    @Autowired
    private XrtmodService xrtmodService;

    @Autowired
    private SetfogService setfogService;

    @Autowired
    private SetfolService setfolService;

    @Autowired
    private TrndocService trndocService;

    @Autowired
    private GlemodService glemodService;

    @Autowired
    private CbsmodService cbsmodService;

    @Autowired
    private SysmodService sysmodService;

    @Autowired
    private TransactionHelpService transactionHelpService;

    @Autowired
    private FeeMapper feeMapper;

    @Autowired
    private FepMapper fepMapper;

    @Autowired
    private FcpMapper fcpMapper;

    @Autowired
    private ActMapper actMapper;

    @Autowired
    private PtyCacheService ptyCacheService;

    @Autowired
    private PtaCacheService ptaCacheService;

    @Autowired
    private PtsptaToolComponent ptsptaToolComponent;

    @Autowired
    private CounterService counterService;

    @Autowired
    private CodetableService codetableService;

    @Autowired
    private CbsRange cbsRange;

    @Autowired
    private DiaMapper diaMapper;

    @Autowired
    private PtyMapper ptyMapper;

    @Autowired
    private Fale01Mapper fale01Mapper;

    @Autowired
    private TrndiaService trndiaService;

    @Autowired
    private DyncDaoService dyncDaoService;

    @Autowired
    private AtpBchCacheService atpBchCacheService;

    @Autowired
    private TdhMapper tdhMapper;
    @Autowired(required = false)
    private LimCecmService limCecmService;

    /**
     * source:setmod.0021.script
     */
    public static int getMonthUnits(Date date1, Date date2) {
        int uNits = Dates.getMonth(date2) - Dates.getMonth(date1);
        if (Dates.getDay(date2) >= Dates.getDay(date1)) {
            uNits = uNits + 1;
        }
        uNits = uNits + 12 * (Dates.getYear(date2) - Dates.getYear(date1));
        return uNits;
    }

    /**
     * source:setmod.0010.script
     *
     * @Rule(target=".mtabut.sav",order=220)
     */
    public void setTrnXreFields(SetmodVo setmodVo, TrnmodVo trnmod) {
        // set TRN fields for recaclulation
        if (MdaUtils.compareTo(setmodVo.getTerminal(), "F") == 0) {
            savIfNotChanged(setmodVo);
        }
        if ((!MdaUtils.isEmpty(getXreflg(setmodVo))) && (!sysmodService.sptIsExeLoaded(trnmod.getSpt().getSta()))) {
            trnmod.getTrn().setXreflg("1");
            trnmod.getTrn().setXrecurblk(MdaUtils.toString(getXrtcurstm(setmodVo)));
        } else {
            trnmod.getTrn().setXreflg(NULLSTR);
            trnmod.getTrn().setXrecurblk(NULLSTR);
        }
    }

    /**
     * source:setmod.0237.script
     *
     * @Rule(target=".mtabut.sav",order=199) method : ruleMtabutSavN199
     */
    public boolean checkXrtChg(SetmodVo setmodVo) {
        //刘文清要求存盘时 检核牌价是否发生变化
        //--zmqzmq---
        //--zmqtest---
        //wrkbch有可能为空
        if (SettleContext.getUserSession().getWrkbch() == null) {
            return true;
        }
        if (MdaUtils.compareTo(SettleContext.getUserSession().getBch().getZmqflg(), "X") == 0) {
            if (setglgService.checkXrtChg_zmq(setmodVo.getSetglg())) {
                return false;
            }
        } else {
            if (setglgService.checkXrtChg(setmodVo.getSetglg())) {
                return false;
            }
        }
        return true;
    }

    /**
     * source:setmod.0069.script
     *
     * @Rule(target=".mtabut.sav",order=1205) ruleMtabutSavN1205
     */
    public void saveSetmod(SetmodVo setmodVo) {
        String trninr = transactionHelpService.getTrninr();
        // setting old pool entries to replaced
        setmodVo.getSetfog().getSetfol().forEach(setfolVo -> {
            if ("D".equals(setfolVo.getSrc())
                    || "P".equals(setfolVo.getSrc())
                    || "A".equals(setfolVo.getSrc())) {
                //如果能够查询到fcp的数据，直接更新
                Fcp fcp = fcpMapper.getFcpByInr(setfolVo.getSrcfcpinr());
                if (fcp != null) {
                    fcp.setRpltrninr(trninr);
                    fcp.setRpldat(Dates.today());
                    fcpMapper.updateByPrimaryKey(fcp);
                }
            }
            //如果金额不等于0，无论无何都需要创建一笔新的fcp数据，
            // 因为pool的数据的replaces trninr变成了当前交易的trninr
            // 如果是本交易产生的或者是手动增加的 都需要创建一笔新的fcp数据
            // 因此删掉了mac值的比较逻辑
            if (setfolVo.getAmt().compareTo(BigDecimal.ZERO) != 0) {
                Fcp fcp = setfogService.setwrkFcp(setfolVo, setmodVo.getRec(), trninr);
                fcp.setSrctrninr(trninr);
                fcp.setSrcdat(Dates.today());
                fcp.setInr(counterService.dbCounterFormat("FCP"));
                fcpMapper.insert(fcp);
                setfolVo.setSrcfcpinr(fcp.getInr());
            }
        });
        // setting old pool entries to replaced
        setmodVo.getSetfeg().getSetfel().forEach(setfelVo -> {
            if ("Y".equals(setfelVo.getCommFeeFlag())) {
                //如果能够查询到fep的数据，直接更新
                Fep oldFep = fepMapper.selectByInr(Strings.getLine(setfelVo.getFepinrlst(), 1));
                if (oldFep != null) {
                    oldFep.setRpltrninr(trninr);
                    oldFep.setRpldat(Dates.today());
                    fepMapper.updateByPrimaryKey(oldFep);
                }
                //插入本次费用条目
                Fep fep = setfegService.setwrkfep(setfelVo, setmodVo.getPtsList(), setmodVo.getRec(), trninr);
                fep.setSrctrninr(trninr);
                fep.setSrcdat(Dates.today());
                fep.setInr(counterService.dbCounterFormat("FEP"));
                fepMapper.insert(fep);
                Streams.streamSet(setfelVo.getFepinrlst(), fep.getInr());
            } else {
                if ("D".equals(setfelVo.getSrc())
                        || "A".equals(setfelVo.getSrc())
                        || "P".equals(setfelVo.getSrc())
                        || "O".equals(setfelVo.getSrc())) {
                    //如果能够查询到fep的数据，直接更新
                    Fep fep = fepMapper.selectByInr(Strings.getLine(setfelVo.getFepinrlst(), 1));
                    if (fep != null) {
                        fep.setRpltrninr(trninr);
                        fep.setRpldat(Dates.today());
                        fepMapper.updateByPrimaryKey(fep);
                    }
                }
                //如果金额不等于0，无论无何都需要创建一笔新的fep数据，
                // 因为pool的数据的replaces trninr变成了当前交易的trninr
                // 如果是本交易产生的或者是手动增加的 都需要创建一笔新的fep数据
                // 因此删掉了mac值的比较逻辑
                if (setfelVo.getAmt().compareTo(BigDecimal.ZERO) != 0) {
                    Fep fep = setfegService.setwrkfep(setfelVo, setmodVo.getPtsList(), setmodVo.getRec(), trninr);
                    fep.setSrctrninr(trninr);
                    fep.setSrcdat(Dates.today());
                    fep.setInr(counterService.dbCounterFormat("FEP"));
                    fepMapper.insert(fep);
                    Streams.streamSet(setfelVo.getFepinrlst(), fep.getInr());
                }
            }
        });
        processCommFee2(setmodVo);
        processCommCbsLine(setmodVo);
        saveFale01(setmodVo);
        saveCecmFep(setmodVo);

    }

    /**
     * 保存cecm报送涉及的费用
     * @param setmodVo
     */
    public void saveCecmFep(SetmodVo setmodVo){
        LimmodVo limmodVo = transactionHelpService.getTransactionStoreSet().getLimmodVo();
        if (limmodVo == null) {
            limmodVo = new LimmodVo();
            limmodVo.reset();
        }
        limmodVo.getCecmBatchVo().getBattrn().setObjtyp("fep");
        if (ObjectUtils.isEmpty(limmodVo.getCecmBatchVo().getCecmmod())) {
            limmodVo.getCecmBatchVo().setCecmmod(new Cecmfep());
        }
        Battrn battrn = limmodVo.getCecmBatchVo().getBattrn();
        battrn.setBatchnam(String.format("%s费用",setmodVo.getRec().getObjtyp()));
        battrn.setCecmfil("trans_comm");

        LimmodVo finalLimmodVo = limmodVo;
        setmodVo.getSetfeg().getSetfel().forEach(setfelVo -> {
            Cecmfep cecmfep=new Cecmfep();
            cecmfep.setFyzl(setfelVo.getFeecod());
            cecmfep.setCur(setfelVo.getCur());
            cecmfep.setSfje(BigDecimalUtils.BigD2stringHalfUP(setfelVo.getAmt(),6));
            cecmfep.setFyfsrq(DateUtils.dateTime());
            cecmfep.setOwnref(setmodVo.getRec().getOwnref());
            finalLimmodVo.getCecmBatchVo().setCecmmod(cecmfep);
            limCecmService.saveCecm(finalLimmodVo);
        });
    }

    public void processCommFee2(SetmodVo setmodVo) {
        String transName = SettleContext.getTransName();
        ICommFeeRegister commFeeRegister = null;
        try {
            commFeeRegister = SpringEnvContext.getBean(atpBchCacheService.getSdTransNameForRegister().toLowerCase() + "." + "commFeeRegister");
        } catch (NoSuchBeanDefinitionException e) {
            log.warn("没有找到收费处理注册类, 不涉及收费流程");
        }
        if (commFeeRegister == null) {
            return;
        }
        CommFeeVo commFeeVo = commFeeRegister.registerCommFee2();
        if (commFeeVo == null) {
            log.warn("注册完的实体类为空，不处理直接返回");
            return;
        }
        if (StringUtils.isEmpty(commFeeVo.getFeeCode())) {
            log.warn("注册完的实体类费用代码为空，不处理直接返回");
            return;
        }
        SetfelVo setfelVo = null;
        List<SetfelVo> setfels = setmodVo.getSetfeg().getSetfel();
        for (SetfelVo setfel : setfels) {
            if ("T".equals(setfel.getSrc()) && commFeeVo.getFeeCode().equals(setfel.getFeecod())) {
                setfelVo = MdaUtils.deepClone(setfel);
                break;
            }
        }
        if (setfelVo == null) {
            log.warn("没有找到对应的费用条目，不处理直接返回");
            return;
        }
        if (setfelVo.getDat1() == null) {
            log.warn("收费起始日期为空，不处理直接返回");
            return;
        }
        //插入fec
        BizInfoVo rec = setmodVo.getRec();
        FecVo fecVo = setfelVo.getWrkfec();
        fecVo.setFeepri("6");
        fecVo.setObjtyp(rec.getObjtyp());
        fecVo.setObjinr(rec.getObjinr());
        fecVo.setBegdat(setfelVo.getDat1());
        fecVo.setEnddat(null);
        fecVo.setVer("0000");
        Fec fec = DtoMapper.INSTANCE.transfer(fecVo);
        cbsRange.sdbRngInsert(fec);
        //更新收费时间
        Object object = dyncDaoService.dyncReadByInr(commFeeVo.getClazz(), rec.getObjinr());
        if (object != null) {
            Date feecoldat = Utils.getFieldValue(object, "feecoldat", null);
            if (feecoldat == null || MdaUtils.compareTo(feecoldat, setfelVo.getDat2()) < 0) {
                Utils.setFieldValue(object, "feecoldat", setfelVo.getDat2());
                dyncDaoService.dyncUpdateByPrimaryKey(object);
                //需要生成下一期的收费diary
                if (commFeeVo.isCloneDia()) {
                    //List<Dia> dias = diaMapper.getDiaByObjtypAndObjinrAndFrmOrderByDat(rec.getObjtyp(), rec.getObjinr(), commFeeVo.getCommFeeTransName());
                    List<DiaVo> dias = transactionHelpService.getTransactionStoreSet().getTransactionVo().getDias();
                    Dia lastDia = null;
                    boolean needInsert = true;
                    if (dias != null && dias.size() > 0) {
                        for (int i = dias.size() - 1; i >= 0; i--) {
                            DiaVo diaVo = dias.get(i);
                            if (commFeeVo.getCommFeeTransName().equalsIgnoreCase(diaVo.getFrm())) {
                                if (MdaUtils.compareTo(diaVo.getDat(), setfelVo.getDat2()) < 0) {
                                    if (lastDia == null) {
                                        lastDia = DtoMapper.INSTANCE.transfer(diaVo);
                                    }
                                    //更新成已处理
                                    if ("".equals(diaVo.getDonflg())) {
                                        diaVo.setDonflg("X");
                                        trndiaService.calculateDiamodflg(diaVo);
                                        diaMapper.updateByPrimaryKey(DtoMapper.INSTANCE.transfer(diaVo));
                                    }
                                } else {
                                    needInsert = false;
                                }
                            }
                        }
                    }
                    if (lastDia != null && needInsert) {
                        if (commFeeVo.getExpiryDate() == null || MdaUtils.compareTo(setfelVo.getDat2(), commFeeVo.getExpiryDate()) < 0) {
                            Dia cloneDia = MdaUtils.deepClone(lastDia);
                            cloneDia.setDat(setfelVo.getDat2());
                            cloneDia.setCretyp("TRN");
                            cloneDia.setCreinr(transactionHelpService.getTrninr());
                            cloneDia.setOwnusr(SettleContext.getUserSession().getUsr().getExtkey());
                            cloneDia.setUsr(SettleContext.getUserSession().getUsr().getExtkey());
                            cloneDia.setDonflg("");
                            String diatyp = cloneDia.getDiatyp();
                            String objtyp = diatyp.substring(0, 3);
                            String key = diatyp.substring(3);
                            cloneDia.setDiatyp(objtyp + MdaUtils.toString(Integer.parseInt(key) + 1, -3));
                            sysmodService.sdbInsertWithLog(cloneDia);
                            DiaVo diaVo = DtoMapper.INSTANCE.transfer(cloneDia);
                            trndiaService.calculateDiamodflg(diaVo);
                            Assert.notNull(dias);
                            dias.add(diaVo);
                        }
                    }
                }
            }
        }
    }

    public void processCommCbsLine(SetmodVo setmodVo) {
        String transName = SettleContext.getTransName();
        ICommFeeRegister commFeeRegister = null;
        try {
            commFeeRegister = SpringEnvContext.getBean(atpBchCacheService.getSdTransNameForRegister().toLowerCase() + "." + "commFeeRegister");
        } catch (NoSuchBeanDefinitionException e) {
            log.warn("没有找到收费处理注册类, 不涉及收费流程");
        }
        if (commFeeRegister == null) {
            return;
        }
        CommCbsLine commCbsLine = commFeeRegister.registerCommCbsLine(setmodVo);
        if (commCbsLine == null) {
            log.warn("注册完的实体类为空，不处理直接返回");
            return;
        }
        if ("I".equals(commCbsLine.getAction())) {
            Object object = dyncDaoService.dyncReadByInr(commCbsLine.getClazz(), commCbsLine.getClazzInr());
            String listStr = Utils.getFieldValue(object, "dtaliadet", "");
            List<CommCbsLine> list = new ArrayList<>();
            if (StringUtils.isNotEmpty(listStr)) {
                list = Utils.toListObject(CommCbsLine.class, listStr);
            }
            if (commCbsLine.getAmt().compareTo(BigDecimal.ZERO) == 0) {
                return;
            } else if (commCbsLine.getAmt().compareTo(BigDecimal.ZERO) > 0) {
                //增额
                SetfelVo setfelVo = null;
                List<SetfelVo> setfels = setmodVo.getSetfeg().getSetfel();
                for (SetfelVo setfel : setfels) {
                    if ("T".equals(setfel.getSrc()) && commCbsLine.getFeeCode().equals(setfel.getFeecod())) {
                        setfelVo = MdaUtils.deepClone(setfel);
                        break;
                    }
                }
                if (setfelVo != null) {
                    commCbsLine.setFeeDate(setfelVo.getDat2());
                }
                list.add(commCbsLine);
            } else if (commCbsLine.getAmt().compareTo(BigDecimal.ZERO) < 0) {
                //减额
                list.add(commCbsLine);
            }
            Utils.setFieldValue(object, "dtaliadet", Utils.toJson(list));
            dyncDaoService.dyncUpdateByPrimaryKey(object);
        } else if ("U".equals(commCbsLine.getAction())) {
            SetfelVo setfelVo = null;
            List<SetfelVo> setfels = setmodVo.getSetfeg().getSetfel();
            for (SetfelVo setfel : setfels) {
                if ("T".equals(setfel.getSrc()) && commCbsLine.getFeeCode().equals(setfel.getFeecod())) {
                    setfelVo = MdaUtils.deepClone(setfel);
                    break;
                }
            }
            if (setfelVo != null && setfelVo.getUnt() > 0) {
                Object object = dyncDaoService.dyncReadByInr(commCbsLine.getClazz(), commCbsLine.getClazzInr());
                String listStr = Utils.getFieldValue(object, "dtaliadet", "");
                List<CommCbsLine> list = new ArrayList<>();
                if (StringUtils.isNotEmpty(listStr)) {
                    list = Utils.toListObject(CommCbsLine.class, listStr);
                }
                //是否一次性收取
                boolean allColFlag = false;
                if (setfelVo.getDat2dft() != null && MdaUtils.compareTo(setfelVo.getDat2(), setfelVo.getDat2dft()) >= 0) {
                    allColFlag = true;
                }
                if (list.size() > 0) {
                    if (allColFlag) {
                        for (CommCbsLine commCbsLine1 : list) {
                            int relUnt = Utils.calcUnt(commCbsLine1.getFeeDate(), setfelVo.getDat2dft(), setfelVo.getWrkfec().getPertyp());
                            commCbsLine1.setFeeDate(Utils.calcDate(commCbsLine1.getFeeDate(), relUnt, setfelVo.getWrkfec().getPertyp(), ""));
                        }
                    } else {
                        for (CommCbsLine commCbsLine1 : list) {
                            if (MdaUtils.compareTo(setfelVo.getDat1(), commCbsLine1.getFeeDate()) >= 0) {
                                commCbsLine1.setFeeDate(Utils.calcDate(commCbsLine1.getFeeDate(), setfelVo.getUnt(), setfelVo.getWrkfec().getPertyp(), ""));
                            }
                        }
                    }
                    Utils.setFieldValue(object, "dtaliadet", Utils.toJson(list));
                    dyncDaoService.dyncUpdateByPrimaryKey(object);
                }
            }
        }
    }

    /*//回滚业务产生的fec数据
    public void rollbackCommFee2(Trn trn) {
        String transName = trn.getInifrm();
        if ("GITOPN|NITOPN|HITOPN|GITCOM|NITCOM".indexOf(transName) > -1) {
            List<Fec> fecList = fecMapper.selectFecByObjtypAndObjinrAndFeeinrAndFeepri(trn.getObjtyp(), trn.getObjinr(), null, "6");
            String feeinr = "";
            if (fecList != null && fecList.size() > 0) {
                feeinr = fecList.get(0).getFeeinr();
            }
            if (StringUtils.isNotEmpty(feeinr)) {
                Fec fec = new Fec();
                fec.setObjtyp(trn.getObjtyp());
                fec.setObjinr(trn.getObjinr());
                fec.setFeepri("6");
                fec.setFeeinr(feeinr);
                Date date = Dates.add(Utils.getMaxDate(), -1);
                cbsRange.sdbRngRead(fec, date);
                if (StringUtils.isNotEmpty(fec.getInr())) {
                    cbsRange.sdbRngDelete(fec);
                }
            }
        }
    }*/

    /**
     * source:setmod.0019.script
     */
    public void setFepPntLev(SetmodVo setmodVo, int arglev) {
        //! Set number of parent levels for which fee pool records are to be read.
        //! Supported values are
        //! -1 : The fee pool is not read
        //!  0 : The pool records for the main contract are read
        //!  1 : The pool records for the main contract and its parent are read (this is the default)
        //!  2 :  The pool records of the parent contract and the parent of the parent contract is read.
        setmodVo.getSetfeg().setFeppntlev(arglev);
        setmodVo.getSetfog().setFcppntlev(arglev);
    }

    /**
     * source:setmod.0000.script
     */
    public void assertSetmod(SetmodVo setmodVo) {
        //根据pts信息重构参与方角色,地址
        ptsChgAssert(setmodVo);

        //费用注册
        internalPostFeeRegistersettlement(setmodVo);
        //-客户收费
        assertSetfog(setmodVo, false);
        //-我行收费
        assertSetfeg(setmodVo, false);
        //账务注册
        internalPostSettleRegistersettlement(setmodVo);
        //-结算
        assertSetglg(setmodVo);

        // remember total amount
        setmodVo.setTotamtsavbog(setmodVo.getSetglg().getTotamt());
        // set SETAMT
        setmodVo.setSetamt(Decimals.add(Decimals.sub(setmodVo.getDocamt(), setmodVo.getRedamt()), setmodVo.getOthdocamt()));
        //自贸区字段赋值
        getZmqacc(setmodVo);
        //试算E01报送
        assertFale01(setmodVo);
    }

    public void assertSetfog(SetmodVo setmodVo, boolean onlyCalcFeeFlag) {
        // - foreign charges - processing before lines
        this.setfogService.calcMacbog(setmodVo);
        if (MdaUtils.compareTo(setmodVo.getSetfog().getMacbog(), setmodVo.getSetfog().getMacbogold()) != 0) {
            this.setfogService.recalcSetfogBog(setmodVo);
        }
        // foreign charges grid lines
        int rows = 0;
        if (setmodVo.getSetfog().getSetfol() != null) {
            rows = setmodVo.getSetfog().getSetfol().size();
        }
        if (rows > 0) {
            for (int i = 0; i < rows; i++) {
                SetfolVo setfolVo = setmodVo.getSetfog().getSetfol().get(i);
                this.setfolService.calcMac(setfolVo, setmodVo);
                if (MdaUtils.compareTo(setfolVo.getMac(), setfolVo.getMacold()) != 0) {
                    this.setfolService.recalcSetfol(setfolVo, setmodVo);
                }
            }
        }
        if (onlyCalcFeeFlag) { //如果只是前端试算费用，这里就可以直接返回，下面的逻辑跟账务有关
            return;
        }
        //与账务试算保持一致，需要根据费用条目生成账务试算数据,不需要试算mac
        this.setfogService.recalcSetfogEog(setmodVo);
    }

    public void assertSetfeg(SetmodVo setmodVo, boolean onlyCalcFeeFlag) {
        // - own charges -
        this.setfegService.calcMacbog(setmodVo.getSetfeg());
        if (MdaUtils.compareTo(setmodVo.getSetfeg().getMacbog(), setmodVo.getSetfeg().getMacbogold()) != 0) {
            this.setfegService.recalcSetfegBog(setmodVo);
        }
        // fee grid lines
        int rows = 0;
        if (setmodVo.getSetfeg().getSetfel() != null) {
            rows = setmodVo.getSetfeg().getSetfel().size();
        }
        if (rows > 0) {
            for (int i = 0; i < rows; i++) {
                SetfelVo setfelVo = setmodVo.getSetfeg().getSetfel().get(i);
                //Modules.postDefaultRule(setfelVo,"mac",true);
                this.setfelService.calcMac(setfelVo, setmodVo);
                if (MdaUtils.compareTo(setfelVo.getMac(), setfelVo.getMacold()) != 0) {
                    this.setfelService.recalcSetfel(setfelVo, setmodVo);
                }
            }
        }
        if (onlyCalcFeeFlag) { //如果只是前端试算费用，这里就可以直接返回，下面的逻辑跟账务有关
            return;
        }
        //与账务试算保持一致，需要根据费用条目生成账务试算数据,不需要试算mac
        this.setfegService.recalcSetfegEog(setmodVo);
    }

    public void assertSetglg(SetmodVo setmodVo) {
        // booking grid - processing before lines
        String mac = this.setglgService.calcMac(setmodVo);
        if (MdaUtils.compareTo(mac, setmodVo.getSetglg().getMacold()) != 0) {
            this.setglgService.recalcSetglgBog(setmodVo);
        }
        // booking grid lines
        int rows = 0;
        if (setmodVo.getSetglg().getSetgll() != null) {
            rows = setmodVo.getSetglg().getSetgll().size();
        }
        if (rows > 0) {
            for (int i = 0; i < rows; i++) {
                SetgllVo setgllVo = setmodVo.getSetglg().getSetgll().get(i);
                this.setgllService.calcMac(setgllVo, setmodVo);
                if (MdaUtils.compareTo(setgllVo.getMac(), setgllVo.getMacold()) != 0) {
                    this.setgllService.recalcSetgll(setgllVo, setmodVo);
                }
            }
        }
        // booking grid - processing after lines
        //Modules.postDefaultRule(this,"setglg.maceog");
        this.setglgService.calcMaceog(setmodVo);
        if (MdaUtils.compareTo(setmodVo.getSetglg().getMaceog(), setmodVo.getSetglg().getMaceogold()) != 0) {
            this.setglgService.recalcSetglgEog(setmodVo);
        }
    }

    /**
     * source:setmod.0012.script
     */
    public void internalAddToStream(IStream argstm, String argval) {
        //! Add line with ArgVal to Argstm if not already in Argstm
        // used in default XRTCURSTM
        int idx = 0;
        if (!MdaUtils.isEmpty(argval)) {
            idx = Streams.streamSearch(argstm, argval);
            if (idx == 0) {
                Streams.streamInsert(argstm, 0, argval);
            }
        }

    }

    /**
     * source:setmod.0018.script
     */
    public void savIfNotChanged(SetmodVo setmodVo) {
        //! This method is posted in Event MTABUT\\SAV if the current panel was not the settlement after setting active panel to settlement.
        //! Before recalulating settlement, the old Total amount is remembered in TOTAMTSAVBOG.
        //!
        //! If the total amount stays to that amount after the redefault, the save is continued, otherwise an Error is set to allow the user to check.
        if (MdaUtils.compareTo(setmodVo.getSetglg().getTotamt(), setmodVo.getTotamtsavbog()) == 0) {
            log.debug("Continue saving transaction as settlement has not changed");
        } else {
            SettleExceptionUtils.sysDump("Settlement has been recalculated since last viewed.\nPlease check settlement and click the same button again,\nSave interrupted due to settlement changes");
        }

    }

    /**
     * source:setmod.0025.script
     */
    public void setmodSetRolCorFlg(String argrol, String argval, IStream parstm) {
        //! Sets the Correspondentflg for role ArgRol to Argval
        //!
        //! The options for ArgVal are as follows:
        //!  Default/empty/no call of SetmodSetRolCorFlg: Create automatic settlement message if and only if no message is sent to ArgRol
        //!  S:  Create automatic settlement message if something is settled to Argrol
        //!  Any other nonempty value: Do not create automatic settlement message to Argrol, even if no message is sent to ArgRol.
        //!
        //! Usually called in RegisterDocument functions
        String key = "ROL-" + argrol + "-CORFLG-" + TAB;
        int line = Streams.streamSearch(parstm, key);
        if (line == 0) {
            Streams.streamInsert(parstm, 0, key + argval);
        } else {
            Streams.streamSetLine(parstm, line, key + argval);
        }

    }

    /**
     * source:setmod.0023.script
     */
    public void ptsChgAssert(SetmodVo setmodVo) {
        //! Add parties of contract to settlement
        // checking PTYINR directly as PtsIsRolSet is not enough for being able to use party in settlemnt. PTYINR is requiered. By default all addresses, even temporary, are allowed in settlement
        MdaUtils.clear(setmodVo.getRoldsc());
        setmodVo.getRoldsc().getRows().add("OWN" + TAB + codetableService.getTblLabel("OWN", "ROLALL"));
        //清理Setpty
        FeeSet feeSet = this.setfegService.getFeeSet();
        feeSet.clearSetpty();
        //补充ptslist 从父交易中获取ptslist
        ptsptaToolComponent.addPtspta(setmodVo.getPtsList(), setmodVo.getRec().getPntinr(), setmodVo.getRec().getPnttyp());
        setmodVo.getPtsList().forEach(ptspta -> {
            String rol = ptspta.getRol();
            String name = ptspta.getNam();
            String ptyinr = ptspta.getPtyinr();
            String ptaInr = ptspta.getPtainr();
            if (!MdaUtils.isEmpty(ptyinr)) {
                Setpty setpty = new Setpty();
                setpty.setRol(rol);
                setpty.setName(name);
                setpty.setPtyInr(ptyinr);
                setpty.setPtaInr(ptaInr);
                feeSet.putSetpty(rol, setpty);
                setmodVo.getRoldsc().getRows().add(rol + TAB + codetableService.getTblLabel(rol, "ROLALL"));
            }
        });
        recalcSetdet(setmodVo);
        this.setDflg(setmodVo);
    }

    /**
     * source:setmod.0034.script
     */
    public void setOpnAmt(SetmodVo setmodVo, BigDecimal argOpnAmt) {
        // to be used for settlement defaulting from RegisterSettlement functions
        // sets the open amount in settlement
        setmodVo.setOpnamt(argOpnAmt);

    }

    @Override
    public void setDftDspAct(SetmodVo setmodVo, String argRol, String argCur, String argDsp, String argAct) {
        //! Set default dsp to be used as account dsp for a party (if party is available in settlement)
        int lineNr = getPtyDetRow(argRol, setmodVo);
        if (lineNr >= 0) {
            setmodVo.getPtydet().get(lineNr).setDftcur(argCur);
            setmodVo.getPtydet().get(lineNr).setDftdsp(argDsp);
            setmodVo.getPtydet().get(lineNr).setDftact(argAct);
        }
    }

    /**
     * source:setmod.0036.script
     */
    public void setFeeCliRol(String argFeeCliRol, SetmodVo setmodVo) {
        //! to be used for settlement defaulting from RegisterSettlement functions
        //! sets the fee client role in settlement
        setmodVo.setFeeclirol(argFeeCliRol);

    }

    /**
     * source:setmod.0038.script
     */
    public void setDocAmt(SetmodVo setmodVo, String argDocCur, BigDecimal argDocAmt, String argDisableFlag) {
        //! To be used for settlement defaulting from RegisterSettlement functions
        //! Sets the document currency and amount in settlement
        //
        //! ArgDocCur:      Document currency. Usually contract currency. If empty, DOCCUR and DOCAMT are not changed
        //! ArgDocAmt:      Document amount
        //! ArgDisableFlag: Defines the enable/disable state of DOCAMT
        //!  possible values: "Disable", "Enable", empty
        //!  If DISABLE even modificatioons of the user are overwritten.
        if (!MdaUtils.isEmpty(argDisableFlag)) {

        }
        if (!MdaUtils.isEmpty(argDocCur)) {
            if (!setmodVo.isModified("doccur")) {
                setmodVo.setDoccur(argDocCur);
            }
            if (!setmodVo.isModified("docamt")) {
                setmodVo.setDocamt(argDocAmt);
            }
        }
    }

    public Date getRefdat() {
        return new Date();
    }

    /**
     * source:setmod.0039.script
     */
    public void setRolDspMdyFlg(SetmodVo setmodVo, String argRolDspMdyFlg) {
        // to be used for settlement defaulting from RegisterSettlement functions
        // If set, the selltement of fees is mandatory in this transaction, i.e. the disposition of all fees is set to "settle now" and disabled
        setmodVo.getSetfeg().setRoldspmdyflg(argRolDspMdyFlg);

    }

    /**
     * source:setmod.0060.script
     */
    public void setPtyActPtaInr(String argRol, String argActPtaInr) {
        //! Set Account party for a party (if party is available in settlement)
        //! ArgRol       Role mnemo
        //! ArgActPtainr PTAINR of party to be used for account defaulting
        //!
        Setpty setpty = this.setfegService.getFeeSet().getSetpty(argRol);
        if (setpty != null) {
            setpty.setActptainr(argActPtaInr);
        }
    }

    /**
     * source:setmod.0063.script
     * 这个是其他模块要求注册的，例如Liaall
     */
    public void setAdditionalContract(String objtyp, String objinr, SetmodVo setmodVo) {
        //! add contract Arggrp to fee pool defaulting
        // old fees are only possible for contracts with INR
//			String grpInr = Platform.recGetInr(argGrp);
        String key = NULLSTR;
        if (!MdaUtils.isEmpty(objinr)) {
            key = objtyp + TAB + objinr;
            if (Streams.streamSearch(setmodVo.getSetaddconstm(), key) == 0) {
                Streams.streamInsert(setmodVo.getSetaddconstm(), 0, key);
            }
        }

    }

    /**
     * source:setmod.0061.script
     */
    public void setPtyGllPty(String argRol, String argRolGlg, String argEuqOnlFlg) {
        String glgPtyInr = "";
        Setpty setpty = null;
        if (StringUtils.isNotEmpty(argEuqOnlFlg)) {
            setpty = this.setfegService.getFeeSet().getSetpty(argRolGlg);
            if (setpty != null) {
                glgPtyInr = setpty.getPtyInr();
            }
        }
        setpty = this.setfegService.getFeeSet().getSetpty(argRol);
        if (setpty != null) {
            if (MdaUtils.compareTo(setpty.getPtyInr(), glgPtyInr) == 0 || StringUtils.isEmpty(argEuqOnlFlg)) {
                setpty.setGllptyrol(argRolGlg);
            } else {
                setpty.setGllptyrol("");
            }
        }
    }

    /**
     * source:setmod.0078.script
     */
    public String getGllRol(String argrol) {
        //!   gets role to which amounts for Argrol are settled.
        //!   (i.e. Argrol if not redirected to other role by SetPtyGllPty)
//			String res = argrol;
        Setpty setpty = this.setfegService.getFeeSet().getSetpty(argrol);
        if (setpty != null && !MdaUtils.isEmpty(setpty.getGllptyrol())) {
            return setpty.getGllptyrol();
        }
        return argrol;
    }

    /**
     * source:setmod.0072.script
     */
    public void setDspPolDft(SetmodVo setmodVo, String argDspFogDft, String argDspFegDft, String argDisableFlag) {
        //! to be used for settlement defaulting from RegisterSettlement functions
        //! sets the default disposition for pool entries
        //! Only necessary, if not "V" (i.e. pool entries are advised asap)
        //! ArgDspFogDft is the default for foreign charges
        //! ArgDspFegDft is the default for own charges
        // call set function of sub modules
        setfogService.setDspPolDft(setmodVo.getSetfog(), argDspFogDft, argDisableFlag);
        setfegService.setDspPolDft(setmodVo.getSetfeg(), argDspFegDft, argDisableFlag);
    }

    /**
     * source:setmod.0081.script
     */
    public void internalPostFeeRegistersettlement(SetmodVo setmodVo) {
        //按照交易码，获取注册Spring的交易Bean
        String transName = SettleContext.getTransName();
        IFeeRegister feeRegister = null;
        try {
            feeRegister = SpringEnvContext.getBean(atpBchCacheService.getSdTransNameForRegister().toLowerCase() + "." + "feeRegister");
        } catch (NoSuchBeanDefinitionException e) {
            throw new CommonServiceException("没有找到交易费用注册类");
        }
        feeRegister.registerSettlement(setmodVo);
    }

    /**
     * source:setmod.0081.script
     */
    public void internalPostSettleRegistersettlement(SetmodVo setmodVo) {
        //按照交易码，获取注册Spring的交易Bean
        String transName = SettleContext.getTransName();
        ISettleRegister settleRegister = null;
        try {
            settleRegister = SpringEnvContext.getBean(atpBchCacheService.getSdTransNameForRegister().toLowerCase() + "." + "settleRegister");
        } catch (NoSuchBeanDefinitionException e) {
            log.warn("没有找到交易账务注册类,{" + transName + "},使用默认的交易账务注册类");
            settleRegister = SpringEnvContext.getBean("default.settleRegister");
        }
        settleRegister.registerSettlement(setmodVo);
    }

    /**
     * source:setmod.0084.script
     */
    public void setDftFeecur(String argRol, String argCur, SetmodVo setmodVo) {
        //! Set default currency to be used to calculate fees for a party (if party is available in settlement)
        //!
        //! The default is that fees are calculated in document curreny
        //!
        //! ArgRol    Role mnemo
        //! ArgCur    Currency to be used
        //!
        // if fee currency is set on Details panel and settled, use it
        int gridcnt = setmodVo.getSetglg().getSetgll().size();
        int lineNr = 0;
        if (gridcnt > 0) {
            lineNr = getPtyDetRow(argRol, setmodVo);
            if (lineNr >= 0) {
                if (!MdaUtils.isEmpty(setmodVo.getPtydet().get(lineNr).getDftfeecur())) {
                    for (int i = 0; i < gridcnt; i++) {
                        if (MdaUtils.compareTo(setmodVo.getSetglg().getSetgll().get(i).getRol(), argRol) == 0) {
                            argCur = setmodVo.getPtydet().get(lineNr).getDftfeecur();
                            break;
                        }
                    }
                }
            }
        }
        Setpty setpty = setfegService.getFeeSet().getSetpty(argRol);
        if (setpty != null) {
            if (MdaUtils.compareTo(setpty.getDftfeecur(), argCur) != 0) {
                setpty.setDftfeecur(argCur);
            }
        }

    }

    public String getNameOfRole(IStream roldsc, String role, String ptyinr) {
        //! gets name of role
        //
        // if PTYINR is empty or matches with ptyinr of that role in settlement try to take it from settlement
        String ptyInr;
        Argument<String> ptyInrBox = new Argument<String>();
        String ptaInr;
        Argument<String> ptaInrBox = new Argument<String>();
        this.getPtxInr(role, ptyInrBox, ptaInrBox);

        ptyInr = ptyInrBox.value;
        ptaInr = ptaInrBox.value;

        int idx = 0;
        String lin = NULLSTR;
        if (MdaUtils.isEmpty(ptyinr) || MdaUtils.compareTo(ptyInr, ptyinr) == 0) {
            idx = Streams.streamSearch(roldsc, role + TAB);
            if (idx > 0) {
                lin = Strings.getLine(roldsc, idx);
                return Strings.trim(Strings.mid(lin, Strings.pos(lin, ":") + 1));
            }
        }
        // otherwise read from database, if PTYINR is available
        if (!MdaUtils.isEmpty(ptyinr)) {
            Pty pty = ptyCacheService.getPtyById(ptyinr);
            if (pty != null) {
                return pty.getNam();
            }
        }
        // if nothing found return empty value
        return "";
    }

    /**
     * source:setmod.0085.script
     */
    public void setDftAcccur(SetmodVo setmodVo, String argRol, String argCur, String argGrpLst) {
        //! Set default currency to be used as account currency for a party (if party is available in settlement)
        //!
        //! The default is using the original curreny
        //!
        //! ArgRol    Role mnemo
        //! ArgCur    Currency to be used
        //! ArgGrpLst List of groups (as used by SetDefaultGlgGrp) seperated by CR. Empty for all.
        //!
        // if account currency is set on Details panel and settled, use it
        int gridcnt = setmodVo.getSetglg().getSetgll().size();
        int lineNr = 0;
        if (gridcnt > 0) {
            lineNr = getPtyDetRow(argRol, setmodVo);
            if (lineNr > 0) {
                if (!MdaUtils.isEmpty(setmodVo.getPtydet().get(lineNr).getDftcur())) {
                    for (int i = 0; i < gridcnt; i++) {
                        if (MdaUtils.compareTo(setmodVo.getSetglg().getSetgll().get(i).getRol(), argRol) == 0) {
                            argCur = setmodVo.getPtydet().get(lineNr).getDftcur();
                            break;
                        }
                    }
                }
            }
        }
        Setpty setpty = this.setfegService.getFeeSet().getSetpty(argRol);
        if (setpty != null) {
            if (MdaUtils.compareTo(setpty.getDftacccur(), argCur) != 0
                    || MdaUtils.compareTo(setpty.getDftacccurgrp(), argGrpLst) != 0) {
                setpty.setDftacccur(argCur);
                setpty.setDftacccurgrp(argGrpLst);
                // ensure recalculation
                gridcnt = setmodVo.getSetglg().getSetgll().size();
                for (int i = 0; i < gridcnt; i++) {
                    setmodVo.getSetglg().getSetgll().get(i).setMacold("<Recalc>");
                }
            }
        }
    }

    /**
     * source:setmod.0095.script
     */
    public int getPtyDetRow(String argrol, SetmodVo setmodVo) {

        int res = -1;
        int gridcnt = setmodVo.getPtydet().size();
        for (int i = 0; i < gridcnt; i++) {
            if (MdaUtils.compareTo(setmodVo.getPtydet().get(i).getRol(), argrol) == 0) {
                res = i;
                break;
            }
        }
        return res;
    }

    public void recalcSetdet(SetmodVo setmodVo) {
        //! Set info details panel
        // Set Pty grid
        if (MdaUtils.isEmpty(setmodVo.getRoldsc())) {
            return;
        }
        // add lines according to avaliable roles
        // for OWN now line is needed
        int needed = 0;
        if (Streams.streamSearch(setmodVo.getRoldsc(), "OWN") > 0) {
            needed = Streams.streamCount(setmodVo.getRoldsc()) - 1;
        } else {
            needed = Streams.streamCount(setmodVo.getRoldsc());
        }
        int gridcnt = setmodVo.getPtydet().size();
        if (gridcnt < needed) {
            while (gridcnt < needed) {
                setmodVo.getPtydet().add(new PtsFeeDetailVo());
                gridcnt++;
            }
        }
        int line = 0;
        int gridcntSetGll = 0;
        if (setmodVo.getSetglg().getSetgll() != null) {
            gridcntSetGll = setmodVo.getSetglg().getSetgll().size();
        }
        //! Set grid (one line for each role in ROLDSC)
        int rolLin = 1;
        String rolGrppath = NULLSTR;
        IStream dspLst = new StreamImpl();
        IStream dspLst2 = new StreamImpl();
        String dspDft = NULLSTR;
        int dspIdx = 0;
        String dsp = NULLSTR;
        String actlst = NULLSTR;
        IStream actstm = new StreamImpl();
        for (int i = 1; i <= Streams.streamCount(setmodVo.getRoldsc()); i++) {
            String rol = Strings.mid(Strings.getLine(setmodVo.getRoldsc(), i), 1, Strings.pos(Strings.getLine(setmodVo.getRoldsc(), i), TAB) - 1);
            if (MdaUtils.compareTo(rol, "OWN") != 0) {
                rolLin = -1;
                PtsptaVo rolpts = ptsptaToolComponent.getPtsFromListByRol(setmodVo.getPtsList(), rol);
                if (rolpts != null) {
                    rolLin = getPtyDetRow(rol, setmodVo);
                    if (rolLin > -1) {
                        setmodVo.getPtydet().get(rolLin).setPtyinr(rolpts.getPtyinr());
                        setmodVo.getPtydet().get(rolLin).setPtainr(rolpts.getPtainr());
                        setmodVo.getPtydet().get(rolLin).setExtkey(rolpts.getExtkey());
//						Codetables.setCodeValues(this.getPtydet().getElement(rolLin),"rol",this.getRoldsc());
                    } else {
                        while (line < gridcnt && !MdaUtils.isEmpty(setmodVo.getPtydet().get(line).getRol())) {
                            line = line + 1;
                        }
                        if (line == gridcnt) {
                            setmodVo.getPtydet().add(new PtsFeeDetailVo());
                            gridcnt = setmodVo.getPtydet().size();
                        }
                        BeanUtils.copyProperties(rolpts, setmodVo.getPtydet().get(line));
                        setmodVo.getPtydet().get(line).setRol(rol);
                        rolLin = line;
                    }
                    if (rolLin >= 0) {
                        if (MdaUtils.isEmpty(setmodVo.getPtydet().get(rolLin).getDftcur())) {
//							Dynamic.disableAndClearField( MdaDriver.getDatafield(this.getPtydet().getElement(rolLin),"dftdsp"));
                            setmodVo.getPtydet().get(rolLin).setDftdsp("");
                            /**
                             if GetFramename <> "CPTECO" then
                             **/
                            if (MdaUtils.compareTo(SettleContext.getTransName(), "CPTECO") != 0 && MdaUtils.compareTo(SettleContext.getTransName(), "GITODZ") != 0) {
                                setmodVo.getPtydet().get(rolLin).getDftact();
                            }
                        } else {
                            // set available dispocodes
//							Systems.setEnabled(this.getPtydet().getElement(rolLin),"dftdsp");
                            Streams.streamSet(dspLst, getDsp(SettleContext.getTransName(), BigDecimal.ZERO, setmodVo));
                            Streams.streamSet(dspLst2, getDsp(SettleContext.getTransName(), BigDecimal.ONE, setmodVo));
                            Streams.streamInsert(dspLst, 0, dspLst2);
                            if (Streams.streamCount(dspLst) > 0) {
                                dspDft = Strings.getLine(dspLst, 1);
                            } else {
                                dspDft = "";
                            }
                            dspIdx = 1;
                            while (dspIdx <= Streams.streamCount(dspLst)) {
                                dsp = Strings.getLine(dspLst, dspIdx);
                                if (MdaUtils.compareTo(dsp, "FND") != 0 && MdaUtils.compareTo(dsp, "HLD") != 0) {
                                    if (gridcntSetGll > 0) {
                                        Streams.streamSetLine(dspLst, dspIdx, dsp + TAB + SETGLL_DSP_CODES.get(dsp));
                                    }
                                    dspIdx = dspIdx + 1;
                                } else {
                                    Streams.streamDelete(dspLst, dspIdx);
                                }
                            }
//							Codetables.setCodeValues(this.getPtydet().getElement(rolLin),"dftdsp",dspLst);
                            // Check if selected dispocode is in list and default if necessary
                            if (Streams.streamSearch(dspLst, setmodVo.getPtydet().get(rolLin).getDftdsp()) == 0) {
                                setmodVo.getPtydet().get(rolLin).setDftdsp(NULLSTR);
                            }
                            if (MdaUtils.isEmpty(setmodVo.getPtydet().get(rolLin).getDftdsp())) {
                                //          PTYDET( $RolLin )\\DFTdsp = $DspDft
                            }
                            // set available accounts
                            if (MdaUtils.isEmpty(setmodVo.getPtydet().get(rolLin).getDftdsp())) {
//								Systems.resetEnabled(this.getPtydet().getElement(rolLin),"dftact");
                                setmodVo.getPtydet().get(rolLin).setDftact(NULLSTR);
//								Systems.resetModified(this.getPtydet().getElement(rolLin),"dftact");
                                setmodVo.getPtydet().get(rolLin).resetModified("dftact");
                            } else {
//								Systems.setEnabled(this.getPtydet().getElement(rolLin),"dftact");
                                /**            $sql = ACTgetsql( PTYDET( $RolLin )\\PTYINR, PTYDET( $RolLin )\\DFTdsp, PTYDET( $RolLin )\\DFTCUR, self, "" )
                                 $actlst = \\TRNMOD.ACTGetSerBlk ( $sql, PTYDET( $RolLin )\\PTYINR, PTYDET( $RolLin )\\DFTdsp, $PRIOFLG, 1 )
                                 if IsEmpty( $actlst ) then
                                 $actlst = ACTGetComBlk( PTYDET( $RolLin )\\DFTdsp, PTYDET( $RolLin )\\DFTdsp, PTYDET( $RolLin )\\DFTCUR, self )
                                 endif
                                 **/
                                actlst = glemodService.getAvailAcc(setmodVo.getPtydet().get(rolLin).getDftdsp(), setmodVo.getPtydet().get(rolLin).getDftcur(), setmodVo.getPtydet().get(rolLin).getPtyinr(), BigDecimal.ONE);
                                // Check if selected account is in list and default if necessary
                                Streams.streamSet(actstm, actlst);
                                if (Streams.streamSearch(actstm, setmodVo.getPtydet().get(rolLin).getDftact()) == 0) {
                                    setmodVo.getPtydet().get(rolLin).setDftact(NULLSTR);
                                }
                                if (MdaUtils.isEmpty(setmodVo.getPtydet().get(rolLin).getDftact()) && !MdaUtils.isEmpty(actlst)) {
                                    setmodVo.getPtydet().get(rolLin).setDftact(Strings.getLine(actlst, 1));
                                }
                            }
                        }
                        PtsFeeDetailVo ptydet = setmodVo.getPtydet().get(rolLin);
                        PtsptaVo ptsptaVo = ptsptaToolComponent.getPtsFromListByRol(setmodVo.getPtsList(), ptydet.getRol());
                        // pass handled fields to PTS of contract
                        if (ptsptaVo != null) {
                            if (StringUtils.isEmpty(ptydet.getDftfeecur())) {
                                ptydet.setDftfeecur(ptsptaVo.getDftfeecur());
                            }
                            ptydet.setDftcur(ptsptaVo.getDftcur());
                            ptydet.setDftdsp(ptsptaVo.getDftdsp());
                            ptydet.setDftact(ptsptaVo.getDftact());
                            if (StringUtils.isEmpty(ptydet.getGlggrpflg())) {
                                ptydet.setGlggrpflg(ptsptaVo.getGlggrpflg());
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * source:setmod.0112.script
     */
    public void fillPtyInrStm(IStream argStm) {
        setfegService.getFeeSet().getAllSetpty().forEach(setpty -> {
            argStm.getRows().add(setpty.getPtyInr());
        });
    }

    /**
     * source:setmod.0165.script
     */
    public void registerSettlementZZ(SetmodVo setmodVo) {
        //! installation specific settlement defaulting
        //! Here: Set items that may be changed in transaction
        //! static items, that are constant in transation should be set in inittransaction order 1710 for performance reasons and to avoid changes again and again for items with special settings in SETxxD or transaction.
//			String path = MdaDriver.getModuleInfo(this.getRecgrp(),tdModuleInfoFullName);
        setmodVo.setRef(setmodVo.getRec().getOwnref());
//			int ignore = 0;
//			if( ! Systems.isModified(this,"doccur") )
//			{
//			  this.setDoccur( Datas.getContent(this,path + "\\CBS\\MAX\\CUR"));
//			  if( ctx.getErrorCode() != 0 || MdaUtils.isEmpty(this.getDoccur()) )
//			  {
//				setmodVo.setDoccur( Datas.getContent(this,path + "\\CBS\\NOM1\\CUR"));
//			  }
//			}
        if (!setmodVo.isModified("refdat") && setmodVo.getRefdat() == null) {
            setmodVo.setRefdat(Dates.today());
        }
        Cbb cbb = setmodVo.getCbsMap().get("MAX");
        if (cbb != null) {
            setmodVo.setDoccur(cbb.getCur());
        }
        if (cbb == null || MdaUtils.isEmpty(setmodVo.getDoccur())) {
            cbb = setmodVo.getCbsMap().get("NOM1");
            if (cbb != null) {
                setmodVo.setDoccur(cbb.getCur());
            }
        }
        setmodVo.setOpndat(setmodVo.getRec().getOpndat());
        setmodVo.setExpdat(setmodVo.getRec().getExpdat());
        // expdat is not in all business sectors available:
        // support of GLGGRPFLG in PTS
        int gridCnt = setmodVo.getPtydet().size();
        for (int i = 0; i < gridCnt; i++) {
            PtsFeeDetailVo ptyDet = setmodVo.getPtydet().get(i);
            if (!MdaUtils.isEmpty(ptyDet.getRol())) {
                switch (ptyDet.getGlggrpflg()) {
                    case "F":
                        this.setglgService.setDefaultGlgGrp(setmodVo.getSetglg(), ptyDet.getRol(), "*SETFEG", "F");
                        this.setglgService.setDefaultGlgGrp(setmodVo.getSetglg(), ptyDet.getRol(), "*SETFOG", "F");
                        break;
                    default:
                        this.setglgService.setDefaultGlgGrp(setmodVo.getSetglg(), ptyDet.getRol(), "*SETFEG", "");
                        this.setglgService.setDefaultGlgGrp(setmodVo.getSetglg(), ptyDet.getRol(), "*SETFOG", "");
                }
                if (MdaUtils.compareTo(ptyDet.getRol(), setmodVo.getFeeclirol()) == 0) {
                    setDftFeecur(ptyDet.getRol(), xrtmodService.sysiso(), setmodVo);
                }
            }
        }
        // if contract will be closed, fees for all parties will be settled now and dispositioncode is disable

        setRolDspMdyFlg(setmodVo, "");


    }

    /**
     * source:setmod.0231.script
     */
    public void removeAllGITFEE(String feeName) {
        String sw = NULLSTR;
        String feecode = NULLSTR;
        for (int i = 1; i <= 10; i++) {
            sw = "";
            feecode = feeName + MdaUtils.toString(i);
            this.setfegService.addFeeData(feecode, sw, 1, Dates.today(), Dates.today());
        }
        this.setfegService.addFeeData(feeName, sw, 1, Dates.today(), Dates.today());

    }

    /**
     * source:setmod.0232.script
     */
    public void clearMac(SetglgVo setglgVo) {
        //Clear( MACOLD )
        for (int i = 0; i < setglgVo.getSetgll().size(); i++) {
            if (MdaUtils.compareTo(setglgVo.getSetgll().get(i).getDebcdtflg(), "C") == 0) {
                setglgVo.getSetgll().get(i).setMacold(NULLSTR);
            }
        }
    }

    /**
     * source:setmod.0233.script
     */
    public void setDftDsp(SetmodVo setmodVo, String argRol, String argCur, String argDsp) {
        //! Set default dsp to be used as account dsp for a party (if party is available in settlement)
        int lineNr = getPtyDetRow(argRol, setmodVo);
        if (lineNr >= 0) {
            setmodVo.getPtydet().get(lineNr).setDftcur(argCur);
            setmodVo.getPtydet().get(lineNr).setDftdsp(argDsp);
        }
    }

    /**
     * source:setmod.0240.script
     */
    public void getZmqacc(SetmodVo setmodVo) {
        String zmqflg = "";
        if (SettleContext.getUserSession().getBch() != null) {
            zmqflg = SettleContext.getUserSession().getBch().getZmqflg();
        }
        if ("X".equalsIgnoreCase(zmqflg)) {
            setmodVo.setZmqflg(zmqflg);
            String ptyinr = "";
            Argument<String> ptyinrBox = new Argument<String>("", ptyinr);
            getAPLptyINR("APL", ptyinrBox, setmodVo);
            ptyinr = ptyinrBox.value;

            if (!MdaUtils.isEmpty(ptyinr)) {
                String zmqact = actMapper.getZmqAcc(ptyinr, SettleContext.getUserSession().getBch().getBranch());
                setmodVo.setZmqacc(zmqact);
            }
        }
    }

    @Override
    public void assertFale01(SetmodVo setmodVo) {
        Map<String, Fale01Vo> maps = new HashMap<>();
        List<SetfelVo> setfels = setmodVo.getSetfeg().getSetfel();
        if (setfels != null && setfels.size() > 0) {
            for (SetfelVo setfelVo : setfels) {
                if (setfelVo.getAmt().compareTo(BigDecimal.ZERO) == 0) {
                    continue;
                }
                if (!"X".equals(setfelVo.getDsp())) {
                    continue;
                }
                //查询PTY
                Pty pty = ptyCacheService.getPtyById(setfelVo.getRolptyinr());
                if (pty == null) {
                    continue;
                }
                String ecifcounntry = "";
                if ("B".equals(pty.getPtytyp())) {
                    //如果是B，需要根据BICCODE获取国家地区
                    Pta pta = ptaCacheService.getPtaByInr(setfelVo.getRolptainr());
                    if (pta != null) {
                        String biccode = pta.getBic();
                        if (StringUtils.isNotEmpty(biccode)) {
                            String cty = biccode.substring(4, 6);
                            ecifcounntry = codetableService.getTblLabel(cty, "CTYCOD");
                        }
                    }
                } else {
                    //如果是C通过核心客户号查询 ecfi 表获取国家地区代码
                    ecifcounntry = ptyMapper.selectEcifCountryByPtyinr(setfelVo.getRolptyinr());
                }
                if (StringUtils.isEmpty(ecifcounntry) || "CHN".equals(ecifcounntry)) {
                    continue;
                }
                String trmcod = "";
                String feeacc = setfelVo.getFeeacc();
                if (feeacc.startsWith("??")) {
                    trmcod = feeacc.substring(2, 6);
                }
                if (!"0732".equals(trmcod)
                        && !"2116".equals(trmcod)
                        && !"2392".equals(trmcod)
                        && !"2405".equals(trmcod)
                        && !"2406".equals(trmcod)
                        && !"1926".equals(trmcod)) {
                    continue;
                }
                String key = setfelVo.getCur() + "-" + ecifcounntry + "-" + trmcod;
                if (maps.containsKey(key)) {
                    BigDecimal amt = maps.get(key).getE0103();
                    maps.get(key).setE0103(amt.add(setfelVo.getAmt()));
                } else {
                    Fale01Vo fale01Vo = new Fale01Vo();
                    fale01Vo.setObjcode("110000000700");
                    fale01Vo.setE0101cur(setfelVo.getCur());
                    fale01Vo.setE0101("226000");
                    fale01Vo.setE0102(ecifcounntry);
                    fale01Vo.setE0103(setfelVo.getAmt());
                    fale01Vo.setTrmcod(trmcod);
                    if ("0732".equals(trmcod)) {
                        fale01Vo.setDeptyp("交易银行部国结处");
                    } else {
                        fale01Vo.setDeptyp("交易银行部贸易融资处");
                    }
                    maps.put(key, fale01Vo);
                }
            }
        }
        List<Fale01Vo> fale01List = new ArrayList<>();
        if (maps.size() > 0) {
            fale01List.addAll(maps.values());
        }
        setmodVo.setFale01List(fale01List);
    }

    @Override
    public void saveFale01(SetmodVo setmodVo) {
        List<Fale01Vo> fale01List = setmodVo.getFale01List();
        if (fale01List != null && fale01List.size() > 0) {
            fale01List.forEach(fale01Vo -> {
                Fale01 fale01 = new Fale01();
                BeanUtils.copyProperties(fale01Vo, fale01);
                fale01.setTrninr(transactionHelpService.getTrninr());
                fale01.setInr(counterService.dbCounterFormat("FALE01"));
                fale01.setCredat(Dates.today());
                fale01.setOwnref(setmodVo.getRec().getOwnref());
                fale01.setSta("W");
                fale01Mapper.insert(fale01);
            });
        }
    }

    @Override
    public void updateSetfelObjmod(List<SetfelVo> setfels, String feecod, SimpleModuleVo linkModule) {
        setfels.forEach(setfel -> {
            if (feecod.equals(setfel.getFeecod())) {
                SimpleModuleVo curLinkModule = null;
                try {
                    curLinkModule = Utils.toObject(SimpleModuleVo.class, setfel.getObjmod());
                } catch (Exception e) {
                    log.error("反序列化{}出现异常, {}", setfel.getObjmod(), e.getMessage());
                    curLinkModule = null;
                }
                if (curLinkModule != null && curLinkModule.getObjtyp().equals(linkModule.getObjtyp())) {
                    setfel.setObjmod(Utils.toJson(linkModule));
                }
            }
        });
    }

    /**
     * source:setmod.0241.script
     */
    public void getAPLptyINR(String rol, Argument<String> ptyval, SetmodVo setmodVo) {
        //>>>---面函移植改造中取PTY表字段的值------------
        //ROL：输入的角色，如：APL表示申请人，BEN表示受益人；
        //ptyfileds：要查的PTY表的字段名称；
        //ptyval：输出该ptyfileds字段的值；
        //<<<------------------------------------------
        ptyval.value = "";
        String framename = SettleContext.getTransName();
        String name = Strings.mid(framename, 1, 2);
        //进口保函和出口保函用同一个GID表----------------
        if (MdaUtils.compareTo(name, "GE") == 0) {
            name = "GI";
        }
        String inr = NULLSTR;
        String paytyp = NULLSTR;
        if (MdaUtils.compareTo(Strings.mid(framename, 4, 3), "FRE") == 0) {
            rol = "OTHCC";
        } else {
            switch (Strings.mid(framename, 1, 3)) {
                case "LIT":
                case "BRT":
                case "BDT":
                case "DIT":
                    rol = "APL";
                    break;
                case "BCT":
                    rol = "DRE";
                    break;
                case "BOT":
                    rol = "DRR";
                    break;
                case "BTT":
                    rol = "BE1";
                    break;
                case "LET":
                case "BET":
                case "DET":
                case "BFT":
                    //-----DZTEST-------
                    rol = "BEN";
                    break;
                case "CPT":
                    paytyp = Utils.getFieldValue(setmodVo.getRec(), "paytyp");
                    if (MdaUtils.compareTo(paytyp, "I") == 0 || MdaUtils.compareTo(paytyp, "T") == 0) {
                        rol = "PYE";
                    } else {
                        rol = "ORC";
                    }
                    break;
                case "GIT":
                case "NIT":
                case "HIT":
                    switch (judgeGIGEType(setmodVo)) {
                        case "NI":
                        case "HI":
                        case "GI":
                            rol = "APL";
                            break;
                        case "GE":
                            rol = "BEN";
                            break;
                    }
                    //---光大出口保函交易---
                    break;
                case "NET":
                case "GET":
                    rol = "BEN";
                    break;
                case "TRT":
                    rol = "FIP";
                    break;
                case "CCT":
                    rol = "PRE";
                    break;
                case "BPT":
                    rol = "FIA";
                    break;
                case "MCT":
                    rol = "ADE";
                    break;
            }
        }
        PtsptaVo ptsptaVo = ptsptaToolComponent.getPtsFromListByRol(setmodVo.getPtsList(), rol);
        if (ptsptaVo != null) {
            inr = ptsptaVo.getPtyinr();
        }
        ptyval.value = inr;

    }

    /**
     * source:setmod.0242.script
     */
    public String judgeGIGEType(SetmodVo setmodVo) {
        String flg = "";
        String hndtyp = "";
        String frame = SettleContext.getTransName();
        switch (frame) {
            case "NITSET":
            case "NITPSE":
            case "GITSET":
            case "GITPSE":
                hndtyp = Utils.getFieldValue(setmodVo.getRec(), "hndtyp");
                switch (hndtyp) {
                    case "OL":
                    case "OC":
                        flg = "GI";
                        break;
                    case "FI":
                    case "FA":
                        flg = "GE";
                        //---光大转开保函和出口保函一致----
                        break;
                    case "OT":
                        flg = "GE";
                        break;
                }
                break;
            default:
                flg = Strings.mid(frame, 1, 2);
        }
        return flg;
    }

    /**
     * source:setmod.0028.script
     */
    public void getPtxInr(String rol, Argument<String> ptyinr, Argument<String> ptainr) {
        Setpty setpty = this.setfegService.getFeeSet().getSetpty(rol);
        if (null != setpty) {
            ptyinr.value = setpty.getPtyInr();
            ptainr.value = setpty.getPtaInr();
        }
    }

    /**
     * 收集当前所有的币种
     *
     * @return
     */
    public IStream getXrtcurstm(SetmodVo setmodVo) {
        //! get a list of foreign currcencies used in settlement except base rate currency
        IStream xrtCurStm = new StreamImpl();
        // currencies in summary grid (both sides)
        int gridcnt = setmodVo.getSetglg().getSetgll().size();
        String baseCur = xrtmodService.basRatCur();
        for (int i = 0; i < gridcnt; i++) {
            SetgllVo setgllVo = setmodVo.getSetglg().getSetgll().get(i);
            if (!MdaUtils.isEmpty(setgllVo.getAmt())) {
                if (MdaUtils.compareTo(setgllVo.getCur(), baseCur) != 0) {
                    internalAddToStream(xrtCurStm, setgllVo.getCur());
                }
                if (MdaUtils.compareTo(setgllVo.getAcccur(), baseCur) != 0) {
                    internalAddToStream(xrtCurStm, setgllVo.getAcccur());
                }
            }
        }
        // fee, minimum & maximum currencies from fee calculation
        gridcnt = setmodVo.getSetfeg().getSetfel().size();
        for (int i = 0; i < gridcnt; i++) {
            SetfelVo setfelVo = setmodVo.getSetfeg().getSetfel().get(i);
            if (!MdaUtils.isEmpty(setfelVo.getCur())) {
                if (MdaUtils.compareTo(setfelVo.getCur(), baseCur) != 0) {
                    internalAddToStream(xrtCurStm, setfelVo.getCur());
                }
            }
            if (!MdaUtils.isEmpty(setfelVo.getWrkfec().getMaxcur())) {
                if (MdaUtils.compareTo(setfelVo.getWrkfec().getMaxcur(), baseCur) != 0) {
                    internalAddToStream(xrtCurStm, setfelVo.getWrkfec().getMaxcur());
                }
            }
            if (!MdaUtils.isEmpty(setfelVo.getWrkfec().getMincur())) {
                if (MdaUtils.compareTo(setfelVo.getWrkfec().getMincur(), baseCur) != 0) {
                    internalAddToStream(xrtCurStm, setfelVo.getWrkfec().getMincur());
                }
            }
        }
        // currencies in SETDOC\\SETAMT and SETFOR are passed to SUMTAB.
        // Thus no need to check them seperately

        xrtCurStm.getRows().sort(String::compareTo);
        return xrtCurStm;
    }

    /**
     * Xreflg 判断币种牌价是否可以，如不可用，允许先保存，在release时候要求重算，这个函数和标记很重要
     *
     * @return
     */
    public String getXreflg(SetmodVo setmodVo) {
        //! Activate XRE if there is a currency without current rates in settlement
        if (xrtmodService.isCurrentXrtAvailable(this.getXrtcurstm(setmodVo), Dates.today())) {
            return "";
        } else {
            return "X";
        }
    }

    /**
     * source:setmod.0026.script
     */
    public String getDsp(String frame, BigDecimal amt, SetmodVo setmodVo) {
        //! Standard logic for disposition defaulting
        //! a) get disposition list from supporter function DefSetDsp
        IStream trn = new StreamImpl();
        Streams.streamSet(trn, defSetDsp(frame, amt, setmodVo));
        //! b) remove external dispositions
        int cnt = Streams.streamCount(trn);
        int i = 1;
        while (i <= cnt) {
            if (this.setglgService.isexternaldsp(Strings.getLine(trn, i))) {
                Streams.streamDelete(trn, i);
                cnt = cnt - 1;
            } else {
                i = i + 1;
            }
        }
        //! c) default to DAD/DAC if list is empty
        if (MdaUtils.isEmpty(trn)) {
            if (MdaUtils.compareTo(amt, 0) > 0) {
                Streams.streamInsert(trn, 0, "DAD");
            } else {
                Streams.streamInsert(trn, 0, "DAC");
            }
        }
        //   d) return result
        return MdaUtils.toString(trn);

    }

    /**
     * source:trnism.0029.script
     */
    public String defSetDsp(String frame, BigDecimal amt, SetmodVo setmodVo) {
        // should not include external dispositions,
        // i.e. those that need a separate module and panels
        // So no PAY, TRF, BAT,...
        // cur, curtyp,amt,flg  used in old function : DefSetDsp
        IStream dsps = new StreamImpl();
        Streams.streamClear(dsps);
        Streams.streamInsert(dsps, 0, "LO");
        Streams.streamInsert(dsps, 0, "TP");
        Streams.streamInsert(dsps, 0, "SP");
        Streams.streamInsert(dsps, 0, "AR");
        String busSec = Strings.mid(frame, 1, 2);
        if (MdaUtils.compareTo(amt, 0) > 0) {
            //新增电商支付汇出汇款CPTECO,PANEL为CPTP1,与原汇款逻辑保持一致
            /**
             if $Frame == "CPTOPN" or $Frame == "CPTATO" then
             **/
            if (MdaUtils.compareTo(frame, "CPTOPN") == 0 || MdaUtils.compareTo(frame, "CPTATO") == 0 || MdaUtils.compareTo(frame, "CPTECO") == 0) {
                Streams.streamInsert(dsps, 0, "FI");
            }
            //收费类交易如果客户是同业客户，则允许选择FI
            //MCTSEL下的交易在下方代码里设置了FI,避免选项重复在此屏蔽
            if (MdaUtils.compareTo(Strings.mid(frame, 3, 4), "TFEE") == 0
                    && MdaUtils.compareTo(busSec, "MC") != 0) {
                Streams.streamInsert(dsps, 0, "FI");
            }
        } else {
            // 出报文的DSP
            if (Strings.pos("CPTADVCPTREPCPTATI", frame) == 0) {
                if (MdaUtils.compareTo(frame, "BDTSET") != 0 && MdaUtils.compareTo(frame, "BFTSET") != 0) {
                    Streams.streamInsert(dsps, 0, "PA");
                }
                // 汇入汇款	贷方帐户类型中增加CC/SC/FI，去掉PAC
            } else {
                Streams.streamInsert(dsps, 0, "FI");
            }
            // 贷记的话可以入其他保证金账
            // 080916最新需求，封掉0433 0437账号
            //  StreamInsert( $Dsps, 0, "SC" )
        }
        if (MdaUtils.compareTo(busSec, "MC") == 0) {
            // Manual Contract项下允许记金融机构账
            Streams.streamInsert(dsps, 0, "FI");
            //刘文青要求转账交易下添加保证金账号
            if (MdaUtils.compareTo(frame, "MCTFEE") == 0) {
                Streams.streamInsert(dsps, 0, "CC");
            }
        }
        // 进口信用证和进口保函需要用到保证金的话，在Cash Cover页面处理
        if (Strings.pos("CCTSETGETSETBOTSETBETSET", frame) > 0 || (MdaUtils.compareTo(busSec, "CP") == 0 && MdaUtils.compareTo(amt, 0) < 0)) {
            Streams.streamInsert(dsps, 0, "CC");
        }
        if (MdaUtils.compareTo(frame, "CCTSET") == 0) {
            Streams.streamInsert(dsps, 0, "FI");
        }
        String dsp = "";
        String line = NULLSTR;
        for (int i = 1; i <= Streams.streamCount(dsps); i++) {
            line = Strings.getLine(dsps, i);
            if (MdaUtils.compareTo(amt, 0) > 0) {
                dsp = dsp + CR + line + "D";
            } else {
                dsp = dsp + CR + line + "C";
            }
        }
        // 刘文清需求：trtopn的所有贷方只能选暂收帐
        if (MdaUtils.compareTo(frame, "TRTOPN") == 0 && MdaUtils.compareTo(amt, 0) < 0) {
            return "ARC";
        } else {
            return Strings.mid(dsp, 2);
        }
    }

    /**
     * source:setmod.0075.script
     */
    public String getCurCal(String inCur) {
        // Gets calender for currency
        // Clear Calendar register
        String calChk = "";
        if (!MdaUtils.isEmpty(inCur)) {
            // check where calendar is defined
            String iniValue = Inis.getIniStr("TDPARA.INI", "Compatibility", "CalendarStorage");
            if (MdaUtils.compareTo(iniValue, "1") == 0) {
                calChk = Inis.getIniStr("CALENDAR/CALENDARS.INI", "Calendars", inCur);
            } else {
                // check, if calendar exists
                calChk = Inis.getIniStr("TDPARA.INI", "Calendars", inCur);
            }
        }
        if (MdaUtils.isEmpty(calChk)) {
            return xrtmodService.calendar();
        } else {
            return inCur;
        }
    }

    @Override
    public boolean isHoliday(String cur, Date date) {
        if (date == null) {
            return false;
        }
        Tdh tdh = new Tdh();
        tdh.setCur(cur);
        tdh.setDat(Utils.fmtDate(date, "yyyy-MM-dd"));
        tdh = tdhMapper.queryByCurAndDat(tdh);
        if (tdh != null) {
            return true;
        }
        return false;
    }

    @Override
    public Date addDays(String cur, Date beginDate, int days, boolean workday) {
        if (workday) {
            int i = 1;
            if (days < 0) {
                i = -1;
            }
            Date endDate = DateUtils.addDays(beginDate, days);
            while (isHoliday(cur, endDate)) {
                endDate = DateUtils.addDays(endDate, i);
            }
            return endDate;
        } else {
            return DateUtils.addDays(beginDate, days);
        }
    }

    public BigDecimal getRelAmount(String argRelTyp, String argRol, SetfelVo argSetFel, SetmodVo setmodVo) {
        BigDecimal relamt = null;
        BigDecimal oldamt = null;
        BigDecimal newamt = null;
        switch (argRelTyp) {
            case "AMEMAX":
                relamt = setmodVo.getAmmamt();
                break;
            case "AMEAMT":
                relamt = setmodVo.getAmeamt();
                break;
            case "CONAMT":
                String objmod = argSetFel.getObjmod();
                if (StringUtils.isNotEmpty(objmod)) {
                    try {
                        SimpleModuleVo linkModule = Utils.toObject(SimpleModuleVo.class, objmod);
                        if (linkModule != null && "DFD".equals(linkModule.getObjtyp())) {
                            DftcreVo dftcreVo = setmodVo.getRec().getDftcreVo();
                            if (dftcreVo != null && "X".equals(dftcreVo.getDfflag())) {
                                relamt = dftcreVo.getDfdgrp().getCbs().getMax().getAmt();
                            }
                        }
                    } catch (Exception e) {
                        log.error("反序列化objmod{}发生错误:{}",objmod,e.getMessage());
                    }
                }
                if (MdaUtils.isEmpty(relamt)) {
                    relamt = setmodVo.getConamt();
                }
                break;
            case "MAXAMT":
                relamt = setmodVo.getMaxamt();
                break;
            case "OPNAMT":
                relamt = setmodVo.getOpnamt();
                break;
            case "NETAMT":
                relamt = setmodVo.getNetamt();
                break;
            case "DOCAMT":
                if (MdaUtils.compareTo(setmodVo.getDocamt(), 0) == 0) {
                    relamt = setmodVo.getConamt();
                } else {
                    relamt = setmodVo.getDocamt();
                }
                break;
            case "LIAAMT":
                //   $RELAMT = getOldLiaamt + getNewLiaamt
                oldamt = new BigDecimal("0");
                newamt = new BigDecimal("0");
                // if OBJMOD is a PTEGRP (from LIAALLG) , take mounts from that LIAALLG
                if (argSetFel.getObjmod().indexOf("PTEGRP") > -1) {
                    //获取 \LIAALL\LIAALLG(1)\OLDAMT  \LIAALL\LIAALLG(1)\AMT 只需要取到下标即可
                    int index = Integer.parseInt(argSetFel.getObjmod().substring(argSetFel.getObjmod().indexOf("(") + 1, argSetFel.getObjmod().indexOf(")")));
                    oldamt = setmodVo.getLiaall().getLiaallg().get(index).getOldamt();
                    newamt = setmodVo.getLiaall().getLiaallg().get(index).getAmt();
                } else {
                    List<Setcbs> setcbsList = setfegService.getFeeSet().getAllSetcbs();
                    for (int i = 0; i < setcbsList.size(); i++) {
                        Setcbs setcbs = setcbsList.get(i);
                        if (argRol.equals(setcbs.getRol()) || StringUtils.isEmpty(setcbs.getRol())) {
                            newamt = Decimals.add(newamt, setcbs.getAmt());
                            SimpleModuleVo linkModule = Utils.toObject(SimpleModuleVo.class, setcbs.getObjmod());
                            if (linkModule != null && StringUtils.isNotEmpty(linkModule.getObjinr())) {
                                String objTyp = linkModule.getObjtyp();
                                String objInr = linkModule.getObjinr();
                                //查找cbb数据
                                Date date = Dates.add(Utils.getMaxDate(), -1);
                                Cbb cbb = new Cbb();
                                log.info("cbsGetBalance入参：cbb:{},objTyp:{},objInr:{},cbcArg:{},extId:{},date:{}", cbb, objTyp, objInr, "LIASUM", "AMT1", date);
                                cbsmodService.cbsGetBalance(cbb, objTyp, objInr, "LIASUM", "AMT1", date);
                                oldamt = Decimals.add(oldamt, cbb.getAmt());
                            }
                        }
                    }
                }
                relamt = Decimals.add(oldamt, newamt);
                break;
            default:
                relamt = new BigDecimal("0");
        }
        return relamt;

    }

    @Override
    public String getRelCur(SetfelVo argSetFel, SetmodVo setmodVo) {
        String objmod = argSetFel.getObjmod();
        if (StringUtils.isNotEmpty(objmod)) {
            try {
                SimpleModuleVo linkModule = Utils.toObject(SimpleModuleVo.class, objmod);
                if (linkModule != null && "DFD".equals(linkModule.getObjtyp())) {
                    DftcreVo dftcreVo = setmodVo.getRec().getDftcreVo();
                    if (dftcreVo != null && "X".equals(dftcreVo.getDfflag())) {
                        return dftcreVo.getDfdgrp().getCbs().getMax().getCur();
                    }
                }
            } catch (Exception e) {
                log.error("反序列化objmod{}发生错误:{}",objmod,e.getMessage());
            }
        }
        return argSetFel.getDoccur();
    }

    public Date getRelevantDateForBalances() {
        return Utils.getMaxDate();
    }

    public boolean isInternalDsp(String argDsp) {
        //! Check if ArgDsp is an internal DSP that should not be visible in SWIFT-messages
        //! Returns true, if it is internal
        switch (argDsp) {
            case "FND":
            case "FNC":
            case "HLD":
                return true;
            default:
                return false;
        }
    }

    public void setAmeAmtFun(BigDecimal argAmeAmt, SetmodVo setmodVo) {
        //! to be used for settlement defaulting from RegisterSettlement functions
        //! sets the amendement amendment amount in settlement
        setmodVo.setAmeamt(argAmeAmt);
    }

    /**
     * source:setmod.0045.script
     */
    public void setAmmAmtFun(SetmodVo setmodVo, BigDecimal argAmmAmt) {
        //! to be used for settlement defaulting from RegisterSettlement functions
        //! sets the amendement amendment amount in settlement
        if (!MdaUtils.isEmpty(argAmmAmt)) {
            setmodVo.setAmmamt(argAmmAmt);
        }
    }

    /**
     * source:setmod.0033.script
     */
    public void setConAmtFun(SetmodVo setmodVo, BigDecimal argConAmt) {
        //! to be used for settlement defaulting from RegisterSettlement functions
        //! sets the contract amount in settlement
        if (!MdaUtils.isEmpty(argConAmt)) {
            setmodVo.setConamt(argConAmt);
        }
    }

    public void setCliSetOptFun(SetmodVo setmodVo, String argCliSetOpt) {
        //! to be used for settlement defaulting from RegisterSettlement functions
        //! sets the client disposition option for settlement
        if (StringUtils.isNotEmpty(argCliSetOpt)) {
            setmodVo.setClisetopt(argCliSetOpt);
        }
    }

    public void setForSetOptFun(SetmodVo setmodVo, String argForSetOpt) {
        //取得上下文
        //! to be used for settlement defaulting from RegisterSettlement functions
        //! sets the disposition option for settlement for foreign parties
        setmodVo.setForsetopt(argForSetOpt);
    }

    /**
     * source:setmod.0031.script
     */
    public void setPtyBasics(SetmodVo setmodVo, String argRol, String argPtyInr, String argPtaInr, String argNam) {
        //! Set Party info for Settlement
        //! ArgRol    Role mnemo
        //! ArgPtyInr Party INR
        //! ArgPtaInr Party address INR
        //! ArgNam    Name of Party
        //!
        //! PtsChgAssert sets ourselves (OWN) and the parties of the main contract to settlement.
        //! If additional parties have to be available, use SetPtyData in PtsChgAssert
        /**
         $RolStmLin = ArgRol + TAB + GetText( "$1 : $2", GetAnyRolNam( \\, RecGetObj( \\MTABUT\\REC ), ArgRol, GetUIL ), ArgNam )
         **/
        String rolStmLin = argRol + TAB + codetableService.getTblLabel(argRol, "ROLALL");
        int rolIdx = Streams.streamSearch(setmodVo.getRoldsc(), argRol + TAB);
        if (rolIdx == 0) {
            Streams.streamInsert(setmodVo.getRoldsc(), 0, rolStmLin);
        } else {
            Streams.streamSetLine(setmodVo.getRoldsc(), rolIdx, rolStmLin);
        }
        Setpty setpty = new Setpty();
        setpty.setPtyInr(argPtyInr);
        setpty.setRol(argRol);
        setpty.setPtaInr(argPtaInr);
        setpty.setName(argNam);
        FeeSet feeSet = this.setfegService.getFeeSet();
        feeSet.putSetpty(argRol, setpty);
    }

    /**
     * source:setmod.0050.script
     */
    public String setGlgAmt(SetmodVo setmodVo, String argId, String argRol, String argCur, BigDecimal argAmt, String argAmttyp) {
        //! Transfer an amount to GL of settlement to settle amounts
        //!
        //! ArgId: Id of Caller. All amounts of an ArgId can be removed using SetglgClrAmount (for Transaction use "TRN")
        //! ArgRol : Role for which amount is to be added
        //! ArgCur/ArgAmt: Amount to be added. If the amount is < 0 it is credited, if > 0 it is debitied.
        //!                Calls with amount zero are allowed
        //! ArgAmttyp : Type of amount. See Codetable SETSUMW:DOCAMTTYP. Empty for "document paid"
        //!
        //! Function returns key allowing setting additional information with SetglgAddAmtFld<xxx> -Functions
        return setglgService.setglgAddAmount(setmodVo.getSetglg(), argId, argRol, argCur, argAmt, argAmttyp, "", "", "", "");
    }

    /**
     * source:setmod.0156.script
     */
    public void printSettlement(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetmodVo setmodVo) {
        // No output of settlement for (automatic converted) TradeConnect messages!
        // (DOS.004691) exception: T99 from settlement (automatic converted with multiple bookings or credit amount)
        if (MdaUtils.compareTo(doceotVo.getCortyp(), "TCO") != 0 || MdaUtils.compareTo(doceotVo.getDocnam(), "\\SETMOD\\CMNSET2") == 0) {
			/*
			 PrintAdvisedFees( ROL, $firstfee )
			 PrintSettlementFees( ROL, $firstfee )
			 */
            printSettlementAccounts(dataMap, doceotVo, setmodVo);
            printDetailledSettlement(dataMap, doceotVo, setmodVo);
        }
    }

    /**
     * source:setmod.0172.script
     */
    private void printSettlementAccounts(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetmodVo setmodVo) {
        printSettlementZLB(dataMap, doceotVo, setmodVo, doceotVo.getRole(), "According to the terms and conditions of above mentioned contract we settle as follows:", "");
    }

    /**
     * source:setmod.0169.script
     */
    private void printSettlementZLB(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetmodVo setmodVo, String rol, String intro, String leavetext) {
        //! Print account information for amounts settled to role ROL.
        //! If anything is settled the itrno is printed before and the leavetext is printed after the account information
        // get settled amount to be shown i.e. all amounts except amounts booked to internal financed accounts
        BigDecimal setamt = setglgService.getSetAmtSysByRolTypDsp(setmodVo.getSetglg(), rol, "", "");
        setamt = Decimals.sub(setamt, setglgService.getSetAmtSysByRolTypDsp(setmodVo.getSetglg(), rol, "", "FNC,FND"));
        if (MdaUtils.compareTo(setamt, 0) == 0) {
            return;
        }
        //Platform.printTemp(protect);
        boolean first = true;
        // suggested as floating text. May be shown as table instead
        List<SetgllVo> setgllVoList = setmodVo.getSetglg().getSetgll();
        for (SetgllVo setgllVo : setgllVoList) {
            if (MdaUtils.compareTo(setgllVo.getRol(), rol) == 0 && MdaUtils.compareTo(setgllVo.getAcccpramt(), 0) != 0) {
                // do not print prelimelary credits
                if (MdaUtils.compareTo(setgllVo.getAcccpramt(), 0) > 0) {
                    // do not print for internal financed amounts
                    if (MdaUtils.compareTo(Strings.mid(setgllVo.getDsp(), 1, 2), "FN") != 0 && MdaUtils.compareTo(setgllVo.getDsp(), "HLD") != 0) {
                        // DO5DOS.005004
                        // do not output internal credit entry for BR that pays our finance account
                        if (!(MdaUtils.compareTo(setgllVo.getDsp(), "BRF") == 0 && MdaUtils.compareTo(setgllVo.getAcccpramt(), 0) < 0)) {
                            if (first && (!MdaUtils.isEmpty(intro))) {
                                DocUtils.putData(dataMap, "setmod.simtxt", intro);
                                first = false;
                            }
                            trndocService.xmlPrtEmptyLine(dataMap, 1);
                            if (MdaUtils.compareTo(setgllVo.getDsp(), "BAT") == 0 || MdaUtils.compareTo(setgllVo.getDsp(), "TRF") == 0) {
                                printExtAccountInfo(dataMap, doceotVo, setgllVo);
                            } else {
                                if (MdaUtils.compareTo(setgllVo.getAcccpramt(), 0) < 0) {
                                    printSettlementZLBC03(dataMap, doceotVo, setmodVo.getSetglg(), setgllVo);
                                } else {
                                    printSettlementZLBD03(dataMap, doceotVo, setmodVo.getSetglg(), setgllVo);
                                }
                            }
                        }
                        if (MdaUtils.compareTo(setgllVo.getAcccpramt(), 0) < 0) {
                            switch (setgllVo.getDsp()) {
                                //  case "PAC", "DAC"
                                case "PAC":
                                case "DAC":
                                case "PAY":
                                    trndocService.printTwoAddresses(dataMap, doceotVo, setgllVo.getSetgrp().getAct(), setgllVo.getSetgrp().getActser());
                                    break;
                                case "IBC":
                                    trndocService.printTwoAddresses(dataMap, doceotVo, setgllVo.getSetgrp().getActser(), setgllVo.getSetgrp().getActser());
                                    break;
                            }
                            switch (setgllVo.getDsp()) {
                                //       case "PAC", "IBC"
                                case "PAC":
                                case "IBC":
                                case "PAY":
                                    DocUtils.putData(dataMap, "setmod.qouref");
                                    break;
                            }
                        } else {
                            switch (setgllVo.getDsp()) {
                                case "DAD":
                                case "PAD":
                                    trndocService.printTwoAddresses(dataMap, doceotVo, setgllVo.getSetgrp().getActhol(), setgllVo.getSetgrp().getActser());
                                    break;
                                case "IBD":
                                    trndocService.printTwoAddresses(dataMap, doceotVo, setgllVo.getSetgrp().getActser(), setgllVo.getSetgrp().getActser());
                                    break;
                            }
                            switch (setgllVo.getDsp()) {
                                case "PAD":
                                case "SID":
                                case "IBD":
                                    DocUtils.putData(dataMap, "setmod.qouref");
                                    break;
                            }
                        }
                    }
                }
            }
        }
        if (!first && (!MdaUtils.isEmpty(leavetext))) {
            trndocService.xmlPrtEmptyLine(dataMap, 1);
            DocUtils.putData(dataMap, "setmod.simtxt", leavetext);
        }
        trndocService.xmlPrtEmptyLine(dataMap, 1);
        //Platform.printTemp( Platform.protect ( false ));
    }


    /**
     * source:setmod.0163.script
     */
    private void printExtAccountInfo(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetgllVo setgllVo) {
        String extinf = "";
        BigDecimal amt = setgllVo.getAcccpramt();
        if (MdaUtils.compareTo(setgllVo.getAcccpramt(), 0) < 0) {
            DocUtils.putData(dataMap, "setmod.creditforeign", setgllVo.getAcccur(), trndocService.xmlFmtAmount(doceotVo, amt.negate(), setgllVo.getAcccur()), Formats.fmtDateLong(setgllVo.getValdat()), setgllVo.getAct(), extinf);
        } else {
            DocUtils.putData(dataMap, "setmod.debitforeign", setgllVo.getAcccur(), trndocService.xmlFmtAmount(doceotVo, amt, setgllVo.getAcccur()), Formats.fmtDateLong(setgllVo.getValdat()), setgllVo.getAct(), extinf);
        }
    }

    /**
     * source:setmod.0168.script
     */
    private void printSettlementZLBC03(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetglgVo setglgVo, SetgllVo setgllVo) {
        //! Print account info for a final credit Line
        // Used XML-Tamplate-Ids:
        // Pfc<Dispocode>[Act] for print final debit for <dispocode> with or without account info
        // Special dispocodes used for prefix (Pfx) and payment orders (PAO)
        // For more common templates the fc may be replaced by xx.
        String cur = setgllVo.getAcccur();
        String amt = trndocService.xmlFmtAmount(doceotVo, Numerics.abs(setgllVo.getAcccpramt()), cur) + setglgService.getCprAdd(setglgVo, setgllVo);
        String val = Strings.getText("Value date $1", trndocService.xmlFmtDate(doceotVo, "L", setgllVo.getValdat()));
        //! Return complete representation of account used in line  ArgSetGllLin of SETGLL (e.g. incl. IBAN if set)
        String act = setgllVo.getAct();
        if (!MdaUtils.isEmpty(setgllVo.getActrec().getIban())) {
            act = Strings.getText("$1 ( IBAN $2 )", setgllVo.getAct(), setgllVo.getActrec().getIban());
        }
        DocUtils.putData(dataMap, "setmod.PfCPfx", cur, amt, val);
        DocUtils.putData(dataMap, "setmod.simtxt", "");

        switch (setgllVo.getDsp()) {
            case "DAC":
                DocUtils.putData(dataMap, "setmod.PfCDacAct", cur, amt, val, act);
                //   case "PAC"
                break;
            case "PAC":
            case "PAY":
                if (MdaUtils.isEmpty(setgllVo.getCoractid())) {
                    DocUtils.putData(dataMap, "setmod.PfcPac", cur, amt, val);
                } else {
                    DocUtils.putData(dataMap, "setmod.PfcPacAct", cur, amt, val, setgllVo.getCoractid());
                }
                break;
            case "SIC":
                DocUtils.putData(dataMap, "setmod.PfcSic", cur, amt, val);
                break;
            case "INC":
                DocUtils.putData(dataMap, "setmod.PxxInx", setgllVo.getStrinf52());
                // interbranch accounts are listed like direct accounts
                break;
            case "IBC":
                if (MdaUtils.compareTo(setgllVo.getRolptyinr(), setgllVo.getActrec().getSerptyinr()) == 0 || MdaUtils.compareTo(setgllVo.getRolptyinr(), setgllVo.getActrec().getHolptyinr()) == 0) {
                    DocUtils.putData(dataMap, "setmod.PfCDacAct", cur, amt, val, act);
                } else {
                    DocUtils.putData(dataMap, "setmod.PfcPacAct", cur, amt, val, act);
                }
                break;
        }
    }

    /**
     * source:setmod.0167.script
     */
    private void printSettlementZLBD03(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetglgVo setglgVo, SetgllVo setgllVo) {
        //! Print account info for a final debit Line
        // Used XML-Tamplate-Ids:
        // Pfd<Dispocode>[Act] for print final debit for <dispocode> with or without account info
        // Special dispocodes used for prefix (Pfx) and payment orders (PAO)
        // For more common templates the fd may be replaced by xx.
        String cur = setgllVo.getAcccur();
        String amt = trndocService.xmlFmtAmount(doceotVo, Numerics.abs(setgllVo.getAcccpramt()), cur) + setglgService.getCprAdd(setglgVo, setgllVo);
        String val = Strings.getText("Value date $1", DateUtils.parseDateToStr("dd.MMMMyyyy", setgllVo.getValdat()));
        String act = setgllVo.getAct();
        if (!MdaUtils.isEmpty(setgllVo.getActrec().getIban())) {
            act = Strings.getText("$1 ( IBAN $2 )", setgllVo.getAct(), setgllVo.getActrec().getIban());
        }
        DocUtils.putData(dataMap, "setmod.PxxPfx", cur, amt, val);
        DocUtils.putData(dataMap, "setmod.simtxt", "");


        switch (setgllVo.getDsp()) {
            case "DAD":
                DocUtils.putData(dataMap, "setmod.PfdDad", cur, amt, val, act);
                break;
            case "PAD":
                if (MdaUtils.isEmpty(setgllVo.getCoractid())) {
                    DocUtils.putData(dataMap, "setmod.PfdPad", cur, amt, val);
                } else {
                    DocUtils.putData(dataMap, "setmod.PfdPadAct", cur, amt, val, setgllVo.getCoractid());
                }
                break;
            case "SID":
                DocUtils.putData(dataMap, "setmod.PfdSicAct", cur, amt, val, SettleContext.getUserSession().getEty().getClearid(), act, SettleContext.getUserSession().getEty().getExtkey());
                break;
            case "IND":
                DocUtils.putData(dataMap, "setmod.PxxInx", setgllVo.getStrinf52());
                // interbranch accounts are listed like direct accounts
                break;
            case "IBD":
                if (MdaUtils.compareTo(setgllVo.getRolptyinr(), setgllVo.getActrec().getSerptyinr()) == 0 || MdaUtils.compareTo(setgllVo.getRolptyinr(), setgllVo.getActrec().getHolptyinr()) == 0) {
                    DocUtils.putData(dataMap, "setmod.PfdDad", cur, amt, val, act);
                } else {
                    DocUtils.putData(dataMap, "setmod.PfdPadAct", cur, amt, val, act);
                }
                break;
        }
    }

    /**
     * source:setmod.0158.script
     */
    private void printDetailledSettlement(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetmodVo setmodVo) {
        String rol = doceotVo.getRole();
        IStream curstm = new StreamImpl();
        Streams.streamSet(curstm, getSettledCur(setmodVo, rol, "X" + CR + "S", "X" + CR + "S", "FNC" + CR + "FND" + CR + "HLD"));
        // if nothing settled, skip to print of advised fees
        if (!MdaUtils.isEmpty(curstm)) {
            // get settled amount to be shown i.e. all amounts except amounts booked to internal financed accounts
            BigDecimal setamt = setglgService.getSetAmtSysByRolTypDsp(setmodVo.getSetglg(), rol, "", "");
            setamt = Decimals.sub(setamt, setglgService.getSetAmtSysByRolTypDsp(setmodVo.getSetglg(), rol, "", "FNC,FND,HLD"));
            //Platform.printTemp( protect);
            //header
            if (MdaUtils.compareTo(setamt, 0) > 0) {
                DocUtils.putData(dataMap, "setmod.DETHEAdbt");
            } else {
                // avoid header if sum = 0
                if (MdaUtils.compareTo(setamt, 0) < 0) {
                    DocUtils.putData(dataMap, "setmod.DETHEAcdt");
                }
            }
            int stmCnt = Streams.streamCount(curstm);
            String doccur = NULLSTR;
            int gridcnt = 0;
            int fnd = 0;
            String line = NULLSTR;
            int tabpos = 0;
            String modid = NULLSTR;
            BigDecimal diff = null;
            String details = NULLSTR;
            IStream enostm = new StreamImpl();
            IStream groupedfees = new StreamImpl();
            int stmCntEno = 0;
            int i = 0;
            String feegrp = NULLSTR;
            String grp = NULLSTR;
            int oldidx = 0;
            String oldlin = NULLSTR;
            int oldamt = 0;
            int stmCntGro = 0;
            String lin = NULLSTR;
            BigDecimal amt = null;
            String feetxt = NULLSTR;
            String newcur1 = NULLSTR;
            BigDecimal rat1 = null;
            BigDecimal newamt1 = null;
            String refcur = NULLSTR;
            String newcur2 = NULLSTR;
            Boolean ininflg = null;
            String amtcur = NULLSTR;
            String newcurc = NULLSTR;
            BigDecimal newamtc = null;
            BigDecimal rat2 = null;
            for (int curstmidx = 1; curstmidx <= stmCnt; curstmidx++) {
                //Platform.printTemp( protect);
                doccur = Strings.getLine(curstm, curstmidx);
                // initialization
                setmodVo.setPrtdetcnt(0);
                setmodVo.setPrtdetamt(new BigDecimal("0"));
                setamt = new BigDecimal("0");
                List<SetgllVo> setgllVoList = setmodVo.getSetglg().getSetgll();
                for (SetgllVo setgllVo : setgllVoList) {
                    if (MdaUtils.compareTo(setgllVo.getRol(), rol) == 0 && MdaUtils.compareTo(setgllVo.getCur(), doccur) == 0) {
                        switch (setgllVo.getDsp()) {
                            case "FNC":
                            case "FND":
                            case "HLD":
                                break;
                            default:
                                setamt = Decimals.add(setamt, setgllVo.getAmt());
                        }
                    }
                }
                // print main amounts settled to that role in this transaction (ABB02) except amounts booked to internal financed accounts
                // DO5DOS.003093
                // sort amounts set by transaction to top
                //   because "Amount financed" must not be at 1st position
                fnd = Streams.streamSearch(setmodVo.getSetglg().getSetglgamtcon(), "TRN");
                while (fnd > 0) {
                    line = Strings.getLine(setmodVo.getSetglg().getSetglgamtcon(), fnd);
                    Streams.streamDelete(setmodVo.getSetglg().getSetglgamtcon(), fnd);
                    Streams.streamInsert(setmodVo.getSetglg().getSetglgamtcon(), 1, line);
                    fnd = Streams.streamSearch(setmodVo.getSetglg().getSetglgamtcon(), "TRN", fnd + 1);
                }
                for (i = 1; i <= Streams.streamCount(setmodVo.getSetglg().getSetglgamtcon()); i++) {
                    line = Strings.getLine(setmodVo.getSetglg().getSetglgamtcon(), i);
                    tabpos = Strings.pos(line, TAB);
                    modid = Strings.mid(line, 1, tabpos - 1);
                    // do not show amounts internally set by modules of SETMOD
                    if (MdaUtils.compareTo(Strings.mid(modid, 1, 4), "*SET") != 0) {
                        line = Strings.mid(line, tabpos + 1);
                        line = Strings.mid(line, 1, Strings.pos(line, CR) - 1);
                        Wrksum wrksum = setmodVo.getWrksumMap().get(modid + TAB + line);
                        if (MdaUtils.compareTo(wrksum.getRol(), rol) == 0) {
                            if (MdaUtils.compareTo(wrksum.getCur(), doccur) == 0) {
                                if (MdaUtils.compareTo(Strings.mid(wrksum.getDsp(), 1, 2), "FN") != 0 && MdaUtils.compareTo(wrksum.getDsp(), "HLD") != 0) {
                                    // DO5DOS.005004
                                    // do not output internal credit entry for BR that pays our finance account
                                    if (!(MdaUtils.compareTo(wrksum.getDsp(), "BRF") == 0 && MdaUtils.compareTo(wrksum.getAmt(), 0) < 0)) {
                                        // (DOS.005028)
                                        // get difference between document amount and calculated basic amount
                                        diff = Decimals.sub(setmodVo.getDocamt(), wrksum.getAmt());
                                        // If difference is equal with reduction amount, DOCAMT and WRKSUM\\AMT are equal.
                                        //   That indicates that document amount will be settled only.
                                        if (MdaUtils.compareTo(diff, setmodVo.getRedamt()) == 0) {
                                            // DOCAMT - REDAMT = WRKSUM\\AMT
                                            printDetailledAmount(dataMap, doceotVo, setmodVo, trndocService.xmlGetTblText(doceotVo, wrksum.getDocamttyp(), "SETSUMW:DOCAMTTYP"), doccur, setmodVo.getDocamt(), setamt);
                                            // print details for reduction of document amount
                                            details = Strings.getText("Less Reduction Amount $1", setmodVo.getRedamt());
                                            printDetailledAmount(dataMap, doceotVo, setmodVo, details, doccur, setmodVo.getRedamt().negate(), setamt);
                                        } else {
                                            // If difference is unequal with REDAMT, other amounts than DOCAMT will be settled.
                                            printDetailledAmount(dataMap, doceotVo, setmodVo, trndocService.xmlGetTblText(doceotVo, wrksum.getDocamttyp(), "SETSUMW:DOCAMTTYP"), doccur, wrksum.getAmt(), setamt);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                // print foreign charges (ABB03)
                for (SetfolVo setfolVo : setmodVo.getSetfog().getSetfol()) {
                    if (MdaUtils.compareTo(setfolVo.getCur(), doccur) == 0 && (MdaUtils.compareTo(setfolVo.getDsp(), "X") == 0 || MdaUtils.compareTo(setfolVo.getDsp(), "S") == 0)) {
                        if (MdaUtils.compareTo(getGllRol(setfolVo.getPtypay()), rol) == 0) {
                            printDetailledAmount(dataMap, doceotVo, setmodVo, setfolService.setFolGetTxtpay(setfolVo, doceotVo.getDocuil()), doccur, setfolVo.getAmt().negate(), setamt);
                        }
                        if (MdaUtils.compareTo(getGllRol(setfolVo.getPtydbt()), rol) == 0) {
                            printDetailledAmount(dataMap, doceotVo, setmodVo, setfolService.setFolGetTxtdbt(setfolVo, doceotVo.getDocuil()), doccur, setfolVo.getAmt(), setamt);
                        }
                    }
                }
                // sort charges by ENO
                Streams.streamClear(enostm);
                Streams.streamSort(enostm, true);
                for (i = 0; i < setmodVo.getSetfeg().getSetfel().size(); i++) {
                    Fee fee = feeMapper.selectByCod(setmodVo.getSetfeg().getSetfel().get(i).getFeecod());
                    if (fee != null) {
                        Streams.streamInsert(enostm, 0, fee.getEno() + MdaUtils.toString(i + 1, -3) + TAB + MdaUtils.toString(i + 1, -3));
                    }
                }
                // print our charges (ABB05)
                Streams.streamClear(groupedfees);
                stmCntEno = Streams.streamCount(enostm);
                for (int enorow = 1; enorow <= stmCntEno; enorow++) {
                    line = Strings.getLine(enostm, enorow);
                    i = Strings.parseInt(Strings.mid(line, Strings.pos(line, TAB) + 1));
                    if (MdaUtils.compareTo(getGllRol(setmodVo.getSetfeg().getSetfel().get(i - 1).getRol()), rol) == 0 && MdaUtils.compareTo(setmodVo.getSetfeg().getSetfel().get(i - 1).getAmt(), 0) != 0 && MdaUtils.compareTo(setmodVo.getSetfeg().getSetfel().get(i - 1).getCur(), doccur) == 0) {
                        if (MdaUtils.compareTo(setmodVo.getSetfeg().getSetfel().get(i - 1).getDsp(), "X") == 0 || MdaUtils.compareTo(setmodVo.getSetfeg().getSetfel().get(i - 1).getDsp(), "S") == 0) {
                            grp = setmodVo.getSetfeg().getSetfel().get(i - 1).getFeecod();
                            oldidx = Streams.streamSearch(groupedfees, grp + TAB);
                            if (oldidx == 0) {
                                Streams.streamInsert(groupedfees, 0, grp + TAB + MdaUtils.toString(setmodVo.getSetfeg().getSetfel().get(i - 1).getAmt()));
                            } else {
                                oldlin = Strings.getLine(groupedfees, oldidx);
                                oldamt = Strings.parseInt(Strings.mid(oldlin, Strings.pos(oldlin, TAB) + 1));
                                Streams.streamSetLine(groupedfees, oldidx, grp + TAB + MdaUtils.toString(Decimals.add(setmodVo.getSetfeg().getSetfel().get(i - 1).getAmt(), oldamt)));
                            }
                        }
                    }
                }
                // print compressed fee information
                stmCntGro = Streams.streamCount(groupedfees);
                if (stmCntGro > 0) {
                    Streams.streamSort(groupedfees, true);
                    for (i = 1; i <= stmCntGro; i++) {
                        lin = Strings.getLine(groupedfees, i);
                        grp = Strings.mid(lin, 1, Strings.pos(lin, TAB) - 1);
                        amt = new BigDecimal(Strings.mid(lin, Strings.pos(lin, TAB) + 1));
                        feetxt = trndocService.xmlGetTblText(doceotVo, grp, "FEEGRP");
                        if (MdaUtils.isEmpty(feetxt)) {
                            feetxt = trndocService.xmlGetTblText(doceotVo, grp, "FEETXT");
                        }
                        printDetailledAmount(dataMap, doceotVo, setmodVo, feetxt, doccur, amt, setamt);
                    }
                }
                // print total amount (ABB06)
                if (MdaUtils.compareTo(setamt, 0) > 0) {
                    printDETSETTAB(dataMap, doceotVo, "Total", " ", doccur, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(setmodVo.getPrtdetamt()), doccur));
                } else {
                    // avoid "Total" line if sum = 0
                    if (MdaUtils.compareTo(setamt, 0) < 0) {
                        printDETSETTAB(dataMap, doceotVo, "Total", " ", doccur, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(setmodVo.getPrtdetamt()), doccur));
                    }
                }
                // conversion information (ABB07+ABB08+ABB09 )
                // print if final or temporary settlement
                for (SetgllVo setgllVo : setmodVo.getSetglg().getSetgll()) {
                    if (MdaUtils.compareTo(setgllVo.getRol(), rol) == 0 && MdaUtils.compareTo(setgllVo.getAmt(), 0) != 0 && MdaUtils.compareTo(setgllVo.getCur(), doccur) == 0) {
                        if (MdaUtils.compareTo(setgllVo.getAcccur(), setgllVo.getCur()) == 0) {
                            newcur1 = xrtmodService.getCurNewCur(setgllVo.getCur());
                            if (!MdaUtils.isEmpty(newcur1)) {
                                trndocService.xmlPrtEmptyLine(dataMap, 1);
                                rat1 = xrtmodService.getCurGlbRat(setgllVo.getCur());
                                newamt1 = Decimals.div(Numerics.abs(setgllVo.getAccamt()), rat1);
                                printDETSETTAB(dataMap, doceotVo, Strings.getText("$1 $3 at the rate of $4", setgllVo.getCur(), newcur1, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(setgllVo.getAmt()), setgllVo.getCur()), rat1), " ", newcur1, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(newamt1), newcur1));
                            }
                        } else {
                            trndocService.xmlPrtEmptyLine(dataMap, 1);
                            refcur = xrtmodService.sysiso();
                            Argument<String> newcur1Box = new Argument<String>("", newcur1);
                            Argument<String> newcur2Box = new Argument<String>();
                            Argument<String> refcurBox = new Argument<String>("", refcur);
                            Argument<Boolean> ininflgBox = new Argument<Boolean>();
                            xrtmodService.xrtCheckInIn(setgllVo.getCur(), setgllVo.getAcccur(), newcur1Box, newcur2Box, refcurBox, ininflgBox);

                            newcur1 = newcur1Box.value;
                            newcur2 = newcur2Box.value;
                            refcur = refcurBox.value;
                            ininflg = ininflgBox.value;

                            amtcur = setgllVo.getCur();
                            amt = setgllVo.getAmt();
                            if (!MdaUtils.isEmpty(newcur1)) {
                                rat1 = xrtmodService.getCurGlbRat(setgllVo.getCur());
                                newamt1 = xrtmodService.amtRnd(Decimals.div(Numerics.abs(setgllVo.getAmt()), rat1), newcur1);
                                printDETSETTAB(dataMap, doceotVo, Strings.getText("$1 $3 at the rate of $4", setgllVo.getCur(), newcur1, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(setgllVo.getAmt()), setgllVo.getCur()), rat1), " ", newcur1, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(newamt1), newcur1));
                                amtcur = newcur1;
                                amt = newamt1;
                            }
                            if (!ininflg) {
                                if (MdaUtils.isEmpty(newcur2)) {
                                    newcurc = setgllVo.getAcccur();
                                    newamtc = setgllVo.getAccamt();
                                } else {
                                    newcurc = newcur2;
                                    newamtc = xrtmodService.amtRnd(Decimals.div(setgllVo.getAccamt(), xrtmodService.getCurGlbRat(setgllVo.getAcccur())), newcur2);
                                }
                                printDETSETTAB(dataMap, doceotVo, Strings.getText("$1 $3 at the rate of $4", amtcur, newcurc, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(amt), amtcur), setgllVo.getRat()), " ", newcurc, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(newamtc), newcurc));
                                amt = newamtc;
                                amtcur = newcurc;
                            }
                            if (!MdaUtils.isEmpty(newcur2)) {
                                rat2 = xrtmodService.getCurGlbRat(setgllVo.getAcccur());
                                printDETSETTAB(dataMap, doceotVo, Strings.getText(MdaUtils.getI18NString("setmod", "CT000328"), newcur2, setgllVo.getAcccur(), trndocService.xmlFmtAmount(doceotVo, Numerics.abs(amt), amtcur), rat2), " ", setgllVo.getAcccur(), trndocService.xmlFmtAmount(doceotVo, Numerics.abs(setgllVo.getAccamt()), setgllVo.getAcccur()));
                            }
                        }
                    }

                }
                trndocService.xmlPrtEmptyLine(dataMap, 1);
            }
        }
        // ####### 改写 LABEL与GOTO   ####    label PrtAdv
        // Print fees advised
        boolean firstfee = false;
        /*
         XMLPrtEmptyLine( 1 )
         */
        printAdvisedFees(dataMap, doceotVo, setmodVo, rol, firstfee);
    }

    /**
     * source:setmod.0076.script
     */
    private String getSettledCur(SetmodVo setmodVo, String argRol, String argDspFxgCdt, String argDspFxgDbt, String argExclDspGll) {
        IStream res = new StreamImpl();
        Streams.streamClear(res);
        IStream dspFxgCdt = new StreamImpl();
        Streams.streamSet(dspFxgCdt, argDspFxgCdt);
        IStream dspFxgdbt = new StreamImpl();
        Streams.streamSet(dspFxgdbt, argDspFxgDbt);
        IStream excl = new StreamImpl();
        Streams.streamSet(excl, argExclDspGll);
        // check own charges grid
        List<SetfelVo> setfelVoList = setmodVo.getSetfeg().getSetfel();
        for (SetfelVo setfelVo : setfelVoList) {
            if (!MdaUtils.isEmpty(setfelVo.getDsp())) {
                if (MdaUtils.compareTo(argRol, setfelVo.getRol()) == 0) {
                    if (Streams.streamSearch(dspFxgdbt, setfelVo.getDsp()) > 0) {
                        if (Streams.streamSearch(res, setfelVo.getCur()) == 0) {
                            Streams.streamInsert(res, 0, setfelVo.getCur());
                        }
                    }
                }
            }
        }
        // check foreign fees
        List<SetfolVo> setfolVoList = setmodVo.getSetfog().getSetfol();
        for (SetfolVo setfolVo : setfolVoList) {
            if (!MdaUtils.isEmpty(setfolVo.getDsp())) {
                if (MdaUtils.compareTo(setfolVo.getPtydbt(), argRol) == 0) {
                    if (Streams.streamSearch(dspFxgdbt, setfolVo.getDsp()) > 0) {
                        if (Streams.streamSearch(res, setfolVo.getCur()) == 0) {
                            Streams.streamInsert(res, 0, setfolVo.getCur());
                        }
                    }
                }
                if (MdaUtils.compareTo(setfolVo.getPtypay(), argRol) == 0) {
                    if (Streams.streamSearch(dspFxgCdt, setfolVo.getDsp()) > 0) {
                        if (Streams.streamSearch(res, setfolVo.getCur()) == 0) {
                            Streams.streamInsert(res, 0, setfolVo.getCur());
                        }
                    }
                }
            }
        }
        // check GL grid (if not ourselves)
        if (MdaUtils.compareTo(argRol, "OWN") != 0) {
            List<SetgllVo> setgllVoList = setmodVo.getSetglg().getSetgll();
            for (SetgllVo setgllVo : setgllVoList) {
                if (MdaUtils.compareTo(argRol, setgllVo.getRol()) == 0 && (!MdaUtils.isEmpty(setgllVo.getAcccpramt())) && Streams.streamSearch(excl, setgllVo.getDsp()) == 0) {
                    if (Streams.streamSearch(res, setgllVo.getCur()) == 0) {
                        Streams.streamInsert(res, 0, setgllVo.getCur());
                    }
                }
            }
        }
        return MdaUtils.toString(res);
    }

    /**
     * source:setmod.0159.script
     */
    private void printDetailledAmount(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetmodVo setmodVo, String argDsc, String argCur, BigDecimal argAmt, BigDecimal argTotAmt) {
        String prtdetsgnflg = "";
        if (MdaUtils.compareTo(argAmt, 0) != 0) {
            // DO5WLB.000623 - use sgn() to avoid dump with arithmetic overflow by multiplication of very big amounts
            if (Numerics.sgn(argTotAmt) * Numerics.sgn(argAmt) < 0) {
                prtdetsgnflg = "-";
            } else {
                if (setmodVo.getPrtdetcnt() > 0) {
                    prtdetsgnflg = "+";
                }
            }
            printDETSETTAB(dataMap, doceotVo, argDsc, prtdetsgnflg, argCur, trndocService.xmlFmtAmount(doceotVo, Numerics.abs(argAmt), argCur));
            setmodVo.setPrtdetcnt(setmodVo.getPrtdetcnt() + 1);
            setmodVo.setPrtdetamt(Decimals.add(setmodVo.getPrtdetamt(), argAmt));
        }
    }

    /**
     * source:setmod.0161.script
     */
    private void printDETSETTAB(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, String desc, String sign, String cur, String amt) {
        int length = trndocService.getCurrentCORLineLength(doceotVo);
        if (length < 0) {
            // -2 is ASCII without restriction, thus print description & amount in two lines
            if (length == -2) {
                DocUtils.putData(dataMap, "", desc + "\r\n");
                DocUtils.putData(dataMap, "", " " + Strings.mid(sign, 1, 1) + " " + Strings.mid(cur, 1, 3) + " " + Strings.mid(amt, 1, 18) + "\r\n");
            } else {
                DocUtils.putData(dataMap, "setmod.DETSETTAB", desc, sign, cur, amt);
            }
        } else {
            // print for Telex/Fax/email
            DocUtils.putData(dataMap, "", Strings.mid(desc, 1, length - 25), " ", Strings.mid(sign, 1, 1), " ", Strings.mid(cur, 1, 3), " ", Strings.mid(amt, 1, 18));
        }
    }

    /**
     * source:setmod.0160.script
     */
    private void printAdvisedFees(Map<String, List<String[]>> dataMap, DoceotVo doceotVo, SetmodVo setmodVo, String rol, Boolean firstfee) {
        boolean first = true;
        boolean feePrinted = false;
        for (SetfolVo setfolVo : setmodVo.getSetfog().getSetfol()) {
            String desc = NULLSTR;
            if (MdaUtils.compareTo(getGllRol(setfolVo.getPtydbt()), rol) == 0 && MdaUtils.compareTo(setfolVo.getAmt(), 0) != 0) {
                if ((MdaUtils.compareTo(setfolVo.getDsp(), "V") == 0)) {
                    if (firstfee) {
                        DocUtils.putData(dataMap, "setmod.feetitle", "Guarantee");
                        firstfee = false;
                    }
                    if (first) {
                        DocUtils.putData(dataMap, "setmod.advnow");
                        first = false;
                    }
                    desc = setfolService.setFolGetTxtdbt(setfolVo, doceotVo.getDocuil());
                    printDETSETTAB(dataMap, doceotVo, desc, "", setfolVo.getCur(), trndocService.xmlFmtAmount(doceotVo, setfolVo.getAmt(), setfolVo.getCur()));
                    feePrinted = true;
                }
            }
        }
        IStream groupedfees = new StreamImpl();
        String feegrp = NULLSTR;
        String grp = NULLSTR;
        int oldidx = 0;
        String oldlin = NULLSTR;
        String lin = NULLSTR;
        BigDecimal oldamt = BigDecimal.ZERO;
        String oldCur = NULLSTR;
        int stmCnt = 0;
        String feetxt = NULLSTR;
        for (SetfelVo setfelVo : setmodVo.getSetfeg().getSetfel()) {
            Streams.streamClear(groupedfees);
            if (!MdaUtils.isEmpty(setfelVo.getFeecod())) {
                if (MdaUtils.compareTo(getGllRol(setfelVo.getRol()), rol) == 0 && MdaUtils.compareTo(setfelVo.getAmt(), 0) != 0) {
                    if ((MdaUtils.compareTo(setfelVo.getDsp(), "V") == 0)) {
                        if (firstfee) {
                            DocUtils.putData(dataMap, "setmod.feetitle", "Guarantee");
                            firstfee = false;
                        }
                        if (first) {
                            DocUtils.putData(dataMap, "setmod.advnow");
                            first = false;
                        }
                        printDETSETTAB(dataMap, doceotVo, getFeetxtInfDocUil(setfelVo), "", setfelVo.getCur(), trndocService.xmlFmtAmount(doceotVo, setfelVo.getAmt(), setfelVo.getCur()));
                        feePrinted = true;
                    }
                }
            }
        }

        if (setmodVo.getSetfog().getSetfol().size() > 0) {
            first = true;
            for (SetfolVo setfolVo : setmodVo.getSetfog().getSetfol()) {
                if (MdaUtils.compareTo(getGllRol(setfolVo.getPtypay()), rol) == 0 && MdaUtils.compareTo(setfolVo.getAmt(), 0) != 0) {
                    if ((MdaUtils.compareTo(setfolVo.getDsp(), "V") == 0)) {
                        if (firstfee) {
                            DocUtils.putData(dataMap, "setmod.feetitle", "Guarantee");
                            firstfee = false;
                        }
                        if (first) {
                            DocUtils.putData(dataMap, "setmod.advnowPay");
                            first = false;
                        }
                        String desc = setfolService.setFolGetTxtpay(setfolVo, doceotVo.getDocuil());
                        printDETSETTAB(dataMap, doceotVo, desc, "", setfolVo.getCur(), trndocService.xmlFmtAmount(doceotVo, setfolVo.getAmt(), setfolVo.getCur()));
                        feePrinted = true;
                    }
                }
            }
        }
        if (!first) {
            DocUtils.putData(dataMap, "setmod.bottombox");
        }
        if (feePrinted) {
            trndocService.xmlPrtEmptyLine(dataMap, 1);
        }
    }

    @Override
    public boolean checkIfAnyFeeSettled(List<SetfelVo> setfelVoList, String rol) {
        return setfelVoList.stream().anyMatch(setfelVo -> setfelVo.getRol().equals(rol) && "X".equals(setfelVo.getDsp()));
    }

    @Override
    public boolean checkIfAnyFeeSettledDsp(List<SetfelVo> setfelVoList, String rol, String dsp) {
        return setfelVoList.stream().anyMatch(setfelVo -> setfelVo.getRol().equals(rol) && dsp.equals(setfelVo.getDsp()));
    }

    @Override
    public SetgllVo getSetgllVoByRol(List<SetgllVo> setgllVoList, String rol) {
        return setgllVoList.stream().filter(setgllVo -> setgllVo.getRol().equals(rol)).findAny().orElse(null);
    }

    /**
     * source:setmod.0071.script
     *
     * @param setfelVo
     */
    private String getFeetxtInfDocUil(SetfelVo setfelVo) {
        //! Get Fee long text in document language
        //! (i.e. recalculate in document language if not modified and not retrieved from pool)
        return setfelVo.getFeetxtinf();

    }

    /**
     * 判断业务是否为国内证
     * 用于获取SPC 是01还是02
     *
     * @param setmodVo
     */
    private void setDflg(SetmodVo setmodVo) {
        String objtyp = setmodVo.getRec().getObjtyp();
        if ("DID".equals(objtyp) || "DED".equals(objtyp) || "BDD".equals(objtyp) || "BFD".equals(objtyp)) {
            setfegService.getFeeSet().setDflg("D");
        } else {
            String pnttyp = setmodVo.getRec().getPnttyp();
            if (StringUtils.isEmpty(pnttyp)) {
                if ("BPD".equals(objtyp)) {
                    String objinr = setmodVo.getRec().getObjinr();
                    String fortyp = Utils.getFieldValue(setmodVo.getRec(), "fortyp", "");
                    if (StringUtils.isEmpty(fortyp)) {
                        fortyp = dyncDaoService.dyncReadFieldByInr(objtyp, objinr, "fortyp");
                    }
                    String fintyp = Utils.getFieldValue(setmodVo.getRec(), "fintyp", "");
                    if (StringUtils.isEmpty(fintyp)) {
                        fintyp = dyncDaoService.dyncReadFieldByInr(objtyp, objinr, "fintyp");
                    }
                    if ("2".equals(fortyp) && "G".equals(fintyp)) {
                        setfegService.getFeeSet().setDflg("D");
                    }
                }
            } else if ("DID".equals(pnttyp) || "DED".equals(pnttyp) || "BDD".equals(pnttyp) || "BFD".equals(pnttyp)) {
                setfegService.getFeeSet().setDflg("D");
            }
        }
    }
}