From 7d1b0a5e039397e89ea91e95d53b5fc3c9efd718 Mon Sep 17 00:00:00 2001 From: TeoV Date: Thu, 11 Jun 2020 12:04:34 +0300 Subject: [PATCH] Add API's for RateProfiles --- apier/v1/api_interfaces.go | 3 + apier/v1/apier_it_test.go | 8 +- apier/v1/caches_it_test.go | 4 +- apier/v1/dispatcher.go | 15 ++ apier/v1/precache_it_test.go | 2 + apier/v1/rateprofiles.go | 134 ++++++++++++++++++ apier/v1/replicator.go | 25 ++++ apier/v1/tprateprofiles.go | 87 ++++++++++++ config/config_defaults.go | 2 + config/config_json_test.go | 10 ++ console/rateprofile_ids.go | 65 +++++++++ console/rateprofile_remove.go | 62 ++++++++ console/rateprofile_set.go | 66 +++++++++ console/rateprofiles.go | 66 +++++++++ ...ingprofile_ids.go => ratingprofile_ids.go} | 2 +- .../mysql/create_tariffplan_tables.sql | 34 +++++ .../postgres/create_tariffplan_tables.sql | 32 +++++ dispatchers/caches_it_test.go | 4 +- dispatchers/replicator.go | 65 +++++++++ engine/datamanager.go | 2 + engine/libtest.go | 2 + engine/storage_csv.go | 2 +- engine/storage_internal_datadb.go | 5 + engine/storage_sql.go | 2 +- engine/tpimporter_csv.go | 12 ++ engine/version.go | 2 + general_tests/tut_smgeneric_it_test.go | 2 +- utils/consts.go | 9 ++ 28 files changed, 713 insertions(+), 11 deletions(-) create mode 100644 apier/v1/rateprofiles.go create mode 100644 apier/v1/tprateprofiles.go create mode 100644 console/rateprofile_ids.go create mode 100644 console/rateprofile_remove.go create mode 100644 console/rateprofile_set.go create mode 100644 console/rateprofiles.go rename console/{rattingprofile_ids.go => ratingprofile_ids.go} (97%) diff --git a/apier/v1/api_interfaces.go b/apier/v1/api_interfaces.go index c820d326c..23c0ed587 100644 --- a/apier/v1/api_interfaces.go +++ b/apier/v1/api_interfaces.go @@ -201,6 +201,7 @@ type ReplicatorSv1Interface interface { GetAttributeProfile(tntID *utils.TenantIDWithArgDispatcher, reply *engine.AttributeProfile) error GetChargerProfile(tntID *utils.TenantIDWithArgDispatcher, reply *engine.ChargerProfile) error GetDispatcherProfile(tntID *utils.TenantIDWithArgDispatcher, reply *engine.DispatcherProfile) error + GetRateProfile(tntID *utils.TenantIDWithArgDispatcher, reply *engine.RateProfile) error GetDispatcherHost(tntID *utils.TenantIDWithArgDispatcher, reply *engine.DispatcherHost) error GetItemLoadIDs(itemID *utils.StringWithApiKey, reply *map[string]int64) error GetFilterIndexes(args *utils.GetFilterIndexesArgWithArgDispatcher, reply *map[string]utils.StringMap) error @@ -226,6 +227,7 @@ type ReplicatorSv1Interface interface { SetAttributeProfile(ap *engine.AttributeProfileWithArgDispatcher, reply *string) error SetChargerProfile(cp *engine.ChargerProfileWithArgDispatcher, reply *string) error SetDispatcherProfile(dpp *engine.DispatcherProfileWithArgDispatcher, reply *string) error + SetRateProfile(dpp *engine.RateProfileWithArgDispatcher, reply *string) error SetActionPlan(args *engine.SetActionPlanArgWithArgDispatcher, reply *string) error SetAccountActionPlans(args *engine.SetAccountActionPlansArgWithArgDispatcher, reply *string) error SetDispatcherHost(dpp *engine.DispatcherHostWithArgDispatcher, reply *string) error @@ -252,4 +254,5 @@ type ReplicatorSv1Interface interface { RemoveChargerProfile(args *utils.TenantIDWithArgDispatcher, reply *string) error RemoveDispatcherProfile(args *utils.TenantIDWithArgDispatcher, reply *string) error RemoveDispatcherHost(args *utils.TenantIDWithArgDispatcher, reply *string) error + RemoveRateProfile(args *utils.TenantIDWithArgDispatcher, reply *string) error } diff --git a/apier/v1/apier_it_test.go b/apier/v1/apier_it_test.go index 0e3ecc8ad..6bcb7d254 100644 --- a/apier/v1/apier_it_test.go +++ b/apier/v1/apier_it_test.go @@ -821,7 +821,7 @@ func testApierLoadAccountActions(t *testing.T) { expectedStats[utils.CacheAccountActionPlans].Items = 1 expectedStats[utils.CacheActionPlans].Items = 1 expectedStats[utils.CacheActions].Items = 1 - expectedStats[utils.CacheLoadIDs].Items = 20 + expectedStats[utils.CacheLoadIDs].Items = 21 expectedStats[utils.CacheRPCConnections].Items = 1 if err := rater.Call(utils.CacheSv1GetCacheStats, new(utils.AttrCacheIDsWithArgDispatcher), &rcvStats); err != nil { t.Error("Got error on CacheSv1.GetCacheStats: ", err.Error()) @@ -859,7 +859,7 @@ func testApierSetRatingProfile(t *testing.T) { expectedStats[utils.CacheActions].Items = 1 expectedStats[utils.CacheRatingProfiles].Items = 1 expectedStats[utils.CacheRPCConnections].Items = 1 - expectedStats[utils.CacheLoadIDs].Items = 20 + expectedStats[utils.CacheLoadIDs].Items = 21 if err := rater.Call(utils.CacheSv1GetCacheStats, new(utils.AttrCacheIDsWithArgDispatcher), &rcvStats); err != nil { t.Error("Got error on CacheSv1.GetCacheStats: ", err.Error()) } else if !reflect.DeepEqual(expectedStats, rcvStats) { @@ -966,7 +966,7 @@ func testApierReloadCache(t *testing.T) { expectedStats[utils.CacheRatingProfiles].Items = 2 expectedStats[utils.CacheRatingPlans].Items = 1 expectedStats[utils.CacheReverseDestinations].Items = 10 - expectedStats[utils.CacheLoadIDs].Items = 20 + expectedStats[utils.CacheLoadIDs].Items = 21 expectedStats[utils.CacheRPCConnections].Items = 1 if err := rater.Call(utils.CacheSv1GetCacheStats, new(utils.AttrCacheIDsWithArgDispatcher), &rcvStats); err != nil { t.Error("Got error on CacheSv1.GetCacheStats: ", err.Error()) @@ -1495,7 +1495,7 @@ func testApierResetDataAfterLoadFromFolder(t *testing.T) { expStats[utils.CacheRouteProfiles].Items = 2 expStats[utils.CacheThresholdProfiles].Items = 1 expStats[utils.CacheThresholds].Items = 1 - expStats[utils.CacheLoadIDs].Items = 20 + expStats[utils.CacheLoadIDs].Items = 21 if err := rater.Call(utils.CacheSv1GetCacheStats, new(utils.AttrCacheIDsWithArgDispatcher), &rcvStats); err != nil { t.Error(err) diff --git a/apier/v1/caches_it_test.go b/apier/v1/caches_it_test.go index 738731faa..35125bd06 100644 --- a/apier/v1/caches_it_test.go +++ b/apier/v1/caches_it_test.go @@ -160,7 +160,7 @@ func testCacheSAfterLoadFromFolder(t *testing.T) { expStats[utils.CacheRouteProfiles].Items = 2 expStats[utils.CacheThresholdProfiles].Items = 1 expStats[utils.CacheThresholds].Items = 1 - expStats[utils.CacheLoadIDs].Items = 20 + expStats[utils.CacheLoadIDs].Items = 21 if err := chcRPC.Call(utils.CacheSv1GetCacheStats, &utils.AttrCacheIDsWithArgDispatcher{}, &rcvStats); err != nil { t.Error(err) @@ -215,7 +215,7 @@ func testCacheSReload(t *testing.T) { expStats[utils.CacheRouteProfiles].Items = 2 expStats[utils.CacheThresholdProfiles].Items = 1 expStats[utils.CacheThresholds].Items = 1 - expStats[utils.CacheLoadIDs].Items = 20 + expStats[utils.CacheLoadIDs].Items = 21 if err := chcRPC.Call(utils.CacheSv1GetCacheStats, &utils.AttrCacheIDsWithArgDispatcher{}, &rcvStats); err != nil { t.Error(err) diff --git a/apier/v1/dispatcher.go b/apier/v1/dispatcher.go index 0d0443e85..ad9ea336f 100755 --- a/apier/v1/dispatcher.go +++ b/apier/v1/dispatcher.go @@ -983,6 +983,11 @@ func (dS *DispatcherReplicatorSv1) GetDispatcherProfile(tntID *utils.TenantIDWit return dS.dS.ReplicatorSv1GetDispatcherProfile(tntID, reply) } +// GetRateProfile +func (dS *DispatcherReplicatorSv1) GetRateProfile(tntID *utils.TenantIDWithArgDispatcher, reply *engine.RateProfile) error { + return dS.dS.ReplicatorSv1GetRateProfile(tntID, reply) +} + // GetDispatcherHost func (dS *DispatcherReplicatorSv1) GetDispatcherHost(tntID *utils.TenantIDWithArgDispatcher, reply *engine.DispatcherHost) error { return dS.dS.ReplicatorSv1GetDispatcherHost(tntID, reply) @@ -1110,6 +1115,11 @@ func (dS *DispatcherReplicatorSv1) SetDispatcherProfile(args *engine.DispatcherP return dS.dS.ReplicatorSv1SetDispatcherProfile(args, reply) } +// SetRateProfile +func (dS *DispatcherReplicatorSv1) SetRateProfile(args *engine.RateProfileWithArgDispatcher, reply *string) error { + return dS.dS.ReplicatorSv1SetRateProfile(args, reply) +} + // SetActionPlan func (dS *DispatcherReplicatorSv1) SetActionPlan(args *engine.SetActionPlanArgWithArgDispatcher, reply *string) error { return dS.dS.ReplicatorSv1SetActionPlan(args, reply) @@ -1239,3 +1249,8 @@ func (dS *DispatcherReplicatorSv1) RemoveDispatcherProfile(args *utils.TenantIDW func (dS *DispatcherReplicatorSv1) RemoveDispatcherHost(args *utils.TenantIDWithArgDispatcher, reply *string) error { return dS.dS.ReplicatorSv1RemoveDispatcherHost(args, reply) } + +// RemoveRateProfile +func (dS *DispatcherReplicatorSv1) RemoveRateProfile(args *utils.TenantIDWithArgDispatcher, reply *string) error { + return dS.dS.ReplicatorSv1RemoveRateProfile(args, reply) +} diff --git a/apier/v1/precache_it_test.go b/apier/v1/precache_it_test.go index b3fe663eb..990eca2d4 100644 --- a/apier/v1/precache_it_test.go +++ b/apier/v1/precache_it_test.go @@ -202,6 +202,8 @@ func testPrecacheGetCacheStatsAfterRestart(t *testing.T) { Items: 15, Groups: 0, }, + utils.CacheRateFilterIndexes: {}, + utils.CacheRateProfiles: {}, utils.CacheRatingPlans: { Items: 4, Groups: 0, diff --git a/apier/v1/rateprofiles.go b/apier/v1/rateprofiles.go new file mode 100644 index 000000000..a5805db9b --- /dev/null +++ b/apier/v1/rateprofiles.go @@ -0,0 +1,134 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package v1 + +import ( + "time" + + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +// GetRateProfile returns an Rate Profile +func (APIerSv1 *APIerSv1) GetRateProfile(arg *utils.TenantIDWithArgDispatcher, reply *engine.RateProfile) error { + if missing := utils.MissingStructFields(arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing + return utils.NewErrMandatoryIeMissing(missing...) + } + if rPrf, err := APIerSv1.DataManager.GetRateProfile(arg.Tenant, arg.ID, true, true, utils.NonTransactional); err != nil { + if err.Error() != utils.ErrNotFound.Error() { + err = utils.NewErrServerError(err) + } + return err + } else { + *reply = *rPrf + } + return nil +} + +// GetRateProfileIDs returns list of rate profile IDs registered for a tenant +func (APIerSv1 *APIerSv1) GetRateProfileIDs(args *utils.TenantArgWithPaginator, attrPrfIDs *[]string) error { + if missing := utils.MissingStructFields(args, []string{utils.Tenant}); len(missing) != 0 { //Params missing + return utils.NewErrMandatoryIeMissing(missing...) + } + prfx := utils.RateProfilePrefix + args.Tenant + ":" + keys, err := APIerSv1.DataManager.DataDB().GetKeysForPrefix(prfx) + if err != nil { + return err + } + if len(keys) == 0 { + return utils.ErrNotFound + } + retIDs := make([]string, len(keys)) + for i, key := range keys { + retIDs[i] = key[len(prfx):] + } + *attrPrfIDs = args.PaginateStringSlice(retIDs) + return nil +} + +// GetRateProfileIDsCount sets in reply var the total number of RateProfileIDs registered for a tenant +// returns ErrNotFound in case of 0 RateProfileIDs +func (APIerSv1 *APIerSv1) GetRateProfileIDsCount(args *utils.TenantArg, reply *int) (err error) { + if missing := utils.MissingStructFields(args, []string{utils.Tenant}); len(missing) != 0 { + return utils.NewErrMandatoryIeMissing(missing...) + } + var keys []string + prfx := utils.RateProfilePrefix + args.Tenant + ":" + if keys, err = APIerSv1.DataManager.DataDB().GetKeysForPrefix(prfx); err != nil { + return err + } + if len(keys) == 0 { + return utils.ErrNotFound + } + *reply = len(keys) + return +} + +type RateProfileWithCache struct { + *engine.RateProfileWithArgDispatcher + Cache *string +} + +//SetRateProfile add/update a new Rate Profile +func (APIerSv1 *APIerSv1) SetRateProfile(rPrf *RateProfileWithCache, reply *string) error { + if missing := utils.MissingStructFields(rPrf.RateProfile, []string{"Tenant", "ID", "Rates"}); len(missing) != 0 { + return utils.NewErrMandatoryIeMissing(missing...) + } + + if err := APIerSv1.DataManager.SetRateProfile(rPrf.RateProfile, true); err != nil { + return utils.APIErrorHandler(err) + } + //generate a loadID for CacheAttributeProfiles and store it in database + if err := APIerSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil { + return utils.APIErrorHandler(err) + } + args := utils.ArgsGetCacheItem{ + CacheID: utils.CacheRateProfiles, + ItemID: rPrf.TenantID(), + } + if err := APIerSv1.CallCache(GetCacheOpt(rPrf.Cache), args); err != nil { + return utils.APIErrorHandler(err) + } + *reply = utils.OK + return nil +} + +// RemoveRateProfile remove a specific Rate Profile +func (APIerSv1 *APIerSv1) RemoveRateProfile(arg *utils.TenantIDWithCache, reply *string) error { + if missing := utils.MissingStructFields(arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing + return utils.NewErrMandatoryIeMissing(missing...) + } + if err := APIerSv1.DataManager.RemoveRateProfile(arg.Tenant, arg.ID, + utils.NonTransactional, true); err != nil { + return utils.APIErrorHandler(err) + } + //generate a loadID for CacheAttributeProfiles and store it in database + if err := APIerSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil { + return utils.APIErrorHandler(err) + } + args := utils.ArgsGetCacheItem{ + CacheID: utils.CacheRateProfiles, + ItemID: utils.ConcatenatedKey(arg.Tenant, arg.ID), + } + if err := APIerSv1.CallCache(GetCacheOpt(arg.Cache), args); err != nil { + return utils.APIErrorHandler(err) + } + *reply = utils.OK + return nil +} diff --git a/apier/v1/replicator.go b/apier/v1/replicator.go index 9d4ccea4c..585fd11f2 100644 --- a/apier/v1/replicator.go +++ b/apier/v1/replicator.go @@ -277,6 +277,15 @@ func (rplSv1 *ReplicatorSv1) GetDispatcherHost(tntID *utils.TenantIDWithArgDispa return nil } +func (rplSv1 *ReplicatorSv1) GetRateProfile(tntID *utils.TenantIDWithArgDispatcher, reply *engine.RateProfile) error { + if rcv, err := rplSv1.dm.DataDB().GetRateProfileDrv(tntID.Tenant, tntID.ID); err != nil { + return err + } else { + *reply = *rcv + } + return nil +} + //GetResourceProfile func (rplSv1 *ReplicatorSv1) GetItemLoadIDs(itemID *utils.StringWithApiKey, reply *map[string]int64) error { if rcv, err := rplSv1.dm.DataDB().GetItemLoadIDsDrv(itemID.Arg); err != nil { @@ -526,6 +535,14 @@ func (rplSv1 *ReplicatorSv1) SetDispatcherHost(dpp *engine.DispatcherHostWithArg return nil } +func (rplSv1 *ReplicatorSv1) SetRateProfile(dpp *engine.RateProfileWithArgDispatcher, reply *string) error { + if err := rplSv1.dm.DataDB().SetRateProfileDrv(dpp.RateProfile); err != nil { + return err + } + *reply = utils.OK + return nil +} + // RemoveThreshold func (rplSv1 *ReplicatorSv1) RemoveThreshold(args *utils.TenantIDWithArgDispatcher, reply *string) error { if err := rplSv1.dm.DataDB().RemoveThresholdDrv(args.Tenant, args.ID); err != nil { @@ -713,6 +730,14 @@ func (rplSv1 *ReplicatorSv1) RemoveDispatcherProfile(args *utils.TenantIDWithArg return nil } +func (rplSv1 *ReplicatorSv1) RemoveRateProfile(args *utils.TenantIDWithArgDispatcher, reply *string) error { + if err := rplSv1.dm.DataDB().RemoveRateProfileDrv(args.Tenant, args.ID); err != nil { + return err + } + *reply = utils.OK + return nil +} + func (rplSv1 *ReplicatorSv1) RemoveDispatcherHost(args *utils.TenantIDWithArgDispatcher, reply *string) error { if err := rplSv1.dm.DataDB().RemoveDispatcherHostDrv(args.Tenant, args.ID); err != nil { return err diff --git a/apier/v1/tprateprofiles.go b/apier/v1/tprateprofiles.go new file mode 100644 index 000000000..10e5c29bf --- /dev/null +++ b/apier/v1/tprateprofiles.go @@ -0,0 +1,87 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package v1 + +import ( + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +// SetTPRateProfile creates a new TPRateProfile within a tariff plan +func (api *APIerSv1) SetTPRateProfile(attrs *engine.TPRateProfile, reply *string) error { + if missing := utils.MissingStructFields(attrs, []string{"TPid", "Tenant", "ID"}); len(missing) != 0 { + return utils.NewErrMandatoryIeMissing(missing...) + } + if err := api.StorDb.SetTPRateProfiles([]*engine.TPRateProfile{attrs}); err != nil { + return utils.NewErrServerError(err) + } + *reply = utils.OK + return nil +} + +// GetTPRateProfile queries specific TPRateProfile on tariff plan +func (api *APIerSv1) GetTPRateProfile(attr *utils.TPTntID, reply *engine.TPRateProfile) error { + if missing := utils.MissingStructFields(attr, []string{"TPid", "Tenant", "ID"}); len(missing) != 0 { //Params missing + return utils.NewErrMandatoryIeMissing(missing...) + } + filter, err := api.StorDb.GetTPRateProfiles(attr.TPid, attr.Tenant, attr.ID) + if err != nil { + if err.Error() != utils.ErrNotFound.Error() { + err = utils.NewErrServerError(err) + } + return err + } + *reply = *filter[0] + return nil +} + +type AttrGetTPRateProfileIds struct { + TPid string // Tariff plan id + utils.PaginatorWithSearch +} + +// GetTPRateProfileIds queries TPRateProfiles identities on specific tariff plan. +func (api *APIerSv1) GetTPRateProfileIds(attrs *AttrGetTPRateProfileIds, reply *[]string) error { + if missing := utils.MissingStructFields(attrs, []string{"TPid"}); len(missing) != 0 { //Params missing + return utils.NewErrMandatoryIeMissing(missing...) + } + ids, err := api.StorDb.GetTpTableIds(attrs.TPid, utils.TBLTPRateProfiles, utils.TPDistinctIds{"tenant", "id"}, + nil, &attrs.PaginatorWithSearch) + if err != nil { + if err.Error() != utils.ErrNotFound.Error() { + err = utils.NewErrServerError(err) + } + return err + } + *reply = ids + return nil +} + +// RemoveTPRateProfile removes specific TPRateProfile on Tariff plan +func (api *APIerSv1) RemoveTPRateProfile(attrs *utils.TPTntID, reply *string) error { + if missing := utils.MissingStructFields(attrs, []string{"TPid", "Tenant", "ID"}); len(missing) != 0 { //Params missing + return utils.NewErrMandatoryIeMissing(missing...) + } + if err := api.StorDb.RemTpData(utils.TBLTPRateProfiles, attrs.TPid, + map[string]string{"tenant": attrs.Tenant, "id": attrs.ID}); err != nil { + return utils.NewErrServerError(err) + } + *reply = utils.OK + return nil +} diff --git a/config/config_defaults.go b/config/config_defaults.go index 98fd90afa..2322fb8d0 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -97,6 +97,7 @@ const CGRATES_CFG_JSON = ` "*charger_profiles": {"remote":false, "replicate":false, "limit": -1, "ttl": "", "static_ttl": false}, "*dispatcher_profiles":{"remote":false, "replicate":false, "limit": -1, "ttl": "", "static_ttl": false}, "*dispatcher_hosts":{"remote":false, "replicate":false, "limit": -1, "ttl": "", "static_ttl": false}, + "*rate_profiles":{"remote":false, "replicate":false, "limit": -1, "ttl": "", "static_ttl": false}, "*filter_indexes" :{"remote":false, "replicate":false, "limit": -1, "ttl": "", "static_ttl": false}, "*load_ids":{"remote":false, "replicate":false, "limit": -1, "ttl": "", "static_ttl": false}, }, @@ -141,6 +142,7 @@ const CGRATES_CFG_JSON = ` "versions": {"limit": -1, "ttl": "", "static_ttl": false}, "tp_dispatcher_profiles":{"limit": -1, "ttl": "", "static_ttl": false}, "tp_dispatcher_hosts":{"limit": -1, "ttl": "", "static_ttl": false}, + "tp_rate_profiles":{"limit": -1, "ttl": "", "static_ttl": false}, }, }, diff --git a/config/config_json_test.go b/config/config_json_test.go index 89f9e5da2..8671793f7 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -371,6 +371,12 @@ func TestDfDataDbJsonCfg(t *testing.T) { Ttl: utils.StringPointer(utils.EmptyString), Limit: utils.IntPointer(-1), Static_ttl: utils.BoolPointer(false)}, + utils.MetaRateProfiles: { + Replicate: utils.BoolPointer(false), + Remote: utils.BoolPointer(false), + Ttl: utils.StringPointer(utils.EmptyString), + Limit: utils.IntPointer(-1), + Static_ttl: utils.BoolPointer(false)}, utils.MetaChargerProfiles: { Replicate: utils.BoolPointer(false), Remote: utils.BoolPointer(false), @@ -500,6 +506,10 @@ func TestDfStorDBJsonCfg(t *testing.T) { Ttl: utils.StringPointer(utils.EmptyString), Limit: utils.IntPointer(-1), Static_ttl: utils.BoolPointer(false)}, + utils.TBLTPRateProfiles: { + Ttl: utils.StringPointer(utils.EmptyString), + Limit: utils.IntPointer(-1), + Static_ttl: utils.BoolPointer(false)}, utils.TBLTPDispatcherHosts: { Ttl: utils.StringPointer(utils.EmptyString), Limit: utils.IntPointer(-1), diff --git a/console/rateprofile_ids.go b/console/rateprofile_ids.go new file mode 100644 index 000000000..3bc20a9b4 --- /dev/null +++ b/console/rateprofile_ids.go @@ -0,0 +1,65 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package console + +import ( + "github.com/cgrates/cgrates/utils" +) + +func init() { + c := &CmdRateProfileIDs{ + name: "rateprofile_ids", + rpcMethod: utils.APIerSv1GetRateProfileIDs, + rpcParams: &utils.TenantArgWithPaginator{}, + } + commands[c.Name()] = c + c.CommandExecuter = &CommandExecuter{c} +} + +// Commander implementation +type CmdRateProfileIDs struct { + name string + rpcMethod string + rpcParams *utils.TenantArgWithPaginator + *CommandExecuter +} + +func (self *CmdRateProfileIDs) Name() string { + return self.name +} + +func (self *CmdRateProfileIDs) RpcMethod() string { + return self.rpcMethod +} + +func (self *CmdRateProfileIDs) RpcParams(reset bool) interface{} { + if reset || self.rpcParams == nil { + self.rpcParams = &utils.TenantArgWithPaginator{} + } + return self.rpcParams +} + +func (self *CmdRateProfileIDs) PostprocessRpcParams() error { + return nil +} + +func (self *CmdRateProfileIDs) RpcResult() interface{} { + var atr []string + return &atr +} diff --git a/console/rateprofile_remove.go b/console/rateprofile_remove.go new file mode 100644 index 000000000..dbf1fe7d9 --- /dev/null +++ b/console/rateprofile_remove.go @@ -0,0 +1,62 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package console + +import "github.com/cgrates/cgrates/utils" + +func init() { + c := &CmdRemoveRateProfile{ + name: "rateprofile_remove", + rpcMethod: utils.APIerSv1RemoveRateProfile, + rpcParams: &utils.TenantIDWithCache{}, + } + commands[c.Name()] = c + c.CommandExecuter = &CommandExecuter{c} +} + +type CmdRemoveRateProfile struct { + name string + rpcMethod string + rpcParams *utils.TenantIDWithCache + *CommandExecuter +} + +func (self *CmdRemoveRateProfile) Name() string { + return self.name +} + +func (self *CmdRemoveRateProfile) RpcMethod() string { + return self.rpcMethod +} + +func (self *CmdRemoveRateProfile) RpcParams(reset bool) interface{} { + if reset || self.rpcParams == nil { + self.rpcParams = &utils.TenantIDWithCache{} + } + return self.rpcParams +} + +func (self *CmdRemoveRateProfile) PostprocessRpcParams() error { + return nil +} + +func (self *CmdRemoveRateProfile) RpcResult() interface{} { + var s string + return &s +} diff --git a/console/rateprofile_set.go b/console/rateprofile_set.go new file mode 100644 index 000000000..062d5c35b --- /dev/null +++ b/console/rateprofile_set.go @@ -0,0 +1,66 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package console + +import ( + v1 "github.com/cgrates/cgrates/apier/v1" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +func init() { + c := &CmdSetRateProfile{ + name: "rateprofile_set", + rpcMethod: utils.APIerSv1SetRateProfile, + rpcParams: &v1.RateProfileWithCache{}, + } + commands[c.Name()] = c + c.CommandExecuter = &CommandExecuter{c} +} + +type CmdSetRateProfile struct { + name string + rpcMethod string + rpcParams *v1.RateProfileWithCache + *CommandExecuter +} + +func (self *CmdSetRateProfile) Name() string { + return self.name +} + +func (self *CmdSetRateProfile) RpcMethod() string { + return self.rpcMethod +} + +func (self *CmdSetRateProfile) RpcParams(reset bool) interface{} { + if reset || self.rpcParams == nil { + self.rpcParams = &v1.RateProfileWithCache{RateProfileWithArgDispatcher: new(engine.RateProfileWithArgDispatcher)} + } + return self.rpcParams +} + +func (self *CmdSetRateProfile) PostprocessRpcParams() error { + return nil +} + +func (self *CmdSetRateProfile) RpcResult() interface{} { + var s string + return &s +} diff --git a/console/rateprofiles.go b/console/rateprofiles.go new file mode 100644 index 000000000..3feea2556 --- /dev/null +++ b/console/rateprofiles.go @@ -0,0 +1,66 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package console + +import ( + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +func init() { + c := &CmdGetRateProfile{ + name: "rateprofile", + rpcMethod: utils.APIerSv1GetRateProfile, + rpcParams: &utils.TenantID{}, + } + commands[c.Name()] = c + c.CommandExecuter = &CommandExecuter{c} +} + +// Commander implementation +type CmdGetRateProfile struct { + name string + rpcMethod string + rpcParams *utils.TenantID + *CommandExecuter +} + +func (self *CmdGetRateProfile) Name() string { + return self.name +} + +func (self *CmdGetRateProfile) RpcMethod() string { + return self.rpcMethod +} + +func (self *CmdGetRateProfile) RpcParams(reset bool) interface{} { + if reset || self.rpcParams == nil { + self.rpcParams = &utils.TenantID{} + } + return self.rpcParams +} + +func (self *CmdGetRateProfile) PostprocessRpcParams() error { + return nil +} + +func (self *CmdGetRateProfile) RpcResult() interface{} { + var atr engine.RateProfile + return &atr +} diff --git a/console/rattingprofile_ids.go b/console/ratingprofile_ids.go similarity index 97% rename from console/rattingprofile_ids.go rename to console/ratingprofile_ids.go index 8b681de06..b8e4ef7dc 100644 --- a/console/rattingprofile_ids.go +++ b/console/ratingprofile_ids.go @@ -24,7 +24,7 @@ import ( func init() { c := &CmdGetRatingProfileIDs{ - name: "ratingprofil_ids", + name: "ratingprofile_ids", rpcMethod: utils.APIerSv1GetRatingProfileIDs, } commands[c.Name()] = c diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql index 10455cf5d..147b84e9b 100644 --- a/data/storage/mysql/create_tariffplan_tables.sql +++ b/data/storage/mysql/create_tariffplan_tables.sql @@ -468,6 +468,40 @@ CREATE TABLE tp_dispatcher_hosts ( `id`,`address`) ); +-- +-- Table structure for table `tp_rate_profiles` +-- + + +DROP TABLE IF EXISTS tp_rate_profiles; +CREATE TABLE tp_rate_profiles ( + `pk` int(11) NOT NULL AUTO_INCREMENT, + `tpid` varchar(64) NOT NULL, + `tenant` varchar(64) NOT NULL, + `id` varchar(64) NOT NULL, + `filter_ids` varchar(64) NOT NULL, + `activation_interval` varchar(64) NOT NULL, + `weight` decimal(8,2) NOT NULL, + `connect_fee` decimal(8,2) NOT NULL, + `rounding_method` varchar(64) NOT NULL, + `rounding_decimals` tinyint(4) NOT NULL, + `min_cost` decimal(8,4) NOT NULL, + `max_cost` decimal(8,4) NOT NULL, + `max_cost_strategy` varchar(64) NOT NULL, + `rate_id` varchar(32) NOT NULL, + `rate_filter_ids` varchar(64) NOT NULL, + `route_weight` decimal(8,2) NOT NULL, + `rate_value` decimal(8,4) NOT NULL, + `rate_unit` varchar(64) NOT NULL, + `rate_increment` varchar(64) NOT NULL, + `rate_blocker` BOOLEAN NOT NULL, + `created_at` TIMESTAMP, + PRIMARY KEY (`pk`), + KEY `tpid` (`tpid`), + UNIQUE KEY `unique_tp_rate_profiles` (`tpid`,`tenant`, + `id`,`filter_ids`,`rate_id` ) +); + -- -- Table structure for table `versions` -- diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql index 88554395b..ca7b04576 100644 --- a/data/storage/postgres/create_tariffplan_tables.sql +++ b/data/storage/postgres/create_tariffplan_tables.sql @@ -455,6 +455,38 @@ CREATE INDEX tp_routes_unique ON tp_routes ("tpid", "tenant", "id", CREATE INDEX tp_dispatcher_hosts_unique ON tp_dispatcher_hosts ("tpid", "tenant", "id", "address"); +-- +-- Table structure for table `tp_rate_profiles` +-- + + DROP TABLE IF EXISTS tp_rate_profiles; + CREATE TABLE tp_rate_profiles ( + "pk" SERIAL PRIMARY KEY, + "tpid" varchar(64) NOT NULL, + "tenant" varchar(64) NOT NULL, + "id" varchar(64) NOT NULL, + "filter_ids" varchar(64) NOT NULL, + "activation_interval" varchar(64) NOT NULL, + "weight" decimal(8,2) NOT NULL, + "connect_fee" decimal(8,4) NOT NULL, + "rounding_method" varchar(64) NOT NULL, + "rounding_decimals" SMALLINT NOT NULL, + "min_cost" decimal(8,4) NOT NULL, + "max_cost" decimal(8,4) NOT NULL, + "max_cost_strategy" VARCHAR(64) NOT NULL, + "rate_id" VARCHAR(64) NOT NULL, + "rate_filter_ids" VARCHAR(64) NOT NULL, + "rate_weight" decimal(8,2) NOT NULL, + "rate_value" decimal(8,4) NOT NULL, + "rate_unit" VARCHAR(64) NOT NULL, + "rate_increment" VARCHAR(64) NOT NULL, + "rate_blocker" BOOLEAN NOT NULL, + "created_at" TIMESTAMP WITH TIME ZONE + ); + CREATE INDEX tp_rate_profiles_ids ON tp_rate_profiles (tpid); + CREATE INDEX tp_rate_profiles_unique ON tp_rate_profiles ("tpid", "tenant", "id", + "filter_ids", "rate_id"); + -- -- Table structure for table `versions` -- diff --git a/dispatchers/caches_it_test.go b/dispatchers/caches_it_test.go index c9130c6ab..a2c88d7ca 100644 --- a/dispatchers/caches_it_test.go +++ b/dispatchers/caches_it_test.go @@ -144,7 +144,7 @@ func testDspChcLoadAfterFolder(t *testing.T) { expStats[utils.CacheRouteProfiles].Items = 3 expStats[utils.CacheThresholdProfiles].Items = 2 expStats[utils.CacheThresholds].Items = 2 - expStats[utils.CacheLoadIDs].Items = 20 + expStats[utils.CacheLoadIDs].Items = 21 if err := dispEngine.RPC.Call(utils.CacheSv1GetCacheStats, &args, &rcvStats); err != nil { t.Error(err) } else if !reflect.DeepEqual(expStats, rcvStats) { @@ -185,6 +185,8 @@ func testDspChcPrecacheStatus(t *testing.T) { utils.CacheRouteFilterIndexes: utils.MetaReady, utils.CacheChargerFilterIndexes: utils.MetaReady, utils.CacheDispatcherFilterIndexes: utils.MetaReady, + utils.CacheRateFilterIndexes: utils.MetaReady, + utils.CacheRateProfiles: utils.MetaReady, utils.CacheLoadIDs: utils.MetaReady, utils.CacheCDRIDs: utils.MetaReady, utils.CacheClosedSessions: utils.MetaReady, diff --git a/dispatchers/replicator.go b/dispatchers/replicator.go index b39fba34f..581b46458 100644 --- a/dispatchers/replicator.go +++ b/dispatchers/replicator.go @@ -563,6 +563,27 @@ func (dS *DispatcherService) ReplicatorSv1GetDispatcherHost(args *utils.TenantID }, utils.MetaReplicator, routeID, utils.ReplicatorSv1GetDispatcherHost, args, reply) } +func (dS *DispatcherService) ReplicatorSv1GetRateProfile(args *utils.TenantIDWithArgDispatcher, reply *engine.RateProfile) (err error) { + tnt := dS.cfg.GeneralCfg().DefaultTenant + if args.TenantID != nil && args.TenantID.Tenant != utils.EmptyString { + tnt = args.TenantID.Tenant + } + if args.ArgDispatcher == nil { + return utils.NewErrMandatoryIeMissing(utils.ArgDispatcherField) + } + if len(dS.cfg.DispatcherSCfg().AttributeSConns) != 0 { + if err = dS.authorize(utils.ReplicatorSv1GetRateProfile, tnt, + args.APIKey, utils.TimePointer(time.Now())); err != nil { + return + } + } + routeID := args.ArgDispatcher.RouteID + return dS.Dispatch(&utils.CGREvent{ + Tenant: tnt, + ID: args.ID, + }, utils.MetaReplicator, routeID, utils.ReplicatorSv1GetRateProfile, args, reply) +} + func (dS *DispatcherService) ReplicatorSv1GetItemLoadIDs(args *utils.StringWithApiKey, rpl *map[string]int64) (err error) { if args == nil { args = &utils.StringWithApiKey{} @@ -1091,6 +1112,28 @@ func (dS *DispatcherService) ReplicatorSv1SetDispatcherProfile(args *engine.Disp utils.ReplicatorSv1SetDispatcherProfile, args, rpl) } +func (dS *DispatcherService) ReplicatorSv1SetRateProfile(args *engine.RateProfileWithArgDispatcher, rpl *string) (err error) { + if args == nil { + args = &engine.RateProfileWithArgDispatcher{} + } + args.Tenant = utils.FirstNonEmpty(args.Tenant, dS.cfg.GeneralCfg().DefaultTenant) + if len(dS.cfg.DispatcherSCfg().AttributeSConns) != 0 { + if args.ArgDispatcher == nil { + return utils.NewErrMandatoryIeMissing(utils.ArgDispatcherField) + } + if err = dS.authorize(utils.ReplicatorSv1SetRateProfile, args.Tenant, + args.APIKey, utils.TimePointer(time.Now())); err != nil { + return + } + } + var routeID *string + if args.ArgDispatcher != nil { + routeID = args.ArgDispatcher.RouteID + } + return dS.Dispatch(&utils.CGREvent{Tenant: args.Tenant}, utils.MetaReplicator, routeID, + utils.ReplicatorSv1SetRateProfile, args, rpl) +} + func (dS *DispatcherService) ReplicatorSv1SetActionPlan(args *engine.SetActionPlanArgWithArgDispatcher, rpl *string) (err error) { if args == nil { args = &engine.SetActionPlanArgWithArgDispatcher{} @@ -1662,3 +1705,25 @@ func (dS *DispatcherService) ReplicatorSv1RemoveDispatcherHost(args *utils.Tenan return dS.Dispatch(&utils.CGREvent{Tenant: args.Tenant}, utils.MetaReplicator, routeID, utils.ReplicatorSv1RemoveDispatcherHost, args, rpl) } + +func (dS *DispatcherService) ReplicatorSv1RemoveRateProfile(args *utils.TenantIDWithArgDispatcher, rpl *string) (err error) { + if args == nil { + args = &utils.TenantIDWithArgDispatcher{} + } + args.Tenant = utils.FirstNonEmpty(args.Tenant, dS.cfg.GeneralCfg().DefaultTenant) + if len(dS.cfg.DispatcherSCfg().AttributeSConns) != 0 { + if args.ArgDispatcher == nil { + return utils.NewErrMandatoryIeMissing(utils.ArgDispatcherField) + } + if err = dS.authorize(utils.ReplicatorSv1RemoveRateProfile, args.Tenant, + args.APIKey, utils.TimePointer(time.Now())); err != nil { + return + } + } + var routeID *string + if args.ArgDispatcher != nil { + routeID = args.ArgDispatcher.RouteID + } + return dS.Dispatch(&utils.CGREvent{Tenant: args.Tenant}, utils.MetaReplicator, routeID, + utils.ReplicatorSv1RemoveRateProfile, args, rpl) +} diff --git a/engine/datamanager.go b/engine/datamanager.go index 11dd004bc..1337107b8 100644 --- a/engine/datamanager.go +++ b/engine/datamanager.go @@ -77,6 +77,7 @@ var ( utils.ChargerProfilePrefix: true, utils.DispatcherProfilePrefix: true, utils.DispatcherHostPrefix: true, + utils.RateProfilePrefix: true, utils.AttributeFilterIndexes: true, utils.ResourceFilterIndexes: true, utils.StatFilterIndexes: true, @@ -84,6 +85,7 @@ var ( utils.RouteFilterIndexes: true, utils.ChargerFilterIndexes: true, utils.DispatcherFilterIndexes: true, + utils.RateFilterIndexes: true, } ) diff --git a/engine/libtest.go b/engine/libtest.go index b846d7b41..668b84a40 100644 --- a/engine/libtest.go +++ b/engine/libtest.go @@ -505,6 +505,8 @@ func GetDefaultEmptyCacheStats() map[string]*ltcache.CacheStats { utils.CacheThresholdFilterIndexes: {}, utils.CacheThresholdProfiles: {}, utils.CacheThresholds: {}, + utils.CacheRateProfiles: {}, + utils.CacheRateFilterIndexes: {}, utils.CacheTimings: {}, utils.CacheDiameterMessages: {}, utils.CacheClosedSessions: {}, diff --git a/engine/storage_csv.go b/engine/storage_csv.go index cfe3946dc..c3bbcaa6e 100644 --- a/engine/storage_csv.go +++ b/engine/storage_csv.go @@ -129,7 +129,7 @@ func NewFileCSVStorage(sep rune, dataPath string) *CSVStorage { chargersPaths := appendName(allFoldersPath, utils.ChargersCsv) dispatcherprofilesPaths := appendName(allFoldersPath, utils.DispatcherProfilesCsv) dispatcherhostsPaths := appendName(allFoldersPath, utils.DispatcherHostsCsv) - rateProfilesFn := append(allFoldersPath, utils.RateProfilesCsv) + rateProfilesFn := appendName(allFoldersPath, utils.RateProfilesCsv) return NewCSVStorage(sep, destinationsPaths, timingsPaths, diff --git a/engine/storage_internal_datadb.go b/engine/storage_internal_datadb.go index bf43b0852..4bd5e38f8 100644 --- a/engine/storage_internal_datadb.go +++ b/engine/storage_internal_datadb.go @@ -303,6 +303,11 @@ func newInternalDBCfg(itemsCacheCfg map[string]*config.ItemOpt, isDataDB bool) m TTL: itemsCacheCfg[utils.TBLTPDispatcherHosts].TTL, StaticTTL: itemsCacheCfg[utils.TBLTPDispatcherHosts].StaticTTL, }, + utils.TBLTPRateProfiles: <cache.CacheConfig{ + MaxItems: itemsCacheCfg[utils.TBLTPRateProfiles].Limit, + TTL: itemsCacheCfg[utils.TBLTPRateProfiles].TTL, + StaticTTL: itemsCacheCfg[utils.TBLTPRateProfiles].StaticTTL, + }, utils.CDRsTBL: <cache.CacheConfig{ MaxItems: itemsCacheCfg[utils.CDRsTBL].Limit, TTL: itemsCacheCfg[utils.CDRsTBL].TTL, diff --git a/engine/storage_sql.go b/engine/storage_sql.go index 8e9829fba..d9addb1ce 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -238,7 +238,7 @@ func (self *SQLStorage) RemTpData(table, tpid string, args map[string]string) er utils.TBLTPSharedGroups, utils.TBLTPActions, utils.TBLTPActionPlans, utils.TBLTPActionTriggers, utils.TBLTPAccountActions, utils.TBLTPResources, utils.TBLTPStats, utils.TBLTPFilters, - utils.TBLTPRoutes, utils.TBLTPAttributes, + utils.TBLTPRoutes, utils.TBLTPAttributes, utils.TBLTPRateProfiles, utils.TBLTPChargers, utils.TBLTPDispatchers, utils.TBLTPDispatcherHosts} { if err := tx.Table(tblName).Where("tpid = ?", tpid).Delete(nil).Error; err != nil { tx.Rollback() diff --git a/engine/tpimporter_csv.go b/engine/tpimporter_csv.go index 67b97d5df..71575ea2f 100644 --- a/engine/tpimporter_csv.go +++ b/engine/tpimporter_csv.go @@ -60,6 +60,7 @@ var fileHandlers = map[string]func(*TPCSVImporter, string) error{ utils.ChargersCsv: (*TPCSVImporter).importChargerProfiles, utils.DispatcherProfilesCsv: (*TPCSVImporter).importDispatcherProfiles, utils.DispatcherHostsCsv: (*TPCSVImporter).importDispatcherHosts, + utils.RateProfilesCsv: (*TPCSVImporter).importRateProfiles, } func (self *TPCSVImporter) Run() error { @@ -357,3 +358,14 @@ func (self *TPCSVImporter) importDispatcherHosts(fn string) error { } return self.StorDb.SetTPDispatcherHosts(dpps) } + +func (self *TPCSVImporter) importRateProfiles(fn string) error { + if self.Verbose { + log.Printf("Processing file: <%s> ", fn) + } + rpps, err := self.csvr.GetTPRateProfiles(self.TPid, "", "") + if err != nil { + return err + } + return self.StorDb.SetTPRateProfiles(rpps) +} diff --git a/engine/version.go b/engine/version.go index bc5ff969e..4dde29297 100644 --- a/engine/version.go +++ b/engine/version.go @@ -164,6 +164,7 @@ func CurrentDataDBVersions() Versions { utils.Chargers: 1, utils.Dispatchers: 1, utils.LoadIDsVrs: 1, + utils.RateProfiles: 1, } } @@ -194,6 +195,7 @@ func CurrentStorDBVersions() Versions { utils.TpRatingProfile: 1, utils.TpChargers: 1, utils.TpDispatchers: 1, + utils.TpRateProfiles: 1, } } diff --git a/general_tests/tut_smgeneric_it_test.go b/general_tests/tut_smgeneric_it_test.go index e00098f2f..fd53570bd 100644 --- a/general_tests/tut_smgeneric_it_test.go +++ b/general_tests/tut_smgeneric_it_test.go @@ -155,7 +155,7 @@ func testTutSMGCacheStats(t *testing.T) { expectedStats[utils.CacheAttributeProfiles].Items = 2 expectedStats[utils.MetaDefault].Items = 1 expectedStats[utils.CacheActionTriggers].Items = 1 - expectedStats[utils.CacheLoadIDs].Items = 20 + expectedStats[utils.CacheLoadIDs].Items = 21 expectedStats[utils.CacheChargerProfiles].Items = 1 expectedStats[utils.CacheRPCConnections].Items = 2 if err := tutSMGRpc.Call(utils.CacheSv1GetCacheStats, new(utils.AttrCacheIDsWithArgDispatcher), &rcvStats); err != nil { diff --git a/utils/consts.go b/utils/consts.go index 7ae3cf7d4..779417f65 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -937,6 +937,7 @@ const ( TpRatingProfile = "TpRatingProfile" TpChargers = "TpChargers" TpDispatchers = "TpDispatchers" + TpRateProfiles = "TpRateProfiles" ) // Dispatcher Const @@ -1447,6 +1448,14 @@ const ( DispatcherServicePing = "DispatcherService.Ping" ) +// RateProfile APIs +const ( + APIerSv1SetRateProfile = "APIerSv1.SetRateProfile" + APIerSv1GetRateProfile = "APIerSv1.GetRateProfile" + APIerSv1GetRateProfileIDs = "APIerSv1.GetRateProfileIDs" + APIerSv1RemoveRateProfile = "APIerSv1.RemoveRateProfile" +) + // AnalyzerS APIs const ( AnalyzerSv1 = "AnalyzerSv1"