From 1225d5e05d346eba3cdf05bc43d589ad468ec4f9 Mon Sep 17 00:00:00 2001 From: TeoV Date: Mon, 13 May 2019 17:17:25 +0300 Subject: [PATCH] Add option for balance_rating_subject in RALs section of config --- config/config.go | 1 + config/config_defaults.go | 7 +++++++ config/config_json_test.go | 7 +++++++ config/config_test.go | 11 +++++++++++ config/libconfig_json.go | 1 + config/ralscfg.go | 18 ++++++++++++------ engine/balances.go | 3 ++- utils/coreutils.go | 9 ++------- utils/coreutils_test.go | 16 +++++++++++++++- 9 files changed, 58 insertions(+), 15 deletions(-) diff --git a/config/config.go b/config/config.go index 153561274..568bc70eb 100755 --- a/config/config.go +++ b/config/config.go @@ -142,6 +142,7 @@ func NewDefaultCGRConfig() (*CGRConfig, error) { cfg.filterSCfg = new(FilterSCfg) cfg.ralsCfg = new(RalsCfg) cfg.ralsCfg.RALsMaxComputedUsage = make(map[string]time.Duration) + cfg.ralsCfg.RALsBalanceRatingSubject = make(map[string]string) cfg.schedulerCfg = new(SchedulerCfg) cfg.cdrsCfg = new(CdrsCfg) cfg.CdreProfiles = make(map[string]*CdreCfg) diff --git a/config/config_defaults.go b/config/config_defaults.go index f53404c61..83d6d4469 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -174,6 +174,13 @@ const CGRATES_CFG_JSON = ` "*data": "107374182400", "*sms": "10000" }, + "balance_rating_subject":{ // default rating subject in case that balance rating subject is empty + "*any": "*zero1ns", + "*voice": "*zero1s", + "*data": "*zero1ns", + "*sms": "*zero1ns", + "*monetary":"*zero1ns", + }, }, diff --git a/config/config_json_test.go b/config/config_json_test.go index b34a21dfc..21cbbfca0 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -239,6 +239,13 @@ func TestDfRalsJsonCfg(t *testing.T) { utils.VOICE: "72h", utils.DATA: "107374182400", utils.SMS: "10000"}, + Balance_rating_subject: &map[string]string{ + utils.ANY: "*zero1ns", + utils.VOICE: "*zero1s", + utils.DATA: "*zero1ns", + utils.SMS: "*zero1ns", + utils.MONETARY: "*zero1ns", + }, } if cfg, err := dfCgrJsonCfg.RalsJsonCfg(); err != nil { t.Error(err) diff --git a/config/config_test.go b/config/config_test.go index f74c240be..edaae42ec 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -474,6 +474,17 @@ func TestCgrCfgJSONDefaultsRALs(t *testing.T) { if !reflect.DeepEqual(eMaxCU, cgrCfg.RalsCfg().RALsMaxComputedUsage) { t.Errorf("Expecting: %+v , received: %+v", eMaxCU, cgrCfg.RalsCfg().RALsMaxComputedUsage) } + eBalRatingSbj := map[string]string{ + utils.ANY: "*zero1ns", + utils.VOICE: "*zero1s", + utils.DATA: "*zero1ns", + utils.SMS: "*zero1ns", + utils.MONETARY: "*zero1ns", + utils.GENERIC: "*zero1ns", + } + if !reflect.DeepEqual(eBalRatingSbj, cgrCfg.RalsCfg().RALsBalanceRatingSubject) { + t.Errorf("Expecting: %+v , received: %+v", eBalRatingSbj, cgrCfg.RalsCfg().RALsBalanceRatingSubject) + } } func TestCgrCfgJSONDefaultsScheduler(t *testing.T) { diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 4a3431358..18922f13d 100755 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -104,6 +104,7 @@ type RalsJsonCfg struct { Rp_subject_prefix_matching *bool Remove_expired *bool Max_computed_usage *map[string]string + Balance_rating_subject *map[string]string } // Scheduler config section diff --git a/config/ralscfg.go b/config/ralscfg.go index 9586e2456..27e94fed3 100644 --- a/config/ralscfg.go +++ b/config/ralscfg.go @@ -26,12 +26,13 @@ import ( // Rater config section type RalsCfg struct { - RALsEnabled bool // start standalone server (no balancer) - RALsThresholdSConns []*RemoteHost // address where to reach ThresholdS config - RALsStatSConns []*RemoteHost - RpSubjectPrefixMatching bool // enables prefix matching for the rating profile subject - RemoveExpired bool - RALsMaxComputedUsage map[string]time.Duration + RALsEnabled bool // start standalone server (no balancer) + RALsThresholdSConns []*RemoteHost // address where to reach ThresholdS config + RALsStatSConns []*RemoteHost + RpSubjectPrefixMatching bool // enables prefix matching for the rating profile subject + RemoveExpired bool + RALsMaxComputedUsage map[string]time.Duration + RALsBalanceRatingSubject map[string]string } //loadFromJsonCfg loads Rals config from JsonCfg @@ -69,6 +70,11 @@ func (ralsCfg *RalsCfg) loadFromJsonCfg(jsnRALsCfg *RalsJsonCfg) (err error) { } } } + if jsnRALsCfg.Balance_rating_subject != nil { + for k, v := range *jsnRALsCfg.Balance_rating_subject { + ralsCfg.RALsBalanceRatingSubject[k] = v + } + } return nil } diff --git a/engine/balances.go b/engine/balances.go index 3a0e7ef1f..7579af278 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -25,6 +25,7 @@ import ( "strings" "time" + "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) @@ -301,7 +302,7 @@ func (b *Balance) debitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala if !b.IsActiveAt(cd.TimeStart) || b.GetValue() <= 0 { return } - if duration, err := utils.ParseZeroRatingSubject(cd.TOR, b.RatingSubject); err == nil { + if duration, err := utils.ParseZeroRatingSubject(cd.TOR, b.RatingSubject, config.CgrConfig().RalsCfg().RALsBalanceRatingSubject); err == nil { // we have *zero based units cc = cd.CreateCallCost() cc.Timespans = append(cc.Timespans, &TimeSpan{ diff --git a/utils/coreutils.go b/utils/coreutils.go index 113226e8a..4adeebb8f 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -340,15 +340,10 @@ func MinDuration(d1, d2 time.Duration) time.Duration { // ParseZeroRatingSubject will parse the subject in the balance // returns duration if able to extract it from subject // returns error if not able to parse duration (ie: if ratingSubject is standard one) -func ParseZeroRatingSubject(tor, rateSubj string) (time.Duration, error) { +func ParseZeroRatingSubject(tor, rateSubj string, defaultRateSubj map[string]string) (time.Duration, error) { rateSubj = strings.TrimSpace(rateSubj) if rateSubj == "" || rateSubj == ANY { - switch tor { - case VOICE: - rateSubj = ZERO_RATING_SUBJECT_PREFIX + "1s" - default: - rateSubj = ZERO_RATING_SUBJECT_PREFIX + "1ns" - } + rateSubj = defaultRateSubj[tor] } if !strings.HasPrefix(rateSubj, ZERO_RATING_SUBJECT_PREFIX) { return 0, errors.New("malformed rating subject: " + rateSubj) diff --git a/utils/coreutils_test.go b/utils/coreutils_test.go index ba7b2924c..3657d9d1b 100644 --- a/utils/coreutils_test.go +++ b/utils/coreutils_test.go @@ -443,11 +443,25 @@ func TestParseZeroRatingSubject(t *testing.T) { subj := []string{"", "*zero1024", "*zero1s", "*zero5m", "*zero10h"} dur := []time.Duration{time.Second, time.Duration(1024), time.Second, 5 * time.Minute, 10 * time.Hour} + dfltRatingSubject := map[string]string{ + ANY: "*zero1ns", + VOICE: "*zero1s", + DATA: "*zero1ns", + SMS: "*zero1ns", + MONETARY: "*zero1ns", + GENERIC: "*zero1ns", + } for i, s := range subj { - if d, err := ParseZeroRatingSubject(VOICE, s); err != nil || d != dur[i] { + if d, err := ParseZeroRatingSubject(VOICE, s, dfltRatingSubject); err != nil || d != dur[i] { t.Error("Error parsing rating subject: ", s, d, err) } } + if d, err := ParseZeroRatingSubject(DATA, EmptyString, dfltRatingSubject); err != nil || d != time.Nanosecond { + t.Error("Error parsing rating subject: ", EmptyString, d, err) + } + if d, err := ParseZeroRatingSubject(MONETARY, EmptyString, dfltRatingSubject); err != nil || d != time.Nanosecond { + t.Error("Error parsing rating subject: ", EmptyString, d, err) + } } func TestConcatenatedKey(t *testing.T) {