From f80f3b90c7ef9f33bf3973c95d4dbaf08aae4b87 Mon Sep 17 00:00:00 2001 From: DanB Date: Tue, 5 Jan 2021 17:44:25 +0100 Subject: [PATCH] AccountS - change decimal rounding closer to 0 so we don't debit too much in case of limits --- accounts/abstractbalance.go | 16 +++++++++------- accounts/concretebalance.go | 13 ++++++++----- accounts/concretebalance_test.go | 22 ++++++++++++++++++++++ loaders/loader.go | 1 + 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/accounts/abstractbalance.go b/accounts/abstractbalance.go index 5a3ea9111..65e58f2f0 100644 --- a/accounts/abstractbalance.go +++ b/accounts/abstractbalance.go @@ -81,9 +81,11 @@ func (aB *abstractBalance) unitFactor(tnt string, ev utils.DataProvider) (uF *ut // balanceLimit returns the balance's limit func (aB *abstractBalance) balanceLimit() (bL *decimal.Big) { + if _, isUnlimited := aB.blnCfg.Opts[utils.MetaBalanceUnlimited]; isUnlimited { + return + } if lmtIface, has := aB.blnCfg.Opts[utils.MetaBalanceLimit]; has { bL = lmtIface.(*decimal.Big) - return } // nothing matched, return default bL = decimal.New(0, 0) @@ -113,6 +115,12 @@ func (aB *abstractBalance) debitUsage(usage *decimal.Big, startTime time.Time, return } + // unitFactor + var uF *utils.UnitFactor + if uF, err = aB.unitFactor(cgrEv.CGREvent.Tenant, evNm); err != nil { + return + } + blcVal := new(decimal.Big).SetFloat64(aB.blnCfg.Value) // FixMe without float64 // balanceLimit @@ -123,12 +131,6 @@ func (aB *abstractBalance) debitUsage(usage *decimal.Big, startTime time.Time, hasLmt = true } - // unitFactor - var uF *utils.UnitFactor - if uF, err = aB.unitFactor(cgrEv.CGREvent.Tenant, evNm); err != nil { - return - } - fmt.Printf("costIcrm: %+v, blncLmt: %+v, hasLmt: %+v, uF: %+v", costIcrm, blncLmt, hasLmt, uF) return diff --git a/accounts/concretebalance.go b/accounts/concretebalance.go index 6fda4e55f..d4e5f4d46 100644 --- a/accounts/concretebalance.go +++ b/accounts/concretebalance.go @@ -81,6 +81,9 @@ func (cB *concreteBalance) unitFactor(tnt string, ev utils.DataProvider) (uF *ut // balanceLimit returns the balance's limit func (cB *concreteBalance) balanceLimit() (bL *decimal.Big) { + if _, isUnlimited := cB.blnCfg.Opts[utils.MetaBalanceUnlimited]; isUnlimited { + return + } if lmtIface, has := cB.blnCfg.Opts[utils.MetaBalanceLimit]; has { bL = lmtIface.(*decimal.Big) return @@ -144,14 +147,14 @@ func (cB *concreteBalance) debitUnits(dUnts *decimal.Big, incrm *decimal.Big, // balanceLimit var hasLmt bool blncLmt := cB.balanceLimit() - if blncLmt.Cmp(decimal.New(0, 0)) != 0 { + if blncLmt != nil && blncLmt.Cmp(decimal.New(0, 0)) != 0 { blcVal = utils.SubstractBig(blcVal, blncLmt) hasLmt = true } - - _, isUnlimited := cB.blnCfg.Opts[utils.MetaBalanceUnlimited] - if blcVal.Cmp(dUnts) == -1 && !isUnlimited { // balance smaller than debit - maxIncrm := utils.DivideBig(blcVal, incrm).RoundToInt() + if blcVal.Cmp(dUnts) == -1 && blncLmt != nil { // balance smaller than debit + // will use special rounding to 0 since otherwise we go negative (ie: 0.05 as increment) + maxIncrm := decimal.WithContext( + decimal.Context{RoundingMode: decimal.ToZero}).Quo(blcVal, incrm).RoundToInt() dUnts = utils.MultiplyBig(incrm, maxIncrm) } rmain := utils.SubstractBig(blcVal, dUnts) diff --git a/accounts/concretebalance_test.go b/accounts/concretebalance_test.go index e18dddf92..bbe4b3fe6 100644 --- a/accounts/concretebalance_test.go +++ b/accounts/concretebalance_test.go @@ -100,4 +100,26 @@ func TestCBDebitUnits(t *testing.T) { } else if cb.blnCfg.Value != -1.25 { t.Errorf("balance remaining: %f", cb.blnCfg.Value) } + //with increment and positive limit + cb = &concreteBalance{ + blnCfg: &utils.Balance{ + ID: "TestCBDebitUnits", + Type: utils.MetaConcrete, + Opts: map[string]interface{}{ + utils.MetaBalanceLimit: decimal.New(5, 1), // 0.5 as limit + }, + Value: 1.25, + }, + fltrS: new(engine.FilterS), + } + if dbted, _, err := cb.debitUnits( + new(decimal.Big).SetFloat64(2.5), + new(decimal.Big).SetFloat64(0.1), + &utils.CGREventWithOpts{CGREvent: &utils.CGREvent{Tenant: "cgrates.org"}}); err != nil { + t.Error(err) + } else if dbted.Cmp(decimal.New(7, 1)) != 0 { // only 1.2 is possible due to increment + t.Errorf("debited: %s, cmp: %v", dbted, dbted.Cmp(new(decimal.Big).SetFloat64(1.2))) + } else if cb.blnCfg.Value != 0.55 { + t.Errorf("balance remaining: %f", cb.blnCfg.Value) + } } diff --git a/loaders/loader.go b/loaders/loader.go index 4468a9c93..91ed716ab 100644 --- a/loaders/loader.go +++ b/loaders/loader.go @@ -1162,6 +1162,7 @@ func (ldr *Loader) allFilesPresent(ldrType string) bool { return true } +// getLdrType returns loaderType for the given fileName func (ldr *Loader) getLdrType(fName string) (ldrType string) { for ldr, rdrs := range ldr.rdrs { if _, has := rdrs[fName]; has {