diff --git a/accounts/abstractbalance.go b/accounts/abstractbalance.go index 9c19eeb33..353cb5191 100644 --- a/accounts/abstractbalance.go +++ b/accounts/abstractbalance.go @@ -178,7 +178,7 @@ func (aB *abstractBalance) debitUsageFromConcrete(usage *utils.Decimal, // debitUsage implements the balanceOperator interface func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time, - cgrEv *utils.CGREvent) (ec *utils.EventCharges, err error) { + cgrEv *utils.CGREvent) (dbted *utils.Decimal, ec *utils.EventCharges, err error) { evNm := utils.MapStorage{ utils.MetaOpts: cgrEv.Opts, @@ -190,7 +190,7 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time, if pass, err = aB.fltrS.Pass(cgrEv.Tenant, aB.blnCfg.FilterIDs, evNm); err != nil { return } else if !pass { - return nil, utils.ErrFilterNotPassingNoCaps + return nil, nil, utils.ErrFilterNotPassingNoCaps } // costIncrement @@ -210,8 +210,6 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time, } } - //origBlclVal := new(decimal.Big).Copy(aB.blnCfg.Units.Big) // so we can restore on errors - // balanceLimit var hasLmt bool blncLmt := aB.balanceLimit() @@ -249,13 +247,11 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time, restoreUnitsFromClones(aB.cncrtBlncs, origConcrtUnts) } if i == maxIter { - //aB.blnCfg.Units.Big = origBlclVal - return nil, utils.ErrMaxIncrementsExceeded + return nil, nil, utils.ErrMaxIncrementsExceeded } - //fmt.Printf("i: %d, usage: %s\n", i, usage) + qriedUsage := usage.Big // so we can detect loops if err = aB.debitUsageFromConcrete(usage, costIcrm, cgrEv); err != nil { if err != utils.ErrInsufficientCredit { - //aB.blnCfg.Units.Big = origBlclVal return } err = nil @@ -266,7 +262,8 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time, usage.Big, decimal.New(2, 0)) usage.Big = roundedUsageWithIncrements(usage.Big, costIcrm.Increment.Big) // make sure usage is multiple of increments if usage.Big.Cmp(usageDenied) >= 0 || - usage.Big.Cmp(decimal.New(0, 0)) == 0 { + usage.Big.Cmp(decimal.New(0, 0)) == 0 || + usage.Big.Cmp(qriedUsage) == 0 { // loop break } continue @@ -287,14 +284,14 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time, } usage.Big = roundedUsageWithIncrements(usage.Big, costIcrm.Increment.Big) if usage.Big.Cmp(usagePaid) <= 0 || - usage.Big.Cmp(usageDenied) >= 0 { + usage.Big.Cmp(usageDenied) >= 0 || + usage.Big.Cmp(qriedUsage) == 0 { // loop break } } // Nothing paid if usagePaid == nil { // since we are erroring, we restore the concerete balances - //aB.blnCfg.Units.Big = origBlclVal usagePaid = decimal.New(0, 0) } @@ -308,5 +305,6 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time, if hasUF { usage.Big = utils.DivideBig(usage.Big, uF.Factor.Big) } + dbted = &utils.Decimal{usagePaid} return } diff --git a/accounts/abstractbalance_test.go b/accounts/abstractbalance_test.go index 7e401ccfc..0e6bd6235 100644 --- a/accounts/abstractbalance_test.go +++ b/accounts/abstractbalance_test.go @@ -133,10 +133,12 @@ func TestABDebitUsage(t *testing.T) { fltrS: new(engine.FilterS), } - if _, err := aB.debitUsage(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0), + if dbted, _, err := aB.debitUsage(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0), time.Now(), new(utils.CGREvent)); err != nil { t.Error(err) - } else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0)) != 0 { + } else if dbted.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 { + t.Errorf("Unexpected debited units: %s", dbted) + } else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 { t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units) } else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(20, 0)) != 0 { t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units) @@ -146,9 +148,11 @@ func TestABDebitUsage(t *testing.T) { aB.blnCfg.Units = utils.NewDecimal(int64(time.Duration(60*time.Second)), 0) aB.cncrtBlncs[0].blnCfg.Units = utils.NewDecimal(29, 0) // not enough concrete - if _, err := aB.debitUsage(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0), + if dbted, _, err := aB.debitUsage(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0), time.Now(), new(utils.CGREvent)); err != nil { t.Error(err) + } else if dbted.Compare(utils.NewDecimal(int64(29*time.Second), 0)) != 0 { + t.Errorf("Unexpected debited units: %s", dbted) } else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(time.Duration(31*time.Second)), 0)) != 0 { // used 29 units t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units) } else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 { @@ -158,9 +162,11 @@ func TestABDebitUsage(t *testing.T) { // limited by concrete aB.cncrtBlncs[0].blnCfg.Units = utils.NewDecimal(0, 0) // not enough concrete - if _, err := aB.debitUsage(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0), + if dbted, _, err := aB.debitUsage(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0), time.Now(), new(utils.CGREvent)); err != nil { t.Error(err) + } else if dbted.Compare(utils.NewDecimal(0, 0)) != 0 { + t.Errorf("Unexpected debited units: %s", dbted) } else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(time.Duration(31*time.Second)), 0)) != 0 { // same as above t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units) } else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 { // same as above @@ -171,9 +177,11 @@ func TestABDebitUsage(t *testing.T) { aB.blnCfg.Units = utils.NewDecimal(int64(time.Duration(29*time.Second)), 0) // not enough abstract aB.cncrtBlncs[0].blnCfg.Units = utils.NewDecimal(60, 0) - if _, err := aB.debitUsage(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0), + if dbted, _, err := aB.debitUsage(utils.NewDecimal(int64(time.Duration(30*time.Second)), 0), time.Now(), new(utils.CGREvent)); err != nil { t.Error(err) + } else if dbted.Compare(utils.NewDecimal(int64(time.Duration(29*time.Second)), 0)) != 0 { + t.Errorf("Unexpected debited units: %s", dbted) } else if aB.blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 { // should be all used t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units) } else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(31, 0)) != 0 { diff --git a/accounts/concretebalance.go b/accounts/concretebalance.go index 8c90e19c1..3573bbb08 100644 --- a/accounts/concretebalance.go +++ b/accounts/concretebalance.go @@ -93,7 +93,7 @@ func (cB *concreteBalance) balanceLimit() (bL *utils.Decimal) { // debit implements the balanceOperator interface func (cB *concreteBalance) debitUsage(usage *utils.Decimal, startTime time.Time, - cgrEv *utils.CGREvent) (ec *utils.EventCharges, err error) { + cgrEv *utils.CGREvent) (dbted *utils.Decimal, ec *utils.EventCharges, err error) { evNm := utils.MapStorage{ utils.MetaOpts: cgrEv.Opts, @@ -105,7 +105,7 @@ func (cB *concreteBalance) debitUsage(usage *utils.Decimal, startTime time.Time, if pass, err = cB.fltrS.Pass(cgrEv.Tenant, cB.blnCfg.FilterIDs, evNm); err != nil { return } else if !pass { - return nil, utils.ErrFilterNotPassingNoCaps + return nil, nil, utils.ErrFilterNotPassingNoCaps } return diff --git a/accounts/libaccounts.go b/accounts/libaccounts.go index ed3125f99..04ce32737 100644 --- a/accounts/libaccounts.go +++ b/accounts/libaccounts.go @@ -92,7 +92,7 @@ func newBalanceOperator(blncCfg *utils.Balance, cncrtBlncs []*concreteBalance, // balanceOperator is the implementation of a balance type type balanceOperator interface { debitUsage(usage *utils.Decimal, startTime time.Time, - cgrEv *utils.CGREvent) (ec *utils.EventCharges, err error) + cgrEv *utils.CGREvent) (dbted *utils.Decimal, ec *utils.EventCharges, err error) } // roundUsageWithIncrements rounds the usage based on increments