UNPKG

futoin-xferengine

Version:

Neutral clustered multi-currency transaction engine with limits

559 lines (493 loc) 23 kB
'use strict'; const expect = require( 'chai' ).expect; const moment = require( 'moment' ); const Executor = require( 'futoin-executor/Executor' ); const SpecTools = require( 'futoin-invoker/SpecTools' ); //SpecTools.on('error', function() { console.log(arguments); } ); module.exports = function( describe, it, vars ) { let as; let ccm; let executor; beforeEach( 'common', function() { ccm = vars.ccm; as = vars.as; executor = vars.executor; } ); describe( 'Deposits', function() { const LimitsFace = require( '../LimitsFace' ); const LimitsService = require( '../LimitsService' ); const InfoFace = require( '../Currency/InfoFace' ); const InfoService = require( '../Currency/InfoService' ); const AccountsFace = require( '../AccountsFace' ); const AccountsService = require( '../AccountsService' ); const DepositTools = require( '../DepositTools' ); const DepositFace = require( '../DepositFace' ); const DepositService = require( '../DepositService' ); const WithdrawFace = require( '../WithdrawFace' ); const WithdrawService = require( '../WithdrawService' ); let system_account; let fee_account; let account_holder; let user_account; const checkBalance = ( as, account, balance ) => { ccm.iface( 'xfer.accounts' ).getAccount( as, account ); as.add( ( as, info ) => expect( info.balance ).to.equal( balance ) ); }; const checkBalanceAll = ( as, system_bal, fee_bal, user_bal ) => { let base; as.add( ( as ) => base = as.state.test_name ); as.add( ( as ) => as.state.test_name = base + ' system' ); checkBalance( as, system_account, system_bal ); as.add( ( as ) => as.state.test_name = base + ' fee' ); checkBalance( as, fee_account, fee_bal ); as.add( ( as ) => as.state.test_name = base + ' user' ); checkBalance( as, user_account, user_bal ); }; beforeEach( 'deposits', function() { as.add( ( as ) => { InfoService.register( as, executor ); InfoFace.register( as, ccm, 'currency.info', executor ); LimitsService.register( as, executor ); LimitsFace.register( as, ccm, 'xfer.limits', executor ); AccountsService.register( as, executor ); AccountsFace.register( as, ccm, 'xfer.accounts', executor ); DepositService.register( as, executor ); DepositFace.register( as, ccm, 'xfer.deposits', executor ); WithdrawService.register( as, executor ); WithdrawFace.register( as, ccm, 'xfer.withdrawals', executor ); }, ( as, err ) => { console.log( err ); console.log( as.state.error_info ); console.log( as.state.last_exception ); } ); as.add( ( as ) => { if ( system_account ) { return; } const xferlim = ccm.iface( 'xfer.limits' ); xferlim.addLimitGroup( as, 'DepositTest' ); xferlim.setLimits( as, 'DepositTest', 'Deposits', 'I:EUR', { deposit_daily_amt : "1.00", deposit_daily_cnt : 2, withdrawal_daily_amt : "1.00", withdrawal_daily_cnt : 4, deposit_weekly_amt : "1.00", deposit_weekly_cnt : 2, withdrawal_weekly_amt : "1.00", withdrawal_weekly_cnt : 4, deposit_monthly_amt : "1.00", deposit_monthly_cnt : 2, withdrawal_monthly_amt : "1.00", withdrawal_monthly_cnt : 4, deposit_min_amt : "0.10", withdrawal_min_amt : "0.01", }, { deposit_daily_amt : "1.00", deposit_daily_cnt : 2, withdrawal_daily_amt : "0.50", withdrawal_daily_cnt : 4, deposit_weekly_amt : "1.00", deposit_weekly_cnt : 2, withdrawal_weekly_amt : "1.00", withdrawal_weekly_cnt : 4, deposit_monthly_amt : "1.00", deposit_monthly_cnt : 2, withdrawal_monthly_amt : "1.00", withdrawal_monthly_cnt : 4, deposit_min_amt : "0.10", withdrawal_min_amt : "0.01", }, false ); xferlim.setLimits( as, 'DepositTest', 'Misc', 'I:EUR', { message_daily_cnt : 1000, failure_daily_cnt : 1000, limithit_daily_cnt : 1000, message_weekly_cnt : 1000, failure_weekly_cnt : 1000, limithit_weekly_cnt : 1000, message_monthly_cnt : 1000, failure_monthly_cnt : 1000, limithit_monthly_cnt : 1000, }, false, false ); xferlim.addLimitGroup( as, 'DepositSystemTest' ); xferlim.setLimits( as, 'DepositSystemTest', 'Payments', 'I:EUR', { outbound_daily_amt : "1000.00", outbound_daily_cnt : 1000, inbound_daily_amt : "1000.00", inbound_daily_cnt : 1000, outbound_weekly_amt : "5000.00", outbound_weekly_cnt : 1000, inbound_weekly_amt : "5000.00", inbound_weekly_cnt : 1000, outbound_monthly_amt : "100000.00", outbound_monthly_cnt : 1000, inbound_monthly_amt :"100000.00", inbound_monthly_cnt : 1000, outbound_min_amt : "0.01", }, false, false ); //-- const xferacct = ccm.iface( 'xfer.accounts' ); xferacct.addAccountHolder( as, 'DepositSystem', 'DepositSystemTest', true, true, {}, {} ); as.add( ( as, holder ) => { xferacct.addAccount( as, holder, 'System', 'I:EUR', 'Source' ); as.add( ( as, id ) => system_account = id ); xferacct.addAccount( as, holder, 'System', 'I:EUR', 'Fee' ); as.add( ( as, id ) => fee_account = id ); } ); xferacct.addAccountHolder( as, 'DepositsUser', 'DepositTest', true, true, {}, {} ); as.add( ( as, holder ) => { account_holder = holder; xferacct.addAccount( as, holder, 'Regular', 'I:EUR', 'Main' ); as.add( ( as, id ) => user_account = id ); } ); }, ( as, err ) => { console.log( err ); console.log( as.state.error_info ); } ); } ); it ( 'should process deposits', function( done ) { as.add( ( as ) => { const deposits = ccm.iface( 'xfer.deposits' ); as.add( ( as ) => as.state.test_name = 'Pre-check' ); deposits.preDepositCheck( as, user_account, system_account, 'I:EUR', '1.00' ); checkBalanceAll( as, '0.00', '0.00', '0.00' ); for ( let i = 0; i < 2; ++i ) { as.add( ( as ) => as.state.test_name = `On deposit #1 ${i}` ); deposits.onDeposit( as, user_account, system_account, 'I:EUR', '0.60', 'T1', {}, moment.utc().format(), { rel_account: fee_account, currency: 'I:EUR', amount: '0.01', reason: 'System fee', } ); if ( !i ) checkBalanceAll( as, '-0.60', '0.01', '0.59' ); as.add( ( as ) => as.state.test_name = `On deposit no-fee #2 ${i}` ); deposits.onDeposit( as, user_account, system_account, 'I:EUR', '0.40', 'T2', {}, moment.utc().format(), null ); if ( !i ) checkBalanceAll( as, '-1.00', '0.01', '0.99' ); } as.add( ( as ) => { as.add( ( as ) => as.state.test_name = 'Pre-check #3' ); deposits.preDepositCheck( as, user_account, system_account, 'I:EUR', '1.00' ); as.add( ( as ) => as.error( 'Fail' ) ); }, ( as, err ) => { if ( err === 'LimitReject' ) { as.success(); } } ); checkBalanceAll( as, '-1.00', '0.01', '0.99' ); as.add( ( as ) => { as.add( ( as ) => as.state.test_name = 'On deposit #3' ); deposits.onDeposit( as, user_account, system_account, 'I:EUR', '1.00', 'T3', {}, moment.utc().format(), { rel_account: fee_account, currency: 'I:EUR', amount: '0.01', reason: 'System fee', } ); as.add( ( as ) => as.error( 'Fail' ) ); }, ( as, err ) => { if ( err === 'LimitReject' ) { as.success(); } } ); checkBalanceAll( as, '-1.00', '0.01', '0.99' ); }, ( as, err ) => { console.log( as.state.test_name ); console.log( err ); console.log( as.state.error_info ); done( as.state.last_exception || 'Fail' ); } ); as.add( ( as ) => done() ); as.execute(); } ); it ( 'should process withdraw', function( done ) { as.add( ( as ) => { const withdraw = ccm.iface( 'xfer.withdrawals' ); checkBalanceAll( as, '-1.00', '0.01', '0.99' ); for ( let i = 0; i < 2; ++i ) { as.add( ( as ) => as.state.test_name = `Start withdraw #1` ); withdraw.startWithdrawal( as, user_account, system_account, 'I:EUR', '0.10', 'T1', {}, moment.utc().format(), { rel_account: fee_account, currency: 'I:EUR', amount: '0.01', reason: 'System fee', } ); as.add( ( as, res ) => { expect( res.xfer_id ).to.be.ok; expect( res.wait_user ).to.be.false; } ); if ( !i ) checkBalanceAll( as, '-0.90', '0.02', '0.88' ); //--- as.add( ( as ) => as.state.test_name = `Start withdraw #2` ); as.add( ( as ) => { withdraw.startWithdrawal( as, user_account, system_account, 'I:EUR', '0.80', 'T2', {}, moment.utc().format() ); as.add( ( as, res ) => { expect( res.xfer_id ).to.be.ok; expect( res.wait_user ).to.be.true; checkBalanceAll( as, '-0.90', '0.02', '0.08' ); as.add( ( as ) => as.state.test_name = `Reject withdraw #2` ); withdraw.rejectWithdrawal( as, res.xfer_id, user_account, system_account, 'I:EUR', '0.80', moment.utc().format() ); checkBalanceAll( as, '-0.90', '0.02', '0.88' ); } ); }, ( as, err ) => { if ( i ) { expect( err ).to.equal( 'AlreadyCanceled' ); as.success(); } } ); if ( !i ) checkBalanceAll( as, '-0.90', '0.02', '0.88' ); // --- as.add( ( as ) => { as.add( ( as ) => as.state.test_name = 'Start withdraw #3' ); withdraw.startWithdrawal( as, user_account, system_account, 'I:EUR', '1.00', 'T3', {}, moment.utc().format() ); as.add( ( as ) => as.error( 'Fail' ) ); }, ( as, err ) => { if ( err === 'NotEnoughFunds' ) { as.success(); } } ); if ( !i ) checkBalanceAll( as, '-0.90', '0.02', '0.88' ); // --- as.add( ( as ) => as.state.test_name = `Start withdraw #4` ); withdraw.startWithdrawal( as, user_account, system_account, 'I:EUR', '0.80', 'T4', {}, moment.utc().format() ); as.add( ( as, res ) => { expect( res.xfer_id ).to.be.ok; expect( res.wait_user ).to.equal( i === 0 ); if ( !i ) checkBalanceAll( as, '-0.90', '0.02', '0.08' ); as.add( ( as ) => as.state.test_name = `Confirm withdraw #4` ); withdraw.confirmWithdrawal( as, res.xfer_id, user_account, system_account, 'I:EUR', '0.80', moment.utc().format() ); if ( !i ) checkBalanceAll( as, '-0.10', '0.02', '0.08' ); as.add( ( as ) => { as.add( ( as ) => as.state.test_name = 'Reject withdraw #4' ); withdraw.rejectWithdrawal( as, res.xfer_id, user_account, system_account, 'I:EUR', '0.80', moment.utc().format() ); as.add( ( as ) => as.error( 'Fail' ) ); }, ( as, err ) => { if ( err === 'AlreadyCompleted' ) { as.success(); } } ); } ); } checkBalanceAll( as, '-0.10', '0.02', '0.08' ); as.add( ( as ) => { as.add( ( as ) => as.state.test_name = 'Start withdraw #5' ); withdraw.startWithdrawal( as, user_account, system_account, 'I:EUR', '0.07', 'T5', {}, moment.utc().format(), { rel_account: fee_account, currency: 'I:EUR', amount: '0.01', reason: 'System fee', } ); as.add( ( as ) => as.error( 'Fail' ) ); }, ( as, err ) => { if ( err === 'LimitReject' ) { as.success(); } } ); as.add( ( as ) => { as.add( ( as ) => as.state.test_name = 'Confirm unknown' ); withdraw.confirmWithdrawal( as, 'aaaaaaaaaaaaaaaaaaaaaa', user_account, system_account, 'I:EUR', '0.80', moment.utc().format() ); as.add( ( as ) => as.error( 'Fail' ) ); }, ( as, err ) => { if ( err === 'UnknownXferID' ) { as.success(); } } ); checkBalanceAll( as, '-0.10', '0.02', '0.08' ); }, ( as, err ) => { console.log( as.state.test_name ); console.log( err ); console.log( as.state.error_info ); done( as.state.last_exception || 'Fail' ); } ); as.add( ( as ) => done() ); as.execute(); } ); it ( 'should trigger just in case checks', function( done ) { as.add( ( as ) => { const dt = new DepositTools( ccm ); as.add( ( as ) => { as.state.test_name = 'Deposit cancel DB step'; dt._domainDbCancelStep( as, null, { type: 'Deposit' } ); as.add( ( as ) => as.error( 'Fail' ) ); }, ( as, err ) => { if ( err === 'NotAllowed' ) as.success(); } ); as.add( ( as ) => { as.state.test_name = 'Deposit cancel ext-out step'; dt._rawCancelExtOut( as, { type: 'Deposit' } ); as.add( ( as ) => as.error( 'Fail' ) ); }, ( as, err ) => { if ( err === 'NotAllowed' ) as.success(); } ); }, ( as, err ) => { console.log( as.state.test_name ); console.log( err ); console.log( as.state.error_info ); done( as.state.last_exception || 'Fail' ); } ); as.add( ( as ) => done() ); as.execute(); } ); } ); };