diff --git a/engine/calldesc.go b/engine/calldesc.go index ce2bd49e0..a7a033393 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -70,16 +70,17 @@ func init() { } var ( - ratingStorage RatingStorage - accountingStorage AccountingStorage - storageLogger LogStorage - cdrStorage CdrStorage - debitPeriod = 10 * time.Second - globalRoundingDecimals = 6 - historyScribe history.Scribe - pubSubServer rpcclient.RpcClientConnection - userService UserService - aliasService AliasService + ratingStorage RatingStorage + accountingStorage AccountingStorage + storageLogger LogStorage + cdrStorage CdrStorage + debitPeriod = 10 * time.Second + globalRoundingDecimals = 6 + historyScribe history.Scribe + pubSubServer rpcclient.RpcClientConnection + userService UserService + aliasService AliasService + prefixMatchingRatingProfile bool ) // Exported method to set the storage getter. @@ -96,6 +97,10 @@ func SetRoundingDecimals(rd int) { globalRoundingDecimals = rd } +func SetPrefixmatchingRatingProfile(flag bool) { + prefixMatchingRatingProfile = flag +} + /* Sets the database for logging (can be de same as storage getter or different db) */ @@ -219,7 +224,7 @@ func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int if recursionDepth > RECURSION_MAX_DEPTH { return utils.ErrMaxRecursionDepth, recursionDepth } - rpf, err := ratingStorage.GetRatingProfile(key, false) + rpf, err := PrefixMatchRatingProfileSubject(key) if err != nil || rpf == nil { return utils.ErrNotFound, recursionDepth } @@ -1034,7 +1039,7 @@ func (cd *CallDescriptor) GetLCR(stats StatsInterface, p *utils.Paginator) (*LCR continue } rpfKey := utils.ConcatenatedKey(ratingProfileSearchKey, supplier) - if rpf, err := ratingStorage.GetRatingProfile(rpfKey, false); err != nil { + if rpf, err := PrefixMatchRatingProfileSubject(rpfKey); err != nil { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: fmt.Sprintf("Rating plan error: %s", err.Error()), diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go index f802252aa..059ccf6f1 100644 --- a/engine/ratingprofile.go +++ b/engine/ratingprofile.go @@ -22,6 +22,7 @@ import ( "encoding/json" "fmt" "sort" + "strings" "time" "github.com/cgrates/cgrates/cache2go" @@ -244,3 +245,21 @@ func (rpf *RatingProfile) GetHistoryRecord(deleted bool) history.Record { type TenantRatingSubject struct { Tenant, Subject string } + +func PrefixMatchRatingProfileSubject(key string) (rp *RatingProfile, err error) { + if !prefixMatchingRatingProfile { + return ratingStorage.GetRatingProfile(key, false) + } + if rp, err = ratingStorage.GetRatingProfile(key, false); err == nil { + return rp, err + } + lastIndex := strings.LastIndex(key, utils.CONCATENATED_KEY_SEP) + baseKey := key[:lastIndex] + subject := key[lastIndex:] + for i := 1; i < len(subject)-1; i++ { + if rp, err = ratingStorage.GetRatingProfile(baseKey+subject[:len(subject)-i], false); err == nil { + return rp, err + } + } + return +} diff --git a/engine/ratingprofile_test.go b/engine/ratingprofile_test.go index 95ef342c0..a94598ad0 100644 --- a/engine/ratingprofile_test.go +++ b/engine/ratingprofile_test.go @@ -249,3 +249,17 @@ func TestRatingProfileRIforTSMidnight(t *testing.T) { t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) } } + +func TestPrefixMatchRatingProfileSubject(t *testing.T) { + prefixMatchingRatingProfile = true + rp, err := PrefixMatchRatingProfileSubject("*out:cgrates.org:data:rif") + if rp == nil || err != nil { + t.Errorf("Error getting rating profile by prefix: %+v (%v)", rp, err) + } + + rp, err = PrefixMatchRatingProfileSubject("*out:cgrates.org:data:rifescu") + if rp == nil || err != nil { + t.Errorf("Error getting rating profile by prefix: %+v (%v)", rp, err) + } + prefixMatchingRatingProfile = false +}