diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go
index 3b804fbf0..7a3d02809 100644
--- a/apier/v1/apier_local_test.go
+++ b/apier/v1/apier_local_test.go
@@ -1467,12 +1467,12 @@ func TestApierLocalSetDC(t *testing.T) {
if !*testLocal {
return
}
- dcs1 := utils.DerivedChargers{
+ dcs1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{
&utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
&utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- }
+ }}
attrs := AttrSetDerivedChargers{Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: dcs1}
var reply string
if err := rater.Call("ApierV1.SetDerivedChargers", attrs, &reply); err != nil {
@@ -1487,12 +1487,12 @@ func TestApierLocalGetDC(t *testing.T) {
return
}
attrs := utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "dan", Subject: "dan"}
- eDcs := utils.DerivedChargers{
+ eDcs := utils.DerivedChargers{Chargers: []*utils.DerivedCharger{
&utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
&utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- }
+ }}
var dcs utils.DerivedChargers
if err := rater.Call("ApierV1.GetDerivedChargers", attrs, &dcs); err != nil {
t.Error("Unexpected error", err.Error())
diff --git a/apier/v1/derivedcharging.go b/apier/v1/derivedcharging.go
index ccaae69a1..2eeefda6b 100644
--- a/apier/v1/derivedcharging.go
+++ b/apier/v1/derivedcharging.go
@@ -33,15 +33,15 @@ func (self *ApierV1) GetDerivedChargers(attrs utils.AttrDerivedChargers, reply *
if hDc, err := engine.HandleGetDerivedChargers(self.RatingDb, &attrs); err != nil {
return utils.NewErrServerError(err)
} else if hDc != nil {
- *reply = hDc
+ *reply = *hDc
}
return nil
}
type AttrSetDerivedChargers struct {
- Direction, Tenant, Category, Account, Subject string
- DerivedChargers utils.DerivedChargers
- Overwrite bool // Do not overwrite if present in redis
+ Direction, Tenant, Category, Account, Subject, DestinationIds string
+ DerivedChargers *utils.DerivedChargers
+ Overwrite bool // Do not overwrite if present in redis
}
func (self *ApierV1) SetDerivedChargers(attrs AttrSetDerivedChargers, reply *string) (err error) {
@@ -60,7 +60,7 @@ func (self *ApierV1) SetDerivedChargers(attrs AttrSetDerivedChargers, reply *str
if len(attrs.Subject) == 0 {
attrs.Subject = utils.ANY
}
- for _, dc := range attrs.DerivedChargers {
+ for _, dc := range attrs.DerivedChargers.Chargers {
if _, err = utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP); err != nil { // Make sure rules are OK before loading in db
return fmt.Errorf("%s:%s", utils.ErrParserError.Error(), err.Error())
}
diff --git a/apier/v1/derivedcharging_test.go b/apier/v1/derivedcharging_test.go
index ccbfb5f41..2a12f14d8 100644
--- a/apier/v1/derivedcharging_test.go
+++ b/apier/v1/derivedcharging_test.go
@@ -48,12 +48,12 @@ func TestGetEmptyDC(t *testing.T) {
*/
func TestSetDC(t *testing.T) {
- dcs1 := utils.DerivedChargers{
+ dcs1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{
&utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
&utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- }
+ }}
attrs := AttrSetDerivedChargers{Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: dcs1}
var reply string
if err := apierDcT.SetDerivedChargers(attrs, &reply); err != nil {
@@ -65,12 +65,12 @@ func TestSetDC(t *testing.T) {
func TestGetDC(t *testing.T) {
attrs := utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "dan", Subject: "dan"}
- eDcs := utils.DerivedChargers{
+ eDcs := utils.DerivedChargers{Chargers: []*utils.DerivedCharger{
&utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
&utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- }
+ }}
var dcs utils.DerivedChargers
if err := apierDcT.GetDerivedChargers(attrs, &dcs); err != nil {
t.Error("Unexpected error", err.Error())
diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql
index 1c4e6c940..14feeb608 100644
--- a/data/storage/mysql/create_tariffplan_tables.sql
+++ b/data/storage/mysql/create_tariffplan_tables.sql
@@ -257,7 +257,7 @@ CREATE TABLE tp_lcr_rules (
`subject` varchar(64) NOT NULL,
`destination_tag` varchar(64) NOT NULL,
`rp_category` varchar(32) NOT NULL,
- `strategy` varchar(16) NOT NULL,
+ `strategy` varchar(18) NOT NULL,
`strategy_params` varchar(256) NOT NULL,
`activation_time` varchar(24) NOT NULL,
`weight` DECIMAL(8,2) NOT NULL,
@@ -280,6 +280,7 @@ CREATE TABLE tp_derived_chargers (
`category` varchar(32) NOT NULL,
`account` varchar(24) NOT NULL,
`subject` varchar(64) NOT NULL,
+ `destination_ids` varchar(64) NOT NULL,
`runid` varchar(24) NOT NULL,
`run_filters` varchar(256) NOT NULL,
`req_type_field` varchar(24) NOT NULL,
diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql
index af915a093..8ecdffc73 100644
--- a/data/storage/postgres/create_tariffplan_tables.sql
+++ b/data/storage/postgres/create_tariffplan_tables.sql
@@ -252,7 +252,7 @@ CREATE TABLE tp_lcr_rules (
subject VARCHAR(64) NOT NULL,
destination_tag VARCHAR(64) NOT NULL,
rp_category VARCHAR(32) NOT NULL,
- strategy VARCHAR(16) NOT NULL,
+ strategy VARCHAR(18) NOT NULL,
strategy_params VARCHAR(256) NOT NULL,
activation_time VARCHAR(24) NOT NULL,
weight NUMERIC(8,2) NOT NULL,
@@ -275,6 +275,7 @@ CREATE TABLE tp_derived_chargers (
category VARCHAR(32) NOT NULL,
account VARCHAR(24) NOT NULL,
subject VARCHAR(64) NOT NULL,
+ destination_ids VARCHAR(64) NOT NULL,
runid VARCHAR(24) NOT NULL,
run_filters VARCHAR(256) NOT NULL,
req_type_field VARCHAR(24) NOT NULL,
diff --git a/data/tariffplans/prepaid1centpsec/DerivedChargers.csv b/data/tariffplans/prepaid1centpsec/DerivedChargers.csv
index 4e59e4ef0..b50586df9 100644
--- a/data/tariffplans/prepaid1centpsec/DerivedChargers.csv
+++ b/data/tariffplans/prepaid1centpsec/DerivedChargers.csv
@@ -1,5 +1,5 @@
-#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],RunId[5],RunFilter[6],ReqTypeField[7],DirectionField[8],TenantField[9],CategoryField[10],AccountField[11],SubjectField[12],DestinationField[13],SetupTimeField[14],PddField[15],AnswerTimeField[16],UsageField[17],SupplierField[18],DisconnectCause[19],RatedField[20],CostField[21]
-*out,cgrates.org,call,dan,dan,extra1,,^prepaid,,,,^rif,^rif,,,,,^1s,*default,*default,*default,*default
-*out,cgrates.org,call,dan,dan,extra2,,,,,,^ivo,^ivo,,,,,,*default,*default,*default,*default
-*out,cgrates.org,call,dan,dan,extra3,~filterhdr1:s/(.+)/special_run3/,,,,,^runusr3,^runusr3,,,,,,*default,*default,*default,*default
-*out,cgrates.org,call,dan,*any,extra1,,,,,,^rif2,^rif2,,,,,,*default,*default,*default,*default
+#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],DestinationIds[5],RunId[6],RunFilter[7],ReqTypeField[8],DirectionField[9],TenantField[10],CategoryField[11],AccountField[12],SubjectField[13],DestinationField[14],SetupTimeField[15],PddField[16],AnswerTimeField[17],UsageField[18],SupplierField[19],DisconnectCause[20],RatedField[21],CostField[22]
+*out,cgrates.org,call,dan,dan,,extra1,,^prepaid,,,,^rif,^rif,,,,,^1s,*default,*default,*default,*default
+*out,cgrates.org,call,dan,dan,,extra2,,,,,,^ivo,^ivo,,,,,,*default,*default,*default,*default
+*out,cgrates.org,call,dan,dan,,extra3,~filterhdr1:s/(.+)/special_run3/,,,,,^runusr3,^runusr3,,,,,,*default,*default,*default,*default
+*out,cgrates.org,call,dan,*any,,extra1,,,,,,^rif2,^rif2,,,,,,*default,*default,*default,*default
diff --git a/data/tariffplans/tutorial/DerivedChargers.csv b/data/tariffplans/tutorial/DerivedChargers.csv
index cd1f4a847..f0b405f7d 100644
--- a/data/tariffplans/tutorial/DerivedChargers.csv
+++ b/data/tariffplans/tutorial/DerivedChargers.csv
@@ -1,2 +1,2 @@
-#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],RunId[5],RunFilter[6],ReqTypeField[7],DirectionField[8],TenantField[9],CategoryField[10],AccountField[11],SubjectField[12],DestinationField[13],SetupTimeField[14],PddField[15],AnswerTimeField[16],UsageField[17],SupplierField[18],DisconnectCause[19],RatedField[20],CostField[21]
-*out,cgrates.org,call,1001,1001,derived_run1,,^*rated,*default,*default,*default,*default,^1002,*default,*default,*default,*default,*default,*default,*default,*default,*default
+#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],DestinationIds[5],RunId[6],RunFilter[7],ReqTypeField[8],DirectionField[9],TenantField[10],CategoryField[11],AccountField[12],SubjectField[13],DestinationField[14],SetupTimeField[15],PddField[16],AnswerTimeField[17],UsageField[18],SupplierField[19],DisconnectCause[20],RatedField[21],CostField[22]
+*out,cgrates.org,call,1001,1001,,derived_run1,,^*rated,*default,*default,*default,*default,^1002,*default,*default,*default,*default,*default,*default,*default,*default,*default
diff --git a/engine/cdrs.go b/engine/cdrs.go
index 642a4bf61..eab196d26 100644
--- a/engine/cdrs.go
+++ b/engine/cdrs.go
@@ -273,7 +273,7 @@ func (self *CdrServer) deriveCdrs(storedCdr *StoredCdr) ([]*StoredCdr, error) {
utils.Logger.Err(fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", storedCdr.CgrId, err.Error()))
return nil, err
}
- for _, dc := range dcs {
+ for _, dc := range dcs.Chargers {
runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
matchingAllFilters := true
for _, dcRunFilter := range runFilters {
diff --git a/engine/handler_derivedcharging.go b/engine/handler_derivedcharging.go
index ecf0a0d69..d5dc087f8 100644
--- a/engine/handler_derivedcharging.go
+++ b/engine/handler_derivedcharging.go
@@ -19,12 +19,13 @@ along with this program. If not, see
package engine
import (
+ "github.com/cgrates/cgrates/cache2go"
"github.com/cgrates/cgrates/utils"
)
// Handles retrieving of DerivedChargers profile based on longest match from AccountingDb
-func HandleGetDerivedChargers(ratingStorage RatingStorage, attrs *utils.AttrDerivedChargers) (utils.DerivedChargers, error) {
- var dcs utils.DerivedChargers
+func HandleGetDerivedChargers(ratingStorage RatingStorage, attrs *utils.AttrDerivedChargers) (*utils.DerivedChargers, error) {
+ dcs := &utils.DerivedChargers{}
strictKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject)
anySubjKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, utils.ANY)
anyAcntKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, utils.ANY, utils.ANY)
@@ -33,10 +34,31 @@ func HandleGetDerivedChargers(ratingStorage RatingStorage, attrs *utils.AttrDeri
for _, dcKey := range []string{strictKey, anySubjKey, anyAcntKey, anyCategKey, anyTenantKey} {
if dcsDb, err := ratingStorage.GetDerivedChargers(dcKey, false); err != nil && err != utils.ErrNotFound {
return nil, err
- } else if dcsDb != nil {
+ } else if dcsDb != nil && DerivedChargersMatchesDest(dcsDb, attrs.Destination) {
dcs = dcsDb
break
}
}
return dcs, nil
}
+
+func DerivedChargersMatchesDest(dcs *utils.DerivedChargers, dest string) bool {
+ if len(dcs.DestinationIds) == 0 || dcs.DestinationIds[utils.ANY] {
+ return true
+ }
+ // check destination ids
+ for _, p := range utils.SplitPrefix(dest, MIN_PREFIX_MATCH) {
+ if x, err := cache2go.Get(utils.DESTINATION_PREFIX + p); err == nil {
+ destIds := x.(map[interface{}]struct{})
+ for value := range dcs.DestinationIds {
+ for idId := range destIds {
+ dId := idId.(string)
+ if value == dId {
+ return true
+ }
+ }
+ }
+ }
+ }
+ return false
+}
diff --git a/engine/handler_derivedcharging_test.go b/engine/handler_derivedcharging_test.go
index 99061f5d3..83a4d2e54 100644
--- a/engine/handler_derivedcharging_test.go
+++ b/engine/handler_derivedcharging_test.go
@@ -18,15 +18,13 @@ along with this program. If not, see
package engine
-/*
import (
- "reflect"
"testing"
- "github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
)
+/*
var cfgDcT *config.CGRConfig
var acntDb AccountingStorage
@@ -94,3 +92,30 @@ func TestHandleGetStoredDC(t *testing.T) {
}
}
*/
+
+func TestHandleDeivedChargersMatchDestRet(t *testing.T) {
+ dcs := &utils.DerivedChargers{
+ DestinationIds: utils.NewStringMap("RET"),
+ }
+ if !DerivedChargersMatchesDest(dcs, "0723045326") {
+ t.Error("Derived charger failed to match dest")
+ }
+}
+
+func TestHandleDeivedChargersMatchDestNat(t *testing.T) {
+ dcs := &utils.DerivedChargers{
+ DestinationIds: utils.NewStringMap("NAT"),
+ }
+ if !DerivedChargersMatchesDest(dcs, "0723045326") {
+ t.Error("Derived charger failed to match dest")
+ }
+}
+
+func TestHandleDeivedChargersMatchDestNatRet(t *testing.T) {
+ dcs := &utils.DerivedChargers{
+ DestinationIds: utils.NewStringMap("NAT", "RET"),
+ }
+ if !DerivedChargersMatchesDest(dcs, "0723045326") {
+ t.Error("Derived charger failed to match dest")
+ }
+}
diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go
index 9154b72e2..9a86b538a 100644
--- a/engine/loader_csv_test.go
+++ b/engine/loader_csv_test.go
@@ -208,10 +208,10 @@ cgrates.org,alodis,TOPUP_EMPTY_AT,,true,true
`
derivedCharges = `
-#Direction,Tenant,Category,Account,Subject,RunId,RunFilter,ReqTypeField,DirectionField,TenantField,TorField,AccountField,SubjectField,DestinationField,SetupTimeField,PddField,AnswerTimeField,UsageField,SupplierField,DisconnectCauseField,CostField,RatedField
-*out,cgrates.org,call,dan,dan,extra1,^filteredHeader1/filterValue1/,^prepaid,,,,rif,rif,,,,,,,,,
-*out,cgrates.org,call,dan,dan,extra2,,,,,,ivo,ivo,,,,,,,,,
-*out,cgrates.org,call,dan,*any,extra1,,,,,,rif2,rif2,,,,,,,,,
+#Direction,Tenant,Category,Account,Subject,DestinationIds,RunId,RunFilter,ReqTypeField,DirectionField,TenantField,TorField,AccountField,SubjectField,DestinationField,SetupTimeField,PddField,AnswerTimeField,UsageField,SupplierField,DisconnectCauseField,CostField,RatedField
+*out,cgrates.org,call,dan,dan,,extra1,^filteredHeader1/filterValue1/,^prepaid,,,,rif,rif,,,,,,,,,
+*out,cgrates.org,call,dan,dan,,extra2,,,,,,ivo,ivo,,,,,,,,,
+*out,cgrates.org,call,dan,*any,,extra1,,,,,,rif2,rif2,,,,,,,,,
`
cdrStats = `
#Id[0],QueueLength[1],TimeWindow[2],SaveInterval[3],Metric[4],SetupInterval[5],TOR[6],CdrHost[7],CdrSource[8],ReqType[9],Direction[10],Tenant[11],Category[12],Account[13],Subject[14],DestinationPrefix[15],PddInterval[16],UsageInterval[17],Supplier[18],DisconnectCause[19],MediationRunIds[20],RatedAccount[21],RatedSubject[22],CostInterval[23],Triggers[24]
@@ -222,7 +222,7 @@ CDRST2,10,10m,,ASR,,,,,,,cgrates.org,call,,,,,,,,,,,,
CDRST2,,,,ACD,,,,,,,,,,,,,,,,,,,,
`
users = `
-#Tenant[0],UserName[1],AttributeName[2],AttributeValue[3]
+#Tenant[0],UserName[1],AttributeName[2],AttributeValue[3],Weight[4]
cgrates.org,rif,false,test0,val0,10
cgrates.org,rif,,test1,val1,10
cgrates.org,dan,,another,value,10
@@ -1095,20 +1095,22 @@ func TestLoadDerivedChargers(t *testing.T) {
if len(csvr.derivedChargers) != 2 {
t.Error("Failed to load derivedChargers: ", csvr.derivedChargers)
}
- expCharger1 := utils.DerivedChargers{
- &utils.DerivedCharger{RunId: "extra1", RunFilters: "^filteredHeader1/filterValue1/", ReqTypeField: "^prepaid", DirectionField: utils.META_DEFAULT,
- TenantField: utils.META_DEFAULT, CategoryField: utils.META_DEFAULT, AccountField: "rif", SubjectField: "rif", DestinationField: utils.META_DEFAULT,
- SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
- SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT},
- &utils.DerivedCharger{RunId: "extra2", ReqTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
- CategoryField: utils.META_DEFAULT, AccountField: "ivo", SubjectField: "ivo", DestinationField: utils.META_DEFAULT,
- SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
- SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT},
- }
+ expCharger1 := &utils.DerivedChargers{
+ DestinationIds: utils.StringMap{},
+ Chargers: []*utils.DerivedCharger{
+ &utils.DerivedCharger{RunId: "extra1", RunFilters: "^filteredHeader1/filterValue1/", ReqTypeField: "^prepaid", DirectionField: utils.META_DEFAULT,
+ TenantField: utils.META_DEFAULT, CategoryField: utils.META_DEFAULT, AccountField: "rif", SubjectField: "rif", DestinationField: utils.META_DEFAULT,
+ SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
+ SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT},
+ &utils.DerivedCharger{RunId: "extra2", ReqTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
+ CategoryField: utils.META_DEFAULT, AccountField: "ivo", SubjectField: "ivo", DestinationField: utils.META_DEFAULT,
+ SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
+ SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT},
+ }}
keyCharger1 := utils.DerivedChargersKey("*out", "cgrates.org", "call", "dan", "dan")
if !csvr.derivedChargers[keyCharger1].Equal(expCharger1) {
- t.Errorf("Expecting: %+v, received: %+v", expCharger1[0], csvr.derivedChargers[keyCharger1][0])
+ t.Errorf("Expecting: %+v, received: %+v", expCharger1.Chargers[0], csvr.derivedChargers[keyCharger1].Chargers[0])
}
}
func TestLoadCdrStats(t *testing.T) {
diff --git a/engine/model_helpers.go b/engine/model_helpers.go
index 9897f69a1..cdcca398b 100644
--- a/engine/model_helpers.go
+++ b/engine/model_helpers.go
@@ -472,7 +472,7 @@ func (tps TpDerivedChargers) GetDerivedChargers() (map[string]*utils.TPDerivedCh
dcs := make(map[string]*utils.TPDerivedChargers)
for _, tpDcMdl := range tps {
tpDc := &utils.TPDerivedChargers{TPid: tpDcMdl.Tpid, Loadid: tpDcMdl.Loadid, Direction: tpDcMdl.Direction, Tenant: tpDcMdl.Tenant, Category: tpDcMdl.Category,
- Account: tpDcMdl.Account, Subject: tpDcMdl.Subject}
+ Account: tpDcMdl.Account, Subject: tpDcMdl.Subject, DestinationIds: tpDcMdl.DestinationIds}
tag := tpDc.GetDerivedChargesId()
if _, hasIt := dcs[tag]; !hasIt {
dcs[tag] = tpDc
diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go
index 3f16319a0..84b74670a 100644
--- a/engine/model_helpers_test.go
+++ b/engine/model_helpers_test.go
@@ -493,9 +493,9 @@ func TestTPDerivedChargersAsExportSlice(t *testing.T) {
},
}
expectedSlc := [][]string{
- []string{"*out", "cgrates.org", "call", "1001", "1001",
+ []string{"*out", "cgrates.org", "call", "1001", "1001", "",
"derived_run1", "", "^rated", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, "^1002", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT},
- []string{"*out", "cgrates.org", "call", "1001", "1001",
+ []string{"*out", "cgrates.org", "call", "1001", "1001", "",
"derived_run2", "", "^rated", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, "^1002", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT},
}
ms := APItoModelDerivedCharger(dcs)
diff --git a/engine/models.go b/engine/models.go
index 99aa63ddb..99d8c505b 100644
--- a/engine/models.go
+++ b/engine/models.go
@@ -255,23 +255,24 @@ type TpDerivedCharger struct {
Category string `index:"2" re:"\w+\s*"`
Account string `index:"3" re:"\w+\s*"`
Subject string `index:"4" re:"\*any\s*|\w+\s*"`
- Runid string `index:"5" re:"\w+\s*"`
- RunFilters string `index:"6" re:"[~^]*[0-9A-Za-z_/:().+]+\s*"`
- ReqTypeField string `index:"7" re:"\*default\s*|[~^*]*[0-9A-Za-z_/:().+]+\s*"`
- DirectionField string `index:"8" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- TenantField string `index:"9" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- CategoryField string `index:"10" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- AccountField string `index:"11" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- SubjectField string `index:"12" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- DestinationField string `index:"13" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- SetupTimeField string `index:"14" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- PddField string `index:"15" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- AnswerTimeField string `index:"16" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- UsageField string `index:"17" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- SupplierField string `index:"18" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- DisconnectCauseField string `index:"19" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- RatedField string `index:"20" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
- CostField string `index:"21" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ DestinationIds string `index:"5" re:""`
+ Runid string `index:"6" re:"\w+\s*"`
+ RunFilters string `index:"7" re:"[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ ReqTypeField string `index:"8" re:"\*default\s*|[~^*]*[0-9A-Za-z_/:().+]+\s*"`
+ DirectionField string `index:"9" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ TenantField string `index:"10" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ CategoryField string `index:"11" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ AccountField string `index:"12" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ SubjectField string `index:"13" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ DestinationField string `index:"14" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ SetupTimeField string `index:"15" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ PddField string `index:"16" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ AnswerTimeField string `index:"17" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ UsageField string `index:"18" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ SupplierField string `index:"19" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ DisconnectCauseField string `index:"20" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ RatedField string `index:"21" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
+ CostField string `index:"22" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
CreatedAt time.Time
}
diff --git a/engine/responder.go b/engine/responder.go
index 0b643e278..531df85da 100644
--- a/engine/responder.go
+++ b/engine/responder.go
@@ -294,12 +294,12 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *StoredCdr, reply *float64) err
maxCallDuration := -1.0
attrsDC := &utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Direction: ev.GetDirection(utils.META_DEFAULT),
Account: ev.GetAccount(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT)}
- var dcs utils.DerivedChargers
- if err := rs.GetDerivedChargers(attrsDC, &dcs); err != nil {
+ dcs := &utils.DerivedChargers{}
+ if err := rs.GetDerivedChargers(attrsDC, dcs); err != nil {
return err
}
dcs, _ = dcs.AppendDefaultRun()
- for _, dc := range dcs {
+ for _, dc := range dcs.Chargers {
if utils.IsSliceMember([]string{utils.META_RATED, utils.RATED}, ev.GetReqType(dc.ReqTypeField)) { // Only consider prepaid and pseudoprepaid for MaxSessionTime
continue
}
@@ -382,8 +382,8 @@ func (rs *Responder) GetSessionRuns(ev *StoredCdr, sRuns *[]*SessionRun) error {
}
attrsDC := &utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Direction: ev.GetDirection(utils.META_DEFAULT),
Account: ev.GetAccount(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT)}
- var dcs utils.DerivedChargers
- if err := rs.GetDerivedChargers(attrsDC, &dcs); err != nil {
+ dcs := &utils.DerivedChargers{}
+ if err := rs.GetDerivedChargers(attrsDC, dcs); err != nil {
rs.getCache().Cache(utils.GET_SESS_RUNS_CACHE_PREFIX+ev.CgrId, &cache2go.CacheItem{
Err: err,
})
@@ -391,7 +391,7 @@ func (rs *Responder) GetSessionRuns(ev *StoredCdr, sRuns *[]*SessionRun) error {
}
dcs, _ = dcs.AppendDefaultRun()
sesRuns := make([]*SessionRun, 0)
- for _, dc := range dcs {
+ for _, dc := range dcs.Chargers {
if !utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, ev.GetReqType(dc.ReqTypeField)) {
continue // We only consider prepaid sessions
}
@@ -426,7 +426,7 @@ func (rs *Responder) GetDerivedChargers(attrs *utils.AttrDerivedChargers, dcs *u
if dcsH, err := HandleGetDerivedChargers(ratingStorage, attrs); err != nil {
return err
} else if dcsH != nil {
- *dcs = dcsH
+ *dcs = *dcsH
}
return nil
}
diff --git a/engine/responder_test.go b/engine/responder_test.go
index 29b1ee2c6..47e8da081 100644
--- a/engine/responder_test.go
+++ b/engine/responder_test.go
@@ -36,8 +36,8 @@ func init() {
// Test internal abilites of GetDerivedChargers
func TestResponderGetDerivedChargers(t *testing.T) {
- cfgedDC := utils.DerivedChargers{&utils.DerivedCharger{RunId: "responder1", ReqTypeField: utils.META_DEFAULT, DirectionField: "test", TenantField: "test",
- CategoryField: "test", AccountField: "test", SubjectField: "test", DestinationField: "test", SetupTimeField: "test", AnswerTimeField: "test", UsageField: "test"}}
+ cfgedDC := &utils.DerivedChargers{DestinationIds: utils.StringMap{}, Chargers: []*utils.DerivedCharger{&utils.DerivedCharger{RunId: "responder1", ReqTypeField: utils.META_DEFAULT, DirectionField: "test", TenantField: "test",
+ CategoryField: "test", AccountField: "test", SubjectField: "test", DestinationField: "test", SetupTimeField: "test", AnswerTimeField: "test", UsageField: "test"}}}
rsponder = &Responder{}
attrs := &utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "responder_test", Subject: "responder_test"}
if err := ratingStorage.SetDerivedChargers(utils.DerivedChargersKey(utils.OUT, utils.ANY, utils.ANY, utils.ANY, utils.ANY), cfgedDC); err != nil {
@@ -46,8 +46,8 @@ func TestResponderGetDerivedChargers(t *testing.T) {
if err := ratingStorage.CacheRatingPrefixes(utils.DERIVEDCHARGERS_PREFIX); err != nil {
t.Error(err)
}
- var dcs utils.DerivedChargers
- if err := rsponder.GetDerivedChargers(attrs, &dcs); err != nil {
+ dcs := &utils.DerivedChargers{}
+ if err := rsponder.GetDerivedChargers(attrs, dcs); err != nil {
t.Error("Unexpected error", err.Error())
} else if !reflect.DeepEqual(dcs, cfgedDC) {
t.Errorf("Expecting: %v, received: %v ", cfgedDC, dcs)
@@ -82,14 +82,14 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) {
t.Error(err)
}
keyCharger1 := utils.ConcatenatedKey("*out", testTenant, "call", "dan", "dan")
- charger1 := utils.DerivedChargers{
+ charger1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{
&utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^" + utils.META_PREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "^dan", SubjectField: "^dan", DestinationField: "^+49151708707", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
&utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "^ivo", SubjectField: "^ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
&utils.DerivedCharger{RunId: "extra3", ReqTypeField: "^" + utils.META_PSEUDOPREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "^rif", SubjectField: "^rif", DestinationField: "^+49151708707", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- }
+ }}
if err := ratingStorage.SetDerivedChargers(keyCharger1, charger1); err != nil {
t.Error("Error on setting DerivedChargers", err.Error())
}
@@ -106,9 +106,9 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) {
} else if danStoredAcnt.BalanceMap[utils.VOICE][0].GetValue() != dansAccount.BalanceMap[utils.VOICE][0].GetValue() {
t.Error("BalanceValue: ", danStoredAcnt.BalanceMap[utils.VOICE][0].GetValue())
}
- var dcs utils.DerivedChargers
+ dcs := &utils.DerivedChargers{}
attrs := &utils.AttrDerivedChargers{Tenant: testTenant, Category: "call", Direction: "*out", Account: "dan", Subject: "dan"}
- if err := rsponder.GetDerivedChargers(attrs, &dcs); err != nil {
+ if err := rsponder.GetDerivedChargers(attrs, dcs); err != nil {
t.Error("Unexpected error", err.Error())
} else if !reflect.DeepEqual(dcs, charger1) {
t.Errorf("Expecting: %+v, received: %+v ", charger1, dcs)
@@ -142,7 +142,7 @@ func TestResponderGetSessionRuns(t *testing.T) {
CategoryField: "^0", AccountField: "^minu", SubjectField: "^rif", DestinationField: "^0256",
SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT,
DisconnectCauseField: utils.META_DEFAULT}
- charger1 := utils.DerivedChargers{extra1DC, extra2DC, extra3DC}
+ charger1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{extra1DC, extra2DC, extra3DC}}
if err := ratingStorage.SetDerivedChargers(keyCharger1, charger1); err != nil {
t.Error("Error on setting DerivedChargers", err.Error())
}
diff --git a/engine/storage_csv.go b/engine/storage_csv.go
index 5d9e65ff6..47da6642b 100644
--- a/engine/storage_csv.go
+++ b/engine/storage_csv.go
@@ -417,11 +417,11 @@ func (csvs *CSVStorage) GetTpDerivedChargers(filter *TpDerivedCharger) ([]TpDeri
log.Print("bad line in derived chargers csv: ", err)
return nil, err
}
- if tpRate, err := csvLoad(TpDerivedCharger{}, record); err != nil {
+ if tp, err := csvLoad(TpDerivedCharger{}, record); err != nil {
log.Print("error loading derived charger: ", err)
return nil, err
} else {
- dc := tpRate.(TpDerivedCharger)
+ dc := tp.(TpDerivedCharger)
if filter != nil {
dc.Tpid = filter.Tpid
dc.Loadid = filter.Loadid
diff --git a/engine/storage_interface.go b/engine/storage_interface.go
index 1490cdcbd..8c51db8ea 100644
--- a/engine/storage_interface.go
+++ b/engine/storage_interface.go
@@ -55,8 +55,8 @@ type RatingStorage interface {
SetCdrStats(*CdrStats) error
GetCdrStats(string) (*CdrStats, error)
GetAllCdrStats() ([]*CdrStats, error)
- GetDerivedChargers(string, bool) (utils.DerivedChargers, error)
- SetDerivedChargers(string, utils.DerivedChargers) error
+ GetDerivedChargers(string, bool) (*utils.DerivedChargers, error)
+ SetDerivedChargers(string, *utils.DerivedChargers) error
GetActions(string, bool) (Actions, error)
SetActions(string, Actions) error
GetSharedGroup(string, bool) (*SharedGroup, error)
diff --git a/engine/storage_map.go b/engine/storage_map.go
index e040d49b1..077ad11c6 100644
--- a/engine/storage_map.go
+++ b/engine/storage_map.go
@@ -722,11 +722,11 @@ func (ms *MapStorage) GetAllActionPlans() (ats map[string]ActionPlans, err error
return
}
-func (ms *MapStorage) GetDerivedChargers(key string, skipCache bool) (dcs utils.DerivedChargers, err error) {
+func (ms *MapStorage) GetDerivedChargers(key string, skipCache bool) (dcs *utils.DerivedChargers, err error) {
key = utils.DERIVEDCHARGERS_PREFIX + key
if !skipCache {
if x, err := cache2go.Get(key); err == nil {
- return x.(utils.DerivedChargers), nil
+ return x.(*utils.DerivedChargers), nil
} else {
return nil, err
}
@@ -740,8 +740,8 @@ func (ms *MapStorage) GetDerivedChargers(key string, skipCache bool) (dcs utils.
return
}
-func (ms *MapStorage) SetDerivedChargers(key string, dcs utils.DerivedChargers) error {
- if len(dcs) == 0 {
+func (ms *MapStorage) SetDerivedChargers(key string, dcs *utils.DerivedChargers) error {
+ if dcs == nil || len(dcs.Chargers) == 0 {
delete(ms.dict, utils.DERIVEDCHARGERS_PREFIX+key)
cache2go.RemKey(utils.DERIVEDCHARGERS_PREFIX + key)
return nil
diff --git a/engine/storage_mongo.go b/engine/storage_mongo.go
index 1fb6164f5..599799bfc 100644
--- a/engine/storage_mongo.go
+++ b/engine/storage_mongo.go
@@ -1107,17 +1107,17 @@ func (ms *MongoStorage) GetAllActionPlans() (ats map[string]ActionPlans, err err
return
}
-func (ms *MongoStorage) GetDerivedChargers(key string, skipCache bool) (dcs utils.DerivedChargers, err error) {
+func (ms *MongoStorage) GetDerivedChargers(key string, skipCache bool) (dcs *utils.DerivedChargers, err error) {
if !skipCache {
if x, err := cache2go.Get(utils.DERIVEDCHARGERS_PREFIX + key); err == nil {
- return x.(utils.DerivedChargers), nil
+ return x.(*utils.DerivedChargers), nil
} else {
return nil, err
}
}
var kv struct {
Key string
- Value utils.DerivedChargers
+ Value *utils.DerivedChargers
}
err = ms.db.C(colDcs).Find(bson.M{"key": key}).One(&kv)
if err == nil {
@@ -1127,8 +1127,8 @@ func (ms *MongoStorage) GetDerivedChargers(key string, skipCache bool) (dcs util
return
}
-func (ms *MongoStorage) SetDerivedChargers(key string, dcs utils.DerivedChargers) (err error) {
- if len(dcs) == 0 {
+func (ms *MongoStorage) SetDerivedChargers(key string, dcs *utils.DerivedChargers) (err error) {
+ if dcs == nil || len(dcs.Chargers) == 0 {
cache2go.RemKey(utils.DERIVEDCHARGERS_PREFIX + key)
err = ms.db.C(colDcs).Remove(bson.M{"key": key})
if err != mgo.ErrNotFound {
@@ -1138,7 +1138,7 @@ func (ms *MongoStorage) SetDerivedChargers(key string, dcs utils.DerivedChargers
}
_, err = ms.db.C(colDcs).Upsert(bson.M{"key": key}, &struct {
Key string
- Value utils.DerivedChargers
+ Value *utils.DerivedChargers
}{Key: key, Value: dcs})
return err
}
diff --git a/engine/storage_redis.go b/engine/storage_redis.go
index 2ced135ad..41531cfd3 100644
--- a/engine/storage_redis.go
+++ b/engine/storage_redis.go
@@ -899,11 +899,11 @@ func (rs *RedisStorage) GetAllActionPlans() (ats map[string]ActionPlans, err err
return
}
-func (rs *RedisStorage) GetDerivedChargers(key string, skipCache bool) (dcs utils.DerivedChargers, err error) {
+func (rs *RedisStorage) GetDerivedChargers(key string, skipCache bool) (dcs *utils.DerivedChargers, err error) {
key = utils.DERIVEDCHARGERS_PREFIX + key
if !skipCache {
if x, err := cache2go.Get(key); err == nil {
- return x.(utils.DerivedChargers), nil
+ return x.(*utils.DerivedChargers), nil
} else {
return nil, err
}
@@ -916,8 +916,8 @@ func (rs *RedisStorage) GetDerivedChargers(key string, skipCache bool) (dcs util
return dcs, err
}
-func (rs *RedisStorage) SetDerivedChargers(key string, dcs utils.DerivedChargers) (err error) {
- if len(dcs) == 0 {
+func (rs *RedisStorage) SetDerivedChargers(key string, dcs *utils.DerivedChargers) (err error) {
+ if dcs == nil || len(dcs.Chargers) == 0 {
_, err = rs.db.Del(utils.DERIVEDCHARGERS_PREFIX + key)
cache2go.RemKey(utils.DERIVEDCHARGERS_PREFIX + key)
return err
diff --git a/engine/storage_redis_local_test.go b/engine/storage_redis_local_test.go
index b3d5e99bc..5a977bf6d 100644
--- a/engine/storage_redis_local_test.go
+++ b/engine/storage_redis_local_test.go
@@ -56,12 +56,12 @@ func TestSetGetDerivedCharges(t *testing.T) {
return
}
keyCharger1 := utils.ConcatenatedKey("*out", "cgrates.org", "call", "dan", "dan")
- charger1 := utils.DerivedChargers{
+ charger1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{
&utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
&utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- }
+ }}
if err := rds.SetDerivedChargers(keyCharger1, charger1); err != nil {
t.Error("Error on setting DerivedChargers", err.Error())
}
diff --git a/engine/tp_reader.go b/engine/tp_reader.go
index 72d62d059..4ca0a5ee7 100644
--- a/engine/tp_reader.go
+++ b/engine/tp_reader.go
@@ -32,7 +32,7 @@ type TpReader struct {
ratingProfiles map[string]*RatingProfile
sharedGroups map[string]*SharedGroup
lcrs map[string]*LCR
- derivedChargers map[string]utils.DerivedChargers
+ derivedChargers map[string]*utils.DerivedChargers
cdrStats map[string]*CdrStats
users map[string]*UserProfile
aliases map[string]*Alias
@@ -62,7 +62,7 @@ func NewTpReader(rs RatingStorage, as AccountingStorage, lr LoadReader, tpid, ti
cdrStats: make(map[string]*CdrStats),
users: make(map[string]*UserProfile),
aliases: make(map[string]*Alias),
- derivedChargers: make(map[string]utils.DerivedChargers),
+ derivedChargers: make(map[string]*utils.DerivedChargers),
}
//add *any and *asap timing tag (in case of no timings file)
tpr.timings[utils.ANY] = &utils.TPTiming{
@@ -893,7 +893,10 @@ func (tpr *TpReader) LoadDerivedChargersFiltered(filter *TpDerivedCharger, save
for _, tpDcs := range storDcs {
tag := tpDcs.GetDerivedChargersKey()
if _, hasIt := tpr.derivedChargers[tag]; !hasIt {
- tpr.derivedChargers[tag] = make(utils.DerivedChargers, 0) // Load object map since we use this method also from LoadDerivedChargers
+ tpr.derivedChargers[tag] = &utils.DerivedChargers{
+ DestinationIds: make(utils.StringMap),
+ Chargers: make([]*utils.DerivedCharger, 0),
+ } // Load object map since we use this method also from LoadDerivedChargers
}
for _, tpDc := range tpDcs.DerivedChargers {
dc, err := utils.NewDerivedCharger(tpDc.RunId, tpDc.RunFilters, tpDc.ReqTypeField, tpDc.DirectionField, tpDc.TenantField, tpDc.CategoryField,
@@ -902,7 +905,8 @@ func (tpr *TpReader) LoadDerivedChargersFiltered(filter *TpDerivedCharger, save
if err != nil {
return err
}
- tpr.derivedChargers[tag] = append(tpr.derivedChargers[tag], dc)
+ tpr.derivedChargers[tag].DestinationIds.Copy(utils.ParseStringMap(tpDcs.DestinationIds))
+ tpr.derivedChargers[tag].Chargers = append(tpr.derivedChargers[tag].Chargers, dc)
}
}
if save {
diff --git a/utils/apitpdata.go b/utils/apitpdata.go
index 565367c1f..08d66b902 100644
--- a/utils/apitpdata.go
+++ b/utils/apitpdata.go
@@ -394,6 +394,7 @@ type TPDerivedChargers struct {
Category string
Account string
Subject string
+ DestinationIds string
DerivedChargers []*TPDerivedCharger
}
@@ -805,7 +806,7 @@ type AttrGetDestination struct {
}
type AttrDerivedChargers struct {
- Direction, Tenant, Category, Account, Subject string
+ Direction, Tenant, Category, Account, Subject, Destination string
}
func NewTAFromAccountKey(accountKey string) (*TenantAccount, error) {
diff --git a/utils/derivedchargers.go b/utils/derivedchargers.go
index e20847b7e..5d9d8def8 100644
--- a/utils/derivedchargers.go
+++ b/utils/derivedchargers.go
@@ -165,40 +165,6 @@ type DerivedCharger struct {
rsrRatedField *RSRField
}
-func DerivedChargersKey(direction, tenant, category, account, subject string) string {
- return ConcatenatedKey(direction, tenant, category, account, subject)
-}
-
-type DerivedChargers []*DerivedCharger
-
-// Precheck that RunId is unique
-func (dcs DerivedChargers) Append(dc *DerivedCharger) (DerivedChargers, error) {
- if dc.RunId == DEFAULT_RUNID {
- return nil, errors.New("Reserved RunId")
- }
- for _, dcLocal := range dcs {
- if dcLocal.RunId == dc.RunId {
- return nil, errors.New("Duplicated RunId")
- }
- }
- return append(dcs, dc), nil
-}
-
-func (dcs DerivedChargers) AppendDefaultRun() (DerivedChargers, error) {
- dcDf, _ := NewDerivedCharger(DEFAULT_RUNID, "", META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT,
- META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT)
- return append(dcs, dcDf), nil
-}
-
-func (dcs DerivedChargers) Equal(other DerivedChargers) bool {
- for i, dc := range dcs {
- if !dc.Equal(other[i]) {
- return false
- }
- }
- return true
-}
-
func (dc *DerivedCharger) Equal(other *DerivedCharger) bool {
return dc.RunId == other.RunId &&
dc.RunFilters == other.RunFilters &&
@@ -218,3 +184,43 @@ func (dc *DerivedCharger) Equal(other *DerivedCharger) bool {
dc.CostField == other.CostField &&
dc.RatedField == other.RatedField
}
+
+func DerivedChargersKey(direction, tenant, category, account, subject string) string {
+ return ConcatenatedKey(direction, tenant, category, account, subject)
+}
+
+type DerivedChargers struct {
+ DestinationIds StringMap
+ Chargers []*DerivedCharger
+}
+
+// Precheck that RunId is unique
+func (dcs *DerivedChargers) Append(dc *DerivedCharger) (*DerivedChargers, error) {
+ if dc.RunId == DEFAULT_RUNID {
+ return nil, errors.New("Reserved RunId")
+ }
+ for _, dcLocal := range dcs.Chargers {
+ if dcLocal.RunId == dc.RunId {
+ return nil, errors.New("Duplicated RunId")
+ }
+ }
+ dcs.Chargers = append(dcs.Chargers, dc)
+ return dcs, nil
+}
+
+func (dcs *DerivedChargers) AppendDefaultRun() (*DerivedChargers, error) {
+ dcDf, _ := NewDerivedCharger(DEFAULT_RUNID, "", META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT,
+ META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT)
+ dcs.Chargers = append(dcs.Chargers, dcDf)
+ return dcs, nil
+}
+
+func (dcs *DerivedChargers) Equal(other *DerivedChargers) bool {
+ dcs.DestinationIds.Equal(other.DestinationIds)
+ for i, dc := range dcs.Chargers {
+ if !dc.Equal(other.Chargers[i]) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/utils/derivedchargers_test.go b/utils/derivedchargers_test.go
index 24f621177..4a2fffe31 100644
--- a/utils/derivedchargers_test.go
+++ b/utils/derivedchargers_test.go
@@ -25,19 +25,20 @@ import (
func TestAppendDerivedChargers(t *testing.T) {
var err error
- dcs := make(DerivedChargers, 0)
+
+ dcs := &DerivedChargers{Chargers: make([]*DerivedCharger, 0)}
if _, err := dcs.Append(&DerivedCharger{RunId: DEFAULT_RUNID}); err == nil {
t.Error("Failed to detect using of the default runid")
}
if dcs, err = dcs.Append(&DerivedCharger{RunId: "FIRST_RUNID"}); err != nil {
t.Error("Failed to add runid")
- } else if len(dcs) != 1 {
- t.Error("Unexpected number of items inside DerivedChargers configuration", len(dcs))
+ } else if len(dcs.Chargers) != 1 {
+ t.Error("Unexpected number of items inside DerivedChargers configuration", len(dcs.Chargers))
}
if dcs, err = dcs.Append(&DerivedCharger{RunId: "SECOND_RUNID"}); err != nil {
t.Error("Failed to add runid")
- } else if len(dcs) != 2 {
- t.Error("Unexpected number of items inside DerivedChargers configuration", len(dcs))
+ } else if len(dcs.Chargers) != 2 {
+ t.Error("Unexpected number of items inside DerivedChargers configuration", len(dcs.Chargers))
}
if _, err := dcs.Append(&DerivedCharger{RunId: "SECOND_RUNID"}); err == nil {
t.Error("Failed to detect duplicate runid")
@@ -135,25 +136,26 @@ func TestDerivedChargersKey(t *testing.T) {
}
func TestAppendDefaultRun(t *testing.T) {
- var dc1 DerivedChargers
+ dc1 := &DerivedChargers{}
dcDf := &DerivedCharger{RunId: DEFAULT_RUNID, RunFilters: "", ReqTypeField: META_DEFAULT, DirectionField: META_DEFAULT,
TenantField: META_DEFAULT, CategoryField: META_DEFAULT, AccountField: META_DEFAULT, SubjectField: META_DEFAULT,
DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PddField: META_DEFAULT, AnswerTimeField: META_DEFAULT, UsageField: META_DEFAULT, SupplierField: META_DEFAULT,
DisconnectCauseField: META_DEFAULT, CostField: META_DEFAULT, RatedField: META_DEFAULT}
- eDc1 := DerivedChargers{dcDf}
+ eDc1 := &DerivedChargers{Chargers: []*DerivedCharger{dcDf}}
if dc1, _ = dc1.AppendDefaultRun(); !reflect.DeepEqual(dc1, eDc1) {
- t.Errorf("Expecting: %+v, received: %+v", eDc1[0], dc1[0])
+ t.Errorf("Expecting: %+v, received: %+v", eDc1.Chargers[0], dc1.Chargers[0])
}
- dc2 := DerivedChargers{
+ dc2 := &DerivedChargers{Chargers: []*DerivedCharger{
&DerivedCharger{RunId: "extra1", RunFilters: "", ReqTypeField: "reqtype2", DirectionField: META_DEFAULT, TenantField: META_DEFAULT, CategoryField: META_DEFAULT,
AccountField: "rif", SubjectField: "rif", DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PddField: META_DEFAULT, AnswerTimeField: META_DEFAULT, UsageField: META_DEFAULT,
DisconnectCauseField: META_DEFAULT},
&DerivedCharger{RunId: "extra2", ReqTypeField: META_DEFAULT, DirectionField: META_DEFAULT, TenantField: META_DEFAULT, CategoryField: META_DEFAULT,
AccountField: "ivo", SubjectField: "ivo", DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PddField: META_DEFAULT, AnswerTimeField: META_DEFAULT,
- UsageField: META_DEFAULT, SupplierField: META_DEFAULT, DisconnectCauseField: META_DEFAULT},
+ UsageField: META_DEFAULT, SupplierField: META_DEFAULT, DisconnectCauseField: META_DEFAULT}},
}
- eDc2 := append(dc2, dcDf)
+ eDc2 := &DerivedChargers{}
+ eDc2.Chargers = append(dc2.Chargers, dcDf)
if dc2, _ = dc2.AppendDefaultRun(); !reflect.DeepEqual(dc2, eDc2) {
- t.Errorf("Expecting: %+v, received: %+v", eDc2, dc2)
+ t.Errorf("Expecting: %+v, received: %+v", eDc2.Chargers, dc2.Chargers)
}
}
diff --git a/utils/map.go b/utils/map.go
index 22a4fde6c..5a71ca506 100644
--- a/utils/map.go
+++ b/utils/map.go
@@ -127,12 +127,18 @@ func (sm StringMap) Slice() []string {
return result
}
+func (sm StringMap) Copy(o StringMap) {
+ for k, v := range o {
+ sm[k] = v
+ }
+}
+
func (sm StringMap) String() string {
return strings.Join(sm.Slice(), INFIELD_SEP)
}
func (sm StringMap) GetOne() string {
- for key := range sm{
+ for key := range sm {
return key
}
return ""