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

import com.brilliance.isc.bo.Cbb;
import com.brilliance.isc.bo.Cbe;
import com.brilliance.isc.common.cbsmod.CbsRange;
import com.brilliance.isc.common.cbsmod.service.CbsmodService;
import com.brilliance.isc.common.cbsmod.service.LscmodService;
import com.brilliance.isc.common.cbsmod.service.XrtmodService;
import com.brilliance.isc.common.counter.service.CounterService;
import com.brilliance.isc.common.util.SettleExceptionUtils;
import com.brilliance.isc.common.util.Utils;
import com.brilliance.isc.common.vo.SimpleModuleVo;
import com.brilliance.isc.mda.dao.CbbMapper;
import com.brilliance.isc.mda.dao.CbeMapper;
import com.brilliance.mda.runtime.mda.impl.Argument;
import com.brilliance.mda.runtime.mda.util.*;
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.Date;
import java.util.List;

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

@Service
public class CbsmodServiceImpl implements CbsmodService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());


    @Autowired
    private CbbMapper cbbMapper;

    @Autowired
    private CbeMapper cbeMapper;

    @Autowired
    private XrtmodService xrtmod;

    @Autowired
    private LscmodService lscmodService;

    @Autowired
    private CbsRange cbsRange;

    @Autowired
    private CounterService counterService;
    /**
     *   source:cbsmod.0000.script
     */
    public void storeEntry(Cbe rec, Object obj,String newType,String newInr)
    {
        logger.info("storeEntry参数cbe:{},obj:{},newType:{},newInr:{}",rec.toString(),obj.toString(),newType,newInr);

        //! Internal CBS-function used as subfunction in CbsStorePreliminaryEntry, CbsStoreEntry
        //! Rec holds the CBE entry to be written
        //! Obj holds the Contractgroup of the owning contract (xxDGRP or PTEGRP)
        //
        // The Entry will be stored in the CBS and
        // the associated CBB entries will be created
        // At first check status of CBS-module
        if( MdaUtils.isEmpty(newType) || MdaUtils.isEmpty(newInr) )
        {
            SettleExceptionUtils.sysDump("No transaction specified. The new TYP and INR has to be set");
        }
        // check passed record (arguments)
        if( MdaUtils.isEmpty(rec.getDat()) )
        {
            SettleExceptionUtils.sysDump("No begin date specified. DAT has to be set");
        }
        if( MdaUtils.isEmpty(rec.getCur()) )
        {
            SettleExceptionUtils.sysDump("No currency specified. CUR has to be set");
        }
        if( MdaUtils.isEmpty(rec.getCbt()) )
        {
            SettleExceptionUtils.sysDump("No CBS entry type specified. CBT has to be set");
        }
        if( MdaUtils.compareTo(rec.getTrninr(),newInr) != 0 )
        {
            if( ! MdaUtils.isEmpty(rec.getTrninr()) )
            {
                SettleExceptionUtils.sysDump("Wrong transaction INR supplied in passed argument.");
            }
            rec.setTrninr( newInr);
        }
        if( MdaUtils.compareTo(rec.getTrntyp(),newType) != 0 )
        {
            if( ! MdaUtils.isEmpty(rec.getTrntyp()) )
            {
                SettleExceptionUtils.sysDump("Wrong transaction TYP supplied in passed argument.");
            }
            rec.setTrntyp( newType);
        }
        String objTyp = "";
        String objInr = "";
        Argument<String> objTypBox = new Argument<String>("",objTyp);
        Argument<String> objInrBox = new Argument<String>("",objInr);
        getObjAndInr( obj, objTypBox, objInrBox, "L" );

        objTyp = objTypBox.value;
        objInr = objInrBox.value;

        rec.setObjtyp( objTyp);
        rec.setObjinr( objInr);
        // default the creation date to today if empty
        if( MdaUtils.isEmpty(rec.getCredat()) )
        {
            rec.setCredat( Dates.today());
        }
        // set XRF-Fields if not already set
        if( MdaUtils.isEmpty(rec.getXrfcur()) )
        {
            rec.setXrfcur( this.xrtmod.sysiso());
            rec.setXrfamt(this.xrtmod.basCurEqu( rec.getCur(), rec.getAmt(), rec.getDat() ));
        }
        // Write the Entry (CBE)
        String inr = this.counterService.dbCounterFormat(Utils.recGetObj(rec));
        rec.setInr(inr);
        cbeMapper.insert(rec);
        // AddStkEntry( Rec, "I" )
        if( !( MdaUtils.compareTo(rec.getRelflg(),"P")== 0) )
        {
            createCbbEntries( rec );
        }
        // 使用新的额度模组
        //LsiProcessCbeEntry( Rec, Obj )

    }
    /**
     *   source:cbsmod.0004.script
     */
    public void createCbbEntries(Cbe rec)
    {
        //! Routine to create all CBB-entries for a given CBE entry
        //! Rec holds the new CBE-entry
        // retrieve the list of columns to be processed
        String cbsConfKey = rec.getObjtyp() + "-" + rec.getCbt();
        String cbcBlk = Inis.getIniBlock("CBSCONF.INI",cbsConfKey,"OPR");
        logger.info("createCbbEntries读取CBSCONF.INI，key:{},value:{}",cbsConfKey+"#"+"OPR",cbcBlk);
        String comFlg = NULLSTR;
        if( MdaUtils.compareTo(rec.getRelflg(),"R")== 0 )
        {
            comFlg = "B";
        }
        else
        {
            comFlg = "A";
        }
        logger.info("createCbbEntries读取comFlg:{},判断条件relflg:{}",comFlg,rec.getRelflg());
        // Insert CBB-records for all relevant CBC-s depending on CBT
        int idx = 1;
        // ####### 改写 LABEL与GOTO   ####    label CBBLoop
        CBBLoop:
        while(true) {
            String blk = Strings.getLine(cbcBlk,idx);
            logger.info("createCbbEntries读取while循环插入cbb,获取cbcBlk当前行数:{},blk:{}",idx,blk);
            if( MdaUtils.isEmpty(blk) )
            {
                return;
            }
            String opr = Strings.mid(blk,1,1);
            // prepare the next new CBB entry
            logger.info("createCbbEntries读取while循环插入cbb,cbb.setobjtyp:{},cbb.setObjinr:{},cbb.setExtid:{},cbb.setCbc:{},rec.getDat:{}",rec.getObjtyp(),rec.getObjinr(),rec.getExtid(),Strings.mid(blk,2,6),rec.getDat());
            Cbb cbb = new Cbb();
            cbb.setObjtyp( rec.getObjtyp());
            cbb.setObjinr( rec.getObjinr());
            cbb.setExtid( rec.getExtid());
            cbb.setCbc( Strings.mid(blk,2,6));
            // load the balance valid at the relevant date
            cbsRange.sdbRngRead(cbb,rec.getDat());
//            if( ctx.getErrorCode() != tdOdbcNotFound )
//            {
//                ctx.reraise();
//                //break;
//            }
            // set the fields of the new CBB entry
            cbb.setObjtyp( rec.getObjtyp());
            cbb.setObjinr( rec.getObjinr());
            cbb.setExtid( rec.getExtid());
            cbb.setBegdat( rec.getDat());
            cbb.setEnddat(null);
            cbb.setCbeinr( rec.getInr());
            cbb.setCbc( Strings.mid(blk,2,6));
            updateCbbAmounts( rec,cbb, opr, comFlg );
            logger.info("createCbbEntries读取while循环插入cbb,cbb.setobjtyp:{},cbb.setObjinr:{},cbb.setExtid:{},cbb.setCbc:{},cbb.setBegdat:{}",rec.getObjtyp(),rec.getObjinr(),rec.getExtid(),Strings.mid(blk,2,6),rec.getDat());
            logger.info("createCbbEntries读取while循环插入cbb,setCbeinr:{},setCbc:{}",rec.getInr(),Strings.mid(blk,2,6));

            cbsRange.sdbRngInsert(cbb);
            // For Informix use dirty read to avoid LOCK WAIT during SELECT
//            Platform.sqlSetDirtyRead();
            //Platform.sdbRngSelectAfterDate(ctx.absGet(Cbsmod.class).getCbb(),rec.getDat());
            List<Cbb> cbbList = cbsRange.sdbRngSelectAfterDate(cbb,rec.getDat());
            String finalComFlg = comFlg;
            cbbList.forEach(cbb1 -> {
                updateCbbAmounts( rec, cbb1, opr, finalComFlg);
                cbbMapper.updateByPrimaryKey(cbb1);
            });

//            Platform.sqlSetCommittedRead();
//            while( ctx.getErrorCode() <= 0 )
//            {
//                ctx.getDaoSession().dbFetch(ctx.absGet(Cbsmod.class).getCbb());
//                if( ctx.getErrorCode() <= 0 )
//                {
//                    updateCbbAmounts( rec, ctx.absGet(Cbsmod.class).getCbb(), opr, comFlg );
//                    Platform.sdbUpdate(ctx.absGet(Cbsmod.class).getCbb());
//                }
//            }
//            if( ctx.getErrorCode() != tdOdbcNotFound )
//            {
//                ctx.reraise();
//                //break;
//            }
            idx = idx + 1;
            // return ; // ####### 改写 LABEL与GOTO  ####   goto CBBLoop
        }
    }
    /**
     *   source:cbsmod.0005.script
     */
    @JsonIgnore
    public void getObjAndInr(Object obj,Argument<String> objTyp,Argument<String> objInr,String lockFlag)
    {
        // use passed module to set the object-type and INR
        // the module might hold a REC subrecord or be the record itself
        // lockflag: If L, check, if contract is reserved or locked
        // This is done by checking if there is a line in Locktable wich contains the INR and Typ of contract
        if (obj instanceof SimpleModuleVo) {
            SimpleModuleVo linkModule = (SimpleModuleVo) obj;
            objTyp.value = linkModule.getObjtyp();
            objInr.value = linkModule.getObjinr();
        } else {
            objTyp.value = Utils.recGetObj(obj);
            objInr.value = Utils.recGetInr(obj);
        }
        logger.info("getObjAndInr读取objTyp.value:{}, objInr.value:{}",objTyp.value, objInr.value);

        /**
         // as currently new contracts could not be locked we have to switch of this check.
         // When there is a possibility to register new contracts into cbs this check
         // could be reactivated.
         // 05.11.2003/jo
         if LockFlag == "L" then
         StreamSet( $lcks, GetContext( "LockTable" ) )
         $found = 0
         if StreamCount( $lcks ) > 0 then
         for $i = 1 to StreamCount( $lcks )
         if Pos( StreamGetLine( $lcks, $i ), ObjTyp ) > 0 and Pos( StreamGetLine( $lcks, $i ), ObjInr ) > 0 then
         $found = $i
         endif
         next
         endif
         if $found == 0 then
         SysDump( "The passed module " + ObjTyp + " " + ObjInr + " is neither locked nor reserved for update.\\nThe module has to be locked or reserved for update previous to write CBS data" )
         endif
         endif
         **/
        if( MdaUtils.isEmpty(objInr.value) )
        {
            SettleExceptionUtils.sysDump("The passed module " + Utils.recGetObj(obj) + " has no defined INR.\n");
        }

    }
    /**
     *   source:cbsmod.0010.script
     */
    public void deleteCbbEntries(Cbe cbeArg)
    {
        //! the CBB-Entries of the passed CBE are deleted.
        //! The fields INR, OBJTYP, OBJINR, CUR, AMT, XRFCUR, XRFAMT are used.
        List<Cbb> cbbList = cbbMapper.getCbbListByCbeInr(cbeArg.getInr());
        logger.info("deleteCbbEntries读取cbbList:{}, 参数:{}",cbbList.toString(),cbeArg.getInr());
        if(MdaUtils.isEmpty(cbbList)){
            return;
        }
        String cbsConfKey = cbeArg.getObjtyp() + "-" + cbeArg.getCbt() + "-OPR";
        logger.info("deleteCbbEntries读取cbsConfKey:{},参数{}+{}",cbsConfKey,cbeArg.getObjtyp(),cbeArg.getCbt());
        cbbList.forEach(cbb -> {
            String opr = Inis.getIniStr("CBSCONF.INI",cbsConfKey,cbb.getCbc());
            logger.info("deleteCbbEntries读取CBSCONF.INI，key:{},value:{}",cbsConfKey+"#"+"OPR",cbb.getCbc());
            List<Cbb> afterCbbList = cbsRange.sdbRngSelectAfterEntry(cbb);
            logger.info("deleteCbbEntries读取afterCbbList:{}",afterCbbList.toString());
            afterCbbList.forEach(afterCbb->{
                updateCbbAmounts( cbeArg, afterCbb, opr + "I", "A" );
                cbbMapper.updateByPrimaryKey(afterCbb);
            });
            cbsRange.sdbRngDelete(cbb);
        });
//        IStream stream = new StreamImpl();
//        Streams.streamClear(stream);
//        Platform.sqlSetDirtyRead();
//        ctx.getDaoSession().dbExecuteSQL("Select INR, CBC from CBB where CBEINR = ?",cbeArg.getInr());
//        IStream cbbStm = new StreamImpl();
//        ctx.getDaoSession().dbFetchStream(cbbStm);
//        ctx.getDaoSession().dbCloseCursor();
//        int max = 0;
//        String cbsConfKey = NULLSTR;
//        String opr = NULLSTR;
//        Argument<String> _oprBox = Argument.box(opr);
//        String lin = NULLSTR;
//        int pos = 0;
//        String cbc = NULLSTR;
//        if( ctx.getErrorCode() == tdOdbcNotFound )
//        {
//            Platform.sqlSetCommittedRead();
//        }
//        else
//        {
//            ctx.reraise();
//            Platform.sqlSetCommittedRead();
//            max = Streams.streamCount(cbbStm);
//            cbsConfKey = cbeArg.getObjtyp() + "-" + cbeArg.getCbt() + "-OPR";
//            opr = "";
//            for(int  idx = 1;idx <= max;idx++)
//            {
//                lin = Strings.getLine(cbbStm,idx);
//                pos = Strings.pos(lin,TAB);
//                cbc = Strings.mid(lin,pos + 1);
//                // Check for every element, whether CBT includes column
//                Caches.cacheRead(_oprBox,"cbsmod",cbsConfKey,cbc);
//                opr = _oprBox.value;
//                if( ctx.getErrorCode() == tdCacheNotFound )
//                {
//                    opr = Inis.getIniStr("CBSCONF.INI",cbsConfKey,cbc);
//                    Caches.cacheWrite(opr,"cbsmod",cbsConfKey,cbc);
//                }
//                else
//                {
//                    ctx.reraise();
//                }
//                if( Strings.len(opr) != 1 )
//                {
//                    opr = " ";
//                }
//                Streams.streamInsert(stream,0,opr + Strings.mid(lin,1,pos - 1));
//            }
//        }
//        int idx = 0;
//        // ####### 改写 LABEL与GOTO   ####    label DelLoop
//        DelLoop:
//        while(true) {
//            idx = idx + 1;
//            if( idx > Streams.streamCount(stream) )
//            {
//                if(1==1) return;
//            }
//            lin = Strings.getLine(stream,idx);
//            opr = Strings.mid(lin,1,1);
//            String inr = Strings.mid(lin,2,8);
//            // read the CBS-Balance entry to be deleted to update later entries
//            ctx.getDaoSession().dbRead(ctx.absGet(Cbsmod.class).getCbb(),inr,"INR");
//            Platform.sdbRngSelectAfterEntry(ctx.absGet(Cbsmod.class).getCbb());
//            while( ctx.getErrorCode() <= 0 )
//            {
//                ctx.getDaoSession().dbFetch(ctx.absGet(Cbsmod.class).getCbb());
//                if( ctx.getErrorCode() <= 0 )
//                {
//                    updateCbbAmounts( cbeArg, ctx.absGet(Cbsmod.class).getCbb(), opr + "I", "A" );
//                    Platform.sdbUpdate(ctx.absGet(Cbsmod.class).getCbb());
//                }
//            }
//            if( ctx.getErrorCode() != tdOdbcNotFound )
//            {
//                ctx.reraise();
//            }
//            // Delete the CBS-Balance entry
//            ctx.getDaoSession().dbRead(ctx.absGet(Cbsmod.class).getCbb(),inr,"INR");
//            Platform.sdbRngDelete(ctx.absGet(Cbsmod.class).getCbb());
//            // return ; // ####### 改写 LABEL与GOTO  ####   goto DelLoop
//        }
    }
    /**
     *   source:cbsmod.0013.script
     */
    public void commitCbbEntries(Cbe cbeArg)
    {
        //! within the CBB-Entries of the passed CBE the commited balance is maintained.
        List<Cbb> cbbList = cbbMapper.getCbbListByCbeInr(cbeArg.getInr());
        if(MdaUtils.isEmpty(cbbList)){
            return;
        }
        String cbsConfKey = cbeArg.getObjtyp() + "-" + cbeArg.getCbt() + "-OPR";
        cbbList.forEach(cbb -> {
            String opr = Inis.getIniStr("CBSCONF.INI",cbsConfKey,cbb.getCbc());
            logger.info("commitCbbEntries读取CBSCONF.INI，key:{},value:{}",cbsConfKey+"#"+"OPR",cbb.getCbc());
            updateCbbAmounts( cbeArg, cbb, opr, "C" );
            cbbMapper.updateByPrimaryKey(cbb);
            List<Cbb> afterCbbList = cbsRange.sdbRngSelectAfterEntry(cbb);
            logger.info("commitCbbEntries读取afterCbbList:{}",afterCbbList.toString());
            afterCbbList.forEach(afterCbb->{
                updateCbbAmounts( cbeArg, afterCbb, opr, "C" );
                cbbMapper.updateByPrimaryKey(afterCbb);
            });
        });


//        IStream stream = new StreamImpl();
//        Streams.streamClear(stream);
//        // load INR-list of all CBB`s to be processed
//        Platform.sqlSetDirtyRead();
//        ctx.getDaoSession().dbExecuteSQL("Select INR, CBC from CBB where CBEINR = ? order by INR ASC",cbeArg.getInr());
//        IStream cbbStm = new StreamImpl();
//        ctx.getDaoSession().dbFetchStream(cbbStm);
//        ctx.getDaoSession().dbCloseCursor();
//        int max = 0;
//        String cbsConfKey = NULLSTR;
//        String opr = NULLSTR;
//        Argument<String> _oprBox = Argument.box(opr);
//        String lin = NULLSTR;
//        int pos = 0;
//        String cbc = NULLSTR;
//        if( ctx.getErrorCode() == tdOdbcNotFound )
//        {
//            Platform.sqlSetCommittedRead();
//        }
//        else
//        {
//            ctx.reraise();
//            Platform.sqlSetCommittedRead();
//            max = Streams.streamCount(cbbStm);
//            cbsConfKey = cbeArg.getObjtyp() + "-" + cbeArg.getCbt() + "-OPR";
//            opr = "";
//            for(int  idx = 1;idx <= max;idx++)
//            {
//                lin = Strings.getLine(cbbStm,idx);
//                pos = Strings.pos(lin,TAB);
//                cbc = Strings.mid(lin,pos + 1);
//                // Check for every element, whether CBT includes column
//                Caches.cacheRead(_oprBox,"cbsmod",cbsConfKey,cbc);
//                opr = _oprBox.value;
//                if( ctx.getErrorCode() == tdCacheNotFound )
//                {
//                    opr = Inis.getIniStr("CBSCONF.INI",cbsConfKey,cbc);
//                    Caches.cacheWrite(opr,"cbsmod",cbsConfKey,cbc);
//                }
//                else
//                {
//                    ctx.reraise();
//                }
//                if( Strings.len(opr) != 1 )
//                {
//                    opr = " ";
//                }
//                Streams.streamInsert(stream,0,opr + Strings.mid(lin,1,pos - 1));
//            }
//        }
//        int idx = 0;
//        // ####### 改写 LABEL与GOTO   ####    label UpdLoop
//        UpdLoop:
//        while(true) {
//            idx = idx + 1;
//            if( idx > Streams.streamCount(stream) )
//            {
//                return ; // ####### 改写 LABEL与GOTO  ####   goto UpdDone
//            }
//            lin = Strings.getLine(stream,idx);
//            opr = Strings.mid(lin,1,1);
//            String inr = Strings.mid(lin,2,8);
//            // read the CBS-Balance entry to be deleted to update later entries
//            ctx.getDaoSession().dbRead(ctx.absGet(Cbsmod.class).getCbb(),inr,"INR");
//            if( ctx.getErrorCode() <= 0 )
//            {
//                updateCbbAmounts( cbeArg, ctx.absGet(Cbsmod.class).getCbb(), opr, "C" );
//                Platform.sdbUpdate(ctx.absGet(Cbsmod.class).getCbb());
//            }
//            else
//            {
//                if( ctx.getErrorCode() != tdOdbcNotFound )
//                {
//                    ctx.reraise();
//                }
//            }
//            Platform.sdbRngSelectAfterEntry(ctx.absGet(Cbsmod.class).getCbb());
//            while( ctx.getErrorCode() <= 0 )
//            {
//                ctx.getDaoSession().dbFetch(ctx.absGet(Cbsmod.class).getCbb());
//                if( ctx.getErrorCode() <= 0 )
//                {
//                    updateCbbAmounts( cbeArg, ctx.absGet(Cbsmod.class).getCbb(), opr, "C" );
//                    Platform.sdbUpdate(ctx.absGet(Cbsmod.class).getCbb());
//                }
//            }
//            if( ctx.getErrorCode() != tdOdbcNotFound )
//            {
//                ctx.reraise();
//            }
//            // return ; // ####### 改写 LABEL与GOTO  ####   goto UpdLoop
//        }
//        // ####### 改写 LABEL与GOTO   ####    label UpdDone

    }
    /**
     *   source:cbsmod.0014.script
     */
    public void updateCbbAmounts(Cbe argCbe,Cbb argCbb,String argOpr,String argComFlg)
    {
        logger.info("updateCbbAmounts参数argCbe.getinr:{},argCbb.getinr:{},argOpr:{},argComFlg:{}",argCbe.getInr(),argCbb.getInr(),argOpr,argComFlg);
        //! ArgCbe Holds the issuing CBE
        //! ArgCbb Holds the CBB to maintained
        //! ArgOpr holds the sign of the requested operation followed by an optional `I` to mark Inversions
        //! ArgComFlg holds a boolean value which values shall be updated, (`A`mount, `C`ommited, `B`oth)
        BigDecimal amtDif = null;
        BigDecimal xrfAmtDif = null;

        switch( argOpr )
        {
            case "+":
                amtDif = argCbe.getAmt();
                xrfAmtDif = argCbe.getXrfamt();
                break;
            case "+I":
                amtDif = argCbe.getAmt().negate();
                xrfAmtDif = argCbe.getXrfamt().negate();
                break;
            case "-":
                amtDif = argCbe.getAmt().negate();
                xrfAmtDif = argCbe.getXrfamt().negate();
                break;
            case "-I":
                amtDif = argCbe.getAmt();
                xrfAmtDif = argCbe.getXrfamt();
                break;
            default:
                SettleExceptionUtils.sysDump("CBSMOD.UpdateCbbAmounts: Undefined Operation '" + Strings.mid(argOpr,1,1) + "' configured in CBSCONF.INI for " + argCbe.getObjtyp() + "/" + argCbe.getCbt());
                amtDif = new BigDecimal("0");
                xrfAmtDif = new BigDecimal("0");
        }
        // for `A`mount and `B`oth handle CUR/AMT and XRFCUR/XRFAMT
        if( MdaUtils.compareTo(argComFlg,"C") != 0 )
        {
            if( MdaUtils.compareTo(argCbb.getCur(),argCbe.getCur()) != 0 )
            {
                if( ! MdaUtils.isEmpty(argCbb.getCur()) && MdaUtils.compareTo(argCbb.getAmt(),0) != 0 )
                {
                    SettleExceptionUtils.sysDump("CBSMOD.UpdateCbbAmounts: Different currency and amount <> 0 encountered.\nCBB = " + argCbb.getCur() + ", CBE = " + argCbe.getCur() + " (CBBINR=" + argCbb.getInr() + ")");
                }
                argCbb.setCur( argCbe.getCur());
                argCbb.setAmt( new BigDecimal("0"));
            }
            if( MdaUtils.compareTo(argCbb.getXrfcur(),argCbe.getXrfcur()) != 0 )
            {
                if( ! MdaUtils.isEmpty(argCbb.getXrfcur()) && MdaUtils.compareTo(argCbb.getXrfamt(),0) != 0 )
                {
                    SettleExceptionUtils.sysDump("CBSMOD.UpdateCbbAmounts: Different XRF-currency and amount <> 0 encountered.\nCBB = " + argCbb.getXrfcur() + ", CBE = " + argCbe.getXrfcur() + " (CBBINR=" + argCbb.getInr() + ")");
                }
                argCbb.setXrfcur( argCbe.getXrfcur());
                argCbb.setXrfamt( new BigDecimal("0"));
            }
            if( MdaUtils.compareTo(Strings.mid(argOpr,2),"I") == 0 && MdaUtils.compareTo(argCbb.getAmt(),0) != 0 )
            {
                xrfAmtDif = xrtmod.amtRnd( Decimals.mul(Decimals.div(amtDif,argCbb.getAmt()),argCbb.getXrfamt()), argCbe.getCur() );
            }
            argCbb.setAmt( Decimals.add(argCbb.getAmt(),amtDif));
            if( MdaUtils.compareTo(argCbb.getAmt(),0) == 0 )
            {
                argCbb.setXrfamt( new BigDecimal("0"));
            }
            else
            {
                argCbb.setXrfamt( Decimals.add(argCbb.getXrfamt(),xrfAmtDif));
            }
        }
        // for `C`ommited and `B`oth handle COMCUR/COMAMT and XCOCUR/XCOAMT
        if( MdaUtils.compareTo(argComFlg,"A") != 0 )
        {
            if( MdaUtils.compareTo(argCbb.getComcur(),argCbe.getCur()) != 0 )
            {
                if( ! MdaUtils.isEmpty(argCbb.getComcur()) && MdaUtils.compareTo(argCbb.getComamt(),0) != 0 )
                {
                    SettleExceptionUtils.sysDump("CBSMOD.UpdateCbbAmounts: Different COM-currency specified and amount <> 0 encountered.\nCBB = " + argCbb.getComcur() + ", CBE = " + argCbe.getCur() + " (CBBINR=" + argCbb.getInr() + ")");
                }
                argCbb.setComcur( argCbe.getCur());
                argCbb.setComamt( new BigDecimal("0"));
            }
            if( MdaUtils.compareTo(argCbb.getXcocur(),argCbe.getXrfcur()) != 0 )
            {
                if( ! MdaUtils.isEmpty(argCbb.getXcocur()) && MdaUtils.compareTo(argCbb.getXcoamt(),0) != 0 )
                {
                    SettleExceptionUtils.sysDump("CBSMOD.UpdateCbbAmounts: Different XCO-currency specified and amount <> 0 encountered.\nCBB = " + argCbb.getXcocur() + ", CBE = " + argCbe.getXrfcur() + " (CBBINR=" + argCbb.getInr() + ")");
                }
                argCbb.setXcocur( argCbe.getXrfcur());
                argCbb.setXcoamt( new BigDecimal("0"));
            }
            if( MdaUtils.compareTo(Strings.mid(argOpr,2),"I") == 0 && MdaUtils.compareTo(argCbb.getComamt(),0) != 0 )
            {
                xrfAmtDif = xrtmod.amtRnd( Decimals.mul(Decimals.div(amtDif,argCbb.getComamt()),argCbb.getXcoamt()), argCbe.getCur() );
            }
            argCbb.setComamt( Decimals.add(argCbb.getComamt(),amtDif));
            if( MdaUtils.compareTo(argCbb.getComamt(),0) == 0 )
            {
                argCbb.setXcoamt( new BigDecimal("0"));
            }
            else
            {
                argCbb.setXcoamt( Decimals.add(argCbb.getXcoamt(),xrfAmtDif));
            }
        }

    }

    /**
     *   source:cbsmod.0001.script
     */
    public void cbsDeleteTrn(String trnTyp,String trnInr)
    {
        //! All CBS-Entries (CBE and CBB) of TRN will be deleted
        //! this includes preliminary and real entries
        // Sets Isolationlevel to dirty read and after select back to committed read
        List<Cbe> cbeList = cbeMapper.getCbeListByTrnTypeAndInr(trnTyp,trnInr);
        logger.info("cbsDeleteTrn获取cbeList:{},参数trntyp:{},trninr:{}",cbeList.toString(),trnTyp,trnInr);
        cbeList.forEach(cbe -> {
            cbeMapper.deleteByPrimaryKey(cbe);
            lscmodService.lsiDeleteCbeEntry(cbe);
            if(!"P".equals(cbe.getRelflg())){
                deleteCbbEntries(cbe);
            }
        });
    }
    /**
     *   source:cbsmod.0002.script
     */
    public void cbsReleaseTrn(String trnTyp,String trnInr)
    {
        //! All CBS-Entries in Status Entered of a specified Transaction
        //! are marked as released.
        //! Preliminary Entries are left as they are.
        List<Cbe> cbeList = cbeMapper.getCbeListByTrnTypeAndInrWithEFlag(trnTyp,trnInr);
        logger.info("cbsReleaseTrn获取cbeList:{},参数trntyp:{},trninr:{}",cbeList.toString(),trnTyp,trnInr);
        cbeList.forEach(cbe -> {
            cbe.setRelflg("R");
            commitCbbEntries(cbe);
            cbeMapper.updateByPrimaryKey(cbe);
        });
    }
    /**
     *   source:cbsmod.0003.script
     */
    public void cbsStoreEntry(Cbe argRec, Object argObj)
    {
        //! Store the passed CBE-entry as normal entry
        //! ArgRec holds the CBE entry to be written
        //! ArgObj holds the Contractgroup of the owning contract (xxDGRP or PTEGRP)
        // Set the release flag to real entry
        argRec.setRelflg("E");
        storeEntry( argRec, argObj,argRec.getTrntyp(),argRec.getTrninr() );
        logger.info("cbsStoreEntry赋值cbe.setrelflg=E,参数argobj:{},trntyp:{},trninr:{}",argObj,argRec.getTrntyp(),argRec.getTrninr());
    }
    /**
     *   source:cbsmod.0006.script
     *   此函数下在多组件模式下，并没有什么用
     */
    public void cbsTrnReset()
    {
        //! Initializes CBS local memory
        /**
         Clear( \\CBSMOD\\OLDTYP )
         Clear( \\CBSMOD\\OLDINR )
         **/
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).setNewtyp(NULLSTR);
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).setNewinr(NULLSTR);
        // Dynamic.lsiInitializeModule();

    }
    /**
     *   source:cbsmod.0007.script
     *   此函数下在多组件模式下，并没有什么用
     */
    public void cbsTrnSetNew(String typArg,String inrArg)
    {
        //! Global procedure to register the new transcation.
        //!
        //! TypArg is the typ of transcation. (Usually TRN or RIM)
        //! InrArg holds the INR of the transaction
//        if( ! MdaUtils.isEmpty(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getNewtyp() + ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getNewinr()) )
//        {
//            Platform.sysDump("CBSMOD: Setting of the new transaction when already set");
//        }
//        if( MdaUtils.isEmpty(typArg) )
//        {
//            Platform.sysDump("CBSMOD: An empty new transaction type is specified");
//        }
//        if( MdaUtils.isEmpty(inrArg) )
//        {
//            Platform.sysDump("CBSMOD: An empty new transaction INR is specified");
//        }
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).setNewtyp( typArg);
//        ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).setNewinr( inrArg);

    }
    /**
     *   source:cbsmod.0008.script
     */
    public void cbsTrnCommit()
    {
        //! Makes all CBS-Updates permanent
        //! Delete CBS-entries attached to the old transaction
        /**
         if not IsEmpty( \\CBSMOD\\OLDTYP + \\CBSMOD\\OLDINR ) then
         CbsDeleteTrn( \\CBSMOD\\OLDTYP, \\CBSMOD\\OLDINR )
         endif
         **/
        // Finally clear the status
        cbsTrnReset();

    }
    /**
     *   source:cbsmod.0009.script
     */
    public void cbsDeleteContract(Object obj)
    {
        //! All CBS-Entries (CBE and CBB) of the Contract will be deleted
        //! this includes preliminary and real entries
        //!
        //! Obj identifies the object. The ObjTyp and ObjInr are extracted from Obj.
        logger.info("cbsDeleteContract参数obj:{}",obj);
        String objTyp = "";
        String objInr = "";
        Argument<String> objTypBox = new Argument<String>("",objTyp);
        Argument<String> objInrBox = new Argument<String>("",objInr);
        getObjAndInr( obj, objTypBox, objInrBox, "" );

        objTyp = objTypBox.value;
        objInr = objInrBox.value;

        List<Cbe> cbeList = cbeMapper.getCbeListByObjTypeAndInr(objTyp,objInr);
        if(!MdaUtils.isEmpty(cbeList)) {
            cbeList.forEach(cbe -> {
                cbeMapper.deleteByPrimaryKey(cbe);
            });
        }
        List<Cbb> cbbList = cbbMapper.getCbbListByObjTypeAndInr(objTyp,objInr);
        if(!MdaUtils.isEmpty(cbbList)) {
            cbbList.forEach(cbb -> {
                cbbMapper.deleteByPrimaryKey(cbb);
            });
        }
        lscmodService.lsiDeleteObject(objTyp,objInr);
//        IStream stm = new StreamImpl();
//        Streams.streamClear(stm);
//        ctx.getDaoSession().dbExecuteSQL("Select INR from CBE where OBJTYP = ? AND OBJINR = ?",objTyp,objInr);
//        ctx.getDaoSession().dbFetchStream(stm);
//        ctx.getDaoSession().dbCloseCursor();
//        int max = 0;
//        if( ctx.getErrorCode() != tdOdbcNotFound )
//        {
//            ctx.reraise();
//            max = Streams.streamCount(stm);
//            for(int  idx = 1;idx <= max;idx++)
//            {
//                ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbe().setInr( Strings.getLine(stm,idx));
//                Platform.sdbDelete(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbe());
//            }
//        }
//        Streams.streamClear(stm);
//        ctx.getDaoSession().dbExecuteSQL("Select INR from CBB where OBJTYP = ? AND OBJINR = ?",objTyp,objInr);
//        ctx.getDaoSession().dbFetchStream(stm);
//        ctx.getDaoSession().dbCloseCursor();
//        if( ctx.getErrorCode() != tdOdbcNotFound )
//        {
//            ctx.reraise();
//            max = Streams.streamCount(stm);
//            for(int  idx = 1;idx <= max;idx++)
//            {
//                ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbb().setInr( Strings.getLine(stm,idx));
//                Platform.sdbDelete(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbb());
//            }
//        }
//        // Delete all limit requests
//        Platform.lsiDeleteObject(objTyp,objInr);

    }
    /**
     *   source:cbsmod.0011.script
     */
    public void cbsReorgCBB(Object obj)
    {
        logger.info("cbsReorgCBB参数obj:{}",obj);
        //! Reorganization of CBB for a contract
        //! Based on the passed module, all balances are recalculated
        //! Thus all CBB`s are deleted and recreated by processing all
        //! CBE`s of the object ordered by date.
        String objTyp = "";
        String objInr = "";
        Argument<String> objTypBox = new Argument<String>("",objTyp);
        Argument<String> objInrBox = new Argument<String>("",objInr);
        getObjAndInr( obj, objTypBox, objInrBox, "" );

        objTyp = objTypBox.value;
        objInr = objInrBox.value;

        List<Cbb> cbbList = cbbMapper.getCbbListByObjTypeAndInr(objTyp,objInr);
        logger.info("cbsReorgCBB获取cbblist:{},参数objtyp:{},objinr:{}",cbbList.toString(),objTyp,objInr);
        if(!MdaUtils.isEmpty(cbbList)) {
            cbbList.forEach(cbb -> {
                cbbMapper.deleteByPrimaryKey(cbb);
            });
        }
        List<Cbe> cbeList = cbeMapper.getCbeListByObjTypeAndInr(objTyp,objInr);
        logger.info("cbsReorgCBB获取cbelist:{},参数objtyp:{},objinr:{}",cbeList.toString(),objTyp,objInr);
        if(!MdaUtils.isEmpty(cbeList)) {
            cbeList.forEach(cbe -> {
                createCbbEntries(cbe);
            });
        }

//        String sql = " WHERE OBJINR = '" + objInr + "' AND OBJTYP = '" + objTyp + "'  ";
//        ctx.getDaoSession().dbSelectCursor(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbb(),sql);
//        ctx.getDaoSession().dbFetch(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbb());
//        while( ctx.getErrorCode() <= 0 )
//        {
//            Platform.sdbDelete(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbb());
//            ctx.getDaoSession().dbFree(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbb());
//            ctx.getDaoSession().dbFetch(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbb());
//        }
//        sql = sql + " ORDER BY DAT, INR";
//        ctx.getDaoSession().dbSelectCursor(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbe(),sql);
//        // ####### 改写 LABEL与GOTO   ####    label NxtCbe
//        NxtCbe:
//        while(true) {
//            ctx.getDaoSession().dbFetch(ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbe());
//            if( ctx.getErrorCode() <= 0 )
//            {
//                ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).createCbbEntries( ctx.absGet(com.ceb.gjjs.mda.manager.module.Cbsmod.class).getCbe());
//                continue ; // ####### 改写 LABEL与GOTO  ####   goto NxtCbe
//            }
//            break;
//        }
//        if( ctx.getErrorCode() != tdOdbcNotFound )
//        {
//            ctx.reraise();
//        }

    }
    /**
     *   source:cbsmod.0012.script
     */
    public Cbb cbsSelectValidInRangeForObject(String objTyp, String objInr, String cbcArg, String extId, Date begDat, Date endDat)
    {
        //! A global procedure to create a cursor for all CBB entries valid within the specified date range
        //! CbbArg is the CBB-Instance the cursor is associated to.
        //! ObjTyp and ObjInr are used to identify the object
        //! CbcArg specifies the column the balances are to be retrieved from
        //! BegDat and EndDat specify the date range
        //! Use CbsSelectValidInRange if the object is available as a module instance
        return cbsRange.sdbRngSelectValidInRange(objTyp, objInr, cbcArg, extId, begDat, endDat);
    }


    public void cbsGetBalance(Cbb cbbArg,String objtyp,String objinr,String cbcArg,String extId,Date perDat)
    {
        logger.info("cbsGetBalance参数cbbArg:{},objtyp:{},objinr:{},cbcArg:{},extId:{},perDat:{}",cbbArg.toString(),objtyp,objinr,cbcArg,extId,perDat);
        //! retrieve balance per specified date
        //!
        //! CbbArg holds the result of the call
        //! Obj is the passed modul holding the object
        //! CbcArg is the selected CBS-column
        //! ExtId is the selected ExtId for multiple columns
        //! PerDat is the date the balance is retrieved from
        cbbArg.setObjtyp( objtyp);
        cbbArg.setObjinr( objinr);
        // CBSXBL
        cbbArg.setExtid( extId);
        cbbArg.setCbc( cbcArg);
        cbsRange.sdbRngRead(cbbArg,perDat);
    }


    public  String checkregularCash( String objinr, String objtyp) {
        //取得上下文
        String rel = "";
        List<Cbe> cbeList = cbeMapper.getCbeListByObjTypAndInrWithCbt(objtyp, objinr, "CCVIN");
        int cout = cbeList.size();
        String act = "";
        String trmtrp = "";
        String rflg = "";
        for (int i = 0; i < cout; i++) {
            act = cbeList.get(i).getAcc();
            trmtrp = "";
            if (!MdaUtils.isEmpty(act)) {

                rflg = "";
                if (Strings.len(act) == 17) {
                    rflg = Strings.mid(act, 7, 2);
                }
                if (Strings.len(act) == 21) {
                    rflg = Strings.mid(act, 11, 2);
                }
                if (MdaUtils.compareTo(Strings.mid(act, 1, 3), "ZMQ") == 0 || MdaUtils.compareTo(Strings.mid(act, 1, 3), "NRA") == 0) {
                    rflg = Strings.mid(act, 10, 2);
                }
                if (MdaUtils.compareTo(rflg, "81") == 0) {
                    rel = "Y";
                }
            }
        }
        return rel;

    }

}
