diff --git a/engine/statmetrics.go b/engine/statmetrics.go index ee2aed256..6d21af3fd 100644 --- a/engine/statmetrics.go +++ b/engine/statmetrics.go @@ -556,6 +556,8 @@ func (acc *StatACC) AddEvent(evID string, ev utils.DataProvider) (err error) { return } else if cost, err = utils.IfaceAsFloat64(val); err != nil { return + } else if cost < 0 { + return utils.ErrPrefix(utils.ErrNegative, utils.Cost) } acc.Sum += cost if val, has := acc.Events[evID]; !has { @@ -686,6 +688,8 @@ func (tcc *StatTCC) AddEvent(evID string, ev utils.DataProvider) (err error) { return } else if cost, err = utils.IfaceAsFloat64(val); err != nil { return + } else if cost < 0 { + return utils.ErrPrefix(utils.ErrNegative, utils.Cost) } tcc.Sum += cost if val, has := tcc.Events[evID]; !has { diff --git a/engine/statmetrics_test.go b/engine/statmetrics_test.go index 7f5b3cf8e..86c647c23 100644 --- a/engine/statmetrics_test.go +++ b/engine/statmetrics_test.go @@ -1052,6 +1052,12 @@ func TestACCGetStringValue(t *testing.T) { if strVal := acc.GetStringValue(config.CgrConfig().GeneralCfg().RoundingDecimals); strVal != utils.NotAvailable { t.Errorf("wrong acc value: %s", strVal) } + expErr := "NEGATIVE:Cost" + if err := acc.AddEvent(ev5.ID, utils.MapStorage{utils.MetaReq: utils.MapStorage{ + utils.Cost: -1, + }}); err == nil || err.Error() != expErr { + t.Errorf("Expected error: %s received %v", expErr, err) + } } func TestACCGetStringValue2(t *testing.T) { @@ -1322,6 +1328,13 @@ func TestTCCGetStringValue(t *testing.T) { if strVal := tcc.GetStringValue(config.CgrConfig().GeneralCfg().RoundingDecimals); strVal != utils.NotAvailable { t.Errorf("wrong tcc value: %s", strVal) } + + expErr := "NEGATIVE:Cost" + if err := tcc.AddEvent(ev5.ID, utils.MapStorage{utils.MetaReq: utils.MapStorage{ + utils.Cost: -1, + }}); err == nil || err.Error() != expErr { + t.Errorf("Expected error: %s received %v", expErr, err) + } } func TestTCCGetStringValue2(t *testing.T) { diff --git a/packages/debian/changelog b/packages/debian/changelog index a03f65336..4fa6ccc57 100644 --- a/packages/debian/changelog +++ b/packages/debian/changelog @@ -162,6 +162,7 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium * [ERs] Added *opts.*partial to control if the event is partial or not * [AttributeS] Added any_context config to control the matching attributes * [DispatcherS] Added any_subsyste config to control the matching dispatchers + * [StatS] AverageCallCost and TotalCallCost now returns error for negative Cost field -- DanB Wed, 19 Feb 2020 13:25:52 +0200 diff --git a/utils/errors.go b/utils/errors.go index aef7d2047..d1716bc9b 100644 --- a/utils/errors.go +++ b/utils/errors.go @@ -75,6 +75,7 @@ var ( ErrMaxConcurentRPCExceededNoCaps = errors.New("max concurent rpc exceeded") // on internal we return this error for concureq ErrMaxConcurentRPCExceeded = errors.New("MAX_CONCURENT_RPC_EXCEEDED") // but the codec will rewrite it with this one to be sure that we corectly dealocate the request ErrMaxIterationsReached = errors.New("maximum iterations reached") + ErrNegative = errors.New("NEGATIVE") ErrMap = map[string]error{ ErrNoMoreData.Error(): ErrNoMoreData,