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

import com.brilliance.mda.runtime.mda.IStream;
import com.brilliance.mda.runtime.mda.impl.Argument;
import com.brilliance.mda.runtime.mda.impl.StreamImpl;
import com.brilliance.mda.runtime.mda.util.*;
import com.brilliance.isc.bo.Cbb;
import com.brilliance.isc.bo.Fec;
import com.brilliance.isc.bo.Fee;
import com.brilliance.isc.bo.Fep;
import com.brilliance.isc.common.cbsmod.CbsRange;
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.converter.DtoMapper;
import com.brilliance.isc.common.exception.CommonServiceException;
import com.brilliance.isc.common.fecism.calcfee.helper.CalcFeeRequestBuilder;
import com.brilliance.isc.common.fecism.service.FecismService;
import com.brilliance.isc.common.fecism.vo.CalcFeeRequest;
import com.brilliance.isc.common.fecism.vo.CalcFeeResponse;
import com.brilliance.isc.common.fecmod.service.FecmodService;
import com.brilliance.isc.common.setfeg.fee.FeeEntity;
import com.brilliance.isc.common.setfeg.fee.Setpty;
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.setglg.service.SetglgService;
import com.brilliance.isc.common.setmod.service.SetmodService;
import com.brilliance.isc.common.setmod.vo.CommCbsLine;
import com.brilliance.isc.common.setmod.vo.SetmodVo;
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.mda.dao.FeeMapper;
import com.brilliance.isc.mda.dao.FepMapper;
import com.brilliance.isc.utils.StringUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.*;

@Service("setfelService")
public class SetfelServiceImpl implements SetfelService {
    private static Logger log = LoggerFactory.getLogger(SetfelServiceImpl.class);


    @Autowired
    private XrtmodService xrtmodService;

    @Autowired
    private FeeMapper feeMapper;

    @Autowired
    private FepMapper fepMapper;

    @Autowired
    private SetmodService setmodService;

    @Autowired
    private SetfegService setfegService;

    @Autowired
    private FecismService fecismService;

    @Autowired
    private CodetableService codetableService;

    @Autowired
    private SetglgService setglgService;

    @Autowired
    private FecmodService fecmodService;

    @Autowired
    private CbsRange cbsRange;

    @Autowired
    private DyncDaoService dyncDaoService;

    @Override
    public void calcMac(SetfelVo setfelVo, SetmodVo setmodVo) {
        // Start with installation specific portion
        IStream stm = new StreamImpl();
        Streams.streamSet(stm, getSetFelIsfMac(setfelVo, setmodVo));
        Streams.streamInsert(stm, 0, Utils.toJson(setmodVo.getRec()));
        Streams.streamInsert(stm, 0, setmodVo.getRoldsc());
        Streams.streamInsert(stm, 0, setfelVo.getRol() + setfelVo.getRolptyinr() + setfelVo.getFeecod() + setfelVo.getSrc() + setfelVo.getDsp() + MdaUtils.toString(setfelVo.getUnt()) + setfelVo.getCur() + Numerics.round(setfelVo.getAmt(), 2) + Formats.fmtDateShort(setfelVo.getDat1()) + Formats.fmtDateShort(setfelVo.getDat2()) + Formats.fmtDateShort(setfelVo.getDat2dft()) + Numerics.round(setfelVo.getUntamt(), 2) + setfelVo.getRolptainr() + Numerics.round(setfelVo.getRelamt(), 2) + setmodVo.getDoccur() + setfelVo.getModflg() + setfelVo.getRoldbt());
        Streams.streamInsert(stm, 0, setfelVo.getCommFeeFlag());
        // redafualt if one of then relevant amounts have been changed
        Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setmodVo.getAmeamt(), 2)));
        Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setmodVo.getAmmamt(), 2)));
        Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setmodVo.getConamt(), 2)));
        Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setmodVo.getMaxamt(), 2)));
        Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setmodVo.getOpnamt(), 2)));
        Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setmodVo.getNetamt(), 2)));
        Streams.streamInsert(stm, 0, MdaUtils.toString(Numerics.round(setmodVo.getDocamt(), 2)));
        Streams.streamInsert(stm, 0, setmodVo.getChato());
        Streams.streamInsert(stm, 0, setmodVo.getParstm());
//        这个值是固定的
//        Streams.streamInsert(stm,0,setmodVo.getDspflg());
        Streams.streamInsert(stm, 0, Formats.fmtDateShort(setmodVo.getFecrefdat()));
        Streams.streamInsert(stm, 0, Formats.fmtDateShort(setmodVo.getRefdat()));
        // as dspcalc depends on amount settled
        if( ! MdaUtils.isEmpty(setfelVo.getRol()) )
        {
            Streams.streamInsert(stm,0,MdaUtils.toString(setglgService.getSetAmtSysByRolTypDsp (setmodVo.getSetglg(), setfelVo.getRol(), "", "" )));
        }
        String wrkFecJson = Utils.toJson(setfelVo.getWrkfec());
        Streams.streamInsert(stm,0,wrkFecJson);
        // as dspCalc depends on amounts settled if not modified
        if( ! setfelVo.isModified("dsp") )
        {
            Streams.streamInsert(stm,0,setmodVo.getSetglg().getSetglgamtcon());
        }
        int gridcnt = setmodVo.getPtydet().size();
        for(int  i = 0;i < gridcnt;i++)
        {
            if( MdaUtils.compareTo(setmodVo.getPtydet().get(i).getRol(),setfelVo.getRol()) == 0 )
            {
                Streams.streamInsert(stm,0,setmodVo.getPtydet().get(i).getDftfeecur());
            }
        }
        setfelVo.setMac( Systems.macGen(stm,0));
    }

    @Override
    public void recalcSetfel(SetfelVo setfelVo, SetmodVo setmodVo){
        log.debug("Setfel mac{}和macold{}不相等，重算Setfel", setfelVo.getMac(), setfelVo.getMacold());
        calcSrc(setfelVo);
        Fee wrkFee = null;
        while(true) {
            if (MdaUtils.isEmpty(setfelVo.getFeecod())) {
                break; // ####### 改写 LABEL与GOTO  ####   goto fecend
            }
            String bcur = xrtmodService.sysiso();
            setfelVo.setDoccur(setmodVo.getDoccur());
            wrkFee = feeMapper.selectByCod(setfelVo.getFeecod());
            if (wrkFee == null) {
                throw new CommonServiceException("找不到费用代码"+setfelVo.getFeecod()+"数据");
            }
            setfelVo.setDscmodflg(wrkFee.getDscmodflg());
            setfelVo.setAccacr(wrkFee.getAccacr());
            //表示是Commission Fee
            if (("2".equals(wrkFee.getStaflg()) && setfelVo.getFeecod().startsWith("GIOPN") && setfelVo.getFeecod().length() > 5)
                    || isGuaranteeAmeFee(setfelVo.getFeecod())) {
                setfelVo.setCommFeeFlag("Y");
                //业务效期
                setfelVo.setDat2dft(setmodVo.getRec().getDat2dft());
                if (!setfelVo.isModified("roundFlag")) {
                    setfelVo.setRoundFlag("N");
                }
            } else {
                setfelVo.setCommFeeFlag("N");
                if (!setfelVo.isModified("roundFlag")) {
                    setfelVo.setRoundFlag("Y");
                }
            }
            buildCommCbsLines(setfelVo, setmodVo);
            String ptyinr = "";
            String ptainr = "";
            String actptyinr = "";
            String rol = NULLSTR;
            if (!setfelVo.isModified("rol")) {
                // if role to debit is set it must not be redefaulted (900574)
                if (MdaUtils.isEmpty(setfelVo.getRoldbt())) {
                    setfelVo.setRol(wrkFee.getRol());
                    rol = setfelVo.getRol();
                    Argument<String> rolBox = new Argument<String>("", rol);
                    Argument<String> ptyinrBox = new Argument<String>("", ptyinr);
                    Argument<String> ptainrBox = new Argument<String>("", ptainr);
                    setfegService.getrolandptxinr(setmodVo, rolBox, ptyinrBox, ptainrBox, setmodVo.getChato(), wrkFee.getRol());

                    rol = rolBox.value;
                    ptyinr = ptyinrBox.value;
                    ptainr = ptainrBox.value;

                    setfelVo.setRol(rol);
                } else {
                    setfelVo.setRol(setfelVo.getRoldbt());
                    rol = setfelVo.getRol();
                    Argument<String> ptyinrBox1 = new Argument<String>("", ptyinr);
                    Argument<String> ptainrBox1 = new Argument<String>("", ptainr);
                    setmodService.getPtxInr(rol, ptyinrBox1, ptainrBox1);

                    ptyinr = ptyinrBox1.value;
                    ptainr = ptainrBox1.value;

                }
            } else {
                rol = setfelVo.getRol();
                Argument<String> ptyinrBox2 = new Argument<String>("", ptyinr);
                Argument<String> ptainrBox2 = new Argument<String>("", ptainr);
                setmodService.getPtxInr(rol, ptyinrBox2, ptainrBox2);

                ptyinr = ptyinrBox2.value;
                ptainr = ptainrBox2.value;

            }
            setfelVo.setFeeacc(wrkFee.getAcc());
            setfelVo.setFeedtacod(wrkFee.getDtacod());
            setfelVo.setFeesftcod(wrkFee.getSftcod());
            //#####
            setfelVo.setTaxacc(wrkFee.getTaxacc());
            //#####
            setfelVo.setRolptyinr(ptyinr);
            setfelVo.setRolptainr(ptainr);
            String cur = NULLSTR;
            if (setfelVo.isModified("cur")) {
                cur = setfelVo.getCur();
            } else {
                cur = getFeeCur(setmodVo, setfelVo, setfelVo.getRol());
            }
            String feetyp = NULLSTR;
            if (MdaUtils.isEmpty(setfelVo.getFepinrlst())) {
                feetyp = "MAN";
                setfelVo.setInftxt("Manual added fee");
                if (!setfelVo.isModified("unt")) {
                    setfelVo.setUnt(1);
                }
            } else {
                FeeEntity feeEntity = setfegService.getFeeSet().getFeeEntityById(Strings.getLine(setfelVo.getFepinrlst(), 1));
                if (feeEntity != null) {
                    feetyp = feeEntity.getType();
                    if (!setfelVo.isModified("inftxt")) {
                        setfelVo.setInftxt(feeEntity.getInftxt());
                    }
                }
            }
            BigDecimal tiramt = setmodService.getRelAmount(wrkFee.getReltir(), setfelVo.getRol(), setfelVo, setmodVo);
            BigDecimal tirbca = xrtmodService.amtConvTypes(setfelVo.getDoccur(), tiramt, "M", bcur, "M", Dates.today());
            if (MdaUtils.isEmpty(setfelVo.getFecmod()) && !setfelVo.isModified("wrkfec")) {
                FecVo fecVo = null;
                FeeEntity feeEntity = setfegService.getFeeSet().getFeeEntityById(Strings.getLine(setfelVo.getFepinrlst(), 1));
                if (feeEntity != null && feeEntity.isReadRecFec()) {
                    Fec fec = new Fec();
                    fec.setObjtyp(setmodVo.getRec().getObjtyp());
                    fec.setObjinr(setmodVo.getRec().getObjinr());
                    fec.setFeepri("6");
                    fec.setFeeinr(wrkFee.getInr());
                    Date date = Dates.add(Utils.getMaxDate(), -1);
                    cbsRange.sdbRngRead(fec, date);
                    if (StringUtils.isNotEmpty(fec.getInr())) {
                        fecVo = DtoMapper.INSTANCE.transfer(fec);
                    }
                    if (fecVo != null) {
                        if (!setfelVo.isModified("ratcal")) {
                            BigDecimal ratcal = Utils.getFieldValue(setmodVo.getRec(), "ratcal", BigDecimal.ZERO);
                            if (ratcal.compareTo(BigDecimal.ZERO) != 0) {
                                fecVo.setRatcal(ratcal);
                            }
                        }
                        if (!setfelVo.isModified("untamt")) {
                            BigDecimal untamt = Utils.getFieldValue(setmodVo.getRec(), "untamt", BigDecimal.ZERO);
                            if (untamt.compareTo(BigDecimal.ZERO) != 0) {
                                fecVo.setUntamt(untamt);
                            }
                        }
                        if (!setfelVo.isModified("minamt")) {
                            BigDecimal minamt = Utils.getFieldValue(setmodVo.getRec(), "minamt", BigDecimal.ZERO);
                            if (minamt.compareTo(BigDecimal.ZERO) != 0) {
                                fecVo.setMinamt(minamt);
                            }
                        }
                        if (!setfelVo.isModified("maxamt")) {
                            BigDecimal maxamt = Utils.getFieldValue(setmodVo.getRec(), "maxamt", BigDecimal.ZERO);
                            if (maxamt.compareTo(BigDecimal.ZERO) != 0) {
                                fecVo.setMaxamt(maxamt);
                            }
                        }
                        if (!setfelVo.isModified("pertyp")) {
                            String pertyp = Utils.getFieldValue(setmodVo.getRec(), "pertyp", "");
                            if (StringUtils.isNotEmpty(pertyp)) {
                                fecVo.setPertyp(pertyp);
                            }
                        }
                    }
                }
                if (fecVo == null) {
                    fecVo = fecmodService.getFec(setmodVo.getRec(), setmodVo.getFecrefdat(), tirbca, ptyinr, wrkFee);
                }
                if (fecVo == null) {
                    throw new CommonServiceException("找不到费用{"+setfelVo.getFeecod()+"}计算规则条目fec");
                }
                setfelVo.setWrkfec(fecVo);
            } else {
                if (setfelVo.getFecmod().contains("LIAALL//LIAALLG")) {
                    String indexStr = setfelVo.getFecmod().substring(setfelVo.getFecmod().indexOf("(")+1, setfelVo.getFecmod().indexOf(")"));
                    try {
                        int index = Integer.parseInt(indexStr);
                        setfelVo.setWrkfec(setmodVo.getLiaall().getLiaallg().get(index).getFec());
                    } catch (Exception e) {
                        throw new CommonServiceException("无法获取表外fec数据");
                    }
                }
            }
            MdaUtils.clear(setfelVo.getDetstm());
            if (MdaUtils.isEmpty(setfelVo.getFecmod())) {
                if (MdaUtils.compareTo(setfelVo.getWrkfec().getLowamt(), 0) != 0) {
                    setfelVo.setInftxt(setfelVo.getInftxt() + CR + Strings.getText("Condition Tier selection based on $1 i.e. $2 $3", codetableService.getTblLabel(wrkFee.getReltir(), "FECAMT"), setfelVo.getDoccur(), Utils.fmtAmount(tiramt, setfelVo.getDoccur())));
                    setfelVo.setInftxt(setfelVo.getInftxt() + CR + Strings.getText("Tier selection amount converted to $1 $2", bcur, Utils.fmtAmount(tirbca, bcur)));
                    if (MdaUtils.compareTo(setfelVo.getWrkfec().getHigamt(), 0) == 0) {
                        setfelVo.setInftxt(setfelVo.getInftxt() + CR + Strings.getText("Tier of $1 $2 or more selected", bcur, Utils.fmtAmount(setfelVo.getWrkfec().getLowamt(), bcur), Utils.fmtAmount(setfelVo.getWrkfec().getHigamt(), bcur)));
                    } else {
                        setfelVo.setInftxt(setfelVo.getInftxt() + CR + Strings.getText("Tier selected between $1 $2 and $1 $3", bcur, Utils.fmtAmount(setfelVo.getWrkfec().getLowamt(), bcur), Utils.fmtAmount(setfelVo.getWrkfec().getHigamt(), bcur)));
                    }
                }
            }
            if (!MdaUtils.isEmpty(setfelVo.getFecirt())) {
                setfelVo.getWrkfec().setRatirs(setfelVo.getFecirt());
                setfelVo.getWrkfec().setRatcal(setfelVo.getRatcal());
            }
            // take rate from condition if.
            // 1. this is not a combination of more than one fee line (Stramcount < 2 ) and
            // 2. the rate is not modified manually and
            // 3. the condition sets an amount
            if (Streams.streamCount(setfelVo.getFepinrlst()) < 2 && (!setfelVo.isModified("untamt")) && (!MdaUtils.isEmpty(setfelVo.getWrkfec().getUntamt()) || (!MdaUtils.isEmpty(setfelVo.getWrkfec().getRatfcc()) && MdaUtils.compareTo(setfelVo.getWrkfec().getRatfcc(), "N") != 0))) {
                setfelVo.setUntamt(setfelVo.getWrkfec().getUntamt());
            }
            // same for RATCAL
            if (Streams.streamCount(setfelVo.getFepinrlst()) < 2 && (!setfelVo.isModified("ratcal")) && (!MdaUtils.isEmpty(setfelVo.getWrkfec().getRatcal()) || (!MdaUtils.isEmpty(setfelVo.getWrkfec().getRatfcc()) && MdaUtils.compareTo(setfelVo.getWrkfec().getRatfcc(), "N") != 0))) {
                setfelVo.setRatcal(setfelVo.getWrkfec().getRatcal());
            }
            if (MdaUtils.compareTo(feetyp, "FEP") == 0 && MdaUtils.compareTo(cur, setfelVo.getCur()) == 0) {
                if (!MdaUtils.isEmpty(setfelVo.getInfdetstm())) {
                    setfelVo.setInftxt(MdaUtils.toString(setfelVo.getInfdetstm()));
                }
                break; // ####### 改写 LABEL与GOTO  ####   goto fecend
            }
            if (!setfelVo.isModified("cur")) {
                setfelVo.setOgiamt(xrtmodService.amtConvTypes(setfelVo.getCur(), setfelVo.getOgiamt(), "S", cur, "B", Dates.today()));
                setfelVo.setCur(cur);
            }
            if (MdaUtils.compareTo(setfelVo.getModflg(), "a") == 0) {
                //计算unt和dat2
                CalcFeeRequest request = CalcFeeRequestBuilder.build(setfelVo, setfelVo.getWrkfec());
                CalcFeeResponse response = fecismService.clcFecAmt(request);
                if (response != null) {
                    setfelVo.setUnt(response.getUnt());
                    setfelVo.setDat2(response.getDat2());
                    setfelVo.setInftxt(response.getInftxt());
                }
                break; // ####### 改写 LABEL与GOTO  ####   goto fecend
            }
            if (!setfelVo.isModified("cur")) {
                if (MdaUtils.compareTo(setfelVo.getCur(), cur) != 0) {
                    setfelVo.setAmt(xrtmodService.amtConvTypes(setfelVo.getCur(), setfelVo.getAmt(), "S", cur, "B", Dates.today()));
                    setfelVo.setCur(cur);
                }
            }
            if (MdaUtils.compareTo(setfelVo.getWrkfec().getCalrul(), "T") == 0) {
                if (!MdaUtils.isEmpty(setfelVo.getInfdetstm())) {
                    setfelVo.setInftxt(MdaUtils.toString(setfelVo.getInfdetstm()));
                }
                break; // ####### 改写 LABEL与GOTO  ####   goto fecend
            }
            if (!setfelVo.isModified("cur")) {
                setfelVo.setCur(cur);
            }
            // if no currency yet, fee cannot be calculated.
            if (MdaUtils.isEmpty(setfelVo.getCur())) {
                break; // ####### 改写 LABEL与GOTO  ####   goto fecend
            }
            // Display all Infotexts on the Details Settlement Panel
            String maxLev = "";
            String cr = "";
            String infTxt = "";
            IStream oitStm = new StreamImpl();
            Streams.streamClear(oitStm);
            IStream inftxtStm = new StreamImpl();
            Streams.streamClear(inftxtStm);
            int fecCount = Streams.streamCount(setfelVo.getFeclst());
            String fecLin = NULLSTR;
            String fecInr = NULLSTR;
            int count = 0;
            String oitLin = NULLSTR;
            for (int i = 1; i <= fecCount; i++) {
                fecLin = Strings.getLine(setfelVo.getFeclst(), i);
                fecInr = Strings.mid(fecLin, 1, Strings.pos(fecLin, TAB) - 1);
                Argument<String> maxLevBox = new Argument<String>("", maxLev);
                //TODO 用的太少，不读取了
//                    Dynamic.oitGetOitData( "FEC", fecInr, "", maxLevBox, oitStm );

                maxLev = maxLevBox.value;

                count = Streams.streamCount(oitStm);
                if (count > 0) {
                    for (int j = 1; j <= count; j++) {
                        oitLin = Strings.getLine(oitStm, j);
                        Streams.streamInsert(inftxtStm, 0, "***" + Strings.mid(oitLin, Strings.pos(oitLin, TAB) + 1));
                    }
                }
            }
            setfelVo.setInftxt(MdaUtils.toString(inftxtStm));
            setfelVo.setFeesftcod(wrkFee.getSftcod());
            // if relevant amount from pool, use it, otherwise recalculate
            if (MdaUtils.compareTo(feetyp, "FEP") == 0 && MdaUtils.compareTo(setfelVo.getRelamt(), 0) != 0) {
                setfelVo.setInftxt(setfelVo.getInftxt() + CR + "Condition used again because settled to different party in different currency");
            } else {
                if (MdaUtils.compareTo(feetyp, "FEP") == 0) {
                    setfelVo.setInftxt(setfelVo.getInftxt() + CR + "Calculated from condition because settled to different party in different currency");
                }
                setfelVo.setRelamt(setmodService.getRelAmount(setfelVo.getWrkfec().getCalcbs(), setfelVo.getRol(), setfelVo, setmodVo));
                setfelVo.setRelcur(setmodService.getRelCur(setfelVo, setmodVo));
            }
            FeeEntity feeEntity = setfegService.getFeeSet().getFeeEntityById(Strings.getLine(setfelVo.getFepinrlst(), 1));
            if ("D".equals(setfelVo.getSrc()) || "A".equals(setfelVo.getSrc()) || "O".equals(setfelVo.getSrc()) || "P".equals(setfelVo.getSrc())) {
                IStream infdetstm = new StreamImpl();
                Streams.streamSet(infdetstm, feeEntity.getInfdetStm());
                int relamtlin = Streams.streamSearch(setfelVo.getInfdetstm(), "RELAMT" + TAB);
                if (relamtlin > 0) {
                    IStream valstm = new StreamImpl();
                    Utils.getTabValues(valstm, Strings.getLine(infdetstm, relamtlin) + TAB);
                    if (Streams.streamCount(valstm) > 2) {
                        setfelVo.setRelcur(Strings.getLine(valstm, 2));
                        setfelVo.setRelamt(new BigDecimal(Strings.getLine(valstm, 3)));
                    }
                }
            } else {
                if (feeEntity != null && StringUtils.isNotEmpty(feeEntity.getInfdetStm())) {
                    setfelVo.setInftxtBegin(feeEntity.getInfdetStm());
                }
            }
            CalcFeeRequest request = CalcFeeRequestBuilder.build(setfelVo, setfelVo.getWrkfec());
            CalcFeeResponse response = fecismService.clcFecAmt(request);
            if (response != null) {
                setfelVo.setInfdetstm(response.getInfdetstm());
                if (StringUtils.isNotEmpty(setfelVo.getInftxt())) {
                    setfelVo.setInftxt(setfelVo.getInftxt() + CR + response.getInftxt());
                } else {
                    setfelVo.setInftxt(response.getInftxt());
                }
                setfelVo.setUnt(response.getUnt());
                setfelVo.setCur(response.getCur());
                setfelVo.setOgiamt(response.getOgiamt());
                setfelVo.setAmt(response.getAmt());
                setfelVo.setMinmaxflg(response.getMinmaxflg());
                setfelVo.setDat1(response.getDat1());
                setfelVo.setDat2(response.getDat2());
                setfelVo.setCommCbsLineGrids(response.getCommCbsLineGrids());
                setfelVo.setDctrat(response.getDctrat());
            } else {
                Argument<String> pathBox = new Argument<String>("", setfelVo.getRelcur());
                fecismService.clcFecAmt(setfelVo, setmodVo, pathBox, setfelVo.getRelamt(), setfelVo.getCur());
                setfelVo.setRelcur(pathBox.value);
            }
            // recredit already paid fees according to CLCDIFFLG
            String relobjtyp = NULLSTR;
            String relobjinr = NULLSTR;
            IStream retStream = new StreamImpl();
            String fepsql = NULLSTR;
            int stmCnt = 0;
            String line = NULLSTR;
            String modFlg = NULLSTR;
            if (!MdaUtils.isEmpty(setfelVo.getCur())) {
                switch (setfelVo.getWrkfec().getClcdifflg()) {
                    case "A":
                    case "R":
                        relobjinr = setmodVo.getRec().getObjinr();
                        relobjtyp = setmodVo.getRec().getObjtyp();

                        fepsql = "SELECT AMT,CUR,MODFLG from FEP  " + Utils.sdbEtyGenSql("fep", " WHERE RELOBJTYP = ? AND RELOBJINR = ? AND FEECOD = ? AND  RPLTRNINR = ' '");
                        // do not use own FEP row if entry from pool is recalculated
                        if (!MdaUtils.isEmpty(setfelVo.getFepinrlst())) {
                            switch (setfelVo.getSrc()) {
                                case "P":
                                case "D":
                                case "A":
                                case "O":
                                    fepsql = fepsql + " AND ( NOT INR = '" + Strings.getLine(setfelVo.getFepinrlst(), 1) + "' ) ";
                                    break;
                            }
                        }
                        // use FEPs in range calulated now only
                        if (!MdaUtils.isEmpty(setfelVo.getDat1()) && !MdaUtils.isEmpty(setfelVo.getDat2())) {
                            fepsql = fepsql + " AND ( not DAT1 < " + Utils.dbSqlDate(setfelVo.getDat1()) + " ) and ( not DAT2 > " + Utils.dbSqlDate(setfelVo.getDat2()) + " ) ";
                        }
                        Map<String, Object> sqlMap = new HashMap<>();
                        sqlMap.put("sql", fepsql);
                        List<Fep> fepList = fepMapper.dyncRead(sqlMap);
//                                Caches.cacheWrite(retStream,"$OldFepStm",relobjtyp,relobjinr,this.getFeecod(),this.getSrc(),this.getDat1(),this.getDat2());
                        BigDecimal oldFepAmt = Decimals.ZERO_SCALE2;
                        stmCnt = fepList.size();
                        for (int i = 0; i < stmCnt; i++) {
                            BigDecimal amt = fepList.get(i).getAmt();
                            cur = fepList.get(i).getCur();
                            modFlg = fepList.get(i).getModflg();
                            if (MdaUtils.compareTo(cur, setfelVo.getCur()) == 0 && (MdaUtils.isEmpty(modFlg) || MdaUtils.compareTo(modFlg, "r") == 0)) {
                                oldFepAmt = Decimals.add(oldFepAmt, amt);
                            } else {
                                String wrn = Strings.getText("Fee $1 have been amended or settled in other currencies in earlier transactions.\\nPlease calculate fee $1 manually.", setfelVo.getFeecod());
                                setfelVo.setInftxt(setfelVo.getInftxt() + CR + CR + wrn);
                                setfelVo.setAmt(new BigDecimal("0"));
                                break; // ####### 改写 LABEL与GOTO  ####   goto fecend
                            }
                        }
                        setfelVo.setInftxt(setfelVo.getInftxt() + CR + Strings.getText("Already charged before: $1 $2", setfelVo.getCur(), Utils.fmtAmount(oldFepAmt, setfelVo.getCur())));
                        if (MdaUtils.compareTo(setfelVo.getWrkfec().getClcdifflg(), "A") == 0 && MdaUtils.compareTo(oldFepAmt, setfelVo.getAmt()) > 0 && MdaUtils.compareTo(setfelVo.getAmt(), 0) > 0) {
                            setfelVo.setInftxt(setfelVo.getInftxt() + CR + "No further calculation as already more has been charged");
                            setfelVo.setAmt(new BigDecimal("0"));
                        } else {
                            setfelVo.setAmt(Decimals.sub(setfelVo.getAmt(), oldFepAmt));
                            if (MdaUtils.compareTo(setfelVo.getAmt(), 0) < 0) {
                                setfelVo.setInftxt(setfelVo.getInftxt() + CR + Strings.getText("Refund: $1 $2", setfelVo.getCur(), Utils.fmtAmount(setfelVo.getAmt().negate(), setfelVo.getCur())));
                            } else {
                                if (MdaUtils.compareTo(setfelVo.getAmt(), 0) > 0) {
                                    setfelVo.setInftxt(setfelVo.getInftxt() + CR + Strings.getText("Now to be charged: $1 $2", setfelVo.getCur(), Utils.fmtAmount(setfelVo.getAmt(), setfelVo.getCur())));
                                }
                            }
                        }
                        break;
                }
            }
            break;
        }
        // Default fields standard
        recalcSetfelStdDft(setfelVo, setmodVo);
        // Do installation specific defaulting
        recalcSetfelIsfDft(setmodVo, setfelVo, wrkFee);
        this.calcMac(setfelVo, setmodVo);
        setfelVo.setMacold(setfelVo.getMac());
    }

    /**
     *   source:setfel.0019.script
     */
    public void recalcSetfelStdDft(SetfelVo setfelVo,SetmodVo setmodVo)
    {
//        Systems.setValues(this,"usrcur",xrtmodService.validCurrencies( Dates.today() ));
        setfelVo.setDsp( dspCalc(setfelVo,setmodVo));
        //费用默认设置免收
        if (!setfelVo.isModified("dsp") && StringUtils.isNotEmpty(setfelVo.getDspdft())) {
            setfelVo.setDsp(setfelVo.getDspdft());
            if ("N".equals(setfelVo.getDsp())) {
                setfelVo.setAmt(BigDecimal.ZERO);
            }
        }
        // from default FEECOD
        // don`t allow changes of code if forbidden by transaction or conditions set by transaction
        if( MdaUtils.compareTo(setfelVo.getModflg(),"f") == 0 || ( ! MdaUtils.isEmpty(setfelVo.getFepinrlst()) ) )
        {
//            Systems.resetEnabled(this,"feecod");
            setfelVo.resetModified("feecod");
        }
        else
        {
//            Systems.setValues(this,"feecod",MdaUtils.toString(ctx.absGet(Setmod.class).getSetfeg().getAvbfeecod()));
//            Systems.setEnabled(this,"feecod");
        }
        // from default AmtDefault ( AMT, USRAMT )
        // Default AMT and USRAMT (enabled, if not fixed, USRAMT not changed and condition)
        // If USAMT is empty, reset modified flag to allow input in AMT again
        if( MdaUtils.isEmpty(setfelVo.getUsramt()) )
        {
            setfelVo.resetModified("usramt");
        }
        // disable if MODFLG disallow changes of amount or fee has already been advised
        if( MdaUtils.compareTo(setfelVo.getModflg(),"f") == 0 || MdaUtils.compareTo(setfelVo.getSrc(),"D")== 0 || MdaUtils.compareTo(setfelVo.getSrc(),"A")== 0 )
        {
//            Systems.resetEnabled(this,"amt");
//            Systems.resetEnabled(this,"usramt");
        }
        else
        {
            // if user has used USRAMT disallow changes in AMT to avoid inconsistent display of amounts
            if( setfelVo.isModified("usramt") )
            {
//                Systems.resetEnabled(this,"amt");
//                Systems.setEnabled(this,"usramt");
            }
            else
            {
                if( MdaUtils.compareTo(setfelVo.getWrkfec().getSetchgflg(),"CP")== 0 || MdaUtils.compareTo(setfelVo.getWrkfec().getSetchgflg(),"AP")== 0 )
                {
//                    Systems.resetEnabled(this,"amt");
//                    Systems.resetEnabled(this,"usramt");
                }
                else
                {
//                    if( MdaUtils.isEmpty(this.getCur()) )
//                    {
//                        Systems.resetEnabled(this,"amt");
//                    }
//                    else
//                    {
//                        Systems.setEnabled(this,"amt");
//                    }
//                    Systems.setEnabled(this,"usramt");
                }
            }
        }
        // from default FEETXT
        if( MdaUtils.isEmpty(setfelVo.getFeecod()) )
        {
            // on empty feecod clear and disable
//            Dynamic.disableAndClearField( MdaDriver.getDatafield(this,"feetxt") );
            setfelVo.setFeetxt("");
        }
        else
        {
            // if modification of text is allowed and not already advised, enable, else disable
//            if( Streams.streamSearch(ctx.absGet(Trnmod.class).getWrkstm().getStm1(),"FEEDSCMODFLG" + this.getFeecod()) > 0 && ( !( MdaUtils.compareTo(this.getSrc(),"D")== 0) ) && ( !( MdaUtils.compareTo(this.getSrc(),"A")== 0) ) )
//            {
//                Systems.setEnabled(this,"feetxt");
//            }
//            else
//            {
//                Systems.resetEnabled(this,"feetxt");
//                Systems.resetModified(this,"feetxt");
//            }
            // if not modified default to table value
            if( ( ! setfelVo.isModified("feetxt") ) )
            {
                setfelVo.setFeetxt( codetableService.getTblLabel(setfelVo.getFeecod(),"FEETXT"));
            }
        }
        // from default FEETXTINF order 200
        // enable only, if changes are allowed by fee definition or Amount as been changed
//        if( Streams.streamSearch(ctx.absGet(Trnmod.class).getWrkstm().getStm1(),"FEEDSCMODFLG" + this.getFeecod()) > 0 || Systems.isModified(this,"amt") )
//        {
//            Systems.setEnabled(this,"feetxtinf");
//        }
//        else
//        {
//            Systems.resetEnabled(this,"feetxtinf");
//            Systems.resetModified(this,"feetxtinf");
//        }
        // if not modified get text (if not retrieved from pool)
        BigDecimal rat = null;
        if( ! setfelVo.isModified("feetxtinf") && ( MdaUtils.isEmpty(setfelVo.getFeetxtinf()) || ( !( MdaUtils.compareTo(setfelVo.getSrc(),"D")== 0) ) && ( !( MdaUtils.compareTo(setfelVo.getSrc(),"A")== 0) ) && ( !( MdaUtils.compareTo(setfelVo.getSrc(),"P")== 0) ) ) )
        {
            if( fecmodService.isUNTAMTValid( setfelVo.getWrkfec()) )
            {
                rat = setfelVo.getUntamt();
            }
            else
            {
                rat = setfelVo.getRatcal();
            }
            //如果费用是手动添加的，feetxtinf置空，每次从数据库中获取
            if ("U".equalsIgnoreCase(setfelVo.getSrc())) {
                setfelVo.setFeetxtinf("");
            }
            setfelVo.setFeetxtinf( fecismService.getfeetxtinf(setfelVo.getFeecod(),setfelVo.getAllcalflg(),setfelVo.getWrkfec(),setfelVo.getFeetxtinf(),rat,setfelVo.getUnt(),setfelVo.getDat1(),setfelVo.getDat2(),setfelVo.getInfdetstm()));
        }
        // if current status is redefault and condition has been changed, set MODFLG to "condition changed"
        if( MdaUtils.compareTo(setfelVo.getModflg(),"r")== 0 && setfelVo.isModified("wrkfec") )
        {
            setfelVo.setModflg("n");
        }
        // from default MODFLG
//        if( MdaUtils.compareTo(setfelVo.getModflg(),"r")== 0 )
//        {
//            Systems.setValues(this,"modflg",this.getModflg());
//            Systems.resetEnabled(this,"modflg");
//        }
//        else
//        {
//            Systems.setValues(this,"modflg",this.getModflg() + CR + "r");
//            Systems.setEnabled(this,"modflg");
//        }
        // from default BUTDET
//        if( MdaUtils.isEmpty(this.getDetstm()) )
//        {
//            Systems.resetEnabled(this,"butdet");
//            Systems.resetVisible(this,"butdet");
//        }
//        else
//        {
//            Systems.setVisible(this,"butdet");
//            Systems.setEnabled(this,"butdet");
//        }
        // from default RATCAL
        // don`t allow changes of code if forbidden by transaction, conditions set by transaction or fee has already been advised before
        if( ! fecmodService.isUNTAMTValid( setfelVo.getWrkfec()) && ( ! MdaUtils.isEmpty(setfelVo.getWrkfec().getCalrul()) ) )
        {
//            if( Streams.streamSearch(this.getFepinrlst(),"TRNLI") == 0 && ( !( MdaUtils.compareTo(this.getSrc(),"D")== 0) ) && ( !( MdaUtils.compareTo(this.getSrc(),"A")== 0) ) )
//            {
//                Systems.setEnabled(this,"ratcal");
//            }
//            else
//            {
//                Systems.resetEnabled(this,"ratcal");
//            }
//            if( MdaUtils.compareTo(this.getModflg(),"r") == 0 )
//            {
//                Systems.resetModified(this,"ratcal");
//            }
//            Systems.setVisible(this,"ratcal");
        }
        else
        {
//            Dynamic.disableAndClearField( MdaDriver.getDatafield(this,"ratcal") );
//            Systems.resetVisible(this,"ratcal");
            setfelVo.setRatcal(BigDecimal.ZERO);
        }
        // from default RATCUR order 10
        // don`t show if AMT is not valid
//        if( Dynamic.isUNTAMTValid( setfelVo.getWrkfec()) )
//        {
//            Systems.setVisible(this,"ratcur");
//            Systems.resetEnabled(this,"ratcur");
//        }
//        else
//        {
//            Systems.resetVisible(this,"ratcur");
//            Systems.resetEnabled(this,"ratcur");
//        }
        // from default RATLAB
        if( MdaUtils.isEmpty(setfelVo.getWrkfec().getCalrul()) )
        {
            setfelVo.setRatlab( "");
        }
        else
        {
            if( fecmodService.isUNTAMTValid( setfelVo.getWrkfec()) )
            {
                setfelVo.setRatlab( "Amount / Unit");
            }
            else
            {
                setfelVo.setRatlab( "Rate");
            }
        }
        // allowed roles are available roles without own
//        IStream rolVal = new StreamImpl();
//        Streams.streamSet(rolVal,setmodVo.getRoldsc());
//        int ownidx = Streams.streamSearch(rolVal,"OWN" + TAB);
//        if( ownidx > 0 )
//        {
//            Streams.streamDelete(rolVal,ownidx);
//        }
//        Codetables.setCodeValues(this,"rol",rolVal);
        // disable if already advised
//        if( MdaUtils.compareTo(this.getSrc(),"D")== 0 || MdaUtils.compareTo(this.getSrc(),"A")== 0 )
//        {
//            Systems.resetEnabled(this,"rol");
//        }
//        else
//        {
//            Systems.setEnabled(this,"rol");
//        }
        // from default UNT
        // disable if already advised
//        if( MdaUtils.compareTo(this.getSrc(),"D")== 0 || MdaUtils.compareTo(this.getSrc(),"P")== 0 || MdaUtils.compareTo(this.getSrc(),"A")== 0 )
//        {
//            Systems.resetEnabled(this,"unt");
//        }
//        else
//        {
//            switch( this.getWrkfec().getCalrul() )
//            {
//                case "C":
//                    Systems.resetEnabled(this,"unt");
//                    break;
//                default:
//                    Systems.setEnabled(this,"unt");
//            }
//        }
        // from default UNTAMT
        // don`t allow changes of code if forbidden by transaction or conditions set by transaction
        if( fecmodService.isUNTAMTValid( setfelVo.getWrkfec()) )
        {
            // disable if already advised
//            if( MdaUtils.compareTo(this.getSrc(),"D")== 0 || MdaUtils.compareTo(this.getSrc(),"A")== 0 || MdaUtils.compareTo(this.getSrc(),"P")== 0 )
//            {
//                Systems.resetEnabled(this,"untamt");
//            }
//            else
//            {
//                if( Streams.streamSearch(this.getFepinrlst(),"TRNLI") == 0 )
//                {
//                    Systems.setEnabled(this,"untamt");
//                }
//                else
//                {
//                    Systems.resetEnabled(this,"untamt");
//                }
//                if( MdaUtils.compareTo(this.getModflg(),"r") == 0 )
//                {
//                    Systems.resetModified(this,"untamt");
//                }
//            }
//            Systems.setVisible(this,"untamt");
        }
        else
        {
//            Dynamic.disableAndClearField( MdaDriver.getDatafield(this,"untamt") );
//            Systems.resetVisible(this,"untamt");
            setfelVo.setUntamt(BigDecimal.ZERO);
        }
        // from default USRCUR
        //! conversion currency enabled only if amount is enabled
//        if( Systems.isEnabled(this,"amt") )
//        {
//            Systems.setEnabled(this,"usrcur");
//        }
//        else
//        {
//            Systems.resetEnabled(this,"usrcur");
//        }
        // set countervalue and system currency
        setfelVo.setXrfamt( xrtmodService.sysCurEqu( setfelVo.getCur(), setfelVo.getAmt(), Dates.today() ));
        setfelVo.setXrfcur( xrtmodService.sysiso());
        setfelVo.setAcrinr(NULLSTR);
//        if( ! MdaUtils.isEmpty(this.getAccacr()) )
//        {
//            Systems.setEnabled(this,"dat1");
//            Systems.setEnabled(this,"dat2");
//        }

    }
    /**
     *   source:setfel.0027.script
     */
    @JsonIgnore
    public String getFeeCur(SetmodVo setmodVo,SetfelVo setfelVo,String argRol)
    {

        // if fee currency is set on Details panel, use it
        int ptydetRow = 0;
        ptydetRow = setmodService.getPtyDetRow ( setfelVo.getRol() ,setmodVo);
        String ptydetFeecur = NULLSTR;
        if( ptydetRow >= 0 )
        {
            ptydetFeecur = setmodVo.getPtydet().get(ptydetRow).getDftfeecur();
        }
        else
        {
            ptydetFeecur = "";
        }
        String dFTFEEcur = NULLSTR;
        if( ! MdaUtils.isEmpty(ptydetFeecur) )
        {
            dFTFEEcur = ptydetFeecur;
        }
        String liaLin = NULLSTR;
        String cur = NULLSTR;
        if( MdaUtils.isEmpty(ptydetFeecur) )
        {
//            Caches.cacheRead(ctx.absGet(Setmod.class).getSetpty(),"SETPTY",argRol);
            Setpty setpty = this.setfegService.getFeeSet().getSetpty(argRol);
            if( setpty == null || MdaUtils.isEmpty(setpty.getDftfeecur()) )
            {
                liaLin = Strings.getLine(setfelVo.getFepinrlst(),1);
                if( ! MdaUtils.isEmpty(liaLin) )
                {
                    if( Strings.pos(liaLin,"TRNLIA") > 0 )
                    {
                        //TODO 这个要去表外的部分
//                        liaLin = Strings.mid(liaLin,Strings.pos(liaLin,"TRNLIA") + 6,2);
//                        cur = Datas.getContent(this,"\\LIAALL\\LIAALLG(" + liaLin + ")\\CUR");
//                        if( ctx.getErrorCode() == 0 && ! MdaUtils.isEmpty(cur) )
//                        {
//                            return  cur;
//                        }
                    }
                }
                return setfelVo.getDoccur();
            } else {
//                ctx.reraise();
                return setpty.getDftfeecur();
            }
        } else {
            return ptydetFeecur;
        }

    }

    /**
     * source:setfel.0028.script
     */
    public void recalcSetfelIsfDft(SetmodVo setmodVo, SetfelVo setfelVo, Fee wrkFee) {
        //! Set installation specific fields (called from RecalcSetFel after common defaults are executed
        // from default DAT1
        if (!setfelVo.isModified("dat1")) {
            switch (setfelVo.getWrkfec().getSetbeg()) {
                case "T":
                    setfelVo.setDat1(Dates.today());
                    break;
                case "O":
                    setfelVo.setDat1(setmodVo.getOpndat());
                    break;
                case "P":
                    int idx = setmodVo.getSetfeg().getSetfel().indexOf(setfelVo);
                    setfelVo.setDat1(setfegService.getLatestFepDate(setfelVo.getFeecod(), setmodVo, idx));
                    break;
            }
        }
        // disable if already advised
//        if( MdaUtils.compareTo(this.getSrc(),"D")== 0 || MdaUtils.compareTo(this.getSrc(),"A")== 0 )
//        {
//            Systems.resetEnabled(this,"dat1");
//        }
//        else
//        {
//            // enable/disable according to calculation rule
//            switch( this.getWrkfec().getCalrul() )
//            {
//                case "C":
//                    switch( this.getModflg() )
//                    {
//                        case "c":
//                        case  "a":
//                            Systems.setEnabled(this,"dat1");
//                            break;
//                        default:
//                            Systems.resetEnabled(this,"dat1");
//                    }
//                    break;
//                default:
//                    Systems.setEnabled(this,"dat1");
//            }
//        }
        // from default DAT2
        // disable if already advised
        if( MdaUtils.compareTo(setfelVo.getSrc(),"D")== 0 || MdaUtils.compareTo(setfelVo.getSrc(),"A")== 0 )
        {
//            Systems.resetEnabled(this,"dat2");
        }
        else
        {
            if( ! setfelVo.isModified("dat2") )
            {
                switch( setfelVo.getWrkfec().getSetend() )
                {
                    case "T":
                        setfelVo.setDat2(Dates.today());
                        break;
                    case "E":
                        setfelVo.setDat2(setmodVo.getExpdat());
                        break;
                }
            }
//            Systems.setEnabled(this,"dat2");
        }
        // from old default DATREFBEG
        //! Only valid for caclulation rule "C"
//        if( MdaUtils.compareTo(this.getWrkfec().getCalrul(),"C")== 0 )
//        {
//            Systems.setEnabled(this,"datrefbeg");
//        }
//        else
//        {
//            Systems.resetEnabled(this,"datrefbeg");
//        }
        // from default RATCUR order 50
        if( MdaUtils.isEmpty(setfelVo.getWrkfec().getRatcur()) )
        {
            setfelVo.setRatcur( xrtmodService.sysiso());
        }
        else
        {
            setfelVo.setRatcur( setfelVo.getWrkfec().getRatcur());
        }
        // use accuing account as account for booking fee (if set)
        if( null !=wrkFee && StringUtils.isNotEmpty(wrkFee.getAccacr()) )
        {
            setfelVo.setFeeacc( wrkFee.getAccacr());
        }
        // usually currency is disabled to aviod mixtures
//        Systems.resetEnabled(this,"cur");

    }

    public void calcSrc(SetfelVo setfelVo) {
        String typ = NULLSTR;
        if (MdaUtils.isEmpty(setfelVo.getFeecod())) {
            setfelVo.setSrc("");
        } else {
            switch (Streams.streamCount(setfelVo.getFepinrlst())) {
                case 0:
                    typ = "U";
                    break;
                case 1:
                    if (MdaUtils.compareTo(Strings.mid(Strings.getLine(setfelVo.getFepinrlst(), 1), 1, 1), "T") == 0) {
                        if (Streams.streamSearch(setfelVo.getFepinrlst(), "TRNLII") == 0 && Streams.streamSearch(setfelVo.getFepinrlst(), "TRNLIA") == 0) {
                            typ = "T";
                        } else {
                            typ = "E";
                        }
                    } else {
                        if (MdaUtils.isEmpty(setfelVo.getAdvtrninr())) {
                            typ = "P";
                        } else {
                            //不考虑Sep Inr
//                            sepinr = ctx.absGet(Setmod.class).getSetfeg().getfepval ( Strings.getLine(this.getFepinrlst(),1), "SEPINR" );
//                            if( MdaUtils.isEmpty(sepinr) )
//                            {
                            FeeEntity feeEntity = setfegService.getFeeSet().getFeeEntityById(Strings.getLine(setfelVo.getFepinrlst(), 1));
                            if (feeEntity != null && MdaUtils.compareTo(feeEntity.getPtyInr(), setfelVo.getRolptyinr()) == 0) {
                                typ = "D";
                            } else {
                                typ = "O";
                            }
                        }
                    }
                    break;
                default:
                    typ = "C";
            }
            setfelVo.setSrc(typ);
        }
    }

    public String dspCalc(SetfelVo setfelVo, SetmodVo setmodVo) {
        boolean trnsetflg = false;
        String roldspmdyflg = NULLSTR;
        IStream options = new StreamImpl();
        String setDef = NULLSTR;
        String poolDef = NULLSTR;
        String setto = NULLSTR;
        int paridx = 0;
        String parlin = NULLSTR;
        String validOpt = NULLSTR;
        if (setfelVo.isModified("dsp")) {
            return setfelVo.getDsp();
        }
        if (MdaUtils.isEmpty(setfelVo.getAmt())) {
//            Systems.resetEnabled(this,"dsp");
            setfelVo.resetModified("dsp");
            return "";
        } else {
            // If \\SETDOC\\ROLDSPMDYFLG is set for role, disable and set to settle now
            trnsetflg = false;
            roldspmdyflg = setmodVo.getSetfeg().getRoldspmdyflg();
            if (!MdaUtils.isEmpty(roldspmdyflg)) {
                if (MdaUtils.compareTo(roldspmdyflg, "*") == 0 || MdaUtils.compareTo(Strings.mid(setfelVo.getRol(), 1, Strings.len(roldspmdyflg)), Strings.mid(roldspmdyflg, 1, Strings.len(roldspmdyflg))) == 0) {
                    trnsetflg = true;
                }
            }
            Streams.streamClear(options);
            setDef = "X";
            Streams.streamInsert(options, 0, "X");
//            }
            // If advised before, only already advised oder settle now is possible. Default for pool is already advised
            if (MdaUtils.compareTo(setfelVo.getSrc(), "D") == 0 || MdaUtils.compareTo(setfelVo.getSrc(), "A") == 0) {
                Streams.streamInsert(options, 0, "D");
                poolDef = "D";
            } else {
                //  else store in pool, advise or settle now are possible. Default for pool is given by  DSPPOLDFT (if not set: "V" for advise asap)
                if (MdaUtils.isEmpty(setmodVo.getSetfeg().getDsppoldft())) {
                    poolDef = "V";
                } else {
                    poolDef = setmodVo.getSetfeg().getDsppoldft();
                }
                Streams.streamInsert(options, 0, "P");
                Streams.streamInsert(options, 0, "V");
            }
            switch (setfelVo.getSrc()) {
                // if temporary settlement has been picked up, settle items now.
                case "A":
                    poolDef = setDef;
                    // if temporary settlement has been picked up, leave entries from pool in pool, stay to default (DO5DOS 3352)
                    break;
                case "D":
                case "P":
                    //          $poolDef = SRC
                    //          $SetDef = SRC
                    break;
                default:
            }
//                }
            Argument<String> setDefBox = new Argument<String>("", setDef);
            Argument<String> poolDefBox = new Argument<String>("", poolDef);
            Argument<String> settoBox = new Argument<String>();
            dspCalcIsm(options, setDefBox, poolDefBox, settoBox, setfelVo, setmodVo);

            setDef = setDefBox.value;
            poolDef = poolDefBox.value;
            setto = settoBox.value;

            if (Streams.streamSearch(options, setDef) == 0) {
                setDef = Strings.getLine(options, 1);
            }
            if (!MdaUtils.isEmpty(setto)) {
                return setto;
            }
            if (trnsetflg) {
                return setDef;
            } else {
                if (!setfelVo.isModified("dsp")) {
                    if (MdaUtils.isEmpty(setfelVo.getAmt())) {
                        return poolDef;
                    } else {

                        // definitions in Conditions always win.
                        if (MdaUtils.compareTo(setfelVo.getWrkfec().getColltr(), "P") == 0) {
                            return poolDef;
                        } else if (MdaUtils.compareTo(setfelVo.getWrkfec().getColltr(), "S") == 0) {
                            return setDef;
                        } else {
                            // retrieve valid default option (if set by SetmodSetRolFeeDspDefault, take it, if not take CLISETOPT/FORSETOPT)
                            paridx = Streams.streamSearch(setmodVo.getParstm(), "ROL-" + setfelVo.getRol() + "-FEEDSP-" + TAB);
                            if (paridx > 0) {
                                parlin = Strings.getLine(setmodVo.getParstm(), paridx);
                                validOpt = Strings.mid(parlin, Strings.pos(parlin, TAB) + 1);
                            } else {
                                if (MdaUtils.compareTo(Strings.mid(setfelVo.getRol(), 1, 2), Strings.mid(setmodVo.getFeeclirol(), 1, 2)) == 0) {
                                    validOpt = setmodVo.getClisetopt();
                                } else {
                                    validOpt = setmodVo.getForsetopt();
                                }
                            }
                            if (MdaUtils.compareTo(validOpt, "U") == 0 && (MdaUtils.compareTo(setfelVo.getSrc(), "D") == 0 || MdaUtils.compareTo(setfelVo.getSrc(), "P") == 0)) {
                                return setfelVo.getSrc();
                            } else {
                                switch (validOpt) {
                                    case "P":
                                    case "V":
                                        if (Streams.streamSearch(options, validOpt) > 0) {
                                            return validOpt;
                                        } else {
                                            return poolDef;
                                        }
                                        //break;
                                    case "S":
                                    case "X":
                                        return setDef;
                                    default:
                                        // if no option is set, default is settle to clients...
                                        if (MdaUtils.compareTo(Strings.mid(setfelVo.getRol(), 1, 2), Strings.mid(setmodVo.getFeeclirol(), 1, 2)) == 0) {
                                            return setDef;
                                        } else {
                                            if (MdaUtils.compareTo(setglgService.getSetAmtSysByRolTypDsp(setmodVo.getSetglg(), setfelVo.getRol(), "", ""), 0) != 0) {
                                                return setDef;
                                            } else {
                                                return poolDef;
                                            }
                                        }
                                }
                            }
                        }
                    }
                } else {
                    return setfelVo.getDsp();
                }
            }
        }
    }

    /**
     * source:setfel.0030.script
     */
    public void dspCalcIsm(IStream argOptions, Argument<String> argSetDef, Argument<String> argPolDef, Argument<String> argSetto, SetfelVo setfelVo, SetmodVo setmodVo) {
        //! Entry point for supporter to set disposition other than the product.
        //! ArgOptions : Stream with possible options
        //! ArgSetDef  : Option to be used for settlement default
        //! ArgPolDef  : Option to be used for pool default
        //! ArgSetto   : If set to an nonempty value this value is used as default.
        //! In addition the Disposition may be enabled or disabled using Enable(Dsp) or Disable(DSP)
        // syndication comission is always setlled directly
        if (Streams.streamSearch(setfelVo.getFepinrlst(), "TRNSYN") > 0) {
            argSetto.value = argSetDef.value;
//            if( MdaUtils.compareTo(ctx.absGet(Setmod.class).getSetfeg().getRoldspmdyflg(),"*") == 0 || MdaUtils.compareTo(Strings.mid(this.getRol(),1,Strings.len(ctx.absGet(Setmod.class).getSetfeg().getRoldspmdyflg())),Strings.mid(ctx.absGet(Setmod.class).getSetfeg().getRoldspmdyflg(),1,Strings.len(ctx.absGet(Setmod.class).getSetfeg().getRoldspmdyflg()))) == 0 )
//            {
//                Systems.resetEnabled(this,"dsp");
//            }
            return;
        }
        /**
         if SRC == "P" and IsEmpty( \\SETMOD\\SETFEG\\ROLDSPMDYFLG ) then
         **/
        if (MdaUtils.compareTo(setfelVo.getSrc(), "P") == 0 && MdaUtils.isEmpty(setmodVo.getSetfeg().getRoldspmdyflg())) {
            if (MdaUtils.compareTo(setmodVo.getClisetopt(), "X") == 0) {
                argSetDef.value = "X";
            } else {
                argSetDef.value = "P";
            }
        }
        int lin = Streams.streamSearch(argOptions, "V");
        if (lin > 0) {
            Streams.streamDelete(argOptions, lin);
        }
        if (MdaUtils.compareTo(argPolDef.value, "V") == 0) {
            if (MdaUtils.compareTo(setmodVo.getClisetopt(), "X") == 0) {
                argPolDef.value = "X";
            } else {
                argPolDef.value = "P";
            }
        }
        if (MdaUtils.compareTo(argSetDef.value, "V") == 0) {
            argSetDef.value = "P";
        }
        argSetto.value = "";

    }

    public String getSetFelIsfMac(SetfelVo setfelVo, SetmodVo setmodVo) {
        //! Function to return MAC portion for ISF-fields
        //! (usually the fields used in RecalcSetfelIsfDft if not already in Default MAC)
        String res = "";
        if (MdaUtils.compareTo(setfelVo.getWrkfec().getCalrul(), "C") == 0) {
            res = MdaUtils.toString(setmodVo.getSetfeg().getWrkcbsamtcon().getValue());
        }
        return res;

    }

    //生成或者创建CommCbsLine
    private void buildCommCbsLines(SetfelVo setfelVo, SetmodVo setmodVo) {
        if (!"T".equals(setfelVo.getSrc())) {
            return;
        }
        BizInfoVo rec = setmodVo.getRec();
        boolean commTxnFlag = false;
        List<CommCbsLine> list = new ArrayList<>();
        if ("Y".equals(setfelVo.getCommFeeFlag()) && !isGuaranteeAmeFee(setfelVo.getFeecod())) {
            commTxnFlag = true;
            if ("GID".equalsIgnoreCase(rec.getObjtyp())) {
                String listStr = dyncDaoService.dyncReadFieldByInr("GIT", rec.getObjinr(), "dtaliadet");
                if (StringUtils.isNotEmpty(listStr)) {
                    list = Utils.toListObject(CommCbsLine.class, listStr);
                }
            } else if ("NID".equalsIgnoreCase(rec.getObjtyp())) {
                String listStr = dyncDaoService.dyncReadFieldByInr("NIT", rec.getObjinr(), "dtaliadet");
                if (StringUtils.isNotEmpty(listStr)) {
                    list = Utils.toListObject(CommCbsLine.class, listStr);
                }
            }
        }
        if (commTxnFlag) {
            boolean includeOpenFlag = false;
            for (CommCbsLine commCbsLine : list) {
                if ("OPEN".equalsIgnoreCase(commCbsLine.getFlag())) {
                    includeOpenFlag = true;
                }
            }
            if (!includeOpenFlag) {
                CommCbsLine commCbsLine = new CommCbsLine();
                Cbb cbb = setmodVo.getCbsMap().getOrDefault("MAX", new Cbb());
                commCbsLine.setCur(cbb.getCur());
                commCbsLine.setAmt(cbb.getAmt());
                commCbsLine.setValueDate(rec.getOpndat());
                commCbsLine.setFlag("OPEN");
                commCbsLine.setFeeDate(setfelVo.getDat1());
                String gartyp = Utils.getFieldValue(rec, "gartyp", "");
                String note = Strings.getText("$1开立发生额 $2 $3", codetableService.getTblLabel(gartyp, "TYPGAR", "CN"), commCbsLine.getCur(), Utils.fmtAmount(xrtmodService.amtRnd(commCbsLine.getAmt(), commCbsLine.getCur()), commCbsLine.getCur()));
                commCbsLine.setNote(note);
                list.add(0, commCbsLine);
            }
            setfelVo.setCommCbsLines(list);
        }
    }

    /**
     * 判断是否为commission的费用
     * @param feecod
     * @return
     */
    public boolean isGuaranteeAmeFee(String feecod) {
        if ("GIAME1".equalsIgnoreCase(feecod) || "GIAME2".equalsIgnoreCase(feecod)
                || "GIAME3".equalsIgnoreCase(feecod) || "GIAME4".equalsIgnoreCase(feecod)
                || "GIAME5".equalsIgnoreCase(feecod) || "GIAME6".equalsIgnoreCase(feecod)
                || "GIAME7".equalsIgnoreCase(feecod) || "GIAME8".equalsIgnoreCase(feecod)
                || "GIAME9".equalsIgnoreCase(feecod)) {
            return true;
        }
        return false;
    }
}
