diff --git a/apier/v1/apier.go b/apier/v1/apier.go
index d04e670b4..b674dbcb1 100644
--- a/apier/v1/apier.go
+++ b/apier/v1/apier.go
@@ -1027,7 +1027,7 @@ func (self *ApierV1) LoadCache(args utils.AttrReloadCache, reply *string) (err e
if args.FlushAll {
cache.Flush()
}
- var dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs []string
+ var dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, lcrPrfIDs []string
if args.DestinationIDs == nil {
dstIDs = nil
} else {
@@ -1128,8 +1128,13 @@ func (self *ApierV1) LoadCache(args utils.AttrReloadCache, reply *string) (err e
} else {
fltrIDs = *args.FilterIDs
}
+ if args.LCRProfileIDs == nil {
+ lcrPrfIDs = nil
+ } else {
+ lcrPrfIDs = *args.LCRProfileIDs
+ }
- if err := self.DataManager.LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs); err != nil {
+ if err := self.DataManager.LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, lcrPrfIDs); err != nil {
return utils.NewErrServerError(err)
}
*reply = utils.OK
@@ -1276,6 +1281,13 @@ func (self *ApierV1) FlushCache(args utils.AttrReloadCache, reply *string) (err
cache.RemKey(utils.FilterPrefix+key, true, utils.NonTransactional)
}
}
+ if args.LCRProfileIDs == nil {
+ cache.RemPrefixKey(utils.LCRProfilePrefix, true, utils.NonTransactional)
+ } else if len(*args.LCRProfileIDs) != 0 {
+ for _, key := range *args.LCRProfileIDs {
+ cache.RemKey(utils.LCRProfilePrefix+key, true, utils.NonTransactional)
+ }
+ }
*reply = utils.OK
return
@@ -1302,6 +1314,7 @@ func (self *ApierV1) GetCacheStats(attrs utils.AttrCacheStats, reply *utils.Cach
cs.Thresholds = cache.CountEntries(utils.ThresholdPrefix)
cs.ThresholdProfiles = cache.CountEntries(utils.ThresholdProfilePrefix)
cs.Filters = cache.CountEntries(utils.FilterPrefix)
+ cs.LCRProfiles = cache.CountEntries(utils.LCRProfilePrefix)
if self.CdrStatsSrv != nil {
var queueIds []string
@@ -1691,6 +1704,25 @@ func (v1 *ApierV1) GetCacheKeys(args utils.ArgsCacheKeys, reply *utils.ArgsCache
}
}
+ if args.LCRProfileIDs != nil {
+ var ids []string
+ if len(*args.LCRProfileIDs) != 0 {
+ for _, id := range *args.LCRProfileIDs {
+ if _, hasIt := cache.Get(utils.LCRProfilePrefix + id); hasIt {
+ ids = append(ids, id)
+ }
+ }
+ } else {
+ for _, id := range cache.GetEntryKeys(utils.LCRProfilePrefix) {
+ ids = append(ids, id[len(utils.LCRProfilePrefix):])
+ }
+ }
+ ids = args.Paginator.PaginateStringSlice(ids)
+ if len(ids) != 0 {
+ reply.LCRProfileIDs = &ids
+ }
+ }
+
return
}
@@ -1727,6 +1759,7 @@ func (self *ApierV1) LoadTariffPlanFromFolder(attrs utils.AttrLoadTpFromFolder,
path.Join(attrs.FolderPath, utils.StatsCsv),
path.Join(attrs.FolderPath, utils.ThresholdsCsv),
path.Join(attrs.FolderPath, utils.FiltersCsv),
+ path.Join(attrs.FolderPath, utils.LCRCsv),
), "", self.Config.DefaultTimezone)
if err := loader.LoadAll(); err != nil {
return utils.NewErrServerError(err)
diff --git a/apier/v1/lcrs.go b/apier/v1/lcrs.go
new file mode 100644
index 000000000..280041407
--- /dev/null
+++ b/apier/v1/lcrs.go
@@ -0,0 +1,67 @@
+/*
+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"
+)
+
+// GetLCRProfile returns a LCDR configuration
+func (apierV1 *ApierV1) GetLCRProfile(arg utils.TenantID, reply *engine.LCRProfile) error {
+ if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if rcfg, err := apierV1.DataManager.GetLCRProfile(arg.Tenant, arg.ID, false, utils.NonTransactional); err != nil {
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
+ } else {
+ *reply = *rcfg
+ }
+ return nil
+}
+
+//SetLCRProfile add a new LCR configuration
+func (apierV1 *ApierV1) SetLCRProfile(res *engine.LCRProfile, reply *string) error {
+ if missing := utils.MissingStructFields(res, []string{"Tenant", "ID"}); len(missing) != 0 {
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if err := apierV1.DataManager.SetLCRProfile(res); err != nil {
+ return utils.APIErrorHandler(err)
+ }
+ *reply = utils.OK
+ return nil
+}
+
+//RemResourceProfile remove a specific resource configuration
+func (apierV1 *ApierV1) RemLCRProfile(arg utils.TenantID, reply *string) error {
+ if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if err := apierV1.DataManager.RemoveLCRProfile(arg.Tenant, arg.ID, utils.NonTransactional); err != nil {
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
+ }
+ *reply = utils.OK
+ return nil
+}
diff --git a/apier/v1/smgenericv1_it_test.go b/apier/v1/smgenericv1_it_test.go
index 593d32c0a..926f31c3f 100644
--- a/apier/v1/smgenericv1_it_test.go
+++ b/apier/v1/smgenericv1_it_test.go
@@ -103,7 +103,7 @@ func TestSMGV1CacheStats(t *testing.T) {
expectedStats := &utils.CacheStats{Destinations: 5, ReverseDestinations: 7, RatingPlans: 4, RatingProfiles: 9,
Actions: 9, ActionPlans: 4, AccountActionPlans: 5, SharedGroups: 1, DerivedChargers: 1,
LcrProfiles: 5, CdrStats: 6, Users: 3, Aliases: 1, ReverseAliases: 2, ResourceProfiles: 3, Resources: 3, StatQueues: 1,
- StatQueueProfiles: 1, Thresholds: 7, ThresholdProfiles: 7, Filters: 15}
+ StatQueueProfiles: 1, Thresholds: 7, ThresholdProfiles: 7, Filters: 16}
var args utils.AttrCacheStats
if err := smgV1Rpc.Call("ApierV1.GetCacheStats", args, &rcvStats); err != nil {
t.Error("Got error on ApierV1.GetCacheStats: ", err.Error())
diff --git a/apier/v2/apier.go b/apier/v2/apier.go
index cd455dbc8..047d3daf0 100644
--- a/apier/v2/apier.go
+++ b/apier/v2/apier.go
@@ -144,6 +144,7 @@ func (self *ApierV2) LoadTariffPlanFromFolder(attrs utils.AttrLoadTpFromFolder,
path.Join(attrs.FolderPath, utils.StatsCsv),
path.Join(attrs.FolderPath, utils.ThresholdsCsv),
path.Join(attrs.FolderPath, utils.FiltersCsv),
+ path.Join(attrs.FolderPath, utils.LCRCsv),
), "", self.Config.DefaultTimezone)
if err := loader.LoadAll(); err != nil {
return utils.NewErrServerError(err)
@@ -184,7 +185,8 @@ func (self *ApierV2) LoadTariffPlanFromFolder(attrs utils.AttrLoadTpFromFolder,
utils.StatQueueProfilePrefix,
utils.ThresholdPrefix,
utils.ThresholdProfilePrefix,
- utils.FilterPrefix} {
+ utils.FilterPrefix,
+ utils.LCRProfilePrefix} {
loadedIDs, _ := loader.GetLoadedIds(prfx)
if err := self.DataManager.CacheDataFromDB(prfx, loadedIDs, true); err != nil {
return utils.NewErrServerError(err)
diff --git a/cmd/cgr-engine/rater.go b/cmd/cgr-engine/rater.go
index 7994eb181..3a0c398a3 100755
--- a/cmd/cgr-engine/rater.go
+++ b/cmd/cgr-engine/rater.go
@@ -43,7 +43,7 @@ func startRater(internalRaterChan chan rpcclient.RpcClientConnection, cacheDoneC
waitTasks = append(waitTasks, cacheTaskChan)
go func() {
defer close(cacheTaskChan)
- var dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs []string
+ var dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, lcrPrfIDs []string
if cCfg, has := cfg.CacheConfig[utils.CacheDestinations]; !has || !cCfg.Precache {
dstIDs = make([]string, 0) // Don't cache any
}
@@ -104,9 +104,12 @@ func startRater(internalRaterChan chan rpcclient.RpcClientConnection, cacheDoneC
if cCfg, has := cfg.CacheConfig[utils.CacheFilters]; !has || !cCfg.Precache {
fltrIDs = make([]string, 0)
}
+ if cCfg, has := cfg.CacheConfig[utils.CacheLCRProfiles]; !has || !cCfg.Precache {
+ lcrPrfIDs = make([]string, 0)
+ }
// ToDo: Add here timings
- if err := dm.LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs); err != nil {
+ if err := dm.LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, lcrPrfIDs); err != nil {
utils.Logger.Crit(fmt.Sprintf(" Cache rating error: %s", err.Error()))
exitChan <- true
return
diff --git a/cmd/cgr-loader/cgr-loader.go b/cmd/cgr-loader/cgr-loader.go
index 920012514..69325d674 100755
--- a/cmd/cgr-loader/cgr-loader.go
+++ b/cmd/cgr-loader/cgr-loader.go
@@ -148,6 +148,7 @@ func main() {
path.Join(*dataPath, utils.StatsCsv),
path.Join(*dataPath, utils.ThresholdsCsv),
path.Join(*dataPath, utils.FiltersCsv),
+ path.Join(*dataPath, utils.LCRCsv),
)
}
diff --git a/cmd/cgr-tester/cgr-tester.go b/cmd/cgr-tester/cgr-tester.go
index 30dbb0acd..82ab90eac 100644
--- a/cmd/cgr-tester/cgr-tester.go
+++ b/cmd/cgr-tester/cgr-tester.go
@@ -67,7 +67,7 @@ func durInternalRater(cd *engine.CallDescriptor) (time.Duration, error) {
}
defer dm.DataDB().Close()
engine.SetDataStorage(dm)
- if err := dm.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil); err != nil {
+ if err := dm.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil); err != nil {
return nilDuration, fmt.Errorf("Cache rating error: %s", err.Error())
}
log.Printf("Runnning %d cycles...", *runs)
diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json
index 797245dd1..671e5f08e 100644
--- a/data/conf/cgrates/cgrates.json
+++ b/data/conf/cgrates/cgrates.json
@@ -46,6 +46,7 @@
// "derived_chargers": {"limit": 10000, "ttl":"0s", "precache": false}, // control derived charging rule caching
// "resource_limits": {"limit": 10000, "ttl":"0s", "precache": false}, // control resource limits caching
// "timings": {"limit": 10000, "ttl":"0s", "precache": false}, // control timings caching
+// "lcr_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, // control lcr_rofiles caching
// },
diff --git a/data/conf/samples/tutmongo/cgrates.json b/data/conf/samples/tutmongo/cgrates.json
index 640c89286..cc6f6d257 100644
--- a/data/conf/samples/tutmongo/cgrates.json
+++ b/data/conf/samples/tutmongo/cgrates.json
@@ -49,6 +49,7 @@
"thresholds": {"limit": 10000, "ttl":"0s", "precache": true},
"threshold_profiles": {"limit": 10000, "ttl":"0s", "precache": true},
"filters": {"limit": 10000, "ttl":"0s", "precache": true},
+ "lcr_profiles": {"limit": 10000, "ttl":"0s", "precache": true},
},
diff --git a/data/conf/samples/tutmysql/cgrates.json b/data/conf/samples/tutmysql/cgrates.json
index 3468f3e06..6b5be1e22 100644
--- a/data/conf/samples/tutmysql/cgrates.json
+++ b/data/conf/samples/tutmysql/cgrates.json
@@ -42,6 +42,7 @@
"thresholds": {"limit": 10000, "ttl":"0s", "precache": true},
"threshold_profiles": {"limit": 10000, "ttl":"0s", "precache": true},
"filters": {"limit": 10000, "ttl":"0s", "precache": true},
+ "lcr_profiles": {"limit": 10000, "ttl":"0s", "precache": true},
},
diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql
index 36553caa1..042fc24d9 100644
--- a/data/storage/mysql/create_tariffplan_tables.sql
+++ b/data/storage/mysql/create_tariffplan_tables.sql
@@ -487,6 +487,30 @@ CREATE TABLE tp_filters (
UNIQUE KEY `unique_tp_filters` (`tpid`,`tenant`, `id`, `filter_type`, `filter_field_name`)
);
+--
+-- Table structure for table `tp_lcr`
+--
+
+DROP TABLE IF EXISTS tp_lcrs;
+CREATE TABLE tp_lcrs (
+ `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,
+ `strategy` varchar(32) NOT NULL,
+ `strategy_params` varchar(64) NOT NULL,
+ `supplier_id` varchar(32) NOT NULL,
+ `ratingplan_ids` varchar(64) NOT NULL,
+ `stat_ids` varchar(64) NOT NULL,
+ `weight` decimal(8,2) NOT NULL,
+ `created_at` TIMESTAMP,
+ PRIMARY KEY (`pk`),
+ KEY `tpid` (`tpid`),
+ UNIQUE KEY `unique_tp_lcr` (`tpid`,`tenant`, `id`,`filter_ids` )
+);
+
--
-- Table structure for table `versions`
--
@@ -497,5 +521,5 @@ CREATE TABLE versions (
`item` varchar(64) NOT NULL,
`version` int(11) NOT NULL,
PRIMARY KEY (`id`),
- UNIQUE KEY `item` (`item`)
+ UNIQUE KEY `id_item` (`id`,`item`)
);
diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql
index 749ff012c..2a99637ae 100644
--- a/data/storage/postgres/create_tariffplan_tables.sql
+++ b/data/storage/postgres/create_tariffplan_tables.sql
@@ -480,7 +480,28 @@ CREATE TABLE tp_filters (
CREATE INDEX tp_filters_idx ON tp_filters (tpid);
CREATE INDEX tp_filters_unique ON tp_filters ("tpid","tenant", "id", "filter_type", "filter_field_name");
+ --
+ -- Table structure for table `tp_resources`
+ --
+ DROP TABLE IF EXISTS tp_lcrs;
+ CREATE TABLE tp_lcrs (
+ "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,
+ "strategy" varchar(32) NOT NULL,
+ "strategy_params" varchar(64) NOT NULL,
+ "supplier_id" varchar(32) NOT NULL,
+ "ratingplan_ids" varchar(64) NOT NULL,
+ "stat_ids" varchar(64) NOT NULL,
+ "weight" decimal(8,2) NOT NULL,
+ "created_at" TIMESTAMP WITH TIME ZONE
+ );
+ CREATE INDEX tp_lcrs_idx ON tp_lcrs (tpid);
+ CREATE INDEX tp_lcrs_unique ON tp_lcrs ("tpid", "tenant", "id", "filter_ids");
--
-- Table structure for table `versions`
@@ -491,5 +512,5 @@ CREATE TABLE versions (
"id" SERIAL PRIMARY KEY,
"item" varchar(64) NOT NULL,
"version" INTEGER NOT NULL,
- UNIQUE (item)
+ UNIQUE ("id","item")
);
diff --git a/data/tariffplans/tutorial/Filters.csv b/data/tariffplans/tutorial/Filters.csv
index 4c1f4ffa0..180334d4a 100644
--- a/data/tariffplans/tutorial/Filters.csv
+++ b/data/tariffplans/tutorial/Filters.csv
@@ -3,6 +3,7 @@ cgrates.org,FLTR_1,*string,Account,1001;1002,2014-07-29T15:00:00Z
cgrates.org,FLTR_1,*string_prefix,Destination,10;20,
cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),
cgrates.org,FLTR_ACNT_1007,*string,Account,1007,2014-07-29T15:00:00Z
+cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL,2014-07-29T15:00:00Z
cgrates.org,FLTR_ACNT_BALANCE_1,*string,Account,1001;1002,2014-07-29T15:00:00Z
diff --git a/engine/libtest.go b/engine/libtest.go
index 62d0ffda2..3810f0078 100644
--- a/engine/libtest.go
+++ b/engine/libtest.go
@@ -135,6 +135,7 @@ func LoadTariffPlanFromFolder(tpPath, timezone string, dm *DataManager, disable_
path.Join(tpPath, utils.StatsCsv),
path.Join(tpPath, utils.ThresholdsCsv),
path.Join(tpPath, utils.FiltersCsv),
+ path.Join(tpPath, utils.LCRCsv),
), "", timezone)
if err := loader.LoadAll(); err != nil {
return utils.NewErrServerError(err)
diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go
index e0f0e924a..c83839f7e 100755
--- a/engine/loader_csv_test.go
+++ b/engine/loader_csv_test.go
@@ -289,6 +289,10 @@ cgrates.org,FLTR_1,*rsr_fields,,Subject(~^1.*1$);Destination(1002),
cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_DE,*destinations,Destination,DST_DE,2014-07-29T15:00:00Z
cgrates.org,FLTR_DST_NL,*destinations,Destination,DST_NL,2014-07-29T15:00:00Z
+`
+ lcrProfiles = `
+#Tenant,ID,FilterIDs,ActivationInterval,Strategy,StrategyParams,SupplierID,RatingPlanIDs,StatIDs,Weight
+cgrates.org,LCR_1,FLTR_ACNT_dan;FLTR_DST_DE,2014-07-29T15:00:00Z,*lowest_cost,,supplier1,RPL_1,,20
`
)
@@ -296,7 +300,7 @@ var csvr *TpReader
func init() {
csvr = NewTpReader(dm.dataDB, NewStringCSVStorage(',', destinations, timings, rates, destinationRates, ratingPlans, ratingProfiles,
- sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resProfiles, stats, thresholds, filters), testTPID, "")
+ sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resProfiles, stats, thresholds, filters, lcrProfiles), testTPID, "")
if err := csvr.LoadDestinations(); err != nil {
log.Print("error in LoadDestinations:", err)
@@ -358,9 +362,12 @@ func init() {
if err := csvr.LoadThresholds(); err != nil {
log.Print("error in LoadThresholds:", err)
}
+ if err := csvr.LoadLCRProfiles(); err != nil {
+ log.Print("error in LoadThresholds:", err)
+ }
csvr.WriteToDatabase(false, false, false)
cache.Flush()
- dm.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dm.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
}
func TestLoadDestinations(t *testing.T) {
@@ -1439,7 +1446,6 @@ func TestLoadResourceProfiles(t *testing.T) {
} else if !reflect.DeepEqual(eResProfiles[resKey], csvr.resProfiles[resKey]) {
t.Errorf("Expecting: %+v, received: %+v", eResProfiles[resKey], csvr.resProfiles[resKey])
}
-
}
func TestLoadStatProfiles(t *testing.T) {
@@ -1612,6 +1618,32 @@ func TestLoadFilters(t *testing.T) {
}
}
+func TestLoadLCRProfiles(t *testing.T) {
+ eLCRprofiles := map[utils.TenantID]*utils.TPLCRProfile{
+ utils.TenantID{Tenant: "cgrates.org", ID: "LCR_1"}: &utils.TPLCRProfile{
+ TPid: testTPID,
+ Tenant: "cgrates.org",
+ ID: "LCR_1",
+ FilterIDs: []string{"FLTR_ACNT_dan", "FLTR_DST_DE"},
+ ActivationInterval: &utils.TPActivationInterval{
+ ActivationTime: "2014-07-29T15:00:00Z",
+ },
+ Strategy: "*lowest_cost",
+ StrategyParams: nil,
+ SupplierID: "supplier1",
+ RatingPlanIDs: []string{"RPL_1"},
+ StatIDs: nil,
+ Weight: 20,
+ },
+ }
+ resKey := utils.TenantID{Tenant: "cgrates.org", ID: "LCR_1"}
+ if len(csvr.lcrProfiles) != len(eLCRprofiles) {
+ t.Errorf("Failed to load LCRProfiles: %s", utils.ToIJSON(csvr.lcrProfiles))
+ } else if !reflect.DeepEqual(eLCRprofiles[resKey], csvr.lcrProfiles[resKey]) {
+ t.Errorf("Expecting: %+v, received: %+v", eLCRprofiles[resKey], csvr.lcrProfiles[resKey])
+ }
+}
+
func TestLoadResource(t *testing.T) {
eResources := []*utils.TenantID{
&utils.TenantID{
diff --git a/engine/loader_it_test.go b/engine/loader_it_test.go
index ad6c89f55..f66a8bb6b 100755
--- a/engine/loader_it_test.go
+++ b/engine/loader_it_test.go
@@ -108,6 +108,7 @@ func TestLoaderITLoadFromCSV(t *testing.T) {
path.Join(*dataDir, "tariffplans", *tpCsvScenario, utils.StatsCsv),
path.Join(*dataDir, "tariffplans", *tpCsvScenario, utils.ThresholdsCsv),
path.Join(*dataDir, "tariffplans", *tpCsvScenario, utils.FiltersCsv),
+ path.Join(*dataDir, "tariffplans", *tpCsvScenario, utils.LCRCsv),
), "", "")
if err = loader.LoadDestinations(); err != nil {
@@ -164,6 +165,9 @@ func TestLoaderITLoadFromCSV(t *testing.T) {
if err = loader.LoadThresholds(); err != nil {
t.Error("Failed loading thresholds: ", err.Error())
}
+ if err = loader.LoadLCRProfiles(); err != nil {
+ t.Error("Failed loading lcr profiles: ", err.Error())
+ }
if err := loader.WriteToDatabase(true, false, false); err != nil {
t.Error("Could not write data into dataDb: ", err.Error())
}
@@ -353,6 +357,20 @@ func TestLoaderITWriteToDatabase(t *testing.T) {
t.Errorf("Expecting: %v, received: %v", sts, rcv)
}
}
+
+ for tenatid, th := range loader.lcrProfiles {
+ rcv, err := loader.dm.GetLCRProfile(tenatid.Tenant, tenatid.ID, true, utils.NonTransactional)
+ if err != nil {
+ t.Errorf("Failed GetLCRProfile, tenant: %s, id: %s, error: %s ", th.Tenant, th.ID, err.Error())
+ }
+ sts, err := APItoLCRProfile(th, "UTC")
+ if err != nil {
+ t.Error(err)
+ }
+ if !reflect.DeepEqual(sts, rcv) {
+ t.Errorf("Expecting: %v, received: %v", sts, rcv)
+ }
+ }
}
// Imports data from csv files in tpScenario to storDb
diff --git a/engine/model_helpers.go b/engine/model_helpers.go
index decc8b6bc..8a621ad91 100755
--- a/engine/model_helpers.go
+++ b/engine/model_helpers.go
@@ -2419,9 +2419,9 @@ func FilterToTPFilter(f *Filter) (tpFltr *utils.TPFilter) {
return
}
-type TpLCRProfiles []*TpLCRProfile
+type TpLCRs []*TpLCR
-func (tps TpLCRProfiles) AsTPLCRProfile() (result []*utils.TPLCRProfile) {
+func (tps TpLCRs) AsTPLCRProfile() (result []*utils.TPLCRProfile) {
mst := make(map[string]*utils.TPLCRProfile)
for _, tp := range tps {
th, found := mst[tp.ID]
@@ -2440,8 +2440,8 @@ func (tps TpLCRProfiles) AsTPLCRProfile() (result []*utils.TPLCRProfile) {
th.StrategyParams = append(th.StrategyParams, strategyParam)
}
}
- if tp.RatingPlanIDs != "" {
- ratingPlansIDsSplit := strings.Split(tp.RatingPlanIDs, utils.INFIELD_SEP)
+ if tp.RatingplanIDs != "" {
+ ratingPlansIDsSplit := strings.Split(tp.RatingplanIDs, utils.INFIELD_SEP)
for _, ratingPlanID := range ratingPlansIDsSplit {
th.RatingPlanIDs = append(th.RatingPlanIDs, ratingPlanID)
}
@@ -2483,10 +2483,10 @@ func (tps TpLCRProfiles) AsTPLCRProfile() (result []*utils.TPLCRProfile) {
return
}
-func APItoModelTPLCRProfile(st *utils.TPLCRProfile) (mdls TpLCRProfiles) {
+func APItoModelTPLCRProfile(st *utils.TPLCRProfile) (mdls TpLCRs) {
if st != nil {
for i, fltr := range st.FilterIDs {
- mdl := &TpLCRProfile{
+ mdl := &TpLCR{
Tenant: st.Tenant,
Tpid: st.TPid,
ID: st.ID,
@@ -2503,9 +2503,9 @@ func APItoModelTPLCRProfile(st *utils.TPLCRProfile) (mdls TpLCRProfiles) {
}
for i, val := range st.RatingPlanIDs {
if i != 0 {
- mdl.RatingPlanIDs += utils.INFIELD_SEP
+ mdl.RatingplanIDs += utils.INFIELD_SEP
}
- mdl.RatingPlanIDs += val
+ mdl.RatingplanIDs += val
}
for i, val := range st.StatIDs {
if i != 0 {
diff --git a/engine/models.go b/engine/models.go
index 8af59b9aa..2a035f367 100755
--- a/engine/models.go
+++ b/engine/models.go
@@ -525,7 +525,7 @@ type TpFilter struct {
CreatedAt time.Time
}
-type TpLCRProfile struct {
+type TpLCR struct {
PK uint `gorm:"primary_key"`
Tpid string
Tenant string `index:"0" re:""`
@@ -535,7 +535,7 @@ type TpLCRProfile struct {
Strategy string `index:"4" re:""`
StrategyParams string `index:"5" re:""`
SupplierID string `index:"6" re:""`
- RatingPlanIDs string `index:"7" re:""`
+ RatingplanIDs string `index:"7" re:""`
StatIDs string `index:"8" re:""`
Weight float64 `index:"9" re:"\d+\.?\d*"`
CreatedAt time.Time
diff --git a/engine/storage_csv.go b/engine/storage_csv.go
index d6e3fc9da..7dad38c77 100755
--- a/engine/storage_csv.go
+++ b/engine/storage_csv.go
@@ -33,26 +33,26 @@ type CSVStorage struct {
readerFunc func(string, rune, int) (*csv.Reader, *os.File, error)
// file names
destinationsFn, ratesFn, destinationratesFn, timingsFn, destinationratetimingsFn, ratingprofilesFn,
- sharedgroupsFn, lcrFn, actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn string
+ sharedgroupsFn, lcrFn, actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn, lcrProfilesFn string
}
func NewFileCSVStorage(sep rune,
destinationsFn, timingsFn, ratesFn, destinationratesFn, destinationratetimingsFn, ratingprofilesFn, sharedgroupsFn, lcrFn,
- actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn string) *CSVStorage {
+ actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn, lcrProfilesFn string) *CSVStorage {
c := new(CSVStorage)
c.sep = sep
c.readerFunc = openFileCSVStorage
c.destinationsFn, c.timingsFn, c.ratesFn, c.destinationratesFn, c.destinationratetimingsFn, c.ratingprofilesFn,
- c.sharedgroupsFn, c.lcrFn, c.actionsFn, c.actiontimingsFn, c.actiontriggersFn, c.accountactionsFn, c.derivedChargersFn, c.cdrStatsFn, c.usersFn, c.aliasesFn, c.resProfilesFn, c.statsFn, c.thresholdsFn, c.filterFn = destinationsFn, timingsFn,
- ratesFn, destinationratesFn, destinationratetimingsFn, ratingprofilesFn, sharedgroupsFn, lcrFn, actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn
+ c.sharedgroupsFn, c.lcrFn, c.actionsFn, c.actiontimingsFn, c.actiontriggersFn, c.accountactionsFn, c.derivedChargersFn, c.cdrStatsFn, c.usersFn, c.aliasesFn, c.resProfilesFn, c.statsFn, c.thresholdsFn, c.filterFn, c.lcrProfilesFn = destinationsFn, timingsFn,
+ ratesFn, destinationratesFn, destinationratetimingsFn, ratingprofilesFn, sharedgroupsFn, lcrFn, actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn, lcrProfilesFn
return c
}
func NewStringCSVStorage(sep rune,
destinationsFn, timingsFn, ratesFn, destinationratesFn, destinationratetimingsFn, ratingprofilesFn, sharedgroupsFn, lcrFn,
- actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn string) *CSVStorage {
+ actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn, lcrProfilesFn string) *CSVStorage {
c := NewFileCSVStorage(sep, destinationsFn, timingsFn, ratesFn, destinationratesFn, destinationratetimingsFn,
- ratingprofilesFn, sharedgroupsFn, lcrFn, actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn)
+ ratingprofilesFn, sharedgroupsFn, lcrFn, actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn, resProfilesFn, statsFn, thresholdsFn, filterFn, lcrProfilesFn)
c.readerFunc = openStringCSVStorage
return c
}
@@ -705,6 +705,34 @@ func (csvs *CSVStorage) GetTPFilters(tpid, id string) ([]*utils.TPFilter, error)
return tpFilter.AsTPFilter(), nil
}
+func (csvs *CSVStorage) GetTPLCRProfiles(tpid, id string) ([]*utils.TPLCRProfile, error) {
+ csvReader, fp, err := csvs.readerFunc(csvs.lcrProfilesFn, csvs.sep, getColumnCount(TpLCR{}))
+ if err != nil {
+ //log.Print("Could not load lcr profiles file: ", err)
+ // allow writing of the other values
+ return nil, nil
+ }
+ if fp != nil {
+ defer fp.Close()
+ }
+ var tpResLimits TpLCRs
+ for record, err := csvReader.Read(); err != io.EOF; record, err = csvReader.Read() {
+ if err != nil {
+ log.Printf("bad line in %s, %s\n", csvs.lcrProfilesFn, err.Error())
+ return nil, err
+ }
+ if tpResLimit, err := csvLoad(TpLCR{}, record); err != nil {
+ log.Print("error loading LCRProfiles: ", err)
+ return nil, err
+ } else {
+ tpLimit := tpResLimit.(TpLCR)
+ tpLimit.Tpid = tpid
+ tpResLimits = append(tpResLimits, &tpLimit)
+ }
+ }
+ return tpResLimits.AsTPLCRProfile(), nil
+}
+
func (csvs *CSVStorage) GetTpIds(colName string) ([]string, error) {
return nil, utils.ErrNotImplemented
}
diff --git a/engine/storage_mongo_stordb.go b/engine/storage_mongo_stordb.go
index 7dce8dec6..04cfb013f 100755
--- a/engine/storage_mongo_stordb.go
+++ b/engine/storage_mongo_stordb.go
@@ -1253,7 +1253,7 @@ func (ms *MongoStorage) GetTPLCRProfiles(tpid, id string) ([]*utils.TPLCRProfile
filter["id"] = id
}
var results []*utils.TPLCRProfile
- session, col := ms.conn(utils.TBLTPLCRProfiles)
+ session, col := ms.conn(utils.TBLTPLcr)
defer session.Close()
err := col.Find(filter).All(&results)
if len(results) == 0 {
@@ -1266,7 +1266,7 @@ func (ms *MongoStorage) SetTPLCRProfiles(tpTHs []*utils.TPLCRProfile) (err error
if len(tpTHs) == 0 {
return
}
- session, col := ms.conn(utils.TBLTPLCRProfiles)
+ session, col := ms.conn(utils.TBLTPLcr)
defer session.Close()
tx := col.Bulk()
for _, tp := range tpTHs {
diff --git a/engine/storage_sql.go b/engine/storage_sql.go
index b1b1a5eab..a765e20b8 100755
--- a/engine/storage_sql.go
+++ b/engine/storage_sql.go
@@ -107,7 +107,8 @@ func (self *SQLStorage) IsDBEmpty() (resp bool, err error) {
utils.TBLTPSharedGroups, utils.TBLTPCdrStats, utils.TBLTPLcrs, utils.TBLTPActions,
utils.TBLTPActionTriggers, utils.TBLTPAccountActions, utils.TBLTPDerivedChargers, utils.TBLTPUsers,
utils.TBLTPAliases, utils.TBLTPResources, utils.TBLTPStats, utils.TBLTPThresholds,
- utils.TBLTPFilters, utils.TBLSMCosts, utils.TBLCDRs, utils.TBLTPActionPlans, utils.TBLVersions,
+ utils.TBLTPFilters, utils.TBLSMCosts, utils.TBLCDRs, utils.TBLTPActionPlans,
+ utils.TBLVersions, utils.TBLTPLcr,
}
for _, tbl := range tbls {
if self.db.HasTable(tbl) {
@@ -126,7 +127,7 @@ func (self *SQLStorage) GetTpIds(colName string) ([]string, error) {
qryStr := fmt.Sprintf(" (SELECT tpid FROM %s)", colName)
if colName == "" {
qryStr = fmt.Sprintf(
- "(SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s)",
+ "(SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s) UNION (SELECT tpid FROM %s)",
utils.TBLTPTimings,
utils.TBLTPDestinations,
utils.TBLTPRates,
@@ -146,7 +147,8 @@ func (self *SQLStorage) GetTpIds(colName string) ([]string, error) {
utils.TBLTPStats,
utils.TBLTPThresholds,
utils.TBLTPFilters,
- utils.TBLTPActionPlans)
+ utils.TBLTPActionPlans,
+ utils.TBLTPLcr)
}
rows, err = self.Db.Query(qryStr)
if err != nil {
@@ -234,7 +236,7 @@ func (self *SQLStorage) RemTpData(table, tpid string, args map[string]string) er
if len(table) == 0 { // Remove tpid out of all tables
for _, tblName := range []string{utils.TBLTPTimings, utils.TBLTPDestinations, utils.TBLTPRates, utils.TBLTPDestinationRates, utils.TBLTPRatingPlans, utils.TBLTPRateProfiles,
utils.TBLTPSharedGroups, utils.TBLTPCdrStats, utils.TBLTPLcrs, utils.TBLTPActions, utils.TBLTPActionPlans, utils.TBLTPActionTriggers, utils.TBLTPAccountActions,
- utils.TBLTPDerivedChargers, utils.TBLTPAliases, utils.TBLTPUsers, utils.TBLTPResources, utils.TBLTPStats, utils.TBLTPFilters} {
+ utils.TBLTPDerivedChargers, utils.TBLTPAliases, utils.TBLTPUsers, utils.TBLTPResources, utils.TBLTPStats, utils.TBLTPFilters, utils.TBLTPLcr} {
if err := tx.Table(tblName).Where("tpid = ?", tpid).Delete(nil).Error; err != nil {
tx.Rollback()
return err
@@ -689,18 +691,18 @@ func (self *SQLStorage) SetTPFilters(ths []*utils.TPFilter) error {
return nil
}
-func (self *SQLStorage) SetTPLCRProfile(ths []*utils.TPLCRProfile) error {
- if len(ths) == 0 {
+func (self *SQLStorage) SetTPLCRProfiles(sts []*utils.TPLCRProfile) error {
+ if len(sts) == 0 {
return nil
}
tx := self.db.Begin()
- for _, th := range ths {
+ for _, stq := range sts {
// Remove previous
- if err := tx.Where(&TpLCRProfile{Tpid: th.TPid, ID: th.ID}).Delete(TpLCRProfile{}).Error; err != nil {
+ if err := tx.Where(&TpLCR{Tpid: stq.TPid, ID: stq.ID}).Delete(TpLCR{}).Error; err != nil {
tx.Rollback()
return err
}
- for _, mst := range APItoModelTPLCRProfile(th) {
+ for _, mst := range APItoModelTPLCRProfile(stq) {
if err := tx.Save(&mst).Error; err != nil {
tx.Rollback()
return err
@@ -1689,6 +1691,22 @@ func (self *SQLStorage) GetTPFilters(tpid, id string) ([]*utils.TPFilter, error)
return aths, nil
}
+func (self *SQLStorage) GetTPLCRProfiles(tpid, id string) ([]*utils.TPLCRProfile, error) {
+ var rls TpLCRs
+ q := self.db.Where("tpid = ?", tpid)
+ if len(id) != 0 {
+ q = q.Where("id = ?", id)
+ }
+ if err := q.Find(&rls).Error; err != nil {
+ return nil, err
+ }
+ arls := rls.AsTPLCRProfile()
+ if len(arls) == 0 {
+ return arls, utils.ErrNotFound
+ }
+ return arls, nil
+}
+
// GetVersions returns slice of all versions or a specific version if tag is specified
func (self *SQLStorage) GetVersions(itm string) (vrs Versions, err error) {
q := self.db.Model(&TBLVersion{})
diff --git a/engine/storage_test.go b/engine/storage_test.go
index 000accc23..9f455e4c6 100644
--- a/engine/storage_test.go
+++ b/engine/storage_test.go
@@ -102,7 +102,7 @@ func TestStorageCacheRefresh(t *testing.T) {
dm.DataDB().GetDestination("T11", false, utils.NonTransactional)
dm.DataDB().SetDestination(&Destination{"T11", []string{"1"}}, utils.NonTransactional)
t.Log("Test cache refresh")
- err := dm.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ err := dm.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
if err != nil {
t.Error("Error cache rating: ", err)
}
diff --git a/engine/tp_reader.go b/engine/tp_reader.go
index 90acbcff6..72fa71a1b 100755
--- a/engine/tp_reader.go
+++ b/engine/tp_reader.go
@@ -1782,7 +1782,7 @@ func (tpr *TpReader) LoadLCRProfilesFiltered(tag string) (err error) {
} else if !has {
tpr.lcrTntID = append(tpr.lcrTntID, &utils.TenantID{Tenant: tntID.Tenant, ID: tntID.ID})
}
- // index resource for filters
+ // index lcr profile for filters
if _, has := tpr.lcrIndexers[tntID.Tenant]; !has {
if tpr.lcrIndexers[tntID.Tenant], err = NewReqFilterIndexer(tpr.dm, resIndxrKey); err != nil {
return
@@ -2212,7 +2212,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
}
if verbose {
- log.Print("LCRProfiles:")
+ log.Print("LCR Profiles:")
}
for _, tpTH := range tpr.lcrProfiles {
th, err := APItoLCRProfile(tpTH, tpr.timezone)
@@ -2300,7 +2300,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose, disable_reverse bool) (err
}
if verbose {
- log.Print("Indexing LCRProfiles")
+ log.Print("Indexing LCR Profiles")
}
for tenant, fltrIdxer := range tpr.lcrIndexers {
if err := fltrIdxer.StoreIndexes(); err != nil {
diff --git a/engine/tpimporter_csv.go b/engine/tpimporter_csv.go
index 01332eb22..733ccd30e 100755
--- a/engine/tpimporter_csv.go
+++ b/engine/tpimporter_csv.go
@@ -61,6 +61,7 @@ var fileHandlers = map[string]func(*TPCSVImporter, string) error{
utils.StatsCsv: (*TPCSVImporter).importStats,
utils.ThresholdsCsv: (*TPCSVImporter).importThresholds,
utils.FiltersCsv: (*TPCSVImporter).importFilters,
+ utils.LCRCsv: (*TPCSVImporter).importLCR,
}
func (self *TPCSVImporter) Run() error {
@@ -85,6 +86,7 @@ func (self *TPCSVImporter) Run() error {
path.Join(self.DirPath, utils.StatsCsv),
path.Join(self.DirPath, utils.ThresholdsCsv),
path.Join(self.DirPath, utils.FiltersCsv),
+ path.Join(self.DirPath, utils.LCRCsv),
)
files, _ := ioutil.ReadDir(self.DirPath)
for _, f := range files {
@@ -397,3 +399,14 @@ func (self *TPCSVImporter) importFilters(fn string) error {
}
return self.StorDb.SetTPFilters(sts)
}
+
+func (self *TPCSVImporter) importLCR(fn string) error {
+ if self.Verbose {
+ log.Printf("Processing file: <%s> ", fn)
+ }
+ rls, err := self.csvr.GetTPLCRProfiles(self.TPid, "")
+ if err != nil {
+ return err
+ }
+ return self.StorDb.SetTPLCRProfiles(rls)
+}
diff --git a/general_tests/acntacts_test.go b/general_tests/acntacts_test.go
index ea8cafa04..6b45644d5 100644
--- a/general_tests/acntacts_test.go
+++ b/general_tests/acntacts_test.go
@@ -57,15 +57,16 @@ ENABLE_ACNT,*enable_account,,,,,,,,,,,,,,false,false,10`
stats := ``
thresholds := ``
filters := ``
+ lcrprofiles := ``
csvr := engine.NewTpReader(dbAcntActs.DataDB(), engine.NewStringCSVStorage(',', destinations, timings, rates, destinationRates, ratingPlans, ratingProfiles,
- sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters), "", "")
+ sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters, lcrprofiles), "", "")
if err := csvr.LoadAll(); err != nil {
t.Fatal(err)
}
csvr.WriteToDatabase(false, false, false)
cache.Flush()
- dbAcntActs.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dbAcntActs.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
expectAcnt := &engine.Account{ID: "cgrates.org:1"}
if acnt, err := dbAcntActs.DataDB().GetAccount("cgrates.org:1"); err != nil {
diff --git a/general_tests/auth_test.go b/general_tests/auth_test.go
index 763f0dd20..ee0f14524 100644
--- a/general_tests/auth_test.go
+++ b/general_tests/auth_test.go
@@ -64,8 +64,9 @@ RP_ANY,DR_ANY_1CNT,*any,10`
stats := ``
thresholds := ``
filters := ``
+ lcrprofiles := ``
csvr := engine.NewTpReader(dbAuth.DataDB(), engine.NewStringCSVStorage(',', destinations, timings, rates, destinationRates, ratingPlans, ratingProfiles,
- sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters), "", "")
+ sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters, lcrprofiles), "", "")
if err := csvr.LoadAll(); err != nil {
t.Fatal(err)
}
@@ -77,7 +78,7 @@ RP_ANY,DR_ANY_1CNT,*any,10`
}
cache.Flush()
- dbAuth.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dbAuth.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
if cachedDests := cache.CountEntries(utils.DESTINATION_PREFIX); cachedDests != 0 {
t.Error("Wrong number of cached destinations found", cachedDests)
diff --git a/general_tests/costs1_test.go b/general_tests/costs1_test.go
index 3990197d3..9c2926401 100644
--- a/general_tests/costs1_test.go
+++ b/general_tests/costs1_test.go
@@ -52,7 +52,7 @@ RP_SMS1,DR_SMS_1,ALWAYS,10`
*out,cgrates.org,data,*any,2012-01-01T00:00:00Z,RP_DATA1,,
*out,cgrates.org,sms,*any,2012-01-01T00:00:00Z,RP_SMS1,,`
csvr := engine.NewTpReader(dataDB.DataDB(), engine.NewStringCSVStorage(',', dests, timings, rates, destinationRates, ratingPlans, ratingProfiles,
- "", "", "", "", "", "", "", "", "", "", "", "", "", ""), "", "")
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""), "", "")
if err := csvr.LoadTimings(); err != nil {
t.Fatal(err)
@@ -74,7 +74,7 @@ RP_SMS1,DR_SMS_1,ALWAYS,10`
}
csvr.WriteToDatabase(false, false, false)
cache.Flush()
- dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
if cachedRPlans := cache.CountEntries(utils.RATING_PLAN_PREFIX); cachedRPlans != 3 {
t.Error("Wrong number of cached rating plans found", cachedRPlans)
diff --git a/general_tests/datachrg1_test.go b/general_tests/datachrg1_test.go
index 5f818c7a2..e42489457 100644
--- a/general_tests/datachrg1_test.go
+++ b/general_tests/datachrg1_test.go
@@ -43,7 +43,7 @@ DR_DATA_2,*any,RT_DATA_1c,*up,4,0,`
RP_DATA1,DR_DATA_2,TM2,10`
ratingProfiles := `*out,cgrates.org,data,*any,2012-01-01T00:00:00Z,RP_DATA1,,`
csvr := engine.NewTpReader(dataDB.DataDB(), engine.NewStringCSVStorage(',', "", timings, rates, destinationRates, ratingPlans, ratingProfiles,
- "", "", "", "", "", "", "", "", "", "", "", "", "", ""), "", "")
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""), "", "")
if err := csvr.LoadTimings(); err != nil {
t.Fatal(err)
}
@@ -61,7 +61,7 @@ RP_DATA1,DR_DATA_2,TM2,10`
}
csvr.WriteToDatabase(false, false, false)
cache.Flush()
- dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
if cachedRPlans := cache.CountEntries(utils.RATING_PLAN_PREFIX); cachedRPlans != 1 {
t.Error("Wrong number of cached rating plans found", cachedRPlans)
diff --git a/general_tests/ddazmbl1_test.go b/general_tests/ddazmbl1_test.go
index 01935f450..fae9da700 100644
--- a/general_tests/ddazmbl1_test.go
+++ b/general_tests/ddazmbl1_test.go
@@ -64,8 +64,9 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10`
stats := ``
thresholds := ``
filters := ``
+ lcrprofiles := ``
csvr := engine.NewTpReader(dataDB.DataDB(), engine.NewStringCSVStorage(',', destinations, timings, rates, destinationRates, ratingPlans, ratingProfiles,
- sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters), "", "")
+ sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters, lcrprofiles), "", "")
if err := csvr.LoadDestinations(); err != nil {
t.Fatal(err)
}
@@ -112,7 +113,7 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10`
t.Error("No account saved")
}
cache.Flush()
- dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
if cachedDests := cache.CountEntries(utils.DESTINATION_PREFIX); cachedDests != 0 {
t.Error("Wrong number of cached destinations found", cachedDests)
diff --git a/general_tests/ddazmbl2_test.go b/general_tests/ddazmbl2_test.go
index 910e6325f..654843f8e 100644
--- a/general_tests/ddazmbl2_test.go
+++ b/general_tests/ddazmbl2_test.go
@@ -64,8 +64,9 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10`
stats := ``
thresholds := ``
filters := ``
+ lcrprofiles := ``
csvr := engine.NewTpReader(dataDB2.DataDB(), engine.NewStringCSVStorage(',', destinations, timings, rates, destinationRates, ratingPlans, ratingProfiles,
- sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters), "", "")
+ sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters, lcrprofiles), "", "")
if err := csvr.LoadDestinations(); err != nil {
t.Fatal(err)
}
@@ -112,7 +113,7 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10`
t.Error("No account saved")
}
cache.Flush()
- dataDB2.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dataDB2.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
if cachedDests := cache.CountEntries(utils.DESTINATION_PREFIX); cachedDests != 0 {
t.Error("Wrong number of cached destinations found", cachedDests)
diff --git a/general_tests/ddazmbl3_test.go b/general_tests/ddazmbl3_test.go
index 4230688cf..4d938f800 100644
--- a/general_tests/ddazmbl3_test.go
+++ b/general_tests/ddazmbl3_test.go
@@ -62,8 +62,9 @@ RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10`
stats := ``
thresholds := ``
filters := ``
+ lcrprofiles := ``
csvr := engine.NewTpReader(dataDB3.DataDB(), engine.NewStringCSVStorage(',', destinations, timings, rates, destinationRates, ratingPlans, ratingProfiles,
- sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters), "", "")
+ sharedGroups, lcrs, actions, actionPlans, actionTriggers, accountActions, derivedCharges, cdrStats, users, aliases, resLimits, stats, thresholds, filters, lcrprofiles), "", "")
if err := csvr.LoadDestinations(); err != nil {
t.Fatal(err)
}
@@ -110,7 +111,7 @@ RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10`
t.Error("No account saved")
}
cache.Flush()
- dataDB3.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dataDB3.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
if cachedDests := cache.CountEntries(utils.DESTINATION_PREFIX); cachedDests != 0 {
t.Error("Wrong number of cached destinations found", cachedDests)
diff --git a/general_tests/smschrg1_test.go b/general_tests/smschrg1_test.go
index 0c0eca418..8fa89a76f 100644
--- a/general_tests/smschrg1_test.go
+++ b/general_tests/smschrg1_test.go
@@ -41,7 +41,7 @@ func TestSMSLoadCsvTpSmsChrg1(t *testing.T) {
ratingPlans := `RP_SMS1,DR_SMS_1,ALWAYS,10`
ratingProfiles := `*out,cgrates.org,sms,*any,2012-01-01T00:00:00Z,RP_SMS1,,`
csvr := engine.NewTpReader(dataDB.DataDB(), engine.NewStringCSVStorage(',', "", timings, rates, destinationRates, ratingPlans, ratingProfiles,
- "", "", "", "", "", "", "", "", "", "", "", "", "", ""), "", "")
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""), "", "")
if err := csvr.LoadTimings(); err != nil {
t.Fatal(err)
}
@@ -59,7 +59,7 @@ func TestSMSLoadCsvTpSmsChrg1(t *testing.T) {
}
csvr.WriteToDatabase(false, false, false)
cache.Flush()
- dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
+ dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
if cachedRPlans := cache.CountEntries(utils.RATING_PLAN_PREFIX); cachedRPlans != 1 {
t.Error("Wrong number of cached rating plans found", cachedRPlans)
diff --git a/general_tests/tut_smgeneric_it_test.go b/general_tests/tut_smgeneric_it_test.go
index a69f9be62..2406bd84d 100644
--- a/general_tests/tut_smgeneric_it_test.go
+++ b/general_tests/tut_smgeneric_it_test.go
@@ -101,7 +101,7 @@ func TestTutSMGCacheStats(t *testing.T) {
expectedStats := &utils.CacheStats{Destinations: 5, ReverseDestinations: 7, RatingPlans: 4, RatingProfiles: 9,
Actions: 9, ActionPlans: 4, AccountActionPlans: 5, SharedGroups: 1, DerivedChargers: 1, LcrProfiles: 5,
CdrStats: 6, Users: 3, Aliases: 1, ReverseAliases: 2, ResourceProfiles: 3, Resources: 3, StatQueues: 1,
- StatQueueProfiles: 1, Thresholds: 7, ThresholdProfiles: 7, Filters: 15}
+ StatQueueProfiles: 1, Thresholds: 7, ThresholdProfiles: 7, Filters: 16}
var args utils.AttrCacheStats
if err := tutSMGRpc.Call("ApierV2.GetCacheStats", args, &rcvStats); err != nil {
t.Error("Got error on ApierV2.GetCacheStats: ", err.Error())
diff --git a/general_tests/tutorial_it_test.go b/general_tests/tutorial_it_test.go
index e60872b31..f11238ae7 100644
--- a/general_tests/tutorial_it_test.go
+++ b/general_tests/tutorial_it_test.go
@@ -105,7 +105,7 @@ func TestTutITCacheStats(t *testing.T) {
expectedStats := &utils.CacheStats{Destinations: 5, ReverseDestinations: 7, RatingPlans: 4, RatingProfiles: 9,
Actions: 9, ActionPlans: 4, AccountActionPlans: 5, SharedGroups: 1, DerivedChargers: 1, LcrProfiles: 5,
CdrStats: 6, Users: 3, Aliases: 1, ReverseAliases: 2, ResourceProfiles: 3, Resources: 3, StatQueues: 1,
- StatQueueProfiles: 1, Thresholds: 7, ThresholdProfiles: 7, Filters: 15}
+ StatQueueProfiles: 1, Thresholds: 7, ThresholdProfiles: 7, Filters: 16}
var args utils.AttrCacheStats
if err := tutLocalRpc.Call("ApierV1.GetCacheStats", args, &rcvStats); err != nil {
t.Error("Got error on ApierV1.GetCacheStats: ", err.Error())
diff --git a/utils/apitpdata.go b/utils/apitpdata.go
index 1760db272..f5dd393a2 100755
--- a/utils/apitpdata.go
+++ b/utils/apitpdata.go
@@ -675,6 +675,7 @@ type ArgsCache struct {
ThresholdIDs *[]string
ThresholdProfileIDs *[]string
FilterIDs *[]string
+ LCRProfileIDs *[]string
}
// Data used to do remote cache reloads via api
@@ -716,6 +717,7 @@ type CacheStats struct {
Thresholds int
ThresholdProfiles int
Filters int
+ LCRProfiles int // LCRProfiles
}
type AttrExpFileCdrs struct {
diff --git a/utils/consts.go b/utils/consts.go
index 337a692ec..9b37b4311 100755
--- a/utils/consts.go
+++ b/utils/consts.go
@@ -113,7 +113,7 @@ const (
TBLTPStats = "tp_stats"
TBLTPThresholds = "tp_thresholds"
TBLTPFilters = "tp_filters"
- TBLTPLCRProfiles = "tp_lcr"
+ TBLTPLcr = "tp_lcrs"
TBLSMCosts = "sm_costs"
TBLCDRs = "cdrs"
TBLVersions = "versions"
@@ -137,6 +137,7 @@ const (
StatsCsv = "Stats.csv"
ThresholdsCsv = "Thresholds.csv"
FiltersCsv = "Filters.csv"
+ LCRCsv = "Lcr.csv"
ROUNDING_UP = "*up"
ROUNDING_MIDDLE = "*middle"
ROUNDING_DOWN = "*down"