Add option for balance_rating_subject in RALs section of config

This commit is contained in:
TeoV
2019-05-13 17:17:25 +03:00
committed by Dan Christian Bogos
parent 9db3cf3dfa
commit 1225d5e05d
9 changed files with 58 additions and 15 deletions

View File

@@ -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)

View File

@@ -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",
},
},

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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

View File

@@ -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
}

View File

@@ -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{

View File

@@ -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)

View File

@@ -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) {