This commit is contained in:
DanB
2015-11-13 19:11:45 +01:00
27 changed files with 224 additions and 153 deletions

View File

@@ -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())

View File

@@ -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())
}

View File

@@ -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())

View File

@@ -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,

View File

@@ -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,

View File

@@ -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
1 #Direction[0] Tenant[1] Category[2] Account[3] Subject[4] RunId[5] DestinationIds[5] RunFilter[6] RunId[6] ReqTypeField[7] RunFilter[7] DirectionField[8] ReqTypeField[8] TenantField[9] DirectionField[9] CategoryField[10] TenantField[10] AccountField[11] CategoryField[11] SubjectField[12] AccountField[12] DestinationField[13] SubjectField[13] SetupTimeField[14] DestinationField[14] PddField[15] SetupTimeField[15] AnswerTimeField[16] PddField[16] UsageField[17] AnswerTimeField[17] SupplierField[18] UsageField[18] DisconnectCause[19] SupplierField[19] RatedField[20] DisconnectCause[20] CostField[21] RatedField[21] CostField[22]
2 *out cgrates.org call dan dan extra1 extra1 ^prepaid ^prepaid ^rif ^rif ^rif ^rif ^1s *default ^1s *default *default *default *default *default *default *default
3 *out cgrates.org call dan dan extra2 extra2 ^ivo ^ivo ^ivo ^ivo *default *default *default *default *default *default *default *default
4 *out cgrates.org call dan dan extra3 ~filterhdr1:s/(.+)/special_run3/ extra3 ~filterhdr1:s/(.+)/special_run3/ ^runusr3 ^runusr3 ^runusr3 ^runusr3 *default *default *default *default *default *default *default *default
5 *out cgrates.org call dan *any extra1 extra1 ^rif2 ^rif2 ^rif2 ^rif2 *default *default *default *default *default *default *default *default

View File

@@ -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
1 #Direction[0] Tenant[1] Category[2] Account[3] Subject[4] RunId[5] DestinationIds[5] RunFilter[6] RunId[6] ReqTypeField[7] RunFilter[7] DirectionField[8] ReqTypeField[8] TenantField[9] DirectionField[9] CategoryField[10] TenantField[10] AccountField[11] CategoryField[11] SubjectField[12] AccountField[12] DestinationField[13] SubjectField[13] SetupTimeField[14] DestinationField[14] PddField[15] SetupTimeField[15] AnswerTimeField[16] PddField[16] UsageField[17] AnswerTimeField[17] SupplierField[18] UsageField[18] DisconnectCause[19] SupplierField[19] RatedField[20] DisconnectCause[20] CostField[21] RatedField[21] CostField[22]
2 *out cgrates.org call 1001 1001 derived_run1 derived_run1 ^*rated *default ^*rated *default *default *default *default *default *default ^1002 *default *default ^1002 *default *default *default *default *default *default *default *default *default *default *default *default *default *default *default *default *default

View File

@@ -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 {

View File

@@ -19,12 +19,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
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
}

View File

@@ -18,15 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
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")
}
}

View File

@@ -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) {

View File

@@ -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

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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())
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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())
}

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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)
}
}

View File

@@ -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 ""