From 7d20097754d01cc6cfaf179cb2871b9c68e09e61 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Tue, 18 Aug 2015 23:05:05 +0300 Subject: [PATCH] no default fallback, fixes #146 --- engine/calldesc.go | 21 +++++++++++---------- engine/loader_csv_test.go | 9 ++++++--- engine/ratingplan_test.go | 4 ++-- engine/ratingprofile.go | 19 ++++++++++--------- engine/ratingprofile_test.go | 32 ++++++++++++++++++++++++++++++++ utils/consts.go | 1 + 6 files changed, 62 insertions(+), 24 deletions(-) diff --git a/engine/calldesc.go b/engine/calldesc.go index 8755d5936..a509e9b67 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -177,10 +177,12 @@ func (cd *CallDescriptor) getAccount() (ub *Account, err error) { Restores the activation periods for the specified prefix from storage. */ func (cd *CallDescriptor) LoadRatingPlans() (err error) { - err = cd.getRatingPlansForPrefix(cd.GetKey(cd.Subject), 1) - if err != nil || !cd.continousRatingInfos() { - // use the default subject - err = cd.getRatingPlansForPrefix(cd.GetKey(FALLBACK_SUBJECT), 1) + var rec int + err, rec = cd.getRatingPlansForPrefix(cd.GetKey(cd.Subject), 1) + if err == utils.ErrNotFound && rec == 1 { + //if err != nil || !cd.continousRatingInfos() { + // use the default subject only if the initial one was not found + err, _ = cd.getRatingPlansForPrefix(cd.GetKey(FALLBACK_SUBJECT), 1) } //load the rating plans if err != nil || !cd.continousRatingInfos() { @@ -192,14 +194,13 @@ func (cd *CallDescriptor) LoadRatingPlans() (err error) { // FIXME: this method is not exhaustive but will cover 99% of cases just good // it will not cover very long calls with very short activation periods for rates -func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int) (err error) { +func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int) (error, int) { if recursionDepth > RECURSION_MAX_DEPTH { - err = errors.New("Max fallback recursion depth reached!" + key) - return + return utils.ErrMaxRecursionDepth, recursionDepth } rpf, err := ratingStorage.GetRatingProfile(key, false) if err != nil || rpf == nil { - return err + return utils.ErrNotFound, recursionDepth } if err = rpf.GetRatingPlansForPrefix(cd); err != nil || !cd.continousRatingInfos() { // try rating profile fallback @@ -228,7 +229,7 @@ func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int tempCD.TimeEnd = cd.RatingInfos[index+1].ActivationTime } for _, fbk := range ri.FallbackKeys { - if err := tempCD.getRatingPlansForPrefix(fbk, recursionDepth); err != nil { + if err, _ := tempCD.getRatingPlansForPrefix(fbk, recursionDepth); err != nil { continue } // extract the rate infos and break @@ -256,7 +257,7 @@ func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int } } } - return + return nil, recursionDepth } // checks if there is rating info for the entire call duration diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 17a4d1dca..338063d23 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -84,6 +84,7 @@ T1,NAT,LANDLINE_OFFPEAK,*middle,4,0, T2,GERMANY,GBP_72,*middle,4,0, T2,GERMANY_O2,GBP_70,*middle,4,0, T2,GERMANY_PREMIUM,GBP_71,*middle,4,0, +GER,GERMANY,R4,*middle,4,0, DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*middle,4,, DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*middle,4,, DATA_RATE,*any,LANDLINE_OFFPEAK,*middle,4,0, @@ -112,6 +113,7 @@ RP_UK,DR_UK_Mobile_BIG5,*any,10 RP_DATA,DATA_RATE,*any,10 RP_MX,MX_DISC,WORKDAYS_00,10 RP_MX,MX_FREE,WORKDAYS_18,10 +GER_ONLY,GER,*any,10 ANY_PLAN,DATA_RATE,*any,10 ` ratingProfiles = ` @@ -136,6 +138,7 @@ ANY_PLAN,DATA_RATE,*any,10 *out,cgrates.org,call,discounted_minutes,2013-01-06T00:00:00Z,RP_UK_Mobile_BIG5_PKG,, *out,cgrates.org,data,rif,2013-01-06T00:00:00Z,RP_DATA,, *out,cgrates.org,call,max,2013-03-23T00:00:00Z,RP_MX,, +*out,cgrates.org,call,nt,2012-02-28T00:00:00Z,GER_ONLY,, *in,cgrates.org,LCR_STANDARD,max,2013-03-23T00:00:00Z,RP_MX,, *out,cgrates.org,call,money,2015-02-28T00:00:00Z,EVENING,, ` @@ -453,7 +456,7 @@ func TestLoadRates(t *testing.T) { } func TestLoadDestinationRates(t *testing.T) { - if len(csvr.destinationRates) != 13 { + if len(csvr.destinationRates) != 14 { t.Error("Failed to load destinationrates: ", len(csvr.destinationRates)) } drs := csvr.destinationRates["RT_STANDARD"] @@ -601,7 +604,7 @@ func TestLoadDestinationRates(t *testing.T) { } func TestLoadRatingPlans(t *testing.T) { - if len(csvr.ratingPlans) != 12 { + if len(csvr.ratingPlans) != 13 { t.Error("Failed to load rating plans: ", len(csvr.ratingPlans)) } rplan := csvr.ratingPlans["STANDARD"] @@ -773,7 +776,7 @@ func TestLoadRatingPlans(t *testing.T) { } func TestLoadRatingProfiles(t *testing.T) { - if len(csvr.ratingProfiles) != 20 { + if len(csvr.ratingProfiles) != 21 { t.Error("Failed to load rating profiles: ", len(csvr.ratingProfiles), csvr.ratingProfiles) } rp := csvr.ratingProfiles["*out:test:0:trp"] diff --git a/engine/ratingplan_test.go b/engine/ratingplan_test.go index 93d8500f8..a13bccc8d 100644 --- a/engine/ratingplan_test.go +++ b/engine/ratingplan_test.go @@ -117,7 +117,7 @@ func TestFallbackWithBackTrace(t *testing.T) { } } -func TestFallbackDefault(t *testing.T) { +func TestFallbackNoDefault(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), @@ -127,7 +127,7 @@ func TestFallbackDefault(t *testing.T) { Subject: "one", Destination: "0723"} cd.LoadRatingPlans() - if len(cd.RatingInfos) != 1 { + if len(cd.RatingInfos) != 0 { t.Error("Error restoring activation periods: ", len(cd.RatingInfos)) } } diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go index 21dc074e1..264551b46 100644 --- a/engine/ratingprofile.go +++ b/engine/ratingprofile.go @@ -179,17 +179,18 @@ func (rp *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error) FallbackKeys: rpa.FallbackKeys}) } else { // add for fallback information - ris = append(ris, &RatingInfo{ - MatchedSubject: "", - MatchedPrefix: "", - MatchedDestId: "", - ActivationTime: rpa.ActivationTime, - RateIntervals: nil, - FallbackKeys: rpa.FallbackKeys, - }) + if len(rpa.FallbackKeys) > 0 { + ris = append(ris, &RatingInfo{ + MatchedSubject: "", + MatchedPrefix: "", + MatchedDestId: "", + ActivationTime: rpa.ActivationTime, + RateIntervals: nil, + FallbackKeys: rpa.FallbackKeys, + }) + } } } - if len(ris) > 0 { cd.addRatingInfos(ris) return diff --git a/engine/ratingprofile_test.go b/engine/ratingprofile_test.go index d2444adcf..ea31d11ca 100644 --- a/engine/ratingprofile_test.go +++ b/engine/ratingprofile_test.go @@ -61,3 +61,35 @@ func TestGetRatingProfileForPrefixFirstEmpty(t *testing.T) { t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos()) } } + +func TestGetRatingProfileNotFound(t *testing.T) { + cd := &CallDescriptor{ + TimeStart: time.Date(2015, 8, 18, 22, 05, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 8, 18, 22, 06, 30, 0, time.UTC), + Tenant: "vdf", + Category: "0", + Direction: OUTBOUND, + Subject: "no_rating_profile", + Destination: "0256098", + } + cd.LoadRatingPlans() + if len(cd.RatingInfos) != 1 || !cd.continousRatingInfos() { + t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos()) + } +} + +func TestGetRatingProfileFoundButNoDestination(t *testing.T) { + cd := &CallDescriptor{ + TimeStart: time.Date(2015, 8, 18, 22, 05, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 8, 18, 22, 06, 30, 0, time.UTC), + Tenant: "cgrates.org", + Category: "call", + Direction: OUTBOUND, + Subject: "nt", + Destination: "447956", + } + cd.LoadRatingPlans() + if len(cd.RatingInfos) != 0 { + t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos()) + } +} diff --git a/utils/consts.go b/utils/consts.go index 279c1d4e1..48907e625 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -17,6 +17,7 @@ var ( ErrNotImplemented = errors.New("NOT_IMPLEMENTED") ErrNotFound = errors.New("NOT_FOUND") ErrServerError = errors.New("SERVER_ERROR") + ErrMaxRecursionDepth = errors.New("MAX_RECURSION_DEPTH") ErrMandatoryIeMissing = errors.New("MANDATORY_IE_MISSING") ErrExists = errors.New("EXISTS") ErrBrokenReference = errors.New("BROKEN_REFERENCE")