diff --git a/apier/v1/auth.go b/apier/v1/auth.go index b952f3011..28b6b4945 100644 --- a/apier/v1/auth.go +++ b/apier/v1/auth.go @@ -38,9 +38,6 @@ func (self *ApierV1) GetMaxUsage(usageRecord engine.UsageRecord, maxUsage *float if usageRecord.RequestType == "" { usageRecord.RequestType = self.Config.DefaultReqType } - if usageRecord.Direction == "" { - usageRecord.Direction = utils.OUT - } if usageRecord.Tenant == "" { usageRecord.Tenant = self.Config.DefaultTenant } diff --git a/apier/v1/debit.go b/apier/v1/debit.go index a80d7fcdf..82f454e48 100644 --- a/apier/v1/debit.go +++ b/apier/v1/debit.go @@ -59,9 +59,6 @@ func (apier *ApierV1) DebitUsageWithOptions(args AttrDebitUsageWithOptions, repl if usageRecord.RequestType == "" { usageRecord.RequestType = apier.Config.DefaultReqType } - if usageRecord.Direction == "" { - usageRecord.Direction = utils.OUT - } if usageRecord.Tenant == "" { usageRecord.Tenant = apier.Config.DefaultTenant } diff --git a/apier/v1/debit_test.go b/apier/v1/debit_test.go index f5f8ad6dc..772b7b06a 100644 --- a/apier/v1/debit_test.go +++ b/apier/v1/debit_test.go @@ -125,7 +125,6 @@ func TestDebitUsageWithOptions(t *testing.T) { Usage: "1", ToR: utils.MONETARY, Category: "call", - Direction: "*out", SetupTime: time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC).String(), AnswerTime: time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC).String(), } diff --git a/cdrc/csv_test.go b/cdrc/csv_test.go index 83e80f28d..a207ab1dd 100644 --- a/cdrc/csv_test.go +++ b/cdrc/csv_test.go @@ -33,10 +33,6 @@ func TestCsvRecordToCDR(t *testing.T) { cdrcConfig.CdrSourceId = "TEST_CDRC" cdrcConfig.ContentFields = append(cdrcConfig.ContentFields, &config.CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, FieldId: utils.MEDI_RUNID, Value: utils.ParseRSRFieldsMustCompile("^*default", utils.INFIELD_SEP)}) - cdrcConfig.ContentFields = append(cdrcConfig.ContentFields, &config.CfgCdrField{Tag: "SupplierTest", Type: utils.META_COMPOSED, - FieldId: utils.SUPPLIER, Value: []*utils.RSRField{&utils.RSRField{Id: "14"}}}) - cdrcConfig.ContentFields = append(cdrcConfig.ContentFields, &config.CfgCdrField{Tag: "DisconnectCauseTest", Type: utils.META_COMPOSED, - FieldId: utils.DISCONNECT_CAUSE, Value: []*utils.RSRField{&utils.RSRField{Id: "16"}}}) csvProcessor := &CsvRecordsProcessor{dfltCdrcCfg: cdrcConfig, cdrcCfgs: []*config.CdrcConfig{cdrcConfig}} cdrRow := []string{"firstField", "secondField"} _, err := csvProcessor.recordToStoredCdr(cdrRow, cdrcConfig) @@ -50,26 +46,23 @@ func TestCsvRecordToCDR(t *testing.T) { t.Error("Failed to parse CDR in rated cdr", err) } expectedCdr := &engine.CDR{ - CGRID: utils.Sha1(cdrRow[3], time.Date(2013, 2, 3, 19, 50, 0, 0, time.UTC).String()), - RunID: "*default", - ToR: cdrRow[2], - OriginID: cdrRow[3], - OriginHost: "0.0.0.0", // Got it over internal interface - Source: "TEST_CDRC", - RequestType: cdrRow[4], - Direction: cdrRow[5], - Tenant: cdrRow[6], - Category: cdrRow[7], - Account: cdrRow[8], - Subject: cdrRow[9], - Destination: cdrRow[10], - SetupTime: time.Date(2013, 2, 3, 19, 50, 0, 0, time.UTC), - AnswerTime: time.Date(2013, 2, 3, 19, 54, 0, 0, time.UTC), - Usage: time.Duration(62) * time.Second, - Supplier: "supplier1", - DisconnectCause: "NORMAL_DISCONNECT", - ExtraFields: map[string]string{}, - Cost: -1, + CGRID: utils.Sha1(cdrRow[3], time.Date(2013, 2, 3, 19, 50, 0, 0, time.UTC).String()), + RunID: "*default", + ToR: cdrRow[2], + OriginID: cdrRow[3], + OriginHost: "0.0.0.0", // Got it over internal interface + Source: "TEST_CDRC", + RequestType: cdrRow[4], + Tenant: cdrRow[6], + Category: cdrRow[7], + Account: cdrRow[8], + Subject: cdrRow[9], + Destination: cdrRow[10], + SetupTime: time.Date(2013, 2, 3, 19, 50, 0, 0, time.UTC), + AnswerTime: time.Date(2013, 2, 3, 19, 54, 0, 0, time.UTC), + Usage: time.Duration(62) * time.Second, + ExtraFields: map[string]string{}, + Cost: -1, } if !reflect.DeepEqual(expectedCdr, rtCdr) { t.Errorf("Expected: \n%v, \nreceived: \n%v", expectedCdr, rtCdr) diff --git a/cdrc/partial_cdr_test.go b/cdrc/partial_cdr_test.go index a8582a0d4..e6d7b8b01 100644 --- a/cdrc/partial_cdr_test.go +++ b/cdrc/partial_cdr_test.go @@ -39,8 +39,10 @@ func TestPartialCDRRecordSort(t *testing.T) { func TestPartialCDRRecordMergeCDRs(t *testing.T) { cdr1 := &engine.CDR{OrderID: 1, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: "TestPartialCDRRecordMergeCDRs", RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1", + OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: "TestPartialCDRRecordMergeCDRs", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", + Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), Partial: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } @@ -55,9 +57,12 @@ func TestPartialCDRRecordMergeCDRs(t *testing.T) { } pCdr := &PartialCDRRecord{cdrs: []*engine.CDR{cdr1, cdr2, cdr3}} eCDR := &engine.CDR{OrderID: 3, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: "TestPartialCDRRecordMergeCDRs", RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 43, 0, 0, time.UTC), Partial: false, + OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: "TestPartialCDRRecordMergeCDRs", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", + Subject: "1001", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 43, 0, 0, time.UTC), Partial: false, Usage: time.Duration(62 * time.Second), ExtraFields: map[string]string{"field_extr1": "val_extr11", "fieldextr2": "valextr2", "disconnect_direction": "upstream"}, } diff --git a/cdrc/xml_test.go b/cdrc/xml_test.go index 57f1e4f43..414fe7e49 100644 --- a/cdrc/xml_test.go +++ b/cdrc/xml_test.go @@ -221,8 +221,6 @@ func TestXMLRPProcess(t *testing.T) { Value: utils.ParseRSRFieldsMustCompile("broadWorksCDR>cdrData>basicModule>localCallId", utils.INFIELD_SEP), Mandatory: true}, &config.CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("^*rated", utils.INFIELD_SEP), Mandatory: true}, - &config.CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, - Value: utils.ParseRSRFieldsMustCompile("^*out", utils.INFIELD_SEP), Mandatory: true}, &config.CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("~broadWorksCDR>cdrData>basicModule>userId:s/.*@(.*)/${1}/", utils.INFIELD_SEP), Mandatory: true}, &config.CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, @@ -255,9 +253,13 @@ func TestXMLRPProcess(t *testing.T) { t.Error(err) } expectedCDRs := []*engine.CDR{ - &engine.CDR{CGRID: "1f045359a0784d15e051d7e41ae30132b139d714", OriginHost: "0.0.0.0", Source: "TestXML", OriginID: "25160047719:0", - ToR: "*voice", RequestType: "*rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Destination: "+4986517174963", - SetupTime: time.Date(2016, 4, 19, 21, 0, 5, 247000000, time.UTC), AnswerTime: time.Date(2016, 4, 19, 21, 0, 6, 813000000, time.UTC), Usage: time.Duration(13483000000), + &engine.CDR{CGRID: "1f045359a0784d15e051d7e41ae30132b139d714", + OriginHost: "0.0.0.0", Source: "TestXML", OriginID: "25160047719:0", + ToR: "*voice", RequestType: "*rated", Tenant: "cgrates.org", + Category: "call", Account: "1001", Destination: "+4986517174963", + SetupTime: time.Date(2016, 4, 19, 21, 0, 5, 247000000, time.UTC), + AnswerTime: time.Date(2016, 4, 19, 21, 0, 6, 813000000, time.UTC), + Usage: time.Duration(13483000000), ExtraFields: map[string]string{}, Cost: -1}, } if !reflect.DeepEqual(expectedCDRs, cdrs) { diff --git a/cmd/cgr-tester/cdr_repl/process_cdr.go b/cmd/cgr-tester/cdr_repl/process_cdr.go index 299e90ad8..36a45997e 100644 --- a/cmd/cgr-tester/cdr_repl/process_cdr.go +++ b/cmd/cgr-tester/cdr_repl/process_cdr.go @@ -52,7 +52,7 @@ func main() { for i := 0; i < 10000; i++ { cdr := &engine.CDR{OriginID: fmt.Sprintf("httpjsonrpc_%d", i), ToR: utils.VOICE, OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_PSEUDOPREPAID, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} cdrs = append(cdrs, cdr) diff --git a/config/config_defaults.go b/config/config_defaults.go index d7ed88158..47312a995 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -180,7 +180,6 @@ const CGRATES_CFG_JSON = ` {"tag":"TOR", "type": "*composed", "value": "ToR"}, {"tag":"OriginID", "type": "*composed", "value": "OriginID"}, {"tag":"RequestType", "type": "*composed", "value": "RequestType"}, - {"tag":"Direction", "type": "*composed", "value": "Direction"}, {"tag":"Tenant", "type": "*composed", "value": "Tenant"}, {"tag":"Category", "type": "*composed", "value": "Category"}, {"tag":"Account", "type": "*composed", "value": "Account"}, @@ -230,7 +229,6 @@ const CGRATES_CFG_JSON = ` {"tag": "TOR", "field_id": "ToR", "type": "*composed", "value": "2", "mandatory": true}, {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "3", "mandatory": true}, {"tag": "RequestType", "field_id": "RequestType", "type": "*composed", "value": "4", "mandatory": true}, - {"tag": "Direction", "field_id": "Direction", "type": "*composed", "value": "5", "mandatory": true}, {"tag": "Tenant", "field_id": "Tenant", "type": "*composed", "value": "6", "mandatory": true}, {"tag": "Category", "field_id": "Category", "type": "*composed", "value": "7", "mandatory": true}, {"tag": "Account", "field_id": "Account", "type": "*composed", "value": "8", "mandatory": true}, @@ -247,7 +245,6 @@ const CGRATES_CFG_JSON = ` {"tag": "TOR", "type": "*composed", "value": "ToR"}, {"tag": "OriginID", "type": "*composed", "value": "OriginID"}, {"tag": "RequestType", "type": "*composed", "value": "RequestType"}, - {"tag": "Direction", "type": "*composed", "value": "Direction"}, {"tag": "Tenant", "type": "*composed", "value": "Tenant"}, {"tag": "Category", "type": "*composed", "value": "Category"}, {"tag": "Account", "type": "*composed", "value": "Account"}, diff --git a/config/config_json_test.go b/config/config_json_test.go index b51e32522..96213618d 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -272,9 +272,6 @@ func TestDfCdreJsonCfgs(t *testing.T) { &CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.REQTYPE)}, - &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), - Type: utils.StringPointer(utils.META_COMPOSED), - Value: utils.StringPointer(utils.DIRECTION)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.TENANT)}, @@ -339,8 +336,6 @@ func TestDfCdrcJsonCfg(t *testing.T) { Value: utils.StringPointer("3"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"), Field_id: utils.StringPointer(utils.REQTYPE), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("4"), Mandatory: utils.BoolPointer(true)}, - &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), Field_id: utils.StringPointer(utils.DIRECTION), Type: utils.StringPointer(utils.META_COMPOSED), - Value: utils.StringPointer("5"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), Field_id: utils.StringPointer(utils.TENANT), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("6"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Category"), Field_id: utils.StringPointer(utils.CATEGORY), Type: utils.StringPointer(utils.META_COMPOSED), @@ -374,9 +369,6 @@ func TestDfCdrcJsonCfg(t *testing.T) { &CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.REQTYPE)}, - &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), - Type: utils.StringPointer(utils.META_COMPOSED), - Value: utils.StringPointer(utils.DIRECTION)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.TENANT)}, diff --git a/config/config_test.go b/config/config_test.go index 222571e59..a94433941 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -103,27 +103,45 @@ func TestCgrCfgCDRC(t *testing.T) { PartialCacheExpiryAction: "*dump_to_file", HeaderFields: make([]*CfgCdrField, 0), ContentFields: []*CfgCdrField{ - &CfgCdrField{FieldId: "ToR", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile("~7:s/^(voice|data|sms|mms|generic)$/*$1/", utils.INFIELD_SEP)}, - &CfgCdrField{FieldId: "AnswerTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile("1", utils.INFIELD_SEP)}, - &CfgCdrField{FieldId: "Usage", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile("~9:s/^(\\d+)$/${1}s/", utils.INFIELD_SEP)}, + &CfgCdrField{FieldId: "ToR", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("~7:s/^(voice|data|sms|mms|generic)$/*$1/", utils.INFIELD_SEP)}, + &CfgCdrField{FieldId: "AnswerTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("1", utils.INFIELD_SEP)}, + &CfgCdrField{FieldId: "Usage", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("~9:s/^(\\d+)$/${1}s/", utils.INFIELD_SEP)}, }, TrailerFields: make([]*CfgCdrField, 0), CacheDumpFields: []*CfgCdrField{ - &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DIRECTION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), + Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), + Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, }, }, } @@ -364,21 +382,37 @@ func TestCgrCfgJSONDefaultsCDRStats(t *testing.T) { func TestCgrCfgJSONDefaultsCdreProfiles(t *testing.T) { eFields := []*CfgCdrField{} eContentFlds := []*CfgCdrField{ - &CfgCdrField{Tag: "CGRID", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("CGRID", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RunID", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("RunID", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "TOR", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("ToR", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "OriginID", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("OriginID", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RequestType", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("RequestType", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Direction", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("Direction", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Tenant", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("Tenant", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Category", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("Category", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Account", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("Account", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Subject", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("Subject", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Destination", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("Destination", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "SetupTime", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("SetupTime", utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "AnswerTime", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("AnswerTime", utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "Usage", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("Usage", utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Cost", Type: "*composed", Value: utils.ParseRSRFieldsMustCompile("Cost", utils.INFIELD_SEP), RoundingDecimals: 4}, + &CfgCdrField{Tag: "CGRID", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("CGRID", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RunID", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("RunID", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "TOR", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("ToR", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "OriginID", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("OriginID", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RequestType", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("RequestType", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Tenant", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("Tenant", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Category", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("Category", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Account", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("Account", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Subject", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("Subject", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Destination", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("Destination", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "SetupTime", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("SetupTime", utils.INFIELD_SEP), + Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "AnswerTime", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("AnswerTime", utils.INFIELD_SEP), + Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "Usage", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("Usage", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Cost", Type: "*composed", + Value: utils.ParseRSRFieldsMustCompile("Cost", utils.INFIELD_SEP), + RoundingDecimals: 4}, } eCdreCfg := map[string]*CdreConfig{ "*default": { diff --git a/config/configcdrc_test.go b/config/configcdrc_test.go index caf7e5a52..ad69e2655 100644 --- a/config/configcdrc_test.go +++ b/config/configcdrc_test.go @@ -53,48 +53,81 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) { PartialCacheExpiryAction: utils.MetaDumpToFile, HeaderFields: make([]*CfgCdrField, 0), ContentFields: []*CfgCdrField{ - &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, + Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, + Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, + Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, + Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, + Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, + Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, + Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, + Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, + Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, + Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, + Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, }, TrailerFields: make([]*CfgCdrField, 0), CacheDumpFields: []*CfgCdrField{ - &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DIRECTION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, }, }, } @@ -117,48 +150,81 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) { PartialCacheExpiryAction: utils.MetaDumpToFile, HeaderFields: make([]*CfgCdrField, 0), ContentFields: []*CfgCdrField{ - &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, + Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, + Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, + Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, + Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, + Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, + Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, + Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, + Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, + Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, + Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, + Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, }, TrailerFields: make([]*CfgCdrField, 0), CacheDumpFields: []*CfgCdrField{ - &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DIRECTION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, }, }, } @@ -181,30 +247,51 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) { PartialCacheExpiryAction: utils.MetaDumpToFile, HeaderFields: make([]*CfgCdrField, 0), ContentFields: []*CfgCdrField{ - &CfgCdrField{FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("~7:s/^(voice|data|sms|mms|generic)$/*$1/", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: false}, - &CfgCdrField{Tag: "", Type: "", FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("1", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: false}, - &CfgCdrField{FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("~9:s/^(\\d+)$/${1}s/", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: false}, + &CfgCdrField{FieldId: utils.TOR, + Value: utils.ParseRSRFieldsMustCompile("~7:s/^(voice|data|sms|mms|generic)$/*$1/", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: false}, + &CfgCdrField{Tag: "", Type: "", FieldId: utils.ANSWER_TIME, + Value: utils.ParseRSRFieldsMustCompile("1", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: false}, + &CfgCdrField{FieldId: utils.USAGE, + Value: utils.ParseRSRFieldsMustCompile("~9:s/^(\\d+)$/${1}s/", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: false}, }, TrailerFields: make([]*CfgCdrField, 0), CacheDumpFields: []*CfgCdrField{ - &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DIRECTION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), + Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), + Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, }, }, } @@ -227,52 +314,88 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) { PartialCacheExpiryAction: utils.MetaDumpToFile, HeaderFields: make([]*CfgCdrField, 0), ContentFields: []*CfgCdrField{ - &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, - &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP), - FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, + Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, + Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, + Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, + Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, + Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, + Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, + Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, + Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, + Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, + Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, + &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, + Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP), + FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), + Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true}, }, TrailerFields: make([]*CfgCdrField, 0), CacheDumpFields: []*CfgCdrField{ - &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DIRECTION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), Layout: "2006-01-02T15:04:05Z07:00"}, - &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, - &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "CGRID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CGRID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RunID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.MEDI_RUNID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TOR, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCID, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.REQTYPE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.CATEGORY, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SUBJECT, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.DESTINATION, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.SETUP_TIME, utils.INFIELD_SEP), + Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.ANSWER_TIME, utils.INFIELD_SEP), + Layout: "2006-01-02T15:04:05Z07:00"}, + &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.USAGE, utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Cost", Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile(utils.COST, utils.INFIELD_SEP)}, }, }, } if !reflect.DeepEqual(eCgrCfg.CdrcProfiles, cgrCfg.CdrcProfiles) { - t.Errorf("Expected: \n%s\n, received: \n%s\n", utils.ToJSON(eCgrCfg.CdrcProfiles), utils.ToJSON(cgrCfg.CdrcProfiles)) + t.Errorf("Expected: \n%s\n, received: \n%s\n", + utils.ToJSON(eCgrCfg.CdrcProfiles), utils.ToJSON(cgrCfg.CdrcProfiles)) } } diff --git a/console/maxusage.go b/console/maxusage.go index ea0d5051b..f49858d6d 100644 --- a/console/maxusage.go +++ b/console/maxusage.go @@ -48,7 +48,7 @@ func (self *CmdGetMaxUsage) RpcMethod() string { func (self *CmdGetMaxUsage) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { - self.rpcParams = &engine.UsageRecord{Direction: "*out"} + self.rpcParams = &engine.UsageRecord{} } return self.rpcParams } diff --git a/data/storage/mysql/create_cdrs_tables.sql b/data/storage/mysql/create_cdrs_tables.sql index 40598db44..4423044ec 100644 --- a/data/storage/mysql/create_cdrs_tables.sql +++ b/data/storage/mysql/create_cdrs_tables.sql @@ -12,23 +12,18 @@ CREATE TABLE cdrs ( origin_id varchar(64) NOT NULL, tor varchar(16) NOT NULL, request_type varchar(24) NOT NULL, - direction varchar(8) NOT NULL, tenant varchar(64) NOT NULL, category varchar(32) NOT NULL, account varchar(128) NOT NULL, subject varchar(128) NOT NULL, destination varchar(128) NOT NULL, setup_time datetime NOT NULL, - pdd DECIMAL(12,9) NOT NULL, answer_time datetime NOT NULL, - `usage` DECIMAL(30,9) NOT NULL, - supplier varchar(128) NOT NULL, - disconnect_cause varchar(64) NOT NULL, + `usage` BIGINT NOT NULL, extra_fields text NOT NULL, cost_source varchar(64) NOT NULL, cost DECIMAL(20,4) NOT NULL, cost_details text, - account_summary text, extra_info text, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, @@ -45,7 +40,7 @@ CREATE TABLE sm_costs ( origin_host varchar(64) NOT NULL, origin_id varchar(64) NOT NULL, cost_source varchar(64) NOT NULL, - `usage` DECIMAL(30,9) NOT NULL, + `usage` BIGINT NOT NULL, cost_details text, created_at TIMESTAMP NULL, deleted_at TIMESTAMP NULL, diff --git a/data/storage/postgres/create_cdrs_tables.sql b/data/storage/postgres/create_cdrs_tables.sql index 1cb0cff64..9b5c9c4fe 100644 --- a/data/storage/postgres/create_cdrs_tables.sql +++ b/data/storage/postgres/create_cdrs_tables.sql @@ -12,23 +12,18 @@ CREATE TABLE cdrs ( origin_id VARCHAR(64) NOT NULL, tor VARCHAR(16) NOT NULL, request_type VARCHAR(24) NOT NULL, - direction VARCHAR(8) NOT NULL, tenant VARCHAR(64) NOT NULL, category VARCHAR(32) NOT NULL, account VARCHAR(128) NOT NULL, subject VARCHAR(128) NOT NULL, destination VARCHAR(128) NOT NULL, setup_time TIMESTAMP WITH TIME ZONE NOT NULL, - pdd NUMERIC(12,9) NOT NULL, answer_time TIMESTAMP WITH TIME ZONE NOT NULL, - usage NUMERIC(30,9) NOT NULL, - supplier VARCHAR(128) NOT NULL, - disconnect_cause VARCHAR(64) NOT NULL, + usage BIGINT NOT NULL, extra_fields jsonb NOT NULL, cost_source VARCHAR(64) NOT NULL, cost NUMERIC(20,4) DEFAULT NULL, cost_details jsonb, - account_summary jsonb, extra_info text, created_at TIMESTAMP WITH TIME ZONE, updated_at TIMESTAMP WITH TIME ZONE NULL, @@ -48,7 +43,7 @@ CREATE TABLE sm_costs ( origin_host VARCHAR(64) NOT NULL, origin_id VARCHAR(64) NOT NULL, cost_source VARCHAR(64) NOT NULL, - usage NUMERIC(30,9) NOT NULL, + usage BIGINT NOT NULL, cost_details jsonb, created_at TIMESTAMP WITH TIME ZONE, deleted_at TIMESTAMP WITH TIME ZONE NULL, diff --git a/engine/action.go b/engine/action.go index fe5627eb0..e6eec5205 100644 --- a/engine/action.go +++ b/engine/action.go @@ -187,14 +187,13 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action) func cdrLogAction(acc *Account, sq *CDRStatsQueueTriggered, a *Action, acs Actions) (err error) { defaultTemplate := map[string]utils.RSRFields{ - utils.TOR: utils.ParseRSRFieldsMustCompile("BalanceType", utils.INFIELD_SEP), - utils.CDRHOST: utils.ParseRSRFieldsMustCompile("^127.0.0.1", utils.INFIELD_SEP), - utils.DIRECTION: utils.ParseRSRFieldsMustCompile("Directions", utils.INFIELD_SEP), - utils.REQTYPE: utils.ParseRSRFieldsMustCompile("^"+utils.META_PREPAID, utils.INFIELD_SEP), - utils.TENANT: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP), - utils.ACCOUNT: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP), - utils.SUBJECT: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP), - utils.COST: utils.ParseRSRFieldsMustCompile("ActionValue", utils.INFIELD_SEP), + utils.TOR: utils.ParseRSRFieldsMustCompile("BalanceType", utils.INFIELD_SEP), + utils.CDRHOST: utils.ParseRSRFieldsMustCompile("^127.0.0.1", utils.INFIELD_SEP), + utils.REQTYPE: utils.ParseRSRFieldsMustCompile("^"+utils.META_PREPAID, utils.INFIELD_SEP), + utils.TENANT: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP), + utils.ACCOUNT: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP), + utils.SUBJECT: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP), + utils.COST: utils.ParseRSRFieldsMustCompile("ActionValue", utils.INFIELD_SEP), } template := make(map[string]string) diff --git a/engine/actions_test.go b/engine/actions_test.go index 59e4b0e92..28767e61b 100644 --- a/engine/actions_test.go +++ b/engine/actions_test.go @@ -113,14 +113,16 @@ func TestActionPlanOnlyWeekdays(t *testing.T) { } func TestActionPlanHourWeekdays(t *testing.T) { - at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{WeekDays: []time.Weekday{time.Monday}, StartTime: "10:01:00"}}} + at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{ + WeekDays: []time.Weekday{time.Monday}, StartTime: "10:01:00"}}} st := at.GetNextStartTime(referenceDate) y, m, d := now.Date() e := time.Date(y, m, d, 10, 1, 0, 0, time.Local) day := e.Day() for i := 0; i < 8; i++ { - e = time.Date(e.Year(), e.Month(), day, e.Hour(), e.Minute(), e.Second(), e.Nanosecond(), e.Location()) + e = time.Date(e.Year(), e.Month(), day, e.Hour(), + e.Minute(), e.Second(), e.Nanosecond(), e.Location()) n := e.AddDate(0, 0, i) if n.Weekday() == time.Monday && (n.Equal(now) || n.After(now)) { e = n @@ -136,7 +138,8 @@ func TestActionPlanOnlyMonthdays(t *testing.T) { y, m, d := now.Date() tomorrow := time.Date(y, m, d, 0, 0, 0, 0, time.Local).AddDate(0, 0, 1) - at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{1, 25, 2, tomorrow.Day()}}}} + at := &ActionTiming{Timing: &RateInterval{ + Timing: &RITiming{MonthDays: utils.MonthDays{1, 25, 2, tomorrow.Day()}}}} st := at.GetNextStartTime(referenceDate) expected := tomorrow if !st.Equal(expected) { @@ -152,7 +155,8 @@ func TestActionPlanHourMonthdays(t *testing.T) { if now.After(testTime) { y, m, d = tomorrow.Date() } - at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()}, StartTime: "10:01:00"}}} + at := &ActionTiming{Timing: &RateInterval{ + Timing: &RITiming{MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()}, StartTime: "10:01:00"}}} st := at.GetNextStartTime(referenceDate) expected := time.Date(y, m, d, 10, 1, 0, 0, time.Local) if !st.Equal(expected) { @@ -164,7 +168,8 @@ func TestActionPlanOnlyMonths(t *testing.T) { y, m, _ := now.Date() nextMonth := time.Date(y, m, 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, 0) - at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Months: utils.Months{time.February, time.May, nextMonth.Month()}}}} + at := &ActionTiming{Timing: &RateInterval{ + Timing: &RITiming{Months: utils.Months{time.February, time.May, nextMonth.Month()}}}} st := at.GetNextStartTime(referenceDate) expected := time.Date(nextMonth.Year(), nextMonth.Month(), 1, 0, 0, 0, 0, time.Local) if !st.Equal(expected) { @@ -250,7 +255,8 @@ func TestActionPlanFirstOfTheMonth(t *testing.T) { func TestActionPlanOnlyYears(t *testing.T) { y, _, _ := referenceDate.Date() nextYear := time.Date(y, 1, 1, 0, 0, 0, 0, time.Local).AddDate(1, 0, 0) - at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{now.Year(), nextYear.Year()}}}} + at := &ActionTiming{Timing: &RateInterval{ + Timing: &RITiming{Years: utils.Years{now.Year(), nextYear.Year()}}}} st := at.GetNextStartTime(referenceDate) expected := nextYear if !st.Equal(expected) { @@ -268,7 +274,8 @@ func TestActionPlanPast(t *testing.T) { } func TestActionPlanHourYears(t *testing.T) { - at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{referenceDate.Year(), referenceDate.Year() + 1}, StartTime: "10:01:00"}}} + at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{ + Years: utils.Years{referenceDate.Year(), referenceDate.Year() + 1}, StartTime: "10:01:00"}}} st := at.GetNextStartTime(referenceDate) expected := time.Date(referenceDate.Year(), 1, 1, 10, 1, 0, 0, time.Local) if referenceDate.After(expected) { @@ -447,8 +454,10 @@ func TestActionPlanFunctionNotAvailable(t *testing.T) { func TestActionTimingPriorityListSortByWeight(t *testing.T) { at1 := &ActionTiming{Timing: &RateInterval{ Timing: &RITiming{ - Years: utils.Years{2020}, - Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December}, + Years: utils.Years{2020}, + Months: utils.Months{time.January, time.February, time.March, + time.April, time.May, time.June, time.July, time.August, time.September, + time.October, time.November, time.December}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00", }, @@ -456,8 +465,10 @@ func TestActionTimingPriorityListSortByWeight(t *testing.T) { }} at2 := &ActionTiming{Timing: &RateInterval{ Timing: &RITiming{ - Years: utils.Years{2020}, - Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December}, + Years: utils.Years{2020}, + Months: utils.Months{time.January, time.February, time.March, + time.April, time.May, time.June, time.July, time.August, time.September, + time.October, time.November, time.December}, MonthDays: utils.MonthDays{2}, StartTime: "00:00:00", }, @@ -475,7 +486,9 @@ func TestActionTimingPriorityListWeight(t *testing.T) { at1 := &ActionTiming{ Timing: &RateInterval{ Timing: &RITiming{ - Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December}, + Months: utils.Months{time.January, time.February, time.March, + time.April, time.May, time.June, time.July, time.August, time.September, + time.October, time.November, time.December}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00", }, @@ -485,7 +498,9 @@ func TestActionTimingPriorityListWeight(t *testing.T) { at2 := &ActionTiming{ Timing: &RateInterval{ Timing: &RITiming{ - Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December}, + Months: utils.Months{time.January, time.February, time.March, + time.April, time.May, time.June, time.July, time.August, time.September, + time.October, time.November, time.December}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00", }, @@ -550,26 +565,33 @@ func TestActionPlansRemoveMember(t *testing.T) { }, } - if err := dm.DataDB().SetActionPlan(ap1.Id, ap1, true, utils.NonTransactional); err != nil { + if err := dm.DataDB().SetActionPlan(ap1.Id, ap1, true, + utils.NonTransactional); err != nil { t.Error(err) } - if err = dm.DataDB().SetActionPlan(ap2.Id, ap2, true, utils.NonTransactional); err != nil { + if err = dm.DataDB().SetActionPlan(ap2.Id, ap2, true, + utils.NonTransactional); err != nil { t.Error(err) } - if err = dm.CacheDataFromDB(utils.ACTION_PLAN_PREFIX, []string{ap1.Id, ap2.Id}, true); err != nil { + if err = dm.CacheDataFromDB(utils.ACTION_PLAN_PREFIX, + []string{ap1.Id, ap2.Id}, true); err != nil { t.Error(err) } - if err = dm.DataDB().SetAccountActionPlans(account1.ID, []string{ap1.Id}, false); err != nil { + if err = dm.DataDB().SetAccountActionPlans(account1.ID, + []string{ap1.Id}, false); err != nil { t.Error(err) } - if err = dm.CacheDataFromDB(utils.AccountActionPlansPrefix, []string{account1.ID}, true); err != nil { + if err = dm.CacheDataFromDB(utils.AccountActionPlansPrefix, + []string{account1.ID}, true); err != nil { t.Error(err) } dm.DataDB().GetAccountActionPlans(account1.ID, true, utils.NonTransactional) // FixMe: remove here after finishing testing of map - if err = dm.DataDB().SetAccountActionPlans(account2.ID, []string{ap2.Id}, false); err != nil { + if err = dm.DataDB().SetAccountActionPlans(account2.ID, + []string{ap2.Id}, false); err != nil { t.Error(err) } - if err = dm.CacheDataFromDB(utils.AccountActionPlansPrefix, []string{account2.ID}, false); err != nil { + if err = dm.CacheDataFromDB(utils.AccountActionPlansPrefix, + []string{account2.ID}, false); err != nil { t.Error(err) } @@ -643,7 +665,8 @@ func TestActionTriggerMatchMinuteBucketBlank(t *testing.T) { ThresholdType: utils.TRIGGER_MAX_BALANCE, ThresholdValue: 2, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: `{"BalanceDirections":"*out"}`} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ExtraParameters: `{"BalanceDirections":"*out"}`} if !at.Match(a) { t.Errorf("Action trigger [%v] does not match action [%v]", at, a) } @@ -658,7 +681,8 @@ func TestActionTriggerMatchMinuteBucketFull(t *testing.T) { ThresholdType: utils.TRIGGER_MAX_BALANCE, ThresholdValue: 2, } - a := &Action{ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, utils.TRIGGER_MAX_BALANCE, 2)} + a := &Action{ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, + utils.TRIGGER_MAX_BALANCE, 2)} if !at.Match(a) { t.Errorf("Action trigger [%v] does not match action [%v]", at, a) } @@ -673,7 +697,9 @@ func TestActionTriggerMatchAllFull(t *testing.T) { ThresholdType: utils.TRIGGER_MAX_BALANCE, ThresholdValue: 2, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*out"}`, utils.TRIGGER_MAX_BALANCE, 2)} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*out"}`, + utils.TRIGGER_MAX_BALANCE, 2)} if !at.Match(a) { t.Errorf("Action trigger [%v] does not match action [%v]", at, a) } @@ -688,7 +714,9 @@ func TestActionTriggerMatchSomeFalse(t *testing.T) { ThresholdType: utils.TRIGGER_MAX_BALANCE, ThresholdValue: 2, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%s"}`, utils.TRIGGER_MAX_BALANCE_COUNTER)} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%s"}`, + utils.TRIGGER_MAX_BALANCE_COUNTER)} if at.Match(a) { t.Errorf("Action trigger [%v] does not match action [%v]", at, a) } @@ -703,7 +731,9 @@ func TestActionTriggerMatcBalanceFalse(t *testing.T) { ThresholdType: utils.TRIGGER_MAX_BALANCE, ThresholdValue: 2, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ExtraParameters: fmt.Sprintf(`{"GroupID":"%s", "ThresholdType":"%s"}`, "TEST", utils.TRIGGER_MAX_BALANCE)} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ExtraParameters: fmt.Sprintf(`{"GroupID":"%s", "ThresholdType":"%s"}`, "TEST", utils.TRIGGER_MAX_BALANCE)} if at.Match(a) { t.Errorf("Action trigger [%v] does not match action [%v]", at, a) } @@ -718,7 +748,8 @@ func TestActionTriggerMatcAllFalse(t *testing.T) { ThresholdType: utils.TRIGGER_MAX_BALANCE, ThresholdValue: 2, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"UniqueID":"ZIP", "GroupID":"%s", "ThresholdType":"%s"}`, "TEST", utils.TRIGGER_MAX_BALANCE)} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ExtraParameters: fmt.Sprintf(`{"UniqueID":"ZIP", "GroupID":"%s", "ThresholdType":"%s"}`, "TEST", utils.TRIGGER_MAX_BALANCE)} if at.Match(a) { t.Errorf("Action trigger [%v] does not match action [%v]", at, a) } @@ -767,10 +798,15 @@ func TestActionTriggers(t *testing.T) { func TestActionResetTriggres(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 10}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 10}}, + utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{ + Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{ + Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } resetTriggersAction(ub, nil, nil, nil) if ub.ActionTriggers[0].Executed == true || ub.ActionTriggers[1].Executed == true { @@ -780,10 +816,12 @@ func TestActionResetTriggres(t *testing.T) { func TestActionResetTriggresExecutesThem(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 10}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 10}}}, + UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{ + &UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{ + Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } resetTriggersAction(ub, nil, nil, nil) if ub.ActionTriggers[0].Executed == true || ub.BalanceMap[utils.MONETARY][0].GetValue() == 12 { @@ -793,10 +831,18 @@ func TestActionResetTriggresExecutesThem(t *testing.T) { func TestActionResetTriggresActionFilter(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 10}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{utils.MONETARY: Balances{ + &Balance{Value: 10}}, utils.VOICE: Balances{ + &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{ + &UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } resetTriggersAction(ub, nil, &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}}, nil) if ub.ActionTriggers[0].Executed == false || ub.ActionTriggers[1].Executed == false { @@ -806,10 +852,19 @@ func TestActionResetTriggresActionFilter(t *testing.T) { func TestActionSetPostpaid(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{ + &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{ + &UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } allowNegativeAction(ub, nil, nil, nil) if !ub.AllowNegative { @@ -819,11 +874,20 @@ func TestActionSetPostpaid(t *testing.T) { func TestActionSetPrepaid(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - AllowNegative: true, - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + AllowNegative: true, + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{ + &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{ + &UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } denyNegativeAction(ub, nil, nil, nil) if ub.AllowNegative { @@ -833,11 +897,20 @@ func TestActionSetPrepaid(t *testing.T) { func TestActionResetPrepaid(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - AllowNegative: true, - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + AllowNegative: true, + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{ + &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{ + utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } resetAccountAction(ub, nil, nil, nil) if !ub.AllowNegative || @@ -852,10 +925,19 @@ func TestActionResetPrepaid(t *testing.T) { func TestActionResetPostpaid(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{ + &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{ + utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } resetAccountAction(ub, nil, nil, nil) if ub.BalanceMap[utils.MONETARY].GetTotalValue() != 0 || @@ -868,12 +950,26 @@ func TestActionResetPostpaid(t *testing.T) { func TestActionTopupResetCredit(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 100}}, + utils.VOICE: Balances{ + &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{ + utils.MONETARY: []*UnitCounter{ + &UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, + Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &utils.ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Value: &utils.ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} topupResetAction(ub, nil, a, nil) if ub.AllowNegative || ub.BalanceMap[utils.MONETARY].GetTotalValue() != 10 || @@ -913,7 +1009,8 @@ func TestActionTopupResetCreditId(t *testing.T) { }, }, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), ID: utils.StringPointer("TEST_B"), Value: &utils.ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), ID: utils.StringPointer("TEST_B"), + Value: &utils.ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} topupResetAction(ub, nil, a, nil) if ub.AllowNegative || ub.BalanceMap[utils.MONETARY].GetTotalValue() != 110 || @@ -932,7 +1029,8 @@ func TestActionTopupResetCreditNoId(t *testing.T) { }, }, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &utils.ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Value: &utils.ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} topupResetAction(ub, nil, a, nil) if ub.AllowNegative || ub.BalanceMap[utils.MONETARY].GetTotalValue() != 20 || @@ -946,11 +1044,22 @@ func TestActionTopupResetMinutes(t *testing.T) { ID: "TEST_UB", BalanceMap: map[string]Balances{ utils.MONETARY: Balances{&Balance{Value: 100}}, - utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), + Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, + Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: &utils.ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), + Value: &utils.ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} topupResetAction(ub, nil, a, nil) if ub.AllowNegative || ub.BalanceMap[utils.VOICE].GetTotalValue() != 5 || @@ -964,12 +1073,27 @@ func TestActionTopupResetMinutes(t *testing.T) { func TestActionTopupCredit(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), + Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, + DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{ + utils.MONETARY: []*UnitCounter{ + &UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, + Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &utils.ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Value: &utils.ValueFormula{Static: 10}, + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} topupAction(ub, nil, a, nil) if ub.AllowNegative || ub.BalanceMap[utils.MONETARY].GetTotalValue() != 110 || @@ -982,12 +1106,23 @@ func TestActionTopupCredit(t *testing.T) { func TestActionTopupMinutes(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), + Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{ + utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: &utils.ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), + Value: &utils.ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} topupAction(ub, nil, a, nil) if ub.AllowNegative || ub.BalanceMap[utils.VOICE].GetTotalValue() != 15 || @@ -1001,12 +1136,26 @@ func TestActionTopupMinutes(t *testing.T) { func TestActionDebitCredit(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{ + &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{ + utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, + Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &utils.ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Value: &utils.ValueFormula{Static: 10}, + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} debitAction(ub, nil, a, nil) if ub.AllowNegative || ub.BalanceMap[utils.MONETARY].GetTotalValue() != 90 || @@ -1019,12 +1168,25 @@ func TestActionDebitCredit(t *testing.T) { func TestActionDebitMinutes(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{ + &Balance{Value: 10, Weight: 20, + DestinationIDs: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{ + utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } - a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: &utils.ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} + a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), + Value: &utils.ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}} debitAction(ub, nil, a, nil) if ub.AllowNegative || ub.BalanceMap[utils.VOICE][0].GetValue() != 5 || @@ -1043,10 +1205,16 @@ func TestActionResetAllCounters(t *testing.T) { BalanceMap: map[string]Balances{ utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{ - &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, - &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET"), Directions: utils.NewStringMap(utils.OUT)}}}, + &Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT"), + Directions: utils.NewStringMap(utils.OUT)}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET"), + Directions: utils.NewStringMap(utils.OUT)}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ThresholdValue: 2, Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Weight: utils.Float64Pointer(20)}, ActionsID: "TEST_ACTIONS", Executed: true}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ThresholdValue: 2, + Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), + Weight: utils.Float64Pointer(20)}, ActionsID: "TEST_ACTIONS", Executed: true}}, } ub.InitCounters() resetCountersAction(ub, nil, nil, nil) @@ -1056,13 +1224,15 @@ func TestActionResetAllCounters(t *testing.T) { len(ub.UnitCounters[utils.MONETARY][0].Counters) != 1 || len(ub.BalanceMap[utils.MONETARY]) != 1 || ub.ActionTriggers[0].Executed != true { - t.Errorf("Reset counters action failed: %+v %+v %+v", ub.UnitCounters, ub.UnitCounters[utils.MONETARY][0], ub.UnitCounters[utils.MONETARY][0].Counters[0]) + t.Errorf("Reset counters action failed: %+v %+v %+v", ub.UnitCounters, + ub.UnitCounters[utils.MONETARY][0], ub.UnitCounters[utils.MONETARY][0].Counters[0]) } if len(ub.UnitCounters) < 1 { t.FailNow() } c := ub.UnitCounters[utils.MONETARY][0].Counters[0] - if c.Filter.GetWeight() != 20 || c.Value != 0 || c.Filter.GetDestinationIDs()["NAT"] == false { + if c.Filter.GetWeight() != 20 || c.Value != 0 || + c.Filter.GetDestinationIDs()["NAT"] == false { t.Errorf("Balance cloned incorrectly: %+v", c) } } @@ -1073,8 +1243,13 @@ func TestActionResetCounterOnlyDefault(t *testing.T) { AllowNegative: true, BalanceMap: map[string]Balances{ utils.MONETARY: Balances{&Balance{Value: 100}}, - utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, + DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, + DestinationIDs: utils.NewStringMap("RET")}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, + ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ThresholdValue: 2, + ActionsID: "TEST_ACTIONS", Executed: true}}, } a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}} ub.InitCounters() @@ -1101,11 +1276,23 @@ func TestActionResetCounterOnlyDefault(t *testing.T) { func TestActionResetCounterCredit(t *testing.T) { ub := &Account{ - ID: "TEST_UB", - AllowNegative: true, - BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{Value: 100}}, utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, - UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}, utils.SMS: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, - ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, + ID: "TEST_UB", + AllowNegative: true, + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{Value: 100}}, + utils.VOICE: Balances{&Balance{Value: 10, Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, + &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, + UnitCounters: UnitCounters{ + utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{ + &CounterFilter{Value: 1, Filter: &BalanceFilter{ + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}, + utils.SMS: []*UnitCounter{&UnitCounter{ + Counters: CounterFilters{&CounterFilter{Value: 1, + Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}, + ActionTriggers: ActionTriggers{ + &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, + ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}}, } a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}} resetCountersAction(ub, nil, a, nil) @@ -1159,8 +1346,10 @@ func TestActionTriggerLogging(t *testing.T) { func TestActionPlanLogging(t *testing.T) { i := &RateInterval{ Timing: &RITiming{ - Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December}, - MonthDays: utils.MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, + time.July, time.August, time.September, time.October, time.November, time.December}, + MonthDays: utils.MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, WeekDays: utils.WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, StartTime: "18:00:00", EndTime: "00:00:00", @@ -1236,7 +1425,9 @@ func TestTopupAction(t *testing.T) { initialUb, _ := dm.DataDB().GetAccount("vdf:minu") a := &Action{ ActionType: TOPUP, - Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &utils.ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)}, + Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &utils.ValueFormula{Static: 25}, + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)}, } at := &ActionTiming{ @@ -1257,7 +1448,9 @@ func TestTopupActionLoaded(t *testing.T) { initialUb, _ := dm.DataDB().GetAccount("vdf:minitsboy") a := &Action{ ActionType: TOPUP, - Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &utils.ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)}, + Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), + Value: &utils.ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)}, } at := &ActionTiming{ @@ -1284,7 +1477,8 @@ func TestActionCdrlogEmpty(t *testing.T) { err := cdrLogAction(acnt, nil, cdrlog, Actions{ &Action{ ActionType: DEBIT, - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, }, }) if err != nil { @@ -1306,11 +1500,13 @@ func TestActionCdrlogWithParams(t *testing.T) { err := cdrLogAction(acnt, nil, cdrlog, Actions{ &Action{ ActionType: DEBIT, - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, }, &Action{ ActionType: DEBIT_RESET, - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, }, }) if err != nil { @@ -1333,11 +1529,13 @@ func TestActionCdrLogParamsWithOverload(t *testing.T) { err := cdrLogAction(acnt, nil, cdrlog, Actions{ &Action{ ActionType: DEBIT, - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, }, &Action{ ActionType: DEBIT_RESET, - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 25}, + DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)}, }, }) if err != nil { @@ -1358,7 +1556,8 @@ func TestActionCdrLogParamsWithOverload(t *testing.T) { } func TestActionSetDDestination(t *testing.T) { - acc := &Account{BalanceMap: map[string]Balances{utils.MONETARY: Balances{&Balance{DestinationIDs: utils.NewStringMap("*ddc_test")}}}} + acc := &Account{BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{DestinationIDs: utils.NewStringMap("*ddc_test")}}}} origD := &Destination{Id: "*ddc_test", Prefixes: []string{"111", "222"}} dm.DataDB().SetDestination(origD, utils.NonTransactional) dm.DataDB().SetReverseDestination(origD, utils.NonTransactional) @@ -1425,11 +1624,13 @@ func TestActionTransactionFuncType(t *testing.T) { actions: []*Action{ &Action{ ActionType: TOPUP, - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 1.1}, Type: utils.StringPointer(utils.MONETARY)}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 1.1}, + Type: utils.StringPointer(utils.MONETARY)}, }, &Action{ ActionType: "VALID_FUNCTION_TYPE", - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 1.1}, Type: utils.StringPointer("test")}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 1.1}, + Type: utils.StringPointer("test")}, }, }, } @@ -1461,7 +1662,8 @@ func TestActionTransactionBalanceType(t *testing.T) { actions: []*Action{ &Action{ ActionType: TOPUP, - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 1.1}, Type: utils.StringPointer(utils.MONETARY)}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 1.1}, + Type: utils.StringPointer(utils.MONETARY)}, }, &Action{ ActionType: TOPUP, @@ -1497,7 +1699,8 @@ func TestActionTransactionBalanceNotType(t *testing.T) { actions: []*Action{ &Action{ ActionType: TOPUP, - Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 1.1}, Type: utils.StringPointer(utils.VOICE)}, + Balance: &BalanceFilter{Value: &utils.ValueFormula{Static: 1.1}, + Type: utils.StringPointer(utils.VOICE)}, }, &Action{ ActionType: TOPUP, diff --git a/engine/cdr.go b/engine/cdr.go index 6b225777d..d2fbd3a97 100644 --- a/engine/cdr.go +++ b/engine/cdr.go @@ -32,10 +32,11 @@ import ( func NewCDRFromExternalCDR(extCdr *ExternalCDR, timezone string) (*CDR, error) { var err error - cdr := &CDR{CGRID: extCdr.CGRID, RunID: extCdr.RunID, OrderID: extCdr.OrderID, ToR: extCdr.ToR, OriginID: extCdr.OriginID, OriginHost: extCdr.OriginHost, - Source: extCdr.Source, RequestType: extCdr.RequestType, Direction: extCdr.Direction, Tenant: extCdr.Tenant, Category: extCdr.Category, - Account: extCdr.Account, Subject: extCdr.Subject, Destination: extCdr.Destination, Supplier: extCdr.Supplier, - DisconnectCause: extCdr.DisconnectCause, CostSource: extCdr.CostSource, Cost: extCdr.Cost, Rated: extCdr.Rated} + cdr := &CDR{CGRID: extCdr.CGRID, RunID: extCdr.RunID, OrderID: extCdr.OrderID, ToR: extCdr.ToR, + OriginID: extCdr.OriginID, OriginHost: extCdr.OriginHost, + Source: extCdr.Source, RequestType: extCdr.RequestType, Tenant: extCdr.Tenant, Category: extCdr.Category, + Account: extCdr.Account, Subject: extCdr.Subject, Destination: extCdr.Destination, + CostSource: extCdr.CostSource, Cost: extCdr.Cost, Rated: extCdr.Rated} if extCdr.SetupTime != "" { if cdr.SetupTime, err = utils.ParseTimeDetectLayout(extCdr.SetupTime, timezone); err != nil { return nil, err @@ -54,11 +55,6 @@ func NewCDRFromExternalCDR(extCdr *ExternalCDR, timezone string) (*CDR, error) { return nil, err } } - if extCdr.PDD != "" { - if cdr.PDD, err = utils.ParseDurationWithSecs(extCdr.PDD); err != nil { - return nil, err - } - } if len(extCdr.CostDetails) != 0 { if err = json.Unmarshal([]byte(extCdr.CostDetails), cdr.CostDetails); err != nil { return nil, err @@ -74,39 +70,35 @@ func NewCDRFromExternalCDR(extCdr *ExternalCDR, timezone string) (*CDR, error) { } func NewCDRWithDefaults(cfg *config.CGRConfig) *CDR { - return &CDR{ToR: utils.VOICE, RequestType: cfg.DefaultReqType, Direction: utils.OUT, Tenant: cfg.DefaultTenant, Category: cfg.DefaultCategory, + return &CDR{ToR: utils.VOICE, RequestType: cfg.DefaultReqType, + Tenant: cfg.DefaultTenant, Category: cfg.DefaultCategory, ExtraFields: make(map[string]string), Cost: -1} } type CDR struct { - CGRID string - RunID string - OrderID int64 // Stor order id used as export order id - OriginHost string // represents the IP address of the host generating the CDR (automatically populated by the server) - Source string // formally identifies the source of the CDR (free form field) - OriginID string // represents the unique accounting id given by the telecom switch generating the CDR - ToR string // type of record, meta-field, should map to one of the TORs hardcoded inside the server <*voice|*data|*sms|*generic> - RequestType string // matching the supported request types by the **CGRateS**, accepted values are hardcoded in the server . - Direction string // matching the supported direction identifiers of the CGRateS <*out> - Tenant string // tenant whom this record belongs - Category string // free-form filter for this record, matching the category defined in rating profiles. - Account string // account id (accounting subsystem) the record should be attached to - Subject string // rating subject (rating subsystem) this record should be attached to - Destination string // destination to be charged - SetupTime time.Time // set-up time of the event. Supported formats: datetime RFC3339 compatible, SQL datetime (eg: MySQL), unix timestamp. - PDD time.Duration // PDD value - AnswerTime time.Time // answer time of the event. Supported formats: datetime RFC3339 compatible, SQL datetime (eg: MySQL), unix timestamp. - Usage time.Duration // event usage information (eg: in case of tor=*voice this will represent the total duration of a call) - Supplier string // Supplier information when available - DisconnectCause string // Disconnect cause of the event - ExtraFields map[string]string // Extra fields to be stored in CDR - CostSource string // The source of this cost - Cost float64 - CostDetails *CallCost // Attach the cost details to CDR when possible - AccountSummary *AccountSummary // Store AccountSummary information - ExtraInfo string // Container for extra information related to this CDR, eg: populated with error reason in case of error on calculation - Rated bool // Mark the CDR as rated so we do not process it during rating - Partial bool // Used for partial record processing by CDRC + CGRID string + RunID string + OrderID int64 // Stor order id used as export order id + OriginHost string // represents the IP address of the host generating the CDR (automatically populated by the server) + Source string // formally identifies the source of the CDR (free form field) + OriginID string // represents the unique accounting id given by the telecom switch generating the CDR + ToR string // type of record, meta-field, should map to one of the TORs hardcoded inside the server <*voice|*data|*sms|*generic> + RequestType string // matching the supported request types by the **CGRateS**, accepted values are hardcoded in the server . + Tenant string // tenant whom this record belongs + Category string // free-form filter for this record, matching the category defined in rating profiles. + Account string // account id (accounting subsystem) the record should be attached to + Subject string // rating subject (rating subsystem) this record should be attached to + Destination string // destination to be charged + SetupTime time.Time // set-up time of the event. Supported formats: datetime RFC3339 compatible, SQL datetime (eg: MySQL), unix timestamp. + AnswerTime time.Time // answer time of the event. Supported formats: datetime RFC3339 compatible, SQL datetime (eg: MySQL), unix timestamp. + Usage time.Duration // event usage information (eg: in case of tor=*voice this will represent the total duration of a call) + ExtraFields map[string]string // Extra fields to be stored in CDR + ExtraInfo string // Container for extra information related to this CDR, eg: populated with error reason in case of error on calculation + Partial bool // Used for partial record processing by CDRC + Rated bool // Mark the CDR as rated so we do not process it during rating + CostSource string // The source of this cost + Cost float64 + CostDetails *CallCost // Attach the cost details to CDR when possible } func (cdr *CDR) CostDetailsJson() string { @@ -114,11 +106,6 @@ func (cdr *CDR) CostDetailsJson() string { return string(mrshled) } -func (cdr *CDR) AccountSummaryJson() string { - mrshled, _ := json.Marshal(cdr.AccountSummary) - return string(mrshled) -} - func (cdr *CDR) ComputeCGRID() { cdr.CGRID = utils.Sha1(cdr.OriginID, cdr.SetupTime.UTC().String()) } @@ -173,8 +160,6 @@ func (cdr *CDR) FieldAsString(rsrFld *utils.RSRField) string { return rsrFld.ParseValue(cdr.Source) case utils.REQTYPE: return rsrFld.ParseValue(cdr.RequestType) - case utils.DIRECTION: - return rsrFld.ParseValue(cdr.Direction) case utils.TENANT: return rsrFld.ParseValue(cdr.Tenant) case utils.CATEGORY: @@ -187,16 +172,10 @@ func (cdr *CDR) FieldAsString(rsrFld *utils.RSRField) string { return rsrFld.ParseValue(cdr.Destination) case utils.SETUP_TIME: return rsrFld.ParseValue(cdr.SetupTime.Format(time.RFC3339)) - case utils.PDD: - return strconv.FormatFloat(cdr.PDD.Seconds(), 'f', -1, 64) case utils.ANSWER_TIME: return rsrFld.ParseValue(cdr.AnswerTime.Format(time.RFC3339)) case utils.USAGE: return strconv.FormatFloat(cdr.Usage.Seconds(), 'f', -1, 64) - case utils.SUPPLIER: - return rsrFld.ParseValue(cdr.Supplier) - case utils.DISCONNECT_CAUSE: - return rsrFld.ParseValue(cdr.DisconnectCause) case utils.MEDI_RUNID: return rsrFld.ParseValue(cdr.RunID) case utils.RATED_FLD: @@ -205,8 +184,6 @@ func (cdr *CDR) FieldAsString(rsrFld *utils.RSRField) string { return rsrFld.ParseValue(strconv.FormatFloat(cdr.Cost, 'f', -1, 64)) // Recommended to use FormatCost case utils.COST_DETAILS: return rsrFld.ParseValue(cdr.CostDetailsJson()) - case utils.ACCOUNT_SUMMARY: - return rsrFld.ParseValue(cdr.AccountSummaryJson()) case utils.PartialField: return rsrFld.ParseValue(strconv.FormatBool(cdr.Partial)) default: @@ -230,8 +207,6 @@ func (cdr *CDR) ParseFieldValue(fieldId, fieldVal, timezone string) error { cdr.OriginID += fieldVal case utils.REQTYPE: cdr.RequestType += fieldVal - case utils.DIRECTION: - cdr.Direction += fieldVal case utils.TENANT: cdr.Tenant += fieldVal case utils.CATEGORY: @@ -248,10 +223,6 @@ func (cdr *CDR) ParseFieldValue(fieldId, fieldVal, timezone string) error { if cdr.SetupTime, err = utils.ParseTimeDetectLayout(fieldVal, timezone); err != nil { return fmt.Errorf("Cannot parse answer time field with value: %s, err: %s", fieldVal, err.Error()) } - case utils.PDD: - if cdr.PDD, err = utils.ParseDurationWithSecs(fieldVal); err != nil { - return fmt.Errorf("Cannot parse answer time field with value: %s, err: %s", fieldVal, err.Error()) - } case utils.ANSWER_TIME: if cdr.AnswerTime, err = utils.ParseTimeDetectLayout(fieldVal, timezone); err != nil { return fmt.Errorf("Cannot parse answer time field with value: %s, err: %s", fieldVal, err.Error()) @@ -260,10 +231,6 @@ func (cdr *CDR) ParseFieldValue(fieldId, fieldVal, timezone string) error { if cdr.Usage, err = utils.ParseDurationWithSecs(fieldVal); err != nil { return fmt.Errorf("Cannot parse duration field with value: %s, err: %s", fieldVal, err.Error()) } - case utils.SUPPLIER: - cdr.Supplier += fieldVal - case utils.DISCONNECT_CAUSE: - cdr.DisconnectCause += fieldVal case utils.COST: if cdr.Cost, err = strconv.ParseFloat(fieldVal, 64); err != nil { return fmt.Errorf("Cannot parse cost field with value: %s, err: %s", fieldVal, err.Error()) @@ -296,8 +263,8 @@ func (cdr *CDR) Clone() *CDR { } // Used in mediation, primaryMandatory marks whether missing field out of request represents error or can be ignored -func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, PDDFld, - answerTimeFld, durationFld, supplierFld, disconnectCauseFld, ratedFld, costFld *utils.RSRField, +func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, + answerTimeFld, durationFld, ratedFld, costFld *utils.RSRField, extraFlds []*utils.RSRField, primaryMandatory bool, timezone string) (*CDR, error) { if RequestTypeFld == nil { RequestTypeFld, _ = utils.NewRSRField(utils.META_DEFAULT) @@ -305,12 +272,6 @@ func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, c if RequestTypeFld.Id == utils.META_DEFAULT { RequestTypeFld.Id = utils.REQTYPE } - if directionFld == nil { - directionFld, _ = utils.NewRSRField(utils.META_DEFAULT) - } - if directionFld.Id == utils.META_DEFAULT { - directionFld.Id = utils.DIRECTION - } if tenantFld == nil { tenantFld, _ = utils.NewRSRField(utils.META_DEFAULT) } @@ -359,24 +320,6 @@ func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, c if durationFld.Id == utils.META_DEFAULT { durationFld.Id = utils.USAGE } - if PDDFld == nil { - PDDFld, _ = utils.NewRSRField(utils.META_DEFAULT) - } - if PDDFld.Id == utils.META_DEFAULT { - PDDFld.Id = utils.PDD - } - if supplierFld == nil { - supplierFld, _ = utils.NewRSRField(utils.META_DEFAULT) - } - if supplierFld.Id == utils.META_DEFAULT { - supplierFld.Id = utils.SUPPLIER - } - if disconnectCauseFld == nil { - disconnectCauseFld, _ = utils.NewRSRField(utils.META_DEFAULT) - } - if disconnectCauseFld.Id == utils.META_DEFAULT { - disconnectCauseFld.Id = utils.DISCONNECT_CAUSE - } if ratedFld == nil { ratedFld, _ = utils.NewRSRField(utils.META_DEFAULT) } @@ -402,10 +345,6 @@ func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, c if primaryMandatory && len(frkStorCdr.RequestType) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.REQTYPE, RequestTypeFld.Id) } - frkStorCdr.Direction = cdr.FieldAsString(directionFld) - if primaryMandatory && len(frkStorCdr.Direction) == 0 { - return nil, utils.NewErrMandatoryIeMissing(utils.DIRECTION, directionFld.Id) - } frkStorCdr.Tenant = cdr.FieldAsString(tenantFld) if primaryMandatory && len(frkStorCdr.Tenant) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.TENANT, tenantFld.Id) @@ -444,14 +383,6 @@ func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, c } else if frkStorCdr.Usage, err = utils.ParseDurationWithSecs(durStr); err != nil { return nil, err } - PDDStr := cdr.FieldAsString(PDDFld) - if primaryMandatory && len(PDDStr) == 0 { - return nil, utils.NewErrMandatoryIeMissing(utils.PDD, PDDFld.Id) - } else if frkStorCdr.PDD, err = utils.ParseDurationWithSecs(PDDStr); err != nil { - return nil, err - } - frkStorCdr.Supplier = cdr.FieldAsString(supplierFld) - frkStorCdr.DisconnectCause = cdr.FieldAsString(disconnectCauseFld) ratedStr := cdr.FieldAsString(ratedFld) if primaryMandatory && len(ratedStr) == 0 { return nil, utils.NewErrMandatoryIeMissing(utils.RATED_FLD, ratedFld.Id) @@ -473,31 +404,27 @@ func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, c func (cdr *CDR) AsExternalCDR() *ExternalCDR { return &ExternalCDR{CGRID: cdr.CGRID, - RunID: cdr.RunID, - OrderID: cdr.OrderID, - OriginHost: cdr.OriginHost, - Source: cdr.Source, - OriginID: cdr.OriginID, - ToR: cdr.ToR, - RequestType: cdr.RequestType, - Direction: cdr.Direction, - Tenant: cdr.Tenant, - Category: cdr.Category, - Account: cdr.Account, - Subject: cdr.Subject, - Destination: cdr.Destination, - SetupTime: cdr.SetupTime.Format(time.RFC3339), - PDD: cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}), - AnswerTime: cdr.AnswerTime.Format(time.RFC3339), - Usage: cdr.FormatUsage(utils.SECONDS), - Supplier: cdr.Supplier, - DisconnectCause: cdr.DisconnectCause, - ExtraFields: cdr.ExtraFields, - CostSource: cdr.CostSource, - Cost: cdr.Cost, - CostDetails: cdr.CostDetailsJson(), - ExtraInfo: cdr.ExtraInfo, - Rated: cdr.Rated, + RunID: cdr.RunID, + OrderID: cdr.OrderID, + OriginHost: cdr.OriginHost, + Source: cdr.Source, + OriginID: cdr.OriginID, + ToR: cdr.ToR, + RequestType: cdr.RequestType, + Tenant: cdr.Tenant, + Category: cdr.Category, + Account: cdr.Account, + Subject: cdr.Subject, + Destination: cdr.Destination, + SetupTime: cdr.SetupTime.Format(time.RFC3339), + AnswerTime: cdr.AnswerTime.Format(time.RFC3339), + Usage: cdr.FormatUsage(utils.SECONDS), + ExtraFields: cdr.ExtraFields, + CostSource: cdr.CostSource, + Cost: cdr.Cost, + CostDetails: cdr.CostDetailsJson(), + ExtraInfo: cdr.ExtraInfo, + Rated: cdr.Rated, } } @@ -520,15 +447,6 @@ func (cdr *CDR) GetUUID() string { func (cdr *CDR) GetSessionIds() []string { return []string{cdr.GetUUID()} } -func (cdr *CDR) GetDirection(fieldName string) string { - if utils.IsSliceMember([]string{utils.DIRECTION, utils.META_DEFAULT, ""}, fieldName) { - return cdr.Direction - } - if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value - return fieldName[len(utils.STATIC_VALUE_PREFIX):] - } - return cdr.FieldAsString(&utils.RSRField{Id: fieldName}) -} func (cdr *CDR) GetSubject(fieldName string) string { if utils.IsSliceMember([]string{utils.SUBJECT, utils.META_DEFAULT, ""}, fieldName) { return cdr.Subject @@ -631,30 +549,6 @@ func (cdr *CDR) GetDuration(fieldName string) (time.Duration, error) { } return utils.ParseDurationWithSecs(durVal) } -func (cdr *CDR) GetPdd(fieldName string) (time.Duration, error) { - if utils.IsSliceMember([]string{utils.PDD, utils.META_DEFAULT, ""}, fieldName) { - return cdr.PDD, nil - } - var PDDVal string - if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value - PDDVal = fieldName[len(utils.STATIC_VALUE_PREFIX):] - } else { - PDDVal = cdr.FieldAsString(&utils.RSRField{Id: fieldName}) - } - return utils.ParseDurationWithSecs(PDDVal) -} -func (cdr *CDR) GetSupplier(fieldName string) string { - if utils.IsSliceMember([]string{utils.SUPPLIER, utils.META_DEFAULT, ""}, fieldName) { - return cdr.Supplier - } - return cdr.FieldAsString(&utils.RSRField{Id: fieldName}) -} -func (cdr *CDR) GetDisconnectCause(fieldName string) string { - if utils.IsSliceMember([]string{utils.DISCONNECT_CAUSE, utils.META_DEFAULT, ""}, fieldName) { - return cdr.DisconnectCause - } - return cdr.FieldAsString(&utils.RSRField{Id: fieldName}) -} func (cdr *CDR) GetOriginatorIP(fieldName string) string { if utils.IsSliceMember([]string{utils.CDRHOST, utils.META_DEFAULT, ""}, fieldName) { return cdr.OriginHost @@ -807,18 +701,14 @@ func (cdr *CDR) AsMapStringIface() (mp map[string]interface{}, err error) { mp[utils.ACCID] = cdr.OriginID mp[utils.TOR] = cdr.ToR mp[utils.REQTYPE] = cdr.RequestType - mp[utils.DIRECTION] = cdr.Direction mp[utils.TENANT] = cdr.Tenant mp[utils.CATEGORY] = cdr.Category mp[utils.ACCOUNT] = cdr.Account mp[utils.SUBJECT] = cdr.Subject mp[utils.DESTINATION] = cdr.Destination mp[utils.SETUP_TIME] = cdr.SetupTime - mp[utils.PDD] = cdr.PDD mp[utils.ANSWER_TIME] = cdr.AnswerTime mp[utils.USAGE] = cdr.Usage - mp[utils.SUPPLIER] = cdr.Supplier - mp[utils.DISCONNECT_CAUSE] = cdr.DisconnectCause mp[utils.CostSource] = cdr.CostSource mp[utils.COST] = cdr.Cost mp[utils.COST_DETAILS] = cdr.CostDetails @@ -868,40 +758,97 @@ func (cdr *CDR) AsExportMap(exportFields []*config.CfgCdrField, httpSkipTlsCheck return } +// AsCDRsTBL converts the CDR into the format used for SQL storage +func (cdr *CDR) AsCDRsql() (cdrSql *CDRsql) { + cdrSql = new(CDRsql) + cdrSql.CGRID = cdr.CGRID + cdrSql.RunID = cdr.RunID + cdrSql.OriginHost = cdr.OriginHost + cdrSql.Source = cdr.Source + cdrSql.OriginID = cdr.OriginID + cdrSql.TOR = cdr.ToR + cdrSql.RequestType = cdr.RequestType + cdrSql.Tenant = cdr.Tenant + cdrSql.Category = cdr.Category + cdrSql.Account = cdr.Account + cdrSql.Subject = cdr.Subject + cdrSql.Destination = cdr.Destination + cdrSql.SetupTime = cdr.SetupTime + cdrSql.AnswerTime = cdr.AnswerTime + cdrSql.Usage = cdr.Usage.Nanoseconds() + cdrSql.ExtraFields = utils.ToJSON(cdr.ExtraFields) + cdrSql.CostSource = cdr.CostSource + cdrSql.Cost = cdr.Cost + cdrSql.CostDetails = utils.ToJSON(cdr.CostDetails) + cdrSql.ExtraInfo = cdr.ExtraInfo + cdrSql.CreatedAt = time.Now() + return +} + +// NewCDRFromSQL converts the CDRsql into CDR +func NewCDRFromSQL(cdrSql *CDRsql) (cdr *CDR, err error) { + cdr = new(CDR) + cdr.CGRID = cdrSql.CGRID + cdr.RunID = cdrSql.RunID + cdr.OriginHost = cdrSql.OriginHost + cdr.Source = cdrSql.Source + cdr.OriginID = cdrSql.OriginID + cdr.ToR = cdrSql.TOR + cdr.RequestType = cdrSql.RequestType + cdr.Tenant = cdrSql.Tenant + cdr.Category = cdrSql.Category + cdr.Account = cdrSql.Account + cdr.Subject = cdrSql.Subject + cdr.Destination = cdrSql.Destination + cdr.SetupTime = cdrSql.SetupTime + cdr.AnswerTime = cdrSql.AnswerTime + cdr.Usage = time.Duration(cdrSql.Usage) + + cdr.CostSource = cdrSql.CostSource + cdr.Cost = cdrSql.Cost + cdr.ExtraInfo = cdrSql.ExtraInfo + if cdrSql.ExtraFields != "" { + if err = json.Unmarshal([]byte(cdrSql.ExtraFields), &cdr.ExtraFields); err != nil { + return nil, err + } + } + if cdrSql.CostDetails != "" { + if err = json.Unmarshal([]byte(cdrSql.CostDetails), cdr.CostDetails); err != nil { + return nil, err + } + } + return +} + type ExternalCDR struct { - CGRID string - RunID string - OrderID int64 - OriginHost string - Source string - OriginID string - ToR string - RequestType string - Direction string - Tenant string - Category string - Account string - Subject string - Destination string - SetupTime string - PDD string - AnswerTime string - Usage string - Supplier string - DisconnectCause string - ExtraFields map[string]string - CostSource string - Cost float64 - CostDetails string - ExtraInfo string - Rated bool // Mark the CDR as rated so we do not process it during mediation + CGRID string + RunID string + OrderID int64 + OriginHost string + Source string + OriginID string + ToR string + RequestType string + Tenant string + Category string + Account string + Subject string + Destination string + SetupTime string + AnswerTime string + Usage string + ExtraFields map[string]string + CostSource string + Cost float64 + CostDetails string + ExtraInfo string + Rated bool // Mark the CDR as rated so we do not process it during mediation } // Used when authorizing requests from outside, eg ApierV1.GetMaxUsage type UsageRecord struct { ToR string RequestType string - Direction string Tenant string Category string Account string @@ -915,8 +862,8 @@ type UsageRecord struct { func (self *UsageRecord) AsStoredCdr(timezone string) (*CDR, error) { var err error - cdr := &CDR{CGRID: self.GetId(), ToR: self.ToR, RequestType: self.RequestType, Direction: self.Direction, - Tenant: self.Tenant, Category: self.Category, Account: self.Account, Subject: self.Subject, Destination: self.Destination} + cdr := &CDR{CGRID: self.GetId(), ToR: self.ToR, RequestType: self.RequestType, Tenant: self.Tenant, + Category: self.Category, Account: self.Account, Subject: self.Subject, Destination: self.Destination} if cdr.SetupTime, err = utils.ParseTimeDetectLayout(self.SetupTime, timezone); err != nil { return nil, err } @@ -940,7 +887,7 @@ func (self *UsageRecord) AsCallDescriptor(timezone string, denyNegative bool) (* cd := &CallDescriptor{ CgrID: self.GetId(), TOR: self.ToR, - Direction: self.Direction, + Direction: utils.OUT, Tenant: self.Tenant, Category: self.Category, Subject: self.Subject, @@ -970,5 +917,5 @@ func (self *UsageRecord) AsCallDescriptor(timezone string, denyNegative bool) (* } func (self *UsageRecord) GetId() string { - return utils.Sha1(self.ToR, self.RequestType, self.Direction, self.Tenant, self.Category, self.Account, self.Subject, self.Destination, self.SetupTime, self.AnswerTime, self.Usage) + return utils.Sha1(self.ToR, self.RequestType, self.Tenant, self.Category, self.Account, self.Subject, self.Destination, self.SetupTime, self.AnswerTime, self.Usage) } diff --git a/engine/cdr_test.go b/engine/cdr_test.go index d76058532..b96ee41b8 100644 --- a/engine/cdr_test.go +++ b/engine/cdr_test.go @@ -33,17 +33,24 @@ func TestCDRInterfaces(t *testing.T) { } func TestNewCDRFromExternalCDR(t *testing.T) { - extCdr := &ExternalCDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1", + extCdr := &ExternalCDR{ + CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: utils.UNIT_TEST, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.DEFAULT_RUNID, - Usage: "0.00000001", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true, + Usage: "0.00000001", Cost: 1.01, Rated: true, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } - eStorCdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10), PDD: time.Duration(7) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true, + eStorCdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: utils.UNIT_TEST, RequestType: utils.META_RATED, RunID: utils.DEFAULT_RUNID, + Tenant: "cgrates.org", Category: "call", Account: "1001", + Subject: "1001", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10), Cost: 1.01, Rated: true, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } if CDR, err := NewCDRFromExternalCDR(extCdr, ""); err != nil { t.Error(err) @@ -53,11 +60,15 @@ func TestNewCDRFromExternalCDR(t *testing.T) { } func TestCDRClone(t *testing.T) { - storCdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10), PDD: time.Duration(7) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true, + storCdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Tenant: "cgrates.org", + Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10), + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, + Cost: 1.01, Rated: true, } if clnStorCdr := storCdr.Clone(); !reflect.DeepEqual(storCdr, clnStorCdr) { t.Errorf("Expecting: %+v, received: %+v", storCdr, clnStorCdr) @@ -65,13 +76,14 @@ func TestCDRClone(t *testing.T) { } func TestFieldAsString(t *testing.T) { - cdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", - OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", - Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + cdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", + OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", + Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10) * time.Second, PDD: time.Duration(5) * time.Second, Supplier: "SUPPL1", + Usage: time.Duration(10) * time.Second, Cost: 1.01, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - Cost: 1.01, } if cdr.FieldAsString(&utils.RSRField{Id: utils.CGRID}) != cdr.CGRID || cdr.FieldAsString(&utils.RSRField{Id: utils.ORDERID}) != "123" || @@ -80,7 +92,6 @@ func TestFieldAsString(t *testing.T) { cdr.FieldAsString(&utils.RSRField{Id: utils.CDRHOST}) != cdr.OriginHost || cdr.FieldAsString(&utils.RSRField{Id: utils.CDRSOURCE}) != cdr.Source || cdr.FieldAsString(&utils.RSRField{Id: utils.REQTYPE}) != cdr.RequestType || - cdr.FieldAsString(&utils.RSRField{Id: utils.DIRECTION}) != cdr.Direction || cdr.FieldAsString(&utils.RSRField{Id: utils.CATEGORY}) != cdr.Category || cdr.FieldAsString(&utils.RSRField{Id: utils.ACCOUNT}) != cdr.Account || cdr.FieldAsString(&utils.RSRField{Id: utils.SUBJECT}) != cdr.Subject || @@ -88,8 +99,6 @@ func TestFieldAsString(t *testing.T) { cdr.FieldAsString(&utils.RSRField{Id: utils.SETUP_TIME}) != cdr.SetupTime.Format(time.RFC3339) || cdr.FieldAsString(&utils.RSRField{Id: utils.ANSWER_TIME}) != cdr.AnswerTime.Format(time.RFC3339) || cdr.FieldAsString(&utils.RSRField{Id: utils.USAGE}) != "10" || - cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}) != "5" || - cdr.FieldAsString(&utils.RSRField{Id: utils.SUPPLIER}) != cdr.Supplier || cdr.FieldAsString(&utils.RSRField{Id: utils.MEDI_RUNID}) != cdr.RunID || cdr.FieldAsString(&utils.RSRField{Id: utils.COST}) != "1.01" || cdr.FieldAsString(&utils.RSRField{Id: "field_extr1"}) != cdr.ExtraFields["field_extr1"] || @@ -103,7 +112,6 @@ func TestFieldAsString(t *testing.T) { cdr.FieldAsString(&utils.RSRField{Id: utils.CDRHOST}) != cdr.OriginHost, cdr.FieldAsString(&utils.RSRField{Id: utils.CDRSOURCE}) != cdr.Source, cdr.FieldAsString(&utils.RSRField{Id: utils.REQTYPE}) != cdr.RequestType, - cdr.FieldAsString(&utils.RSRField{Id: utils.DIRECTION}) != cdr.Direction, cdr.FieldAsString(&utils.RSRField{Id: utils.CATEGORY}) != cdr.Category, cdr.FieldAsString(&utils.RSRField{Id: utils.ACCOUNT}) != cdr.Account, cdr.FieldAsString(&utils.RSRField{Id: utils.SUBJECT}) != cdr.Subject, @@ -111,8 +119,6 @@ func TestFieldAsString(t *testing.T) { cdr.FieldAsString(&utils.RSRField{Id: utils.SETUP_TIME}) != cdr.SetupTime.Format(time.RFC3339), cdr.FieldAsString(&utils.RSRField{Id: utils.ANSWER_TIME}) != cdr.AnswerTime.Format(time.RFC3339), cdr.FieldAsString(&utils.RSRField{Id: utils.USAGE}) != "10", - cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}) != "5", - cdr.FieldAsString(&utils.RSRField{Id: utils.SUPPLIER}) != cdr.Supplier, cdr.FieldAsString(&utils.RSRField{Id: utils.MEDI_RUNID}) != cdr.RunID, cdr.FieldAsString(&utils.RSRField{Id: utils.COST}) != "1.01", cdr.FieldAsString(&utils.RSRField{Id: "field_extr1"}) != cdr.ExtraFields["field_extr1"], @@ -122,15 +128,18 @@ func TestFieldAsString(t *testing.T) { } func TestFieldsAsString(t *testing.T) { - cdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", - OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", - Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10) * time.Second, PDD: time.Duration(5) * time.Second, Supplier: "SUPPL1", + cdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: "test", + RequestType: utils.META_RATED, Tenant: "cgrates.org", + Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, } eVal := "call_from_1001" - if val := cdr.FieldsAsString(utils.ParseRSRFieldsMustCompile("Category;^_from_;Account", utils.INFIELD_SEP)); val != eVal { + if val := cdr.FieldsAsString( + utils.ParseRSRFieldsMustCompile("Category;^_from_;Account", utils.INFIELD_SEP)); val != eVal { t.Errorf("Expecting : %s, received: %s", eVal, val) } } @@ -265,40 +274,47 @@ func TestCDRAsHttpForm(t *testing.T) { */ func TestCDRForkCdr(t *testing.T) { - storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), PDD: time.Duration(200) * time.Millisecond, - AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10) * time.Second, Supplier: "suppl1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}, Cost: 1.01} - rtSampleCdrOut, err := storCdr.ForkCdr("sample_run1", &utils.RSRField{Id: utils.REQTYPE}, &utils.RSRField{Id: utils.DIRECTION}, &utils.RSRField{Id: utils.TENANT}, + storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, + RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", Account: "1001", + Subject: "1001", Destination: "1002", RunID: utils.DEFAULT_RUNID, + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10) * time.Second, Cost: 1.01, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}} + rtSampleCdrOut, err := storCdr.ForkCdr("sample_run1", &utils.RSRField{Id: utils.REQTYPE}, &utils.RSRField{Id: utils.TENANT}, &utils.RSRField{Id: utils.CATEGORY}, &utils.RSRField{Id: utils.ACCOUNT}, &utils.RSRField{Id: utils.SUBJECT}, &utils.RSRField{Id: utils.DESTINATION}, - &utils.RSRField{Id: utils.SETUP_TIME}, &utils.RSRField{Id: utils.PDD}, &utils.RSRField{Id: utils.ANSWER_TIME}, &utils.RSRField{Id: utils.USAGE}, - &utils.RSRField{Id: utils.SUPPLIER}, &utils.RSRField{Id: utils.DISCONNECT_CAUSE}, &utils.RSRField{Id: utils.RATED_FLD}, &utils.RSRField{Id: utils.COST}, + &utils.RSRField{Id: utils.SETUP_TIME}, &utils.RSRField{Id: utils.ANSWER_TIME}, &utils.RSRField{Id: utils.USAGE}, + &utils.RSRField{Id: utils.RATED_FLD}, &utils.RSRField{Id: utils.COST}, []*utils.RSRField{&utils.RSRField{Id: "field_extr1"}, &utils.RSRField{Id: "field_extr2"}}, true, "") if err != nil { t.Error("Unexpected error received", err) } - expctSplRatedCdr := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), PDD: time.Duration(200) * time.Millisecond, AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, Supplier: "suppl1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}, - RunID: "sample_run1", Rated: false, Cost: 1.01} + expctSplRatedCdr := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", + OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10) * time.Second, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}, + RunID: "sample_run1", Rated: false, Cost: 1.01} if !reflect.DeepEqual(expctSplRatedCdr, rtSampleCdrOut) { t.Errorf("Expected: %v, received: %v", expctSplRatedCdr, rtSampleCdrOut) } } func TestCDRForkCdrStaticVals(t *testing.T) { - storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", - OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", + storCdr := CDR{ + CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", + OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, + Usage: time.Duration(10) * time.Second, Cost: 1.01, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } rsrStPostpaid, _ := utils.NewRSRField("^" + utils.META_POSTPAID) - rsrStIn, _ := utils.NewRSRField("^*in") rsrStCgr, _ := utils.NewRSRField("^cgrates.com") rsrStPC, _ := utils.NewRSRField("^premium_call") rsrStFA, _ := utils.NewRSRField("^first_account") @@ -306,52 +322,55 @@ func TestCDRForkCdrStaticVals(t *testing.T) { rsrStST, _ := utils.NewRSRField("^2013-12-07T08:42:24Z") rsrStAT, _ := utils.NewRSRField("^2013-12-07T08:42:26Z") rsrStDur, _ := utils.NewRSRField("^12s") - rsrStSuppl, _ := utils.NewRSRField("^supplier1") - rsrStDCause, _ := utils.NewRSRField("^HANGUP_COMPLETE") - rsrPDD, _ := utils.NewRSRField("^3") rsrStRated, _ := utils.NewRSRField("^true") rsrStCost, _ := utils.NewRSRField("^1.2") - rtCdrOut2, err := storCdr.ForkCdr("wholesale_run", rsrStPostpaid, rsrStIn, rsrStCgr, rsrStPC, rsrStFA, rsrStFS, &utils.RSRField{Id: utils.DESTINATION}, - rsrStST, rsrPDD, rsrStAT, rsrStDur, rsrStSuppl, rsrStDCause, rsrStRated, rsrStCost, []*utils.RSRField{}, true, "") + rtCdrOut2, err := storCdr.ForkCdr("wholesale_run", rsrStPostpaid, rsrStCgr, rsrStPC, rsrStFA, rsrStFS, &utils.RSRField{Id: utils.DESTINATION}, + rsrStST, rsrStAT, rsrStDur, rsrStRated, rsrStCost, []*utils.RSRField{}, true, "") if err != nil { t.Error("Unexpected error received", err) } - expctRatedCdr2 := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, - Direction: "*in", Tenant: "cgrates.com", Category: "premium_call", Account: "first_account", Subject: "first_subject", Destination: "1002", + expctRatedCdr2 := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", + OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, + Tenant: "cgrates.com", Category: "premium_call", Account: "first_account", + Subject: "first_subject", Destination: "1002", SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), - AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(12) * time.Second, PDD: time.Duration(3) * time.Second, - Supplier: "supplier1", DisconnectCause: "HANGUP_COMPLETE", Rated: true, Cost: 1.2, + AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(12) * time.Second, Rated: true, Cost: 1.2, ExtraFields: map[string]string{}, RunID: "wholesale_run"} if !reflect.DeepEqual(rtCdrOut2, expctRatedCdr2) { t.Errorf("Received: %v, expected: %v", rtCdrOut2, expctRatedCdr2) } - _, err = storCdr.ForkCdr("wholesale_run", &utils.RSRField{Id: "dummy_header"}, &utils.RSRField{Id: utils.DIRECTION}, &utils.RSRField{Id: utils.TENANT}, - &utils.RSRField{Id: utils.TOR}, &utils.RSRField{Id: utils.ACCOUNT}, &utils.RSRField{Id: utils.SUBJECT}, &utils.RSRField{Id: utils.DESTINATION}, - &utils.RSRField{Id: utils.SETUP_TIME}, &utils.RSRField{Id: utils.PDD}, &utils.RSRField{Id: utils.ANSWER_TIME}, &utils.RSRField{Id: utils.USAGE}, - &utils.RSRField{Id: utils.SUPPLIER}, - &utils.RSRField{Id: utils.DISCONNECT_CAUSE}, &utils.RSRField{Id: utils.RATED_FLD}, &utils.RSRField{Id: utils.COST}, []*utils.RSRField{}, true, "") + _, err = storCdr.ForkCdr("wholesale_run", &utils.RSRField{Id: "dummy_header"}, + &utils.RSRField{Id: utils.TENANT}, &utils.RSRField{Id: utils.TOR}, &utils.RSRField{Id: utils.ACCOUNT}, + &utils.RSRField{Id: utils.SUBJECT}, &utils.RSRField{Id: utils.DESTINATION}, + &utils.RSRField{Id: utils.SETUP_TIME}, &utils.RSRField{Id: utils.ANSWER_TIME}, &utils.RSRField{Id: utils.USAGE}, + &utils.RSRField{Id: utils.RATED_FLD}, &utils.RSRField{Id: utils.COST}, []*utils.RSRField{}, true, "") if err == nil { t.Error("Failed to detect missing header") } } func TestCDRForkCdrFromMetaDefaults(t *testing.T) { - storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", - OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", - Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10) * time.Second, PDD: time.Duration(4) * time.Second, Supplier: "SUPPL3", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, + storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, + RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", + Account: "1001", Subject: "1001", Destination: "1002", RunID: utils.DEFAULT_RUNID, + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10) * time.Second, Cost: 1.01, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } - expctCdr := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(4) * time.Second, Supplier: "SUPPL3", Cost: 1.01, - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, RunID: "wholesale_run"} - cdrOut, err := storCdr.ForkCdr("wholesale_run", &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, - &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, - &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, - &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, + expctCdr := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", + OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10) * time.Second, Cost: 1.01, RunID: "wholesale_run", + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + cdrOut, err := storCdr.ForkCdr("wholesale_run", &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, + &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, + &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, + &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, []*utils.RSRField{&utils.RSRField{Id: "field_extr1"}, &utils.RSRField{Id: "fieldextr2"}}, true, "") if err != nil { t.Fatal("Unexpected error received", err) @@ -361,7 +380,7 @@ func TestCDRForkCdrFromMetaDefaults(t *testing.T) { t.Errorf("Expected: %v, received: %v", expctCdr, cdrOut) } // Should also accept nil as defaults - if cdrOut, err := storCdr.ForkCdr("wholesale_run", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + if cdrOut, err := storCdr.ForkCdr("wholesale_run", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []*utils.RSRField{&utils.RSRField{Id: "field_extr1"}, &utils.RSRField{Id: "fieldextr2"}}, true, ""); err != nil { t.Fatal("Unexpected error received", err) } else if !reflect.DeepEqual(expctCdr, cdrOut) { @@ -370,28 +389,35 @@ func TestCDRForkCdrFromMetaDefaults(t *testing.T) { } func TestCDRAsExternalCDR(t *testing.T) { - storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", + storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10), PDD: time.Duration(7) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01} - expectOutCdr := &ExternalCDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10), Cost: 1.01, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + expectOutCdr := &ExternalCDR{ + CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.DEFAULT_RUNID, - Usage: "0.00000001", PDD: "7", Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, CostDetails: "null"} + Usage: "0.00000001", Cost: 1.01, CostDetails: "null", + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} if cdrOut := storCdr.AsExternalCDR(); !reflect.DeepEqual(expectOutCdr, cdrOut) { t.Errorf("Expected: %+v, received: %+v", expectOutCdr, cdrOut) } } func TestCDREventFields(t *testing.T) { - cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", - OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dans", - Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 27, 0, time.UTC), - RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, Supplier: "suppl1", + cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: "test", RequestType: utils.META_RATED, Tenant: "cgrates.org", + Category: "call", Account: "dan", Subject: "dans", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 27, 0, time.UTC), + RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01} if ev := cdr.AsEvent(""); ev != Event(cdr) { @@ -406,9 +432,6 @@ func TestCDREventFields(t *testing.T) { if res := cdr.GetUUID(); res != "dsafdsaf" { t.Error("Received: ", res) } - if res := cdr.GetDirection(utils.META_DEFAULT); res != "*out" { - t.Error("Received: ", res) - } if res := cdr.GetSubject(utils.META_DEFAULT); res != "dans" { t.Error("Received: ", res) } @@ -442,9 +465,6 @@ func TestCDREventFields(t *testing.T) { if dur, _ := cdr.GetDuration(utils.META_DEFAULT); dur != cdr.Usage { t.Error("Received: ", dur) } - if suppl := cdr.GetSupplier(utils.META_DEFAULT); suppl != cdr.Supplier { - t.Error("Received: ", suppl) - } if res := cdr.GetOriginatorIP(utils.META_DEFAULT); res != cdr.OriginHost { t.Error("Received: ", res) } @@ -454,13 +474,17 @@ func TestCDREventFields(t *testing.T) { } func TesUsageReqAsCDR(t *testing.T) { - setupReq := &UsageRecord{ToR: utils.VOICE, RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", + setupReq := &UsageRecord{ToR: utils.VOICE, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", Usage: "0.00000001", - } - eStorCdr := &CDR{ToR: utils.VOICE, RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(10)} + SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", + Usage: "0.00000001"} + eStorCdr := &CDR{ToR: utils.VOICE, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", + Subject: "1001", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10)} if CDR, err := setupReq.AsStoredCdr(""); err != nil { t.Error(err) } else if !reflect.DeepEqual(eStorCdr, CDR) { @@ -469,13 +493,19 @@ func TesUsageReqAsCDR(t *testing.T) { } func TestUsageReqAsCD(t *testing.T) { - req := &UsageRecord{ToR: utils.VOICE, RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", + req := &UsageRecord{ToR: utils.VOICE, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", Usage: "0.00000001", + SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", + Usage: "0.00000001", } - eCD := &CallDescriptor{CgrID: "9473e7b2e075d168b9da10ae957ee68fe5a217e4", TOR: req.ToR, Direction: req.Direction, Tenant: req.Tenant, - Category: req.Category, Account: req.Account, Subject: req.Subject, Destination: req.Destination, - TimeStart: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), TimeEnd: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).Add(time.Duration(10)), DenyNegativeAccount: true} + eCD := &CallDescriptor{CgrID: "48ca1a2eb82b028fbfc809e36a585061a775ffc3", TOR: req.ToR, + Direction: utils.OUT, Tenant: req.Tenant, + Category: req.Category, Account: req.Account, + Subject: req.Subject, Destination: req.Destination, + TimeStart: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + TimeEnd: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).Add(time.Duration(10)), + DenyNegativeAccount: true} if cd, err := req.AsCallDescriptor("", true); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCD, cd) { @@ -511,7 +541,6 @@ func TestCDRAsMapStringIface(t *testing.T) { OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1002", @@ -521,40 +550,35 @@ func TestCDRAsMapStringIface(t *testing.T) { AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, - Supplier: "SUPPL1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, } mp := map[string]interface{}{ - "field_extr1": "val_extr1", - "fieldextr2": "valextr2", - utils.CGRID: cdr.CGRID, - utils.MEDI_RUNID: utils.DEFAULT_RUNID, - utils.ORDERID: cdr.OrderID, - utils.CDRHOST: "192.168.1.1", - utils.CDRSOURCE: utils.UNIT_TEST, - utils.ACCID: "dsafdsaf", - utils.TOR: utils.VOICE, - utils.REQTYPE: utils.META_RATED, - utils.DIRECTION: "*out", - utils.TENANT: "cgrates.org", - utils.CATEGORY: "call", - utils.ACCOUNT: "1002", - utils.SUBJECT: "1001", - utils.DESTINATION: "+4986517174963", - utils.SETUP_TIME: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), - utils.PDD: time.Duration(0) * time.Second, - utils.ANSWER_TIME: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - utils.USAGE: time.Duration(10) * time.Second, - utils.SUPPLIER: "SUPPL1", - utils.DISCONNECT_CAUSE: cdr.DisconnectCause, - utils.CostSource: cdr.CostSource, - utils.COST: 1.01, - utils.COST_DETAILS: cdr.CostDetails, - utils.RATED: false, - utils.PartialField: false, - utils.ExtraInfo: cdr.ExtraInfo, + "field_extr1": "val_extr1", + "fieldextr2": "valextr2", + utils.CGRID: cdr.CGRID, + utils.MEDI_RUNID: utils.DEFAULT_RUNID, + utils.ORDERID: cdr.OrderID, + utils.CDRHOST: "192.168.1.1", + utils.CDRSOURCE: utils.UNIT_TEST, + utils.ACCID: "dsafdsaf", + utils.TOR: utils.VOICE, + utils.REQTYPE: utils.META_RATED, + utils.TENANT: "cgrates.org", + utils.CATEGORY: "call", + utils.ACCOUNT: "1002", + utils.SUBJECT: "1001", + utils.DESTINATION: "+4986517174963", + utils.SETUP_TIME: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + utils.ANSWER_TIME: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + utils.USAGE: time.Duration(10) * time.Second, + utils.CostSource: cdr.CostSource, + utils.COST: 1.01, + utils.COST_DETAILS: cdr.CostDetails, + utils.RATED: false, + utils.PartialField: false, + utils.ExtraInfo: cdr.ExtraInfo, } if cdrMp, err := cdr.AsMapStringIface(); err != nil { t.Error(err) @@ -571,7 +595,7 @@ func TestCDRAsExportRecord(t *testing.T) { ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", @@ -635,12 +659,15 @@ func TestCDRAsExportRecord(t *testing.T) { } func TestCDRAsExportMap(t *testing.T) { - cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", - OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "+4986517174963", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(10) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, + cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", + OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", + Subject: "1001", Destination: "+4986517174963", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, + Usage: time.Duration(10) * time.Second, Cost: 1.01, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } eCDRMp := map[string]string{ utils.CGRID: cdr.CGRID, diff --git a/engine/cdrecsv_test.go b/engine/cdrecsv_test.go index 2b1ec84ba..1158a7dcf 100644 --- a/engine/cdrecsv_test.go +++ b/engine/cdrecsv_test.go @@ -32,11 +32,14 @@ func TestCsvCdrWriter(t *testing.T) { writer := &bytes.Buffer{} cfg, _ := config.NewDefaultCGRConfig() storedCdr1 := &CDR{ - CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", - RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", - Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(), - Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, - ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01, + CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), + ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", + Account: "1001", Subject: "1001", Destination: "1002", + SetupTime: time.Unix(1383813745, 0).UTC(), + AnswerTime: time.Unix(1383813746, 0).UTC(), + Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 1.01, + ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, } cdre, err := NewCDRExporter([]*CDR{storedCdr1}, cfg.CdreProfiles["*default"], utils.MetaFileCSV, "", "", "firstexport", true, 1, ',', map[string]float64{}, 0.0, cfg.RoundingDecimals, cfg.HttpSkipTlsVerify, nil) @@ -50,7 +53,7 @@ func TestCsvCdrWriter(t *testing.T) { if err := cdre.writeCsv(csvWriter); err != nil { t.Error("Unexpected error: ", err) } - expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6,*default,*voice,dsafdsaf,*rated,*out,cgrates.org,call,1001,1001,1002,2013-11-07T08:42:25Z,2013-11-07T08:42:26Z,10,1.01000` + expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6,*default,*voice,dsafdsaf,*rated,cgrates.org,call,1001,1001,1002,2013-11-07T08:42:25Z,2013-11-07T08:42:26Z,10,1.01000` result := strings.TrimSpace(writer.String()) if result != expected { t.Errorf("Expected: \n%s received: \n%s.", expected, result) @@ -63,11 +66,15 @@ func TestCsvCdrWriter(t *testing.T) { func TestAlternativeFieldSeparator(t *testing.T) { writer := &bytes.Buffer{} cfg, _ := config.NewDefaultCGRConfig() - storedCdr1 := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", - RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", - Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(), - Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, - ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01, + storedCdr1 := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), + ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", + Account: "1001", Subject: "1001", Destination: "1002", + SetupTime: time.Unix(1383813745, 0).UTC(), + AnswerTime: time.Unix(1383813746, 0).UTC(), + Usage: time.Duration(10) * time.Second, + RunID: utils.DEFAULT_RUNID, Cost: 1.01, + ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, } cdre, err := NewCDRExporter([]*CDR{storedCdr1}, cfg.CdreProfiles["*default"], utils.MetaFileCSV, "", "", "firstexport", true, 1, '|', map[string]float64{}, 0.0, cfg.RoundingDecimals, cfg.HttpSkipTlsVerify, nil) @@ -81,7 +88,7 @@ func TestAlternativeFieldSeparator(t *testing.T) { if err := cdre.writeCsv(csvWriter); err != nil { t.Error("Unexpected error: ", err) } - expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6|*default|*voice|dsafdsaf|*rated|*out|cgrates.org|call|1001|1001|1002|2013-11-07T08:42:25Z|2013-11-07T08:42:26Z|10|1.01000` + expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6|*default|*voice|dsafdsaf|*rated|cgrates.org|call|1001|1001|1002|2013-11-07T08:42:25Z|2013-11-07T08:42:26Z|10|1.01000` result := strings.TrimSpace(writer.String()) if result != expected { t.Errorf("Expected: \n%s received: \n%s.", expected, result) diff --git a/engine/cdrefwv_test.go b/engine/cdrefwv_test.go index 9a52e878b..4c29f3065 100644 --- a/engine/cdrefwv_test.go +++ b/engine/cdrefwv_test.go @@ -28,28 +28,45 @@ import ( ) var hdrJsnCfgFlds = []*config.CdrFieldJsonCfg{ - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("TypeOfRecord"), Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("10"), Width: utils.IntPointer(2)}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Filler1"), Type: utils.StringPointer(utils.META_FILLER), Width: utils.IntPointer(3)}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("DistributorCode"), Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("VOI"), Width: utils.IntPointer(3)}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("FileSeqNr"), Type: utils.StringPointer(utils.META_HANDLER), Value: utils.StringPointer(META_EXPORTID), - Width: utils.IntPointer(5), Strip: utils.StringPointer("right"), Padding: utils.StringPointer("zeroleft")}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("LastCdr"), Type: utils.StringPointer(utils.META_HANDLER), Value: utils.StringPointer(META_LASTCDRATIME), + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("TypeOfRecord"), + Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("10"), + Width: utils.IntPointer(2)}, + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Filler1"), + Type: utils.StringPointer(utils.META_FILLER), Width: utils.IntPointer(3)}, + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("DistributorCode"), + Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("VOI"), + Width: utils.IntPointer(3)}, + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("FileSeqNr"), + Type: utils.StringPointer(utils.META_HANDLER), Value: utils.StringPointer(META_EXPORTID), + Width: utils.IntPointer(5), Strip: utils.StringPointer("right"), + Padding: utils.StringPointer("zeroleft")}, + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("LastCdr"), + Type: utils.StringPointer(utils.META_HANDLER), Value: utils.StringPointer(META_LASTCDRATIME), Width: utils.IntPointer(12), Layout: utils.StringPointer("020106150400")}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("FileCreationfTime"), Type: utils.StringPointer(utils.META_HANDLER), Value: utils.StringPointer(META_TIMENOW), + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("FileCreationfTime"), + Type: utils.StringPointer(utils.META_HANDLER), Value: utils.StringPointer(META_TIMENOW), Width: utils.IntPointer(12), Layout: utils.StringPointer("020106150400")}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("FileVersion"), Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("01"), Width: utils.IntPointer(2)}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Filler2"), Type: utils.StringPointer(utils.META_FILLER), Width: utils.IntPointer(105)}, + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("FileVersion"), + Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("01"), + Width: utils.IntPointer(2)}, + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Filler2"), + Type: utils.StringPointer(utils.META_FILLER), Width: utils.IntPointer(105)}, } var contentJsnCfgFlds = []*config.CdrFieldJsonCfg{ - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("TypeOfRecord"), Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("20"), Width: utils.IntPointer(2)}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Account"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.ACCOUNT), Width: utils.IntPointer(12), + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("TypeOfRecord"), + Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("20"), Width: utils.IntPointer(2)}, + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Account"), Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer(utils.ACCOUNT), Width: utils.IntPointer(12), Strip: utils.StringPointer("left"), Padding: utils.StringPointer("right")}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.SUBJECT), Width: utils.IntPointer(5), + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"), Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer(utils.SUBJECT), Width: utils.IntPointer(5), Strip: utils.StringPointer("right"), Padding: utils.StringPointer("right")}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("CLI"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("cli"), Width: utils.IntPointer(15), + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("CLI"), Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer("cli"), Width: utils.IntPointer(15), Strip: utils.StringPointer("xright"), Padding: utils.StringPointer("right")}, - &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.DESTINATION), Width: utils.IntPointer(24), + &config.CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"), Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer(utils.DESTINATION), Width: utils.IntPointer(24), Strip: utils.StringPointer("xright"), Padding: utils.StringPointer("right")}, &config.CdrFieldJsonCfg{Tag: utils.StringPointer("TOR"), Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("02"), Width: utils.IntPointer(2)}, &config.CdrFieldJsonCfg{Tag: utils.StringPointer("SubtypeTOR"), Type: utils.StringPointer(utils.META_CONSTANT), Value: utils.StringPointer("11"), Width: utils.IntPointer(4), @@ -117,11 +134,12 @@ func TestWriteCdr(t *testing.T) { } cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), ToR: utils.VOICE, OrderID: 1, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", - RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", - Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", + Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 2.34567, + Usage: time.Duration(10) * time.Second, + RunID: utils.DEFAULT_RUNID, Cost: 2.34567, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } @@ -178,7 +196,8 @@ func TestWriteCdrs(t *testing.T) { TrailerFields: trailerCfgFlds, } cdr1 := &CDR{CGRID: utils.Sha1("aaa1", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), - ToR: utils.VOICE, OrderID: 2, OriginID: "aaa1", OriginHost: "192.168.1.1", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", + ToR: utils.VOICE, OrderID: 2, OriginID: "aaa1", OriginHost: "192.168.1.1", + RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1010", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), @@ -186,20 +205,24 @@ func TestWriteCdrs(t *testing.T) { ExtraFields: map[string]string{"productnumber": "12341", "fieldextr2": "valextr2"}, } cdr2 := &CDR{CGRID: utils.Sha1("aaa2", time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC).String()), - ToR: utils.VOICE, OrderID: 4, OriginID: "aaa2", OriginHost: "192.168.1.2", RequestType: utils.META_PREPAID, Direction: "*out", Tenant: "cgrates.org", + ToR: utils.VOICE, OrderID: 4, OriginID: "aaa2", OriginHost: "192.168.1.2", + RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", Destination: "1011", SetupTime: time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 7, 42, 26, 0, time.UTC), - Usage: time.Duration(5) * time.Minute, RunID: utils.DEFAULT_RUNID, Cost: 1.40001, + Usage: time.Duration(5) * time.Minute, + RunID: utils.DEFAULT_RUNID, Cost: 1.40001, ExtraFields: map[string]string{"productnumber": "12342", "fieldextr2": "valextr2"}, } cdr3 := &CDR{} cdr4 := &CDR{CGRID: utils.Sha1("aaa3", time.Date(2013, 11, 7, 9, 42, 18, 0, time.UTC).String()), - ToR: utils.VOICE, OrderID: 3, OriginID: "aaa4", OriginHost: "192.168.1.4", RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org", + ToR: utils.VOICE, OrderID: 3, OriginID: "aaa4", OriginHost: "192.168.1.4", + RequestType: utils.META_POSTPAID, Tenant: "cgrates.org", Category: "call", Account: "1004", Subject: "1004", Destination: "1013", SetupTime: time.Date(2013, 11, 7, 9, 42, 18, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 9, 42, 26, 0, time.UTC), - Usage: time.Duration(20) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 2.34567, + Usage: time.Duration(20) * time.Second, + RunID: utils.DEFAULT_RUNID, Cost: 2.34567, ExtraFields: map[string]string{"productnumber": "12344", "fieldextr2": "valextr2"}, } cfg, _ := config.NewDefaultCGRConfig() diff --git a/engine/cdrs.go b/engine/cdrs.go index 953160bee..1b3ba3864 100644 --- a/engine/cdrs.go +++ b/engine/cdrs.go @@ -166,9 +166,6 @@ func (self *CdrServer) storeSMCost(smCost *SMCost, checkDuplicate bool) error { // Returns error if not able to properly store the CDR, mediation is async since we can always recover offline func (self *CdrServer) processCdr(cdr *CDR) (err error) { - if cdr.Direction == "" { - cdr.Direction = utils.OUT - } if cdr.RequestType == "" { cdr.RequestType = self.cgrCfg.DefaultReqType } @@ -248,7 +245,7 @@ func (self *CdrServer) deriveRateStoreStatsReplicate(cdr *CDR, store, cdrstats, } if err := LoadAlias(&AttrMatchingAlias{ Destination: cdrRun.Destination, - Direction: cdrRun.Direction, + Direction: utils.OUT, Tenant: cdrRun.Tenant, Category: cdrRun.Category, Account: cdrRun.Account, @@ -275,21 +272,6 @@ func (self *CdrServer) deriveRateStoreStatsReplicate(cdr *CDR, store, cdrstats, } } } - // Store AccountSummary if requested - if self.cgrCfg.CDRScdrAccountSummary { - for _, ratedCDR := range ratedCDRs { - if utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID, utils.META_PSEUDOPREPAID, utils.PSEUDOPREPAID, - utils.META_POSTPAID, utils.POSTPAID}, ratedCDR.RequestType) { - acntID := utils.ConcatenatedKey(ratedCDR.Tenant, ratedCDR.Account) - acnt, err := self.dm.DataDB().GetAccount(acntID) - if err != nil { - utils.Logger.Err(fmt.Sprintf(" Querying AccountDigest for account: %s got error: %s", acntID, err.Error())) - } else if acnt.ID != "" { - ratedCDR.AccountSummary = acnt.AsAccountSummary() - } - } - } - } // Store rated CDRs if store { for _, ratedCDR := range ratedCDRs { @@ -340,7 +322,7 @@ func (self *CdrServer) deriveCdrs(cdr *CDR) ([]*CDR, error) { } if err := LoadAlias(&AttrMatchingAlias{ Destination: cdr.Destination, - Direction: cdr.Direction, + Direction: utils.OUT, Tenant: cdr.Tenant, Category: cdr.Category, Account: cdr.Account, @@ -349,7 +331,7 @@ func (self *CdrServer) deriveCdrs(cdr *CDR) ([]*CDR, error) { }, cdr, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound { return nil, err } - attrsDC := &utils.AttrDerivedChargers{Tenant: cdr.Tenant, Category: cdr.Category, Direction: cdr.Direction, + attrsDC := &utils.AttrDerivedChargers{Tenant: cdr.Tenant, Category: cdr.Category, Direction: utils.OUT, Account: cdr.Account, Subject: cdr.Subject, Destination: cdr.Destination} var dcs utils.DerivedChargers if err := self.rals.Call("Responder.GetDerivedChargers", attrsDC, &dcs); err != nil { @@ -369,18 +351,14 @@ func (self *CdrServer) deriveCdrs(cdr *CDR) ([]*CDR, error) { continue } dcRequestTypeFld, _ := utils.NewRSRField(dc.RequestTypeField) - dcDirFld, _ := utils.NewRSRField(dc.DirectionField) dcTenantFld, _ := utils.NewRSRField(dc.TenantField) dcCategoryFld, _ := utils.NewRSRField(dc.CategoryField) dcAcntFld, _ := utils.NewRSRField(dc.AccountField) dcSubjFld, _ := utils.NewRSRField(dc.SubjectField) dcDstFld, _ := utils.NewRSRField(dc.DestinationField) dcSTimeFld, _ := utils.NewRSRField(dc.SetupTimeField) - dcPddFld, _ := utils.NewRSRField(dc.PDDField) dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField) dcDurFld, _ := utils.NewRSRField(dc.UsageField) - dcSupplFld, _ := utils.NewRSRField(dc.SupplierField) - dcDCauseFld, _ := utils.NewRSRField(dc.DisconnectCauseField) dcRatedFld, _ := utils.NewRSRField(dc.RatedField) dcCostFld, _ := utils.NewRSRField(dc.CostField) @@ -389,8 +367,8 @@ func (self *CdrServer) deriveCdrs(cdr *CDR) ([]*CDR, error) { dcExtraFields = append(dcExtraFields, &utils.RSRField{Id: key}) } - forkedCdr, err := cdr.ForkCdr(dc.RunID, dcRequestTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld, - dcSTimeFld, dcPddFld, dcATimeFld, dcDurFld, dcSupplFld, dcDCauseFld, dcRatedFld, dcCostFld, dcExtraFields, true, self.cgrCfg.DefaultTimezone) + forkedCdr, err := cdr.ForkCdr(dc.RunID, dcRequestTypeFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld, + dcSTimeFld, dcATimeFld, dcDurFld, dcRatedFld, dcCostFld, dcExtraFields, true, self.cgrCfg.DefaultTimezone) if err != nil { utils.Logger.Err(fmt.Sprintf("Could not fork CGR with cgrid %s, run: %s, error: %s", cdr.CGRID, dc.RunID, err.Error())) continue // do not add it to the forked CDR list @@ -470,7 +448,7 @@ func (self *CdrServer) getCostFromRater(cdr *CDR) (*CallCost, error) { } cd := &CallDescriptor{ TOR: cdr.ToR, - Direction: cdr.Direction, + Direction: utils.OUT, Tenant: cdr.Tenant, Category: cdr.Category, Subject: cdr.Subject, diff --git a/engine/cdrstats.go b/engine/cdrstats.go index 842ed2a48..ffaf57236 100644 --- a/engine/cdrstats.go +++ b/engine/cdrstats.go @@ -105,9 +105,6 @@ func (cs *CdrStats) AcceptCdr(cdr *CDR) bool { if len(cs.ReqType) > 0 && !utils.IsSliceMember(cs.ReqType, cdr.RequestType) { return false } - if len(cs.Direction) > 0 && !utils.IsSliceMember(cs.Direction, cdr.Direction) { - return false - } if len(cs.Tenant) > 0 && !utils.IsSliceMember(cs.Tenant, cdr.Tenant) { return false } @@ -150,20 +147,6 @@ func (cs *CdrStats) AcceptCdr(cdr *CDR) bool { return false } } - if len(cs.PddInterval) > 0 { - if cdr.PDD < cs.PddInterval[0] { - return false - } - if len(cs.PddInterval) > 1 && cdr.PDD >= cs.PddInterval[1] { - return false - } - } - if len(cs.Supplier) > 0 && !utils.IsSliceMember(cs.Supplier, cdr.Supplier) { - return false - } - if len(cs.DisconnectCause) > 0 && !utils.IsSliceMember(cs.DisconnectCause, cdr.DisconnectCause) { - return false - } if len(cs.MediationRunIds) > 0 && !utils.IsSliceMember(cs.MediationRunIds, cdr.RunID) { return false } diff --git a/engine/cdrstats_queue.go b/engine/cdrstats_queue.go index 20a9a6711..d1150e67a 100644 --- a/engine/cdrstats_queue.go +++ b/engine/cdrstats_queue.go @@ -201,7 +201,6 @@ func (sq *CDRStatsQueue) simplifyCdr(cdr *CDR) *QCdr { return &QCdr{ SetupTime: cdr.SetupTime, AnswerTime: cdr.AnswerTime, - Pdd: cdr.PDD, Usage: cdr.Usage, Cost: cdr.Cost, Dest: cdr.Destination, diff --git a/engine/cgrcdr.go b/engine/cgrcdr.go index 54e0af8e6..de3cbe296 100644 --- a/engine/cgrcdr.go +++ b/engine/cgrcdr.go @@ -66,18 +66,14 @@ func (cgrCdr CgrCdr) AsStoredCdr(timezone string) *CDR { storCdr.OriginHost = cgrCdr[utils.CDRHOST] storCdr.Source = cgrCdr[utils.CDRSOURCE] storCdr.RequestType = cgrCdr[utils.REQTYPE] - storCdr.Direction = utils.OUT storCdr.Tenant = cgrCdr[utils.TENANT] storCdr.Category = cgrCdr[utils.CATEGORY] storCdr.Account = cgrCdr[utils.ACCOUNT] storCdr.Subject = cgrCdr[utils.SUBJECT] storCdr.Destination = cgrCdr[utils.DESTINATION] storCdr.SetupTime, _ = utils.ParseTimeDetectLayout(cgrCdr[utils.SETUP_TIME], timezone) // Not interested to process errors, should do them if necessary in a previous step - storCdr.PDD, _ = utils.ParseDurationWithSecs(cgrCdr[utils.PDD]) storCdr.AnswerTime, _ = utils.ParseTimeDetectLayout(cgrCdr[utils.ANSWER_TIME], timezone) storCdr.Usage, _ = utils.ParseDurationWithSecs(cgrCdr[utils.USAGE]) - storCdr.Supplier = cgrCdr[utils.SUPPLIER] - storCdr.DisconnectCause = cgrCdr[utils.DISCONNECT_CAUSE] storCdr.ExtraFields = cgrCdr.getExtraFields() storCdr.Cost = -1 if costStr, hasIt := cgrCdr[utils.COST]; hasIt { diff --git a/engine/cgrcdr_test.go b/engine/cgrcdr_test.go index bcf267b12..b020ca2e8 100644 --- a/engine/cgrcdr_test.go +++ b/engine/cgrcdr_test.go @@ -33,19 +33,25 @@ func TestCgrCdrInterfaces(t *testing.T) { } func TestCgrCdrAsCDR(t *testing.T) { - cgrCdr := CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "dsafdsaf", utils.CDRHOST: "192.168.1.1", utils.CDRSOURCE: "internal_test", utils.REQTYPE: utils.META_RATED, - utils.DIRECTION: utils.OUT, - utils.TENANT: "cgrates.org", utils.CATEGORY: "call", - utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-07T08:42:20Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", - utils.USAGE: "10", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2"} + cgrCdr := CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "dsafdsaf", utils.CDRHOST: "192.168.1.1", + utils.CDRSOURCE: "internal_test", utils.REQTYPE: utils.META_RATED, + utils.TENANT: "cgrates.org", utils.CATEGORY: "call", + utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", + utils.SETUP_TIME: "2013-11-07T08:42:20Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", + utils.USAGE: "10", "field_extr1": "val_extr1", "fieldextr2": "valextr2"} setupTime, _ := utils.ParseTimeDetectLayout(cgrCdr[utils.SETUP_TIME], "") - expctRtCdr := &CDR{CGRID: utils.Sha1(cgrCdr[utils.ACCID], setupTime.String()), ToR: utils.VOICE, OriginID: cgrCdr[utils.ACCID], OriginHost: cgrCdr[utils.CDRHOST], + expctRtCdr := &CDR{CGRID: utils.Sha1(cgrCdr[utils.ACCID], setupTime.String()), + ToR: utils.VOICE, OriginID: cgrCdr[utils.ACCID], + OriginHost: cgrCdr[utils.CDRHOST], Source: cgrCdr[utils.CDRSOURCE], RequestType: cgrCdr[utils.REQTYPE], - Direction: cgrCdr[utils.DIRECTION], Tenant: cgrCdr[utils.TENANT], Category: cgrCdr[utils.CATEGORY], Account: cgrCdr[utils.ACCOUNT], Subject: cgrCdr[utils.SUBJECT], - Destination: cgrCdr[utils.DESTINATION], SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: -1} + Tenant: cgrCdr[utils.TENANT], Category: cgrCdr[utils.CATEGORY], + Account: cgrCdr[utils.ACCOUNT], Subject: cgrCdr[utils.SUBJECT], + Destination: cgrCdr[utils.DESTINATION], + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10) * time.Second, Cost: -1, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} if CDR := cgrCdr.AsStoredCdr(""); !reflect.DeepEqual(expctRtCdr, CDR) { t.Errorf("Expecting %v, received: %v", expctRtCdr, CDR) } @@ -59,26 +65,21 @@ func TestReplicatedCgrCdrAsCDR(t *testing.T) { utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-07T08:42:20Z", utils.PDD: "0.200", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "10", utils.SUPPLIER: "SUPPL1", utils.DISCONNECT_CAUSE: "NORMAL_CLEARING", utils.COST: "0.12", utils.RATED: "true", "field_extr1": "val_extr1", "fieldextr2": "valextr2"} expctRtCdr := &CDR{CGRID: cgrCdr[utils.CGRID], - ToR: cgrCdr[utils.TOR], - OriginID: cgrCdr[utils.ACCID], - OriginHost: cgrCdr[utils.CDRHOST], - Source: cgrCdr[utils.CDRSOURCE], - RequestType: cgrCdr[utils.REQTYPE], - Direction: cgrCdr[utils.DIRECTION], - Tenant: cgrCdr[utils.TENANT], - Category: cgrCdr[utils.CATEGORY], - Account: cgrCdr[utils.ACCOUNT], - Subject: cgrCdr[utils.SUBJECT], - Destination: cgrCdr[utils.DESTINATION], - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), - PDD: time.Duration(200) * time.Millisecond, - AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, - Supplier: cgrCdr[utils.SUPPLIER], - DisconnectCause: cgrCdr[utils.DISCONNECT_CAUSE], - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - Cost: 0.12, - Rated: true, + ToR: cgrCdr[utils.TOR], + OriginID: cgrCdr[utils.ACCID], + OriginHost: cgrCdr[utils.CDRHOST], + Source: cgrCdr[utils.CDRSOURCE], + RequestType: cgrCdr[utils.REQTYPE], + Tenant: cgrCdr[utils.TENANT], + Category: cgrCdr[utils.CATEGORY], + Account: cgrCdr[utils.ACCOUNT], + Subject: cgrCdr[utils.SUBJECT], + Destination: cgrCdr[utils.DESTINATION], + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10) * time.Second, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, + Cost: 0.12, Rated: true, } if CDR := cgrCdr.AsStoredCdr(""); !reflect.DeepEqual(expctRtCdr, CDR) { t.Errorf("Expecting %v, received: %v", expctRtCdr, CDR) diff --git a/engine/event.go b/engine/event.go index 1c5ca5ad5..3f1af1eea 100644 --- a/engine/event.go +++ b/engine/event.go @@ -28,7 +28,6 @@ type Event interface { GetCgrId(timezone string) string GetUUID() string GetSessionIds() []string // Returns identifiers needed to control a session (eg disconnect) - GetDirection(string) string GetSubject(string) string GetAccount(string) string GetDestination(string) string @@ -41,9 +40,6 @@ type Event interface { GetAnswerTime(string, string) (time.Time, error) GetEndTime(string, string) (time.Time, error) GetDuration(string) (time.Duration, error) - GetPdd(string) (time.Duration, error) - GetSupplier(string) string - GetDisconnectCause(string) string GetExtraFields() map[string]string MissingParameter(string) bool ParseEventValue(*utils.RSRField, string) string diff --git a/engine/fscdr.go b/engine/fscdr.go index a6aee5816..5f42497a0 100644 --- a/engine/fscdr.go +++ b/engine/fscdr.go @@ -24,7 +24,6 @@ import ( "reflect" "strconv" "strings" - "time" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" @@ -131,20 +130,14 @@ func (fsCdr FSCdr) AsStoredCdr(timezone string) *CDR { storCdr.OriginHost = fsCdr.vars[FS_IP] storCdr.Source = FS_CDR_SOURCE storCdr.RequestType = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_REQTYPE], fsCdr.cgrCfg.DefaultReqType) - storCdr.Direction = utils.OUT storCdr.Tenant = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_TENANT], fsCdr.cgrCfg.DefaultTenant) storCdr.Category = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_CATEGORY], fsCdr.cgrCfg.DefaultCategory) storCdr.Account = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_ACCOUNT], fsCdr.vars[FS_USERNAME]) storCdr.Subject = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_SUBJECT], fsCdr.vars[utils.CGR_ACCOUNT], fsCdr.vars[FS_USERNAME]) storCdr.Destination = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_DESTINATION], fsCdr.vars[FS_CALL_DEST_NR], fsCdr.vars[FS_SIP_REQUSER]) storCdr.SetupTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_SETUP_TIME], timezone) // Not interested to process errors, should do them if necessary in a previous step - pddStr := utils.FirstNonEmpty(fsCdr.vars[FS_PROGRESS_MEDIAMSEC], fsCdr.vars[FS_PROGRESSMS]) - pddStr += "ms" - storCdr.PDD, _ = time.ParseDuration(pddStr) storCdr.AnswerTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_ANSWER_TIME], timezone) storCdr.Usage, _ = utils.ParseDurationWithSecs(fsCdr.vars[FS_DURATION]) - storCdr.Supplier = fsCdr.vars[utils.CGR_SUPPLIER] - storCdr.DisconnectCause = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_DISCONNECT_CAUSE], fsCdr.vars["hangup_cause"]) storCdr.ExtraFields = fsCdr.getExtraFields() storCdr.Cost = -1 return storCdr diff --git a/engine/fscdr_test.go b/engine/fscdr_test.go index 64c90e303..37dce794b 100644 --- a/engine/fscdr_test.go +++ b/engine/fscdr_test.go @@ -53,10 +53,15 @@ func TestCDRFields(t *testing.T) { } setupTime, _ := utils.ParseTimeDetectLayout("1436280728", "") answerTime, _ := utils.ParseTimeDetectLayout("1436280728", "") - expctCDR := &CDR{CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41", ToR: utils.VOICE, OriginID: "e3133bf7-dcde-4daf-9663-9a79ffcef5ad", - OriginHost: "127.0.0.1", Source: "freeswitch_json", Direction: utils.OUT, Category: "call", RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Account: "1001", Subject: "1001", - Destination: "1003", SetupTime: setupTime, PDD: time.Duration(28) * time.Millisecond, AnswerTime: answerTime, Usage: time.Duration(66) * time.Second, Supplier: "supplier1", - DisconnectCause: "NORMAL_CLEARING", ExtraFields: map[string]string{"sip_user_agent": "PJSUA v2.3 Linux-3.2.0.4/x86_64/glibc-2.13"}, Cost: -1} + expctCDR := &CDR{CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41", + ToR: utils.VOICE, OriginID: "e3133bf7-dcde-4daf-9663-9a79ffcef5ad", + OriginHost: "127.0.0.1", Source: "freeswitch_json", Category: "call", + RequestType: utils.META_PREPAID, Tenant: "cgrates.org", + Account: "1001", Subject: "1001", + Destination: "1003", SetupTime: setupTime, + AnswerTime: answerTime, Usage: time.Duration(66) * time.Second, + Cost: -1, + ExtraFields: map[string]string{"sip_user_agent": "PJSUA v2.3 Linux-3.2.0.4/x86_64/glibc-2.13"}} if CDR := fsCdr.AsStoredCdr(""); !reflect.DeepEqual(expctCDR, CDR) { t.Errorf("Expecting: %v, received: %v", expctCDR, CDR) } diff --git a/engine/models.go b/engine/models.go index ded146bd6..b123d13c0 100755 --- a/engine/models.go +++ b/engine/models.go @@ -398,59 +398,6 @@ func (ta *TpAlias) GetId() string { return utils.ConcatenatedKey(ta.Direction, ta.Tenant, ta.Category, ta.Account, ta.Subject, ta.Context) } -type TBLCDRs struct { - ID int64 - Cgrid string - RunID string - OriginHost string - Source string - OriginID string - Tor string - RequestType string - Direction string - Tenant string - Category string - Account string - Subject string - Destination string - SetupTime time.Time - Pdd float64 - AnswerTime time.Time - Usage float64 - Supplier string - DisconnectCause string - ExtraFields string - Cost float64 - CostDetails string - CostSource string - AccountSummary string - ExtraInfo string - CreatedAt time.Time - UpdatedAt time.Time - DeletedAt *time.Time -} - -func (t TBLCDRs) TableName() string { - return utils.TBLCDRs -} - -type TBLSMCosts struct { - ID int64 - Cgrid string - RunID string - OriginHost string - OriginID string - CostSource string - Usage float64 - CostDetails string - CreatedAt time.Time - DeletedAt *time.Time -} - -func (t TBLSMCosts) TableName() string { - return utils.TBLSMCosts -} - type TpResource struct { PK uint `gorm:"primary_key"` Tpid string @@ -468,16 +415,6 @@ type TpResource struct { CreatedAt time.Time } -type TBLVersion struct { - ID uint - Item string - Version int64 -} - -func (t TBLVersion) TableName() string { - return utils.TBLVersions -} - type TpStats struct { PK uint `gorm:"primary_key"` Tpid string @@ -524,3 +461,61 @@ type TpFilter struct { ActivationInterval string `index:"5" re:""` CreatedAt time.Time } + +type CDRsql struct { + ID int64 + CGRID string + RunID string + OriginHost string + Source string + OriginID string + TOR string + RequestType string + Tenant string + Category string + Account string + Subject string + Destination string + SetupTime time.Time + AnswerTime time.Time + Usage int64 + ExtraFields string + CostSource string + Cost float64 + CostDetails string + ExtraInfo string + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt *time.Time +} + +func (t CDRsql) TableName() string { + return utils.CDRsTBL +} + +type SMCostSQL struct { + ID int64 + Cgrid string + RunID string + OriginHost string + OriginID string + CostSource string + Usage float64 + CostDetails string + CreatedAt time.Time + DeletedAt *time.Time +} + +func (t SMCostSQL) TableName() string { + return utils.SMCostsTBL +} + +type TBLVersion struct { + ID uint + Item string + Version int64 +} + +func (t TBLVersion) TableName() string { + return utils.TBLVersions +} diff --git a/engine/responder.go b/engine/responder.go index a8014a128..c67ee312e 100644 --- a/engine/responder.go +++ b/engine/responder.go @@ -302,7 +302,7 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) error { if err := LoadAlias( &AttrMatchingAlias{ Destination: ev.Destination, - Direction: ev.Direction, + Direction: utils.OUT, Tenant: ev.Tenant, Category: ev.Category, Account: ev.Account, @@ -314,7 +314,8 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) error { } maxCallDuration := -1.0 - attrsDC := &utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Direction: ev.GetDirection(utils.META_DEFAULT), + attrsDC := &utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), + Category: ev.GetCategory(utils.META_DEFAULT), Direction: utils.OUT, Account: ev.GetAccount(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT)} dcs := &utils.DerivedChargers{} if err := rs.GetDerivedChargers(attrsDC, dcs); err != nil { @@ -354,7 +355,7 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) error { CgrID: ev.GetCgrId(rs.Timezone), RunID: dc.RunID, TOR: ev.ToR, - Direction: ev.GetDirection(dc.DirectionField), + Direction: utils.OUT, Tenant: ev.GetTenant(dc.TenantField), Category: ev.GetCategory(dc.CategoryField), Subject: ev.GetSubject(dc.SubjectField), @@ -407,7 +408,7 @@ func (rs *Responder) GetSessionRuns(ev *CDR, sRuns *[]*SessionRun) error { if err := LoadAlias( &AttrMatchingAlias{ Destination: ev.Destination, - Direction: ev.Direction, + Direction: utils.OUT, Tenant: ev.Tenant, Category: ev.Category, Account: ev.Account, @@ -418,8 +419,10 @@ func (rs *Responder) GetSessionRuns(ev *CDR, sRuns *[]*SessionRun) error { } //utils.Logger.Info(fmt.Sprintf("DC after: %+v", ev)) - 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), Destination: ev.GetDestination(utils.META_DEFAULT)} + attrsDC := &utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), + Category: ev.GetCategory(utils.META_DEFAULT), Direction: utils.OUT, + Account: ev.GetAccount(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT), + Destination: ev.GetDestination(utils.META_DEFAULT)} //utils.Logger.Info(fmt.Sprintf("Derived chargers for: %+v", attrsDC)) dcs := &utils.DerivedChargers{} if err := rs.GetDerivedChargers(attrsDC, dcs); err != nil { @@ -453,7 +456,7 @@ func (rs *Responder) GetSessionRuns(ev *CDR, sRuns *[]*SessionRun) error { CgrID: ev.GetCgrId(rs.Timezone), RunID: dc.RunID, TOR: ev.ToR, - Direction: ev.GetDirection(dc.DirectionField), + Direction: utils.OUT, Tenant: ev.GetTenant(dc.TenantField), Category: ev.GetCategory(dc.CategoryField), Subject: ev.GetSubject(dc.SubjectField), diff --git a/engine/responder_test.go b/engine/responder_test.go index b865a20b8..567f0f10e 100644 --- a/engine/responder_test.go +++ b/engine/responder_test.go @@ -55,11 +55,14 @@ func TestResponderGetDerivedChargers(t *testing.T) { func TestResponderGetDerivedMaxSessionTime(t *testing.T) { testTenant := "vdf" - cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", - OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan", Subject: "dan", - Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - Cost: 1.01} + cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: "test", + RequestType: utils.META_RATED, Tenant: testTenant, Category: "call", Account: "dan", Subject: "dan", + Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, + Cost: 1.01} var maxSessionTime float64 if err := rsponder.GetDerivedMaxSessionTime(cdr, &maxSessionTime); err != nil { t.Error(err) @@ -75,8 +78,10 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) { } b10 := &Balance{Value: 10, Weight: 10, DestinationIDs: utils.NewStringMap("DE_TMOBILE")} b20 := &Balance{Value: 20, Weight: 10, DestinationIDs: utils.NewStringMap("DE_TMOBILE")} - rifsAccount := &Account{ID: utils.ConcatenatedKey(testTenant, "rif"), BalanceMap: map[string]Balances{utils.VOICE: Balances{b10}}} - dansAccount := &Account{ID: utils.ConcatenatedKey(testTenant, "dan"), BalanceMap: map[string]Balances{utils.VOICE: Balances{b20}}} + rifsAccount := &Account{ID: utils.ConcatenatedKey(testTenant, "rif"), + BalanceMap: map[string]Balances{utils.VOICE: Balances{b10}}} + dansAccount := &Account{ID: utils.ConcatenatedKey(testTenant, "dan"), + BalanceMap: map[string]Balances{utils.VOICE: Balances{b20}}} if err := dm.DataDB().SetAccount(rifsAccount); err != nil { t.Error(err) } @@ -123,11 +128,13 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) { func TestResponderGetSessionRuns(t *testing.T) { testTenant := "vdf" - cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", - OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_PREPAID, Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan2", Subject: "dan2", - Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), PDD: 3 * time.Second, - AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Supplier: "suppl1", - RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, + cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), + OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", + OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_PREPAID, + Tenant: testTenant, Category: "call", Account: "dan2", Subject: "dan2", + Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01} keyCharger1 := utils.ConcatenatedKey("*out", testTenant, "call", "dan2", "dan2") dfDC := &utils.DerivedCharger{RunID: utils.DEFAULT_RUNID, RequestTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT, @@ -456,85 +463,98 @@ func TestResponderGetLCR(t *testing.T) { } else if !reflect.DeepEqual(eLcLcr.SupplierCosts, lcrLc.SupplierCosts) { t.Errorf("Expecting: %+v, received: %+v", eLcLcr.SupplierCosts, lcrLc.SupplierCosts) } + /* + // Test *qos_threshold strategy here, + // FixMe with newly stats + cdQosThreshold := &CallDescriptor{ + TimeStart: time.Date(2015, 04, 06, 17, 40, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 04, 06, 17, 41, 0, 0, time.UTC), + Tenant: "tenant12", + Direction: utils.OUT, + Category: "call_qos_threshold", + Destination: "+4986517174963", + Account: "dan", + Subject: "dan", + } + eQTLcr := &LCRCost{ + Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", + Strategy: LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "35;;;;4m;;;;;;;;;", Weight: 10.0}, + SupplierCosts: []*LCRSupplierCost{ + &LCRSupplierCost{Supplier: "*out:tenant12:call:ivo12", Cost: 0, Duration: 60 * time.Second, + QOS: map[string]float64{TCD: -1, ACC: -1, TCC: -1, ASR: -1, ACD: -1, PDD: -1, DDC: -1}, qosSortParams: []string{"35", "4m"}}, + &LCRSupplierCost{Supplier: "*out:tenant12:call:rif12", Cost: 0.4, Duration: 60 * time.Second, + QOS: map[string]float64{TCD: -1, ACC: -1, TCC: -1, ASR: -1, ACD: -1, PDD: -1, DDC: -1}, qosSortParams: []string{"35", "4m"}}, + &LCRSupplierCost{Supplier: "*out:tenant12:call:dan12", Cost: 0.6, Duration: 60 * time.Second, + QOS: map[string]float64{TCD: -1, ACC: -1, TCC: -1, ASR: -1, ACD: -1, PDD: -1, DDC: -1}, qosSortParams: []string{"35", "4m"}}, + }, + } + var lcrQT LCRCost + if err := rsponder.GetLCR(&AttrGetLcr{CallDescriptor: cdQosThreshold}, &lcrQT); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eQTLcr.Entry, lcrQT.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eQTLcr.Entry, lcrQT.Entry) - // Test *qos_threshold strategy here - cdQosThreshold := &CallDescriptor{ - TimeStart: time.Date(2015, 04, 06, 17, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2015, 04, 06, 17, 41, 0, 0, time.UTC), - Tenant: "tenant12", - Direction: utils.OUT, - Category: "call_qos_threshold", - Destination: "+4986517174963", - Account: "dan", - Subject: "dan", - } - eQTLcr := &LCRCost{ - Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", Strategy: LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "35;;;;4m;;;;;;;;;", Weight: 10.0}, - SupplierCosts: []*LCRSupplierCost{ - &LCRSupplierCost{Supplier: "*out:tenant12:call:ivo12", Cost: 0, Duration: 60 * time.Second, QOS: map[string]float64{TCD: -1, ACC: -1, TCC: -1, ASR: -1, ACD: -1, PDD: -1, DDC: -1}, qosSortParams: []string{"35", "4m"}}, - &LCRSupplierCost{Supplier: "*out:tenant12:call:rif12", Cost: 0.4, Duration: 60 * time.Second, QOS: map[string]float64{TCD: -1, ACC: -1, TCC: -1, ASR: -1, ACD: -1, PDD: -1, DDC: -1}, qosSortParams: []string{"35", "4m"}}, - &LCRSupplierCost{Supplier: "*out:tenant12:call:dan12", Cost: 0.6, Duration: 60 * time.Second, QOS: map[string]float64{TCD: -1, ACC: -1, TCC: -1, ASR: -1, ACD: -1, PDD: -1, DDC: -1}, qosSortParams: []string{"35", "4m"}}, - }, - } - var lcrQT LCRCost - if err := rsponder.GetLCR(&AttrGetLcr{CallDescriptor: cdQosThreshold}, &lcrQT); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eQTLcr.Entry, lcrQT.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eQTLcr.Entry, lcrQT.Entry) + } else if !reflect.DeepEqual(eQTLcr.SupplierCosts, lcrQT.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eQTLcr.SupplierCosts, lcrQT.SupplierCosts) + } - } else if !reflect.DeepEqual(eQTLcr.SupplierCosts, lcrQT.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eQTLcr.SupplierCosts, lcrQT.SupplierCosts) - } + cdr := &CDR{AnswerTime: time.Now(), Usage: 3 * time.Minute, Cost: 1} + rsponder.Stats.Call("CDRStatsV1.AppendCDR", cdr, &r) + cdr = &CDR{AnswerTime: time.Now(), Usage: 5 * time.Minute, Cost: 2} + rsponder.Stats.Call("CDRStatsV1.AppendCDR", cdr, &r) - cdr := &CDR{Supplier: "rif12", AnswerTime: time.Now(), Usage: 3 * time.Minute, Cost: 1} - rsponder.Stats.Call("CDRStatsV1.AppendCDR", cdr, &r) - cdr = &CDR{Supplier: "dan12", AnswerTime: time.Now(), Usage: 5 * time.Minute, Cost: 2} - rsponder.Stats.Call("CDRStatsV1.AppendCDR", cdr, &r) + eQTLcr = &LCRCost{ + Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", + Strategy: LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "35;;;;4m;;;;;;;;;", Weight: 10.0}, + SupplierCosts: []*LCRSupplierCost{ + &LCRSupplierCost{Supplier: "*out:tenant12:call:ivo12", Cost: 0, Duration: 60 * time.Second, + QOS: map[string]float64{PDD: -1, TCD: -1, ACC: -1, TCC: -1, ASR: -1, ACD: -1, DDC: -1}, qosSortParams: []string{"35", "4m"}}, + &LCRSupplierCost{Supplier: "*out:tenant12:call:dan12", Cost: 0.6, Duration: 60 * time.Second, + QOS: map[string]float64{PDD: -1, ACD: 300, TCD: 300, ASR: 100, ACC: 2, TCC: 2, DDC: 2}, qosSortParams: []string{"35", "4m"}}, + }, + } + if err := rsponder.GetLCR(&AttrGetLcr{CallDescriptor: cdQosThreshold}, &lcrQT); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eQTLcr.Entry, lcrQT.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eQTLcr.Entry, lcrQT.Entry) + } else if !reflect.DeepEqual(eQTLcr.SupplierCosts, lcrQT.SupplierCosts) { + t.Errorf("Expecting: %s, received: %s", + utils.ToJSON(eQTLcr.SupplierCosts), utils.ToJSON(lcrQT.SupplierCosts)) + } - eQTLcr = &LCRCost{ - Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", Strategy: LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "35;;;;4m;;;;;;;;;", Weight: 10.0}, - SupplierCosts: []*LCRSupplierCost{ - &LCRSupplierCost{Supplier: "*out:tenant12:call:ivo12", Cost: 0, Duration: 60 * time.Second, QOS: map[string]float64{PDD: -1, TCD: -1, ACC: -1, TCC: -1, ASR: -1, ACD: -1, DDC: -1}, qosSortParams: []string{"35", "4m"}}, - &LCRSupplierCost{Supplier: "*out:tenant12:call:dan12", Cost: 0.6, Duration: 60 * time.Second, QOS: map[string]float64{PDD: -1, ACD: 300, TCD: 300, ASR: 100, ACC: 2, TCC: 2, DDC: 2}, qosSortParams: []string{"35", "4m"}}, - }, - } - if err := rsponder.GetLCR(&AttrGetLcr{CallDescriptor: cdQosThreshold}, &lcrQT); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eQTLcr.Entry, lcrQT.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eQTLcr.Entry, lcrQT.Entry) - } else if !reflect.DeepEqual(eQTLcr.SupplierCosts, lcrQT.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eQTLcr.SupplierCosts, lcrQT.SupplierCosts) - } + // Test *qos strategy here + cdQos := &CallDescriptor{ + TimeStart: time.Date(2015, 04, 06, 17, 40, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 04, 06, 17, 41, 0, 0, time.UTC), + Tenant: "tenant12", + Direction: utils.OUT, + Category: "call_qos", + Destination: "+4986517174963", + Account: "dan", + Subject: "dan", + } + eQosLcr := &LCRCost{ + Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", Strategy: LCR_STRATEGY_QOS, Weight: 10.0}, + SupplierCosts: []*LCRSupplierCost{ + &LCRSupplierCost{Supplier: "*out:tenant12:call:ivo12", Cost: 0, Duration: 60 * time.Second, + QOS: map[string]float64{ACD: -1, PDD: -1, TCD: -1, ASR: -1, ACC: -1, TCC: -1, DDC: -1}, qosSortParams: []string{ASR, PDD, ACD, TCD, ACC, TCC, DDC}}, + &LCRSupplierCost{Supplier: "*out:tenant12:call:dan12", Cost: 0.6, Duration: 60 * time.Second, + QOS: map[string]float64{ACD: 300, PDD: -1, TCD: 300, ASR: 100, ACC: 2, TCC: 2, DDC: 2}, qosSortParams: []string{ASR, PDD, ACD, TCD, ACC, TCC, DDC}}, + &LCRSupplierCost{Supplier: "*out:tenant12:call:rif12", Cost: 0.4, Duration: 60 * time.Second, + QOS: map[string]float64{ACD: 180, PDD: -1, TCD: 180, ASR: 100, ACC: 1, TCC: 1, DDC: 1}, qosSortParams: []string{ASR, PDD, ACD, TCD, ACC, TCC, DDC}}, + }, + } + var lcrQ LCRCost + if err := rsponder.GetLCR(&AttrGetLcr{CallDescriptor: cdQos}, &lcrQ); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eQosLcr.Entry, lcrQ.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eQosLcr.Entry, lcrQ.Entry) - // Test *qos strategy here - cdQos := &CallDescriptor{ - TimeStart: time.Date(2015, 04, 06, 17, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2015, 04, 06, 17, 41, 0, 0, time.UTC), - Tenant: "tenant12", - Direction: utils.OUT, - Category: "call_qos", - Destination: "+4986517174963", - Account: "dan", - Subject: "dan", - } - eQosLcr := &LCRCost{ - Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", Strategy: LCR_STRATEGY_QOS, Weight: 10.0}, - SupplierCosts: []*LCRSupplierCost{ - &LCRSupplierCost{Supplier: "*out:tenant12:call:ivo12", Cost: 0, Duration: 60 * time.Second, QOS: map[string]float64{ACD: -1, PDD: -1, TCD: -1, ASR: -1, ACC: -1, TCC: -1, DDC: -1}, qosSortParams: []string{ASR, PDD, ACD, TCD, ACC, TCC, DDC}}, - &LCRSupplierCost{Supplier: "*out:tenant12:call:dan12", Cost: 0.6, Duration: 60 * time.Second, QOS: map[string]float64{ACD: 300, PDD: -1, TCD: 300, ASR: 100, ACC: 2, TCC: 2, DDC: 2}, qosSortParams: []string{ASR, PDD, ACD, TCD, ACC, TCC, DDC}}, - &LCRSupplierCost{Supplier: "*out:tenant12:call:rif12", Cost: 0.4, Duration: 60 * time.Second, QOS: map[string]float64{ACD: 180, PDD: -1, TCD: 180, ASR: 100, ACC: 1, TCC: 1, DDC: 1}, qosSortParams: []string{ASR, PDD, ACD, TCD, ACC, TCC, DDC}}, - }, - } - var lcrQ LCRCost - if err := rsponder.GetLCR(&AttrGetLcr{CallDescriptor: cdQos}, &lcrQ); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eQosLcr.Entry, lcrQ.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eQosLcr.Entry, lcrQ.Entry) - - } else if !reflect.DeepEqual(eQosLcr.SupplierCosts, lcrQ.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eQosLcr.SupplierCosts, lcrQ.SupplierCosts) - } + } else if !reflect.DeepEqual(eQosLcr.SupplierCosts, lcrQ.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eQosLcr.SupplierCosts, lcrQ.SupplierCosts) + } + */ } func TestResponderGobSMCost(t *testing.T) { diff --git a/engine/statscdrs_test.go b/engine/statscdrs_test.go deleted file mode 100644 index 5b55ccac3..000000000 --- a/engine/statscdrs_test.go +++ /dev/null @@ -1,555 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package engine - -import ( - "testing" - "time" - - "github.com/cgrates/cgrates/utils" -) - -func TestCDRStatsQueueInit(t *testing.T) { - sq := NewCDRStatsQueue(&CdrStats{Metrics: []string{ASR, ACC}}) - if len(sq.metrics) != 2 { - t.Error("Expected 2 metrics got ", len(sq.metrics)) - } -} - -func TestStatsValue(t *testing.T) { - sq := NewCDRStatsQueue(&CdrStats{Metrics: []string{ASR, ACD, TCD, ACC, TCC}}) - cdr := &CDR{ - SetupTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - Usage: 10 * time.Second, - Cost: 1, - } - sq.AppendCDR(cdr) - cdr.Cost = 2 - sq.AppendCDR(cdr) - cdr.Cost = 3 - sq.AppendCDR(cdr) - s := sq.GetStats() - if s[ASR] != 100 || - s[ACD] != 10 || - s[TCD] != 30 || - s[ACC] != 2 || - s[TCC] != 6 { - t.Errorf("Error getting stats: %+v", s) - } -} - -func TestStatsSimplifyCDR(t *testing.T) { - cdr := &CDR{ - ToR: "tor", - OriginID: "accid", - OriginHost: "cdrhost", - Source: "cdrsource", - RequestType: "reqtype", - Direction: "direction", - Tenant: "tenant", - Category: "category", - Account: "account", - Subject: "subject", - Destination: "12345678", - SetupTime: time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC), - Usage: 10 * time.Second, - RunID: "mri", - Cost: 10, - } - sq := &CDRStatsQueue{} - qcdr := sq.simplifyCdr(cdr) - if cdr.SetupTime != qcdr.SetupTime || - cdr.AnswerTime != qcdr.AnswerTime || - cdr.Usage != qcdr.Usage || - cdr.Cost != qcdr.Cost { - t.Errorf("Failed to simplify cdr: %+v", qcdr) - } -} - -func TestAcceptCdr(t *testing.T) { - sq := NewCDRStatsQueue(nil) - cdr := &CDR{ - ToR: "tor", - OriginID: "accid", - OriginHost: "cdrhost", - Source: "cdrsource", - RequestType: "reqtype", - Direction: "direction", - Tenant: "tenant", - Category: "category", - Account: "account", - Subject: "subject", - Destination: "0723045326", - SetupTime: time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC), - Usage: 10 * time.Second, - PDD: 7 * time.Second, - Supplier: "supplier1", - DisconnectCause: "normal", - RunID: "mri", - Cost: 10, - } - sq.conf = &CdrStats{} - if sq.conf.AcceptCdr(cdr) != true { - t.Errorf("Should have accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{TOR: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{CdrHost: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{CdrSource: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{Direction: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{Tenant: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{Category: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{Account: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{Subject: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{Supplier: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{DisconnectCause: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{DestinationIds: []string{"test"}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{DestinationIds: []string{"NAT", "RET"}} - if sq.conf.AcceptCdr(cdr) != true { - t.Errorf("Should have accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC), time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC)}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC)}} - if sq.conf.AcceptCdr(cdr) != true { - t.Errorf("Should have accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC), time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)}} - if sq.conf.AcceptCdr(cdr) != true { - t.Errorf("Should have accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{UsageInterval: []time.Duration{11 * time.Second}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{UsageInterval: []time.Duration{1 * time.Second, 10 * time.Second}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{PddInterval: []time.Duration{8 * time.Second}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{PddInterval: []time.Duration{3 * time.Second, 7 * time.Second}} - if sq.conf.AcceptCdr(cdr) == true { - t.Errorf("Should have NOT accepted this CDR: %+v", cdr) - } - sq.conf = &CdrStats{PddInterval: []time.Duration{3 * time.Second, 8 * time.Second}} - if sq.conf.AcceptCdr(cdr) != true { - t.Errorf("Should have accepted this CDR: %+v", cdr) - } -} - -func TestCDRStatsQueueIds(t *testing.T) { - cdrStats := NewStats(dm, 0) - ids := []string{} - if err := cdrStats.GetQueueIds(0, &ids); err != nil { - t.Error("Errorf getting queue ids: ", err) - } - result := len(ids) - expected := 5 - if result != expected { - t.Errorf("Errorf loading stats queues. Expected %v was %v (%v)", expected, result, ids) - } -} - -func TestStatsAppendCdr(t *testing.T) { - cdrStats := NewStats(dm, 0) - cdr := &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 10 * time.Second, - Cost: 10, - Supplier: "suppl1", - DisconnectCause: "NORMAL_CLEARNING", - } - err := cdrStats.AppendCDR(cdr, nil) - if err != nil { - t.Error("Error appending cdr to stats: ", err) - } - t.Log(cdrStats.queues) - if len(cdrStats.queues) != 5 || - len(cdrStats.queues["CDRST1"].Cdrs) != 0 || - len(cdrStats.queues["CDRST2"].Cdrs) != 1 { - t.Error("Error appending cdr to queue: ", utils.ToIJSON(cdrStats.queues)) - } -} - -func TestStatsGetValues(t *testing.T) { - cdrStats := NewStats(dm, 0) - cdr := &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 10 * time.Second, - Cost: 10, - } - cdrStats.AppendCDR(cdr, nil) - cdr = &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 2 * time.Second, - Cost: 4, - } - cdrStats.AppendCDR(cdr, nil) - valMap := make(map[string]float64) - if err := cdrStats.GetValues("CDRST2", &valMap); err != nil { - t.Error("Error getting metric values: ", err) - } - if len(valMap) != 2 || valMap["ACD"] != 6 || valMap["ASR"] != 100 { - t.Error("Error on metric map: ", valMap) - } -} - -func TestStatsReloadQueues(t *testing.T) { - cdrStats := NewStats(dm, 0) - cdr := &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 10 * time.Second, - Cost: 10, - } - cdrStats.AppendCDR(cdr, nil) - if err := cdrStats.ReloadQueues(nil, nil); err != nil { - t.Error("Error reloading queues: ", err) - } - ids := []string{} - if err := cdrStats.GetQueueIds(0, &ids); err != nil { - t.Error("Error getting queue ids: ", err) - } - result := len(ids) - expected := 5 - if result != expected { - t.Errorf("Error loading stats queues. Expected %v was %v: %v", expected, result, ids) - } - valMap := make(map[string]float64) - if err := cdrStats.GetValues("CDRST2", &valMap); err != nil { - t.Error("Error getting metric values: ", err) - } - if len(valMap) != 2 || valMap["ACD"] != 10 || valMap["ASR"] != 100 { - t.Error("Error on metric map: ", valMap) - } -} - -func TestStatsReloadQueuesWithDefault(t *testing.T) { - cdrStats := NewStats(dm, 0) - cdrStats.AddQueue(&CdrStats{ - Id: utils.META_DEFAULT, - }, nil) - cdr := &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 10 * time.Second, - Cost: 10, - } - cdrStats.AppendCDR(cdr, nil) - - if err := cdrStats.ReloadQueues(nil, nil); err != nil { - t.Error("Error reloading queues: ", err) - } - ids := []string{} - if err := cdrStats.GetQueueIds(0, &ids); err != nil { - t.Error("Error getting queue ids: ", err) - } - result := len(ids) - expected := 6 - if result != expected { - t.Errorf("Error loading stats queues. Expected %v was %v", expected, result) - } - valMap := make(map[string]float64) - if err := cdrStats.GetValues("CDRST2", &valMap); err != nil { - t.Error("Error getting metric values: ", err) - } - if len(valMap) != 2 || valMap["ACD"] != 10 || valMap["ASR"] != 100 { - t.Error("Error on metric map: ", valMap) - } -} - -func TestStatsReloadQueuesWithIds(t *testing.T) { - cdrStats := NewStats(dm, 0) - cdr := &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 10 * time.Second, - Cost: 10, - } - cdrStats.AppendCDR(cdr, nil) - if err := cdrStats.ReloadQueues([]string{"CDRST1"}, nil); err != nil { - t.Error("Error reloading queues: ", err) - } - ids := []string{} - if err := cdrStats.GetQueueIds(0, &ids); err != nil { - t.Error("Error getting queue ids: ", err) - } - result := len(ids) - expected := 6 - if result != expected { - t.Errorf("Error loading stats queues. Expected %v was %v", expected, result) - } - valMap := make(map[string]float64) - if err := cdrStats.GetValues("CDRST2", &valMap); err != nil { - t.Error("Error getting metric values: ", err) - } - if len(valMap) != 2 || valMap["ACD"] != 10 || valMap["ASR"] != 100 { - t.Error("Error on metric map: ", valMap) - } -} - -func TestStatsSaveQueues(t *testing.T) { - cdrStats := NewStats(dm, 0) - cdr := &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 10 * time.Second, - Cost: 10, - } - cdrStats.AppendCDR(cdr, nil) - ids := []string{} - cdrStats.GetQueueIds(0, &ids) - if _, found := cdrStats.queueSavers["CDRST1"]; !found { - t.Error("Error creating queue savers: ", cdrStats.queueSavers) - } -} - -func TestStatsResetQueues(t *testing.T) { - cdrStats := NewStats(dm, 0) - cdr := &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 10 * time.Second, - Cost: 10, - } - cdrStats.AppendCDR(cdr, nil) - if err := cdrStats.ResetQueues(nil, nil); err != nil { - t.Error("Error reloading queues: ", err) - } - ids := []string{} - if err := cdrStats.GetQueueIds(0, &ids); err != nil { - t.Error("Error getting queue ids: ", err) - } - result := len(ids) - expected := 6 - if result != expected { - t.Errorf("Error loading stats queues. Expected %v was %v", expected, result) - } - valMap := make(map[string]float64) - if err := cdrStats.GetValues("CDRST2", &valMap); err != nil { - t.Error("Error getting metric values: ", err) - } - if len(valMap) != 2 || valMap["ACD"] != STATS_NA || valMap["ASR"] != STATS_NA { - t.Error("Error on metric map: ", valMap) - } -} - -func TestStatsResetQueuesWithIds(t *testing.T) { - cdrStats := NewStats(dm, 0) - cdr := &CDR{ - Tenant: "cgrates.org", - Category: "call", - AnswerTime: time.Now(), - SetupTime: time.Now(), - Usage: 10 * time.Second, - Cost: 10, - } - cdrStats.AppendCDR(cdr, nil) - if err := cdrStats.ResetQueues([]string{"CDRST1"}, nil); err != nil { - t.Error("Error reloading queues: ", err) - } - ids := []string{} - if err := cdrStats.GetQueueIds(0, &ids); err != nil { - t.Error("Error getting queue ids: ", err) - } - result := len(ids) - expected := 6 - if result != expected { - t.Errorf("Error loading stats queues. Expected %v was %v", expected, result) - } - valMap := make(map[string]float64) - if err := cdrStats.GetValues("CDRST2", &valMap); err != nil { - t.Error("Error getting metric values: ", err) - } - if len(valMap) != 2 || valMap["ACD"] != 10 || valMap["ASR"] != 100 { - t.Error("Error on metric map: ", valMap) - } -} - -func TestStatsSaveRestoreQeue(t *testing.T) { - sq := &CDRStatsQueue{ - conf: &CdrStats{Id: "TTT"}, - Cdrs: []*QCdr{&QCdr{Cost: 9.0}}, - } - if err := dm.DataDB().SetCdrStatsQueue(sq); err != nil { - t.Error("Error saving metric: ", err) - } - recovered, err := dm.DataDB().GetCdrStatsQueue(sq.GetId()) - if err != nil { - t.Error("Error loading metric: ", err) - } - if len(recovered.Cdrs) != 1 || recovered.Cdrs[0].Cost != sq.Cdrs[0].Cost { - t.Errorf("Expecting %+v got: %+v", sq.Cdrs[0], recovered.Cdrs[0]) - } -} - -func TestStatsPurgeTimeOne(t *testing.T) { - sq := NewCDRStatsQueue(&CdrStats{Metrics: []string{ASR, ACD, TCD, ACC, TCC}, TimeWindow: 30 * time.Minute}) - cdr := &CDR{ - SetupTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - Usage: 10 * time.Second, - Cost: 1, - } - qcdr := sq.AppendCDR(cdr) - qcdr.EventTime = qcdr.SetupTime - s := sq.GetStats() - if s[ASR] != -1 || - s[ACD] != -1 || - s[TCD] != -1 || - s[ACC] != -1 || - s[TCC] != -1 { - t.Errorf("Error getting stats: %+v", s) - } -} - -func TestStatsPurgeTime(t *testing.T) { - sq := NewCDRStatsQueue(&CdrStats{Metrics: []string{ASR, ACD, TCD, ACC, TCC}, TimeWindow: 30 * time.Minute}) - cdr := &CDR{ - SetupTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - Usage: 10 * time.Second, - Cost: 1, - } - qcdr := sq.AppendCDR(cdr) - qcdr.EventTime = qcdr.SetupTime - cdr.Cost = 2 - qcdr = sq.AppendCDR(cdr) - qcdr.EventTime = qcdr.SetupTime - cdr.Cost = 3 - qcdr = sq.AppendCDR(cdr) - qcdr.EventTime = qcdr.SetupTime - s := sq.GetStats() - if s[ASR] != -1 || - s[ACD] != -1 || - s[TCD] != -1 || - s[ACC] != -1 || - s[TCC] != -1 { - t.Errorf("Error getting stats: %+v", s) - } -} - -func TestStatsPurgeTimeFirst(t *testing.T) { - sq := NewCDRStatsQueue(&CdrStats{Metrics: []string{ASR, ACD, TCD, ACC, TCC}, TimeWindow: 30 * time.Minute}) - cdr := &CDR{ - SetupTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - Usage: 10 * time.Second, - Cost: 1, - } - qcdr := sq.AppendCDR(cdr) - cdr.Cost = 2 - cdr.SetupTime = time.Date(2024, 7, 14, 14, 25, 0, 0, time.UTC) - cdr.AnswerTime = time.Date(2024, 7, 14, 14, 25, 0, 0, time.UTC) - qcdr.EventTime = qcdr.SetupTime - sq.AppendCDR(cdr) - cdr.Cost = 3 - sq.AppendCDR(cdr) - s := sq.GetStats() - if s[ASR] != 100 || - s[ACD] != 10 || - s[TCD] != 20 || - s[ACC] != 2.5 || - s[TCC] != 5 { - t.Errorf("Error getting stats: %+v", s) - } -} - -func TestStatsPurgeLength(t *testing.T) { - sq := NewCDRStatsQueue(&CdrStats{Metrics: []string{ASR, ACD, TCD, ACC, TCC}, QueueLength: 1}) - cdr := &CDR{ - SetupTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - Usage: 10 * time.Second, - Cost: 1, - } - sq.AppendCDR(cdr) - cdr.Cost = 2 - sq.AppendCDR(cdr) - cdr.Cost = 3 - sq.AppendCDR(cdr) - s := sq.GetStats() - if s[ASR] != 100 || - s[ACD] != 10 || - s[TCD] != 10 || - s[ACC] != 3 || - s[TCC] != 3 { - t.Errorf("Error getting stats: %+v", s) - } -} diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index 9b05f5b7f..b5dc8e025 100755 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -256,7 +256,7 @@ func (ms *MongoStorage) EnsureIndexes() (err error) { Background: false, Sparse: false, } - if err = db.C(utils.TBLCDRs).EnsureIndex(idx); err != nil { + if err = db.C(utils.CDRsTBL).EnsureIndex(idx); err != nil { return } for _, idxKey := range ms.cdrsIndexes { @@ -267,7 +267,7 @@ func (ms *MongoStorage) EnsureIndexes() (err error) { Background: false, Sparse: false, } - if err = db.C(utils.TBLCDRs).EnsureIndex(idx); err != nil { + if err = db.C(utils.CDRsTBL).EnsureIndex(idx); err != nil { return } } @@ -278,7 +278,7 @@ func (ms *MongoStorage) EnsureIndexes() (err error) { Background: false, Sparse: false, } - if err = db.C(utils.TBLSMCosts).EnsureIndex(idx); err != nil { + if err = db.C(utils.SMCostsTBL).EnsureIndex(idx); err != nil { return } idx = mgo.Index{ @@ -288,7 +288,7 @@ func (ms *MongoStorage) EnsureIndexes() (err error) { Background: false, Sparse: false, } - if err = db.C(utils.TBLSMCosts).EnsureIndex(idx); err != nil { + if err = db.C(utils.SMCostsTBL).EnsureIndex(idx); err != nil { return } idx = mgo.Index{ @@ -298,7 +298,7 @@ func (ms *MongoStorage) EnsureIndexes() (err error) { Background: false, Sparse: false, } - if err = db.C(utils.TBLSMCosts).EnsureIndex(idx); err != nil { + if err = db.C(utils.SMCostsTBL).EnsureIndex(idx); err != nil { return } } diff --git a/engine/storage_mongo_stordb.go b/engine/storage_mongo_stordb.go index 02a219b2a..c8bf5bf38 100755 --- a/engine/storage_mongo_stordb.go +++ b/engine/storage_mongo_stordb.go @@ -888,13 +888,13 @@ func (ms *MongoStorage) SetSMCost(smc *SMCost) error { if smc.CostDetails == nil { return nil } - session, col := ms.conn(utils.TBLSMCosts) + session, col := ms.conn(utils.SMCostsTBL) defer session.Close() return col.Insert(smc) } func (ms *MongoStorage) RemoveSMCost(smc *SMCost) error { - session, col := ms.conn(utils.TBLSMCosts) + session, col := ms.conn(utils.SMCostsTBL) defer session.Close() tx := col.Bulk() tx.Remove(bson.M{"cgrid": smc.CGRID, "runid": smc.RunID}, smc) @@ -917,7 +917,7 @@ func (ms *MongoStorage) GetSMCosts(cgrid, runid, originHost, originIDPrefix stri filter[OriginIDLow] = bson.M{"$regex": bson.RegEx{Pattern: fmt.Sprintf("^%s", originIDPrefix)}} } // Execute query - session, col := ms.conn(utils.TBLSMCosts) + session, col := ms.conn(utils.SMCostsTBL) defer session.Close() iter := col.Find(filter).Iter() var smCost SMCost @@ -938,7 +938,7 @@ func (ms *MongoStorage) SetCDR(cdr *CDR, allowUpdate bool) (err error) { if cdr.OrderID == 0 { cdr.OrderID = ms.cnter.Next() } - session, col := ms.conn(utils.TBLCDRs) + session, col := ms.conn(utils.CDRsTBL) defer session.Close() if allowUpdate { _, err = col.Upsert(bson.M{CGRIDLow: cdr.CGRID, RunIDLow: cdr.RunID}, cdr) @@ -980,7 +980,7 @@ func (ms *MongoStorage) cleanEmptyFilters(filters bson.M) { } } -// _, err := col(utils.TBLCDRs).UpdateAll(bson.M{CGRIDLow: bson.M{"$in": cgrIds}}, bson.M{"$set": bson.M{"deleted_at": time.Now()}}) +// _, err := col(utils.CDRsTBL).UpdateAll(bson.M{CGRIDLow: bson.M{"$in": cgrIds}}, bson.M{"$set": bson.M{"deleted_at": time.Now()}}) func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, int64, error) { var minPDD, maxPDD, minUsage, maxUsage *time.Duration if len(qryFltr.MinPDD) != 0 { @@ -1111,7 +1111,7 @@ func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, } //file.WriteString(fmt.Sprintf("AFTER: %v\n", utils.ToIJSON(filters))) //file.Close() - session, col := ms.conn(utils.TBLCDRs) + session, col := ms.conn(utils.CDRsTBL) defer session.Close() if remove { if chgd, err := col.RemoveAll(filters); err != nil { diff --git a/engine/storage_sql.go b/engine/storage_sql.go index dc549f812..cb90a015d 100755 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -57,7 +57,7 @@ func (self *SQLStorage) Flush(scriptsPath string) (err error) { return err } } - if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 FROM %s", utils.TBLCDRs)); err != nil { + if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 FROM %s", utils.CDRsTBL)); err != nil { return err } if err := SetDBVersions(self); err != nil { @@ -668,19 +668,14 @@ func (self *SQLStorage) SetSMCost(smc *SMCost) error { if smc.CostDetails == nil { return nil } - tss, err := json.Marshal(smc.CostDetails) - if err != nil { - utils.Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err)) - return err - } tx := self.db.Begin() - cd := &TBLSMCosts{ + cd := &SMCostSQL{ Cgrid: smc.CGRID, RunID: smc.RunID, OriginHost: smc.OriginHost, OriginID: smc.OriginID, CostSource: smc.CostSource, - CostDetails: string(tss), + CostDetails: smc.CostDetails.AsJSON(), Usage: smc.Usage, CreatedAt: time.Now(), } @@ -695,7 +690,7 @@ func (self *SQLStorage) SetSMCost(smc *SMCost) error { func (self *SQLStorage) RemoveSMCost(smc *SMCost) error { tx := self.db.Begin() - if err := tx.Where(&TBLSMCosts{Cgrid: smc.CGRID, RunID: smc.RunID}).Delete(SMCost{}).Error; err != nil { + if err := tx.Where(&SMCostSQL{Cgrid: smc.CGRID, RunID: smc.RunID}).Delete(SMCost{}).Error; err != nil { tx.Rollback() return err } @@ -706,7 +701,7 @@ func (self *SQLStorage) RemoveSMCost(smc *SMCost) error { // GetSMCosts is used to retrieve one or multiple SMCosts based on filter func (self *SQLStorage) GetSMCosts(cgrid, runid, originHost, originIDPrefix string) ([]*SMCost, error) { var smCosts []*SMCost - filter := &TBLSMCosts{} + filter := &SMCostSQL{} if cgrid != "" { filter.Cgrid = cgrid } @@ -720,7 +715,7 @@ func (self *SQLStorage) GetSMCosts(cgrid, runid, originHost, originIDPrefix stri if originIDPrefix != "" { q = self.db.Where(filter).Where(fmt.Sprintf("origin_id LIKE '%s%%'", originIDPrefix)) } - results := make([]*TBLSMCosts, 0) + results := make([]*SMCostSQL, 0) if err := q.Find(&results).Error; err != nil { return nil, err } @@ -756,73 +751,18 @@ func (self *SQLStorage) LogActionTiming(source string, at *ActionTiming, as Acti } func (self *SQLStorage) SetCDR(cdr *CDR, allowUpdate bool) error { - extraFields, err := json.Marshal(cdr.ExtraFields) - if err != nil { - return err - } tx := self.db.Begin() - saved := tx.Save(&TBLCDRs{ - Cgrid: cdr.CGRID, - RunID: cdr.RunID, - OriginHost: cdr.OriginHost, - Source: cdr.Source, - OriginID: cdr.OriginID, - Tor: cdr.ToR, - RequestType: cdr.RequestType, - Direction: cdr.Direction, - Tenant: cdr.Tenant, - Category: cdr.Category, - Account: cdr.Account, - Subject: cdr.Subject, - Destination: cdr.Destination, - SetupTime: cdr.SetupTime, - Pdd: cdr.PDD.Seconds(), - AnswerTime: cdr.AnswerTime, - Usage: cdr.Usage.Seconds(), - Supplier: cdr.Supplier, - DisconnectCause: cdr.DisconnectCause, - ExtraFields: string(extraFields), - CostSource: cdr.CostSource, - Cost: cdr.Cost, - CostDetails: cdr.CostDetailsJson(), - AccountSummary: utils.ToJSON(cdr.AccountSummary), - ExtraInfo: cdr.ExtraInfo, - CreatedAt: time.Now(), - }) + cdrSql := cdr.AsCDRsql() + cdrSql.CreatedAt = time.Now() + saved := tx.Save(cdrSql) if saved.Error != nil { tx.Rollback() if !allowUpdate { return saved.Error } tx = self.db.Begin() - updated := tx.Model(&TBLCDRs{}).Where(&TBLCDRs{Cgrid: cdr.CGRID, RunID: cdr.RunID, OriginID: cdr.OriginID}).Updates( - TBLCDRs{ - OriginHost: cdr.OriginHost, - Source: cdr.Source, - OriginID: cdr.OriginID, - Tor: cdr.ToR, - RequestType: cdr.RequestType, - Direction: cdr.Direction, - Tenant: cdr.Tenant, - Category: cdr.Category, - Account: cdr.Account, - Subject: cdr.Subject, - Destination: cdr.Destination, - SetupTime: cdr.SetupTime, - Pdd: cdr.PDD.Seconds(), - AnswerTime: cdr.AnswerTime, - Usage: cdr.Usage.Seconds(), - Supplier: cdr.Supplier, - DisconnectCause: cdr.DisconnectCause, - ExtraFields: string(extraFields), - CostSource: cdr.CostSource, - Cost: cdr.Cost, - CostDetails: cdr.CostDetailsJson(), - AccountSummary: utils.ToJSON(cdr.AccountSummary), - ExtraInfo: cdr.ExtraInfo, - UpdatedAt: time.Now(), - }, - ) + cdrSql.UpdatedAt = time.Now() + updated := tx.Model(&CDRsql{}).Where(&CDRsql{CGRID: cdr.CGRID, RunID: cdr.RunID, OriginID: cdr.OriginID}).Updates(cdrSql) if updated.Error != nil { tx.Rollback() return updated.Error @@ -836,7 +776,7 @@ func (self *SQLStorage) SetCDR(cdr *CDR, allowUpdate bool) error { // qryFltr.Unscoped will ignore soft deletes or delete records permanently func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, int64, error) { var cdrs []*CDR - q := self.db.Table(utils.TBLCDRs).Select("*") + q := self.db.Table(utils.CDRsTBL).Select("*") if qryFltr.Unscoped { q = q.Unscoped() } @@ -942,10 +882,10 @@ func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, q = q.Where("disconnect_cause not in (?)", qryFltr.NotDisconnectCauses) } if len(qryFltr.Costs) != 0 { - q = q.Where(utils.TBLCDRs+".cost in (?)", qryFltr.Costs) + q = q.Where(utils.CDRsTBL+".cost in (?)", qryFltr.Costs) } if len(qryFltr.NotCosts) != 0 { - q = q.Where(utils.TBLCDRs+".cost not in (?)", qryFltr.NotCosts) + q = q.Where(utils.CDRsTBL+".cost not in (?)", qryFltr.NotCosts) } if len(qryFltr.ExtraFields) != 0 { // Extra fields searches, implemented as contains in extra field qIds := bytes.NewBufferString("(") @@ -982,10 +922,10 @@ func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, q = q.Where(qIds.String()) } if qryFltr.OrderIDStart != nil { // Keep backwards compatible by testing 0 value - q = q.Where(utils.TBLCDRs+".id >= ?", *qryFltr.OrderIDStart) + q = q.Where(utils.CDRsTBL+".id >= ?", *qryFltr.OrderIDStart) } if qryFltr.OrderIDEnd != nil { - q = q.Where(utils.TBLCDRs+".id < ?", *qryFltr.OrderIDEnd) + q = q.Where(utils.CDRsTBL+".id < ?", *qryFltr.OrderIDEnd) } if qryFltr.SetupTimeStart != nil { q = q.Where("setup_time >= ?", qryFltr.SetupTimeStart) @@ -1012,41 +952,41 @@ func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, q = q.Where("updated_at < ?", qryFltr.UpdatedAtEnd) } if len(qryFltr.MinUsage) != 0 { - if minUsage, err := utils.ParseDurationWithSecs(qryFltr.MinUsage); err != nil { + minUsage, err := utils.ParseDurationWithNanosecs(qryFltr.MinUsage) + if err != nil { return nil, 0, err + } + if self.db.Dialect().GetName() == utils.MYSQL { // MySQL needs escaping for usage + q = q.Where("`usage` >= ?", minUsage.Nanoseconds()) } else { - if self.db.Dialect().GetName() == utils.MYSQL { // MySQL needs escaping for usage - q = q.Where("`usage` >= ?", minUsage.Seconds()) - } else { - q = q.Where("usage >= ?", minUsage.Seconds()) - } + q = q.Where("usage >= ?", minUsage.Nanoseconds()) } } if len(qryFltr.MaxUsage) != 0 { - if maxUsage, err := utils.ParseDurationWithSecs(qryFltr.MaxUsage); err != nil { + maxUsage, err := utils.ParseDurationWithNanosecs(qryFltr.MaxUsage) + if err != nil { return nil, 0, err + } + if self.db.Dialect().GetName() == utils.MYSQL { // MySQL needs escaping for usage + q = q.Where("`usage` < ?", maxUsage.Nanoseconds()) } else { - if self.db.Dialect().GetName() == utils.MYSQL { // MySQL needs escaping for usage - q = q.Where("`usage` < ?", maxUsage.Seconds()) - } else { - q = q.Where("usage < ?", maxUsage.Seconds()) - } + q = q.Where("usage < ?", maxUsage.Nanoseconds()) } } if len(qryFltr.MinPDD) != 0 { - if minPDD, err := utils.ParseDurationWithSecs(qryFltr.MinPDD); err != nil { + if minPDD, err := utils.ParseDurationWithNanosecs(qryFltr.MinPDD); err != nil { return nil, 0, err } else { - q = q.Where("pdd >= ?", minPDD.Seconds()) + q = q.Where("pdd >= ?", minPDD.Nanoseconds()) } } if len(qryFltr.MaxPDD) != 0 { - if maxPDD, err := utils.ParseDurationWithSecs(qryFltr.MaxPDD); err != nil { + if maxPDD, err := utils.ParseDurationWithNanosecs(qryFltr.MaxPDD); err != nil { return nil, 0, err } else { - q = q.Where("pdd < ?", maxPDD.Seconds()) + q = q.Where("pdd < ?", maxPDD.Nanoseconds()) } } @@ -1087,58 +1027,16 @@ func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, return nil, cnt, nil } // Execute query - results := make([]*TBLCDRs, 0) + results := make([]*CDRsql, 0) if err := q.Find(&results).Error; err != nil { return nil, 0, err } for _, result := range results { - extraFieldsMp := make(map[string]string) - if result.ExtraFields != "" { - if err := json.Unmarshal([]byte(result.ExtraFields), &extraFieldsMp); err != nil { - return nil, 0, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %v, error: %s", result.Cgrid, result.RunID, err.Error()) - } + if cdr, err := NewCDRFromSQL(result); err != nil { + return nil, 0, err + } else { + cdrs = append(cdrs, cdr) } - var callCost CallCost - if result.CostDetails != "" { - if err := json.Unmarshal([]byte(result.CostDetails), &callCost); err != nil { - return nil, 0, fmt.Errorf("JSON unmarshal callcost error for cgrid: %s, runid: %v, error: %s", result.Cgrid, result.RunID, err.Error()) - } - } - acntSummary, err := NewAccountSummaryFromJSON(result.AccountSummary) - if err != nil { - return nil, 0, fmt.Errorf("JSON unmarshal account summary error for cgrid: %s, runid: %v, error: %s", result.Cgrid, result.RunID, err.Error()) - } - usageDur := time.Duration(result.Usage * utils.NANO_MULTIPLIER) - pddDur := time.Duration(result.Pdd * utils.NANO_MULTIPLIER) - storCdr := &CDR{ - CGRID: result.Cgrid, - RunID: result.RunID, - OrderID: result.ID, - OriginHost: result.OriginHost, - Source: result.Source, - OriginID: result.OriginID, - ToR: result.Tor, - RequestType: result.RequestType, - Direction: result.Direction, - Tenant: result.Tenant, - Category: result.Category, - Account: result.Account, - Subject: result.Subject, - Destination: result.Destination, - SetupTime: result.SetupTime, - PDD: pddDur, - AnswerTime: result.AnswerTime, - Usage: usageDur, - Supplier: result.Supplier, - DisconnectCause: result.DisconnectCause, - ExtraFields: extraFieldsMp, - CostSource: result.CostSource, - Cost: result.Cost, - CostDetails: &callCost, - AccountSummary: acntSummary, - ExtraInfo: result.ExtraInfo, - } - cdrs = append(cdrs, storCdr) } if len(cdrs) == 0 && !remove { return cdrs, 0, utils.ErrNotFound diff --git a/engine/suretax_test.go b/engine/suretax_test.go index 63c1cb404..16d554ed5 100644 --- a/engine/suretax_test.go +++ b/engine/suretax_test.go @@ -30,11 +30,16 @@ import ( func TestNewSureTaxRequest(t *testing.T) { CGRID := utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()) cdr := &CDR{CGRID: CGRID, OrderID: 123, ToR: utils.VOICE, - OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID, - Usage: time.Duration(12) * time.Second, PDD: time.Duration(7) * time.Second, - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true, + OriginID: "dsafdsaf", OriginHost: "192.168.1.1", + Source: utils.UNIT_TEST, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", + Subject: "1001", Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + RunID: utils.DEFAULT_RUNID, + Usage: time.Duration(12) * time.Second, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, + Cost: 1.01, Rated: true, } cfg, _ := config.NewDefaultCGRConfig() stCfg := cfg.SureTaxCfg() diff --git a/engine/users_test.go b/engine/users_test.go index 6983bb7a0..ca51f5261 100644 --- a/engine/users_test.go +++ b/engine/users_test.go @@ -610,7 +610,6 @@ func TestUsersUsageRecordGetLoadUserProfile(t *testing.T) { ur := &UsageRecord{ ToR: utils.USERS, RequestType: utils.USERS, - Direction: "*out", Tenant: "", Category: "call", Account: utils.USERS, @@ -628,7 +627,6 @@ func TestUsersUsageRecordGetLoadUserProfile(t *testing.T) { expected := &UsageRecord{ ToR: "04", RequestType: "4", - Direction: "*out", Tenant: "", Category: "call", Account: "rif", @@ -657,7 +655,6 @@ func TestUsersExternalCDRGetLoadUserProfileExtraFields(t *testing.T) { ur := &ExternalCDR{ ToR: utils.USERS, RequestType: utils.USERS, - Direction: "*out", Tenant: "", Category: "call", Account: utils.USERS, @@ -678,7 +675,6 @@ func TestUsersExternalCDRGetLoadUserProfileExtraFields(t *testing.T) { expected := &ExternalCDR{ ToR: "04", RequestType: "4", - Direction: "*out", Tenant: "", Category: "call", Account: "rif", @@ -710,7 +706,6 @@ func TestUsersExternalCDRGetLoadUserProfileExtraFieldsNotFound(t *testing.T) { ur := &ExternalCDR{ ToR: utils.USERS, RequestType: utils.USERS, - Direction: "*out", Tenant: "", Category: "call", Account: utils.USERS, @@ -744,7 +739,6 @@ func TestUsersExternalCDRGetLoadUserProfileExtraFieldsSet(t *testing.T) { ur := &ExternalCDR{ ToR: utils.USERS, RequestType: utils.USERS, - Direction: "*out", Tenant: "", Category: "call", Account: utils.USERS, @@ -766,7 +760,6 @@ func TestUsersExternalCDRGetLoadUserProfileExtraFieldsSet(t *testing.T) { expected := &ExternalCDR{ ToR: "04", RequestType: "4", - Direction: "*out", Tenant: "", Category: "call", Account: "rif", diff --git a/engine/version.go b/engine/version.go index 18df01307..9abfde5c8 100644 --- a/engine/version.go +++ b/engine/version.go @@ -104,9 +104,17 @@ func (vers Versions) Compare(curent Versions, storType string) string { return "" } +func CurrentStorDBVersions() Versions { + return Versions{utils.COST_DETAILS: 2, utils.CDRsTBL: 2} +} + +func CurrentDataDBVersions() Versions { + return Versions{utils.Accounts: 2, utils.Actions: 2, utils.ActionTriggers: 2, utils.ActionPlans: 2, utils.SharedGroups: 2} +} + func CurrentDBVersions(storType string) Versions { - dataDbVersions := Versions{utils.Accounts: 2, utils.Actions: 2, utils.ActionTriggers: 2, utils.ActionPlans: 2, utils.SharedGroups: 2} - storDbVersions := Versions{utils.COST_DETAILS: 2} + dataDbVersions := CurrentDataDBVersions() + storDbVersions := CurrentStorDBVersions() allVersions := make(Versions) for k, v := range dataDbVersions { @@ -127,13 +135,5 @@ func CurrentDBVersions(storType string) Versions { return nil } -func CurrentStorDBVersions() Versions { - return Versions{utils.COST_DETAILS: 2} -} - -func CurrentDataDBVersions() Versions { - return Versions{utils.Accounts: 2, utils.Actions: 2, utils.ActionTriggers: 2, utils.ActionPlans: 2, utils.SharedGroups: 2} -} - // Versions will keep trac of various item versions type Versions map[string]int64 // map[item]versionNr diff --git a/general_tests/auth_test.go b/general_tests/auth_test.go index 763f0dd20..18a3a59dd 100644 --- a/general_tests/auth_test.go +++ b/general_tests/auth_test.go @@ -94,7 +94,7 @@ RP_ANY,DR_ANY_1CNT,*any,10` } func TestAuthPostpaidNoAcnt(t *testing.T) { - cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org", + cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Tenant: "cgrates.org", Category: "call", Account: "nonexistent", Subject: "testauthpostpaid1", Destination: "4986517174963", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)} var maxSessionTime float64 @@ -105,7 +105,7 @@ func TestAuthPostpaidNoAcnt(t *testing.T) { func TestAuthPostpaidNoDestination(t *testing.T) { // Test subject which does not have destination attached - cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org", + cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Tenant: "cgrates.org", Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid1", Destination: "441231234", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)} var maxSessionTime float64 @@ -116,7 +116,7 @@ func TestAuthPostpaidNoDestination(t *testing.T) { func TestAuthPostpaidFallbackDest(t *testing.T) { // Test subject which has fallback for destination - cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org", + cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Tenant: "cgrates.org", Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid2", Destination: "441231234", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)} var maxSessionTime float64 @@ -129,7 +129,7 @@ func TestAuthPostpaidFallbackDest(t *testing.T) { func TestAuthPostpaidWithDestination(t *testing.T) { // Test subject which does not have destination attached - cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org", + cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Tenant: "cgrates.org", Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid1", Destination: "4986517174963", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)} var maxSessionTime float64 diff --git a/general_tests/fsevcorelate_test.go b/general_tests/fsevcorelate_test.go index 448c88703..d7e06ac36 100644 --- a/general_tests/fsevcorelate_test.go +++ b/general_tests/fsevcorelate_test.go @@ -569,9 +569,6 @@ func TestEvCdrCorelate(t *testing.T) { if evStoredCdr.RequestType != jsnStoredCdr.RequestType { t.Errorf("evStoredCdr.RequestType: %s, jsnStoredCdr.RequestType: %s", evStoredCdr.RequestType, jsnStoredCdr.RequestType) } - if evStoredCdr.Direction != jsnStoredCdr.Direction { - t.Errorf("evStoredCdr.Direction: %s, jsnStoredCdr.Direction: %s", evStoredCdr.Direction, jsnStoredCdr.Direction) - } if evStoredCdr.Tenant != jsnStoredCdr.Tenant { t.Errorf("evStoredCdr.Tenant: %s, jsnStoredCdr.Tenant: %s", evStoredCdr.Tenant, jsnStoredCdr.Tenant) } @@ -590,19 +587,10 @@ func TestEvCdrCorelate(t *testing.T) { if evStoredCdr.SetupTime != jsnStoredCdr.SetupTime { t.Errorf("evStoredCdr.SetupTime: %v, jsnStoredCdr.SetupTime: %v", evStoredCdr.SetupTime, jsnStoredCdr.SetupTime) } - if evStoredCdr.PDD != jsnStoredCdr.PDD { - t.Errorf("evStoredCdr.PDD: %v, jsnStoredCdr.PDD: %v", evStoredCdr.PDD, jsnStoredCdr.PDD) - } if evStoredCdr.AnswerTime != jsnStoredCdr.AnswerTime { t.Errorf("evStoredCdr.AnswerTime: %v, jsnStoredCdr.AnswerTime: %v", evStoredCdr.AnswerTime, jsnStoredCdr.AnswerTime) } if evStoredCdr.Usage != jsnStoredCdr.Usage { t.Errorf("evStoredCdr.Usage: %v, jsnStoredCdr.Usage: %v", evStoredCdr.Usage, jsnStoredCdr.Usage) } - if evStoredCdr.Supplier != jsnStoredCdr.Supplier { - t.Errorf("evStoredCdr.Supplier: %s, jsnStoredCdr.Supplier: %s", evStoredCdr.Supplier, jsnStoredCdr.Supplier) - } - if evStoredCdr.DisconnectCause != jsnStoredCdr.DisconnectCause { - t.Errorf("evStoredCdr.DisconnectCause: %s, jsnStoredCdr.DisconnectCause: %s", evStoredCdr.DisconnectCause, jsnStoredCdr.DisconnectCause) - } } diff --git a/sessionmanager/fsevent.go b/sessionmanager/fsevent.go index 790b76d18..5a546060f 100644 --- a/sessionmanager/fsevent.go +++ b/sessionmanager/fsevent.go @@ -347,7 +347,6 @@ func (fsev FSEvent) AsStoredCdr(timezone string) *engine.CDR { storCdr.OriginHost = fsev.GetOriginatorIP(utils.META_DEFAULT) storCdr.Source = "FS_" + fsev.GetName() storCdr.RequestType = fsev.GetReqType(utils.META_DEFAULT) - storCdr.Direction = fsev.GetDirection(utils.META_DEFAULT) storCdr.Tenant = fsev.GetTenant(utils.META_DEFAULT) storCdr.Category = fsev.GetCategory(utils.META_DEFAULT) storCdr.Account = fsev.GetAccount(utils.META_DEFAULT) @@ -356,11 +355,8 @@ func (fsev FSEvent) AsStoredCdr(timezone string) *engine.CDR { storCdr.SetupTime, _ = fsev.GetSetupTime(utils.META_DEFAULT, timezone) storCdr.AnswerTime, _ = fsev.GetAnswerTime(utils.META_DEFAULT, timezone) storCdr.Usage, _ = fsev.GetDuration(utils.META_DEFAULT) - storCdr.PDD, _ = fsev.GetPdd(utils.META_DEFAULT) storCdr.ExtraFields = fsev.GetExtraFields() storCdr.Cost = -1 - storCdr.Supplier = fsev.GetSupplier(utils.META_DEFAULT) - storCdr.DisconnectCause = fsev.GetDisconnectCause(utils.META_DEFAULT) return storCdr } diff --git a/sessionmanager/fsevent_test.go b/sessionmanager/fsevent_test.go index 8bdd1a6be..3c68a7f41 100644 --- a/sessionmanager/fsevent_test.go +++ b/sessionmanager/fsevent_test.go @@ -371,7 +371,6 @@ func TestEventParseStatic(t *testing.T) { answerTime, _ := ev.GetAnswerTime("^2013-12-07 08:42:24", "") dur, _ := ev.GetDuration("^60s") if ev.GetReqType("^test") != "test" || - ev.GetDirection("^test") != "test" || ev.GetTenant("^test") != "test" || ev.GetCategory("^test") != "test" || ev.GetAccount("^test") != "test" || @@ -379,12 +378,9 @@ func TestEventParseStatic(t *testing.T) { ev.GetDestination("^test") != "test" || setupTime != time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC) || answerTime != time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC) || - dur != time.Duration(60)*time.Second || - ev.GetSupplier("^test") != "test" || - ev.GetDisconnectCause("^test") != "test" { + dur != time.Duration(60)*time.Second { t.Error("Values out of static not matching", ev.GetReqType("^test") != "test", - ev.GetDirection("^test") != "test", ev.GetTenant("^test") != "test", ev.GetCategory("^test") != "test", ev.GetAccount("^test") != "test", @@ -392,9 +388,7 @@ func TestEventParseStatic(t *testing.T) { ev.GetDestination("^test") != "test", setupTime != time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), answerTime != time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), - dur != time.Duration(60)*time.Second, - ev.GetSupplier("^test") != "test", - ev.GetDisconnectCause("^test") != "test") + dur != time.Duration(60)*time.Second) } } @@ -424,7 +418,6 @@ Task-Runtime: 1349437318` answerTime, _ := ev.GetAnswerTime("Event-Date-Local", "") dur, _ := ev.GetDuration("Event-Calling-Line-Number") if ev.GetReqType("FreeSWITCH-Hostname") != "h1.ip-switch.net" || - ev.GetDirection("FreeSWITCH-Hostname") != "*out" || ev.GetTenant("FreeSWITCH-Hostname") != "h1.ip-switch.net" || ev.GetCategory("FreeSWITCH-Hostname") != "h1.ip-switch.net" || ev.GetAccount("FreeSWITCH-Hostname") != "h1.ip-switch.net" || @@ -432,12 +425,9 @@ Task-Runtime: 1349437318` ev.GetDestination("FreeSWITCH-Hostname") != "h1.ip-switch.net" || setupTime != time.Date(2012, 10, 5, 13, 41, 38, 0, time.UTC) || answerTime != time.Date(2012, 10, 5, 13, 41, 38, 0, time.UTC) || - dur != time.Duration(65)*time.Second || - ev.GetSupplier("FreeSWITCH-Hostname") != "h1.ip-switch.net" || - ev.GetDisconnectCause("FreeSWITCH-Hostname") != "h1.ip-switch.net" { + dur != time.Duration(65)*time.Second { t.Error("Values out of static not matching", ev.GetReqType("FreeSWITCH-Hostname") != "h1.ip-switch.net", - ev.GetDirection("FreeSWITCH-Hostname") != "*out", ev.GetTenant("FreeSWITCH-Hostname") != "h1.ip-switch.net", ev.GetCategory("FreeSWITCH-Hostname") != "h1.ip-switch.net", ev.GetAccount("FreeSWITCH-Hostname") != "h1.ip-switch.net", @@ -445,9 +435,7 @@ Task-Runtime: 1349437318` ev.GetDestination("FreeSWITCH-Hostname") != "h1.ip-switch.net", setupTime != time.Date(2012, 10, 5, 13, 41, 38, 0, time.UTC), answerTime != time.Date(2012, 10, 5, 13, 41, 38, 0, time.UTC), - dur != time.Duration(65)*time.Second, - ev.GetSupplier("FreeSWITCH-Hostname") != "h1.ip-switch.net", - ev.GetDisconnectCause("FreeSWITCH-Hostname") != "h1.ip-switch.net") + dur != time.Duration(65)*time.Second) } } @@ -482,7 +470,6 @@ func TestParseFsHangup(t *testing.T) { answerTime, _ := ev.GetAnswerTime(utils.META_DEFAULT, "") dur, _ := ev.GetDuration(utils.META_DEFAULT) if ev.GetReqType(utils.META_DEFAULT) != utils.META_PREPAID || - ev.GetDirection(utils.META_DEFAULT) != "*out" || ev.GetTenant(utils.META_DEFAULT) != "cgrates.org" || ev.GetCategory(utils.META_DEFAULT) != "call" || ev.GetAccount(utils.META_DEFAULT) != "1001" || @@ -490,12 +477,9 @@ func TestParseFsHangup(t *testing.T) { ev.GetDestination(utils.META_DEFAULT) != "1003" || setupTime.UTC() != time.Date(2015, 7, 7, 14, 52, 8, 0, time.UTC) || answerTime.UTC() != time.Date(2015, 7, 7, 14, 52, 8, 0, time.UTC) || - dur != time.Duration(66)*time.Second || - ev.GetSupplier(utils.META_DEFAULT) != "supplier1" || - ev.GetDisconnectCause(utils.META_DEFAULT) != "NORMAL_CLEARING" { + dur != time.Duration(66)*time.Second { t.Error("Default values not matching", ev.GetReqType(utils.META_DEFAULT) != utils.META_PREPAID, - ev.GetDirection(utils.META_DEFAULT) != "*out", ev.GetTenant(utils.META_DEFAULT) != "cgrates.org", ev.GetCategory(utils.META_DEFAULT) != "call", ev.GetAccount(utils.META_DEFAULT) != "1001", @@ -503,9 +487,7 @@ func TestParseFsHangup(t *testing.T) { ev.GetDestination(utils.META_DEFAULT) != "1003", setupTime.UTC() != time.Date(2015, 7, 7, 14, 52, 8, 0, time.UTC), answerTime.UTC() != time.Date(2015, 7, 7, 14, 52, 8, 0, time.UTC), - dur != time.Duration(66)*time.Second, - ev.GetSupplier(utils.META_DEFAULT) != "supplier1", - ev.GetDisconnectCause(utils.META_DEFAULT) != "NORMAL_CLEARING") + dur != time.Duration(66)*time.Second) } } @@ -635,11 +617,12 @@ func TestFsEvAsStoredCdr(t *testing.T) { setupTime, _ := utils.ParseTimeDetectLayout("1436280728", "") aTime, _ := utils.ParseTimeDetectLayout("1436280728", "") eStoredCdr := &engine.CDR{CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41", - ToR: utils.VOICE, OriginID: "e3133bf7-dcde-4daf-9663-9a79ffcef5ad", OriginHost: "10.0.3.15", Source: "FS_CHANNEL_HANGUP_COMPLETE", RequestType: utils.META_PREPAID, - Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", + ToR: utils.VOICE, OriginID: "e3133bf7-dcde-4daf-9663-9a79ffcef5ad", + OriginHost: "10.0.3.15", Source: "FS_CHANNEL_HANGUP_COMPLETE", RequestType: utils.META_PREPAID, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1003", SetupTime: setupTime, AnswerTime: aTime, - Usage: time.Duration(66) * time.Second, PDD: time.Duration(28) * time.Millisecond, Supplier: "supplier1", - DisconnectCause: "NORMAL_CLEARING", ExtraFields: make(map[string]string), Cost: -1} + Usage: time.Duration(66) * time.Second, + ExtraFields: make(map[string]string), Cost: -1} if storedCdr := ev.AsStoredCdr(""); !reflect.DeepEqual(eStoredCdr, storedCdr) { t.Errorf("Expecting: %+v, received: %+v", eStoredCdr, storedCdr) } diff --git a/sessionmanager/fssessionmanager.go b/sessionmanager/fssessionmanager.go index f68ef9eb9..c378672ee 100644 --- a/sessionmanager/fssessionmanager.go +++ b/sessionmanager/fssessionmanager.go @@ -128,7 +128,7 @@ func (sm *FSSessionManager) setCgrLcr(ev engine.Event, connId string) error { } cd := &engine.CallDescriptor{ CgrID: ev.GetCgrId(sm.Timezone()), - Direction: ev.GetDirection(utils.META_DEFAULT), + Direction: utils.OUT, Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT), diff --git a/sessionmanager/kamevent.go b/sessionmanager/kamevent.go index 6556ae507..e2077eddc 100644 --- a/sessionmanager/kamevent.go +++ b/sessionmanager/kamevent.go @@ -328,7 +328,6 @@ func (kev KamEvent) AsStoredCdr(timezone string) *engine.CDR { storCdr.OriginHost = kev.GetOriginatorIP(utils.META_DEFAULT) storCdr.Source = kev.GetCdrSource() storCdr.RequestType = kev.GetReqType(utils.META_DEFAULT) - storCdr.Direction = kev.GetDirection(utils.META_DEFAULT) storCdr.Tenant = kev.GetTenant(utils.META_DEFAULT) storCdr.Category = kev.GetCategory(utils.META_DEFAULT) storCdr.Account = kev.GetAccount(utils.META_DEFAULT) @@ -337,9 +336,6 @@ func (kev KamEvent) AsStoredCdr(timezone string) *engine.CDR { storCdr.SetupTime, _ = kev.GetSetupTime(utils.META_DEFAULT, timezone) storCdr.AnswerTime, _ = kev.GetAnswerTime(utils.META_DEFAULT, timezone) storCdr.Usage, _ = kev.GetDuration(utils.META_DEFAULT) - storCdr.PDD, _ = kev.GetPdd(utils.META_DEFAULT) - storCdr.Supplier = kev.GetSupplier(utils.META_DEFAULT) - storCdr.DisconnectCause = kev.GetDisconnectCause(utils.META_DEFAULT) storCdr.ExtraFields = kev.GetExtraFields() storCdr.Cost = -1 diff --git a/sessionmanager/osipsevent.go b/sessionmanager/osipsevent.go index 4057d2eea..2fb3f3ce3 100644 --- a/sessionmanager/osipsevent.go +++ b/sessionmanager/osipsevent.go @@ -272,7 +272,6 @@ func (osipsEv *OsipsEvent) AsStoredCdr(timezone string) *engine.CDR { storCdr.OriginHost = osipsEv.GetOriginatorIP(utils.META_DEFAULT) storCdr.Source = "OSIPS_" + osipsEv.GetName() storCdr.RequestType = osipsEv.GetReqType(utils.META_DEFAULT) - storCdr.Direction = osipsEv.GetDirection(utils.META_DEFAULT) storCdr.Tenant = osipsEv.GetTenant(utils.META_DEFAULT) storCdr.Category = osipsEv.GetCategory(utils.META_DEFAULT) storCdr.Account = osipsEv.GetAccount(utils.META_DEFAULT) @@ -281,9 +280,6 @@ func (osipsEv *OsipsEvent) AsStoredCdr(timezone string) *engine.CDR { storCdr.SetupTime, _ = osipsEv.GetSetupTime(utils.META_DEFAULT, timezone) storCdr.AnswerTime, _ = osipsEv.GetAnswerTime(utils.META_DEFAULT, timezone) storCdr.Usage, _ = osipsEv.GetDuration(utils.META_DEFAULT) - storCdr.PDD, _ = osipsEv.GetPdd(utils.META_DEFAULT) - storCdr.Supplier = osipsEv.GetSupplier(utils.META_DEFAULT) - storCdr.DisconnectCause = osipsEv.GetDisconnectCause(utils.META_DEFAULT) storCdr.ExtraFields = osipsEv.GetExtraFields() storCdr.Cost = -1 return storCdr diff --git a/sessionmanager/osipsevent_test.go b/sessionmanager/osipsevent_test.go index 31b0e4e8f..102b2dab7 100644 --- a/sessionmanager/osipsevent_test.go +++ b/sessionmanager/osipsevent_test.go @@ -142,12 +142,15 @@ func TestOsipsEventMissingParameter(t *testing.T) { func TestOsipsEventAsStoredCdr(t *testing.T) { setupTime, _ := utils.ParseTimeDetectLayout("1406370492", "") answerTime, _ := utils.ParseTimeDetectLayout("1406370499", "") - eStoredCdr := &engine.CDR{CGRID: utils.Sha1("ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", setupTime.UTC().String()), - ToR: utils.VOICE, OriginID: "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", OriginHost: "172.16.254.77", Source: "OSIPS_E_ACC_CDR", + eStoredCdr := &engine.CDR{ + CGRID: utils.Sha1("ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", setupTime.UTC().String()), + ToR: utils.VOICE, OriginID: "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", + OriginHost: "172.16.254.77", Source: "OSIPS_E_ACC_CDR", RequestType: utils.META_PREPAID, - Direction: utils.OUT, Tenant: "itsyscom.com", Category: "call", Account: "dan", Subject: "dan", + Tenant: "itsyscom.com", Category: "call", Account: "dan", Subject: "dan", Destination: "+4986517174963", SetupTime: setupTime, AnswerTime: answerTime, - Usage: time.Duration(20) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "supplier3", DisconnectCause: "200", ExtraFields: map[string]string{"extra1": "val1", "extra2": "val2"}, Cost: -1} + Usage: time.Duration(20) * time.Second, + ExtraFields: map[string]string{"extra1": "val1", "extra2": "val2"}, Cost: -1} if storedCdr := osipsEv.AsStoredCdr(""); !reflect.DeepEqual(eStoredCdr, storedCdr) { t.Errorf("Expecting: %+v, received: %+v", eStoredCdr, storedCdr) } @@ -163,8 +166,8 @@ func TestOsipsAccMissedToStoredCdr(t *testing.T) { }} eStoredCdr := &engine.CDR{CGRID: utils.Sha1("27b1e6679ad0109b5d756e42bb4c9c28@0:0:0:0:0:0:0:0", setupTime.UTC().String()), ToR: utils.VOICE, OriginID: "27b1e6679ad0109b5d756e42bb4c9c28@0:0:0:0:0:0:0:0", OriginHost: "172.16.254.77", Source: "OSIPS_E_ACC_MISSED_EVENT", - RequestType: utils.META_PSEUDOPREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Supplier: "supplier1", - DisconnectCause: "404", Destination: "1002", SetupTime: setupTime, AnswerTime: setupTime, + RequestType: utils.META_PSEUDOPREPAID, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", + Destination: "1002", SetupTime: setupTime, AnswerTime: setupTime, Usage: time.Duration(0), ExtraFields: map[string]string{"extra1": "val1", "extra2": "val2"}, Cost: -1} if storedCdr := osipsEv.AsStoredCdr(""); !reflect.DeepEqual(eStoredCdr, storedCdr) { t.Errorf("Expecting: %+v, received: %+v", eStoredCdr, storedCdr) diff --git a/sessionmanager/session.go b/sessionmanager/session.go index 4e528a546..f91f2923a 100644 --- a/sessionmanager/session.go +++ b/sessionmanager/session.go @@ -272,7 +272,6 @@ func (s *Session) AsActiveSessions() []*ActiveSession { sTime, _ := s.eventStart.GetSetupTime(utils.META_DEFAULT, s.sessionManager.Timezone()) aTime, _ := s.eventStart.GetAnswerTime(utils.META_DEFAULT, s.sessionManager.Timezone()) usage, _ := s.eventStart.GetDuration(utils.META_DEFAULT) - pdd, _ := s.eventStart.GetPdd(utils.META_DEFAULT) for _, sessionRun := range s.sessionRuns { aSession := &ActiveSession{ CGRID: s.eventStart.GetCgrId(s.sessionManager.Timezone()), @@ -281,7 +280,6 @@ func (s *Session) AsActiveSessions() []*ActiveSession { CdrHost: s.eventStart.GetOriginatorIP(utils.META_DEFAULT), CdrSource: "FS_" + s.eventStart.GetName(), ReqType: s.eventStart.GetReqType(utils.META_DEFAULT), - Direction: s.eventStart.GetDirection(utils.META_DEFAULT), Tenant: s.eventStart.GetTenant(utils.META_DEFAULT), Category: s.eventStart.GetCategory(utils.META_DEFAULT), Account: s.eventStart.GetAccount(utils.META_DEFAULT), @@ -290,9 +288,7 @@ func (s *Session) AsActiveSessions() []*ActiveSession { SetupTime: sTime, AnswerTime: aTime, Usage: usage, - Pdd: pdd, ExtraFields: s.eventStart.GetExtraFields(), - Supplier: s.eventStart.GetSupplier(utils.META_DEFAULT), SMId: "UNKNOWN", } if sessionRun.DerivedCharger != nil { @@ -326,18 +322,15 @@ type ActiveSession struct { OriginID string // represents the unique accounting id given by the telecom switch generating the CDR CdrHost string // represents the IP address of the host generating the CDR (automatically populated by the server) CdrSource string // formally identifies the source of the CDR (free form field) - ReqType string // matching the supported request types by the **CGRateS**, accepted values are hardcoded in the server . - Direction string // matching the supported direction identifiers of the CGRateS <*out> + ReqType string // matching the supported request types by the **CGRateS**, accepted values are hardcoded in the server Tenant string // tenant whom this record belongs Category string // free-form filter for this record, matching the category defined in rating profiles. Account string // account id (accounting subsystem) the record should be attached to Subject string // rating subject (rating subsystem) this record should be attached to Destination string // destination to be charged SetupTime time.Time // set-up time of the event. Supported formats: datetime RFC3339 compatible, SQL datetime (eg: MySQL), unix timestamp. - Pdd time.Duration // PDD value AnswerTime time.Time // answer time of the event. Supported formats: datetime RFC3339 compatible, SQL datetime (eg: MySQL), unix timestamp. Usage time.Duration // event usage information (eg: in case of tor=*voice this will represent the total duration of a call) - Supplier string // Supplier information when available ExtraFields map[string]string // Extra fields to be stored in CDR SMId string SMConnId string diff --git a/sessionmanager/smg_event.go b/sessionmanager/smg_event.go index 0f6091ebe..c2e7dffc5 100644 --- a/sessionmanager/smg_event.go +++ b/sessionmanager/smg_event.go @@ -424,7 +424,6 @@ func (self SMGenericEvent) AsStoredCdr(cfg *config.CGRConfig, timezone string) * storCdr.OriginHost = self.GetOriginatorIP(utils.META_DEFAULT) storCdr.Source = self.GetCdrSource() storCdr.RequestType = utils.FirstNonEmpty(self.GetReqType(utils.META_DEFAULT), storCdr.RequestType) - storCdr.Direction = utils.FirstNonEmpty(self.GetDirection(utils.META_DEFAULT), storCdr.Direction) storCdr.Tenant = utils.FirstNonEmpty(self.GetTenant(utils.META_DEFAULT), storCdr.Tenant) storCdr.Category = utils.FirstNonEmpty(self.GetCategory(utils.META_DEFAULT), storCdr.Category) storCdr.Account = self.GetAccount(utils.META_DEFAULT) @@ -433,9 +432,6 @@ func (self SMGenericEvent) AsStoredCdr(cfg *config.CGRConfig, timezone string) * storCdr.SetupTime, _ = self.GetSetupTime(utils.META_DEFAULT, timezone) storCdr.AnswerTime, _ = self.GetAnswerTime(utils.META_DEFAULT, timezone) storCdr.Usage, _ = self.GetUsage(utils.META_DEFAULT) - storCdr.PDD, _ = self.GetPdd(utils.META_DEFAULT) - storCdr.Supplier = self.GetSupplier(utils.META_DEFAULT) - storCdr.DisconnectCause = self.GetDisconnectCause(utils.META_DEFAULT) storCdr.ExtraFields = self.GetExtraFields() storCdr.Cost = -1 return storCdr diff --git a/sessionmanager/smg_event_test.go b/sessionmanager/smg_event_test.go index 103c2eac3..e95bdfbe1 100644 --- a/sessionmanager/smg_event_test.go +++ b/sessionmanager/smg_event_test.go @@ -172,10 +172,12 @@ func TestSMGenericEventAsStoredCdr(t *testing.T) { smGev["Extra1"] = "Value1" smGev["Extra2"] = 5 eStoredCdr := &engine.CDR{CGRID: "70c4d16dce41d1f2777b4e8442cff39cf87f5f19", - ToR: utils.SMS, OriginID: "12345", OriginHost: "10.0.3.15", Source: "SMG_TEST_EVENT", RequestType: utils.META_PREPAID, - Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "account1", Subject: "subject1", - Destination: "+4986517174963", SetupTime: time.Date(2015, 11, 9, 14, 21, 24, 0, time.UTC), AnswerTime: time.Date(2015, 11, 9, 14, 22, 2, 0, time.UTC), - Usage: time.Duration(83) * time.Second, PDD: time.Duration(300) * time.Millisecond, Supplier: "supplier1", DisconnectCause: "NORMAL_DISCONNECT", + ToR: utils.SMS, OriginID: "12345", OriginHost: "10.0.3.15", Source: "SMG_TEST_EVENT", + RequestType: utils.META_PREPAID, + Tenant: "cgrates.org", Category: "call", Account: "account1", Subject: "subject1", + Destination: "+4986517174963", SetupTime: time.Date(2015, 11, 9, 14, 21, 24, 0, time.UTC), + AnswerTime: time.Date(2015, 11, 9, 14, 22, 2, 0, time.UTC), + Usage: time.Duration(83) * time.Second, ExtraFields: map[string]string{"Extra1": "Value1", "Extra2": "5"}, Cost: -1} if storedCdr := smGev.AsStoredCdr(cfg, "UTC"); !reflect.DeepEqual(eStoredCdr, storedCdr) { t.Errorf("Expecting: %+v, received: %+v", eStoredCdr, storedCdr) diff --git a/sessionmanager/smg_session.go b/sessionmanager/smg_session.go index fe5e0f49c..fae1689d0 100644 --- a/sessionmanager/smg_session.go +++ b/sessionmanager/smg_session.go @@ -261,7 +261,6 @@ func (self *SMGSession) AsActiveSession(timezone string) *ActiveSession { defer self.mux.RUnlock() sTime, _ := self.EventStart.GetSetupTime(utils.META_DEFAULT, timezone) aTime, _ := self.EventStart.GetAnswerTime(utils.META_DEFAULT, timezone) - pdd, _ := self.EventStart.GetPdd(utils.META_DEFAULT) aSession := &ActiveSession{ CGRID: self.CGRID, TOR: self.EventStart.GetTOR(utils.META_DEFAULT), @@ -270,7 +269,6 @@ func (self *SMGSession) AsActiveSession(timezone string) *ActiveSession { CdrHost: self.EventStart.GetOriginatorIP(utils.META_DEFAULT), CdrSource: self.EventStart.GetCdrSource(), ReqType: self.EventStart.GetReqType(utils.META_DEFAULT), - Direction: self.EventStart.GetDirection(utils.META_DEFAULT), Tenant: self.EventStart.GetTenant(utils.META_DEFAULT), Category: self.EventStart.GetCategory(utils.META_DEFAULT), Account: self.EventStart.GetAccount(utils.META_DEFAULT), @@ -279,9 +277,7 @@ func (self *SMGSession) AsActiveSession(timezone string) *ActiveSession { SetupTime: sTime, AnswerTime: aTime, Usage: self.TotalUsage, - Pdd: pdd, ExtraFields: self.EventStart.GetExtraFields(), - Supplier: self.EventStart.GetSupplier(utils.META_DEFAULT), SMId: "CGR-DA", } if self.CD != nil { diff --git a/utils/consts.go b/utils/consts.go index aa0c6871c..8dec0b96e 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -112,8 +112,8 @@ const ( TBLTPStats = "tp_stats" TBLTPThresholds = "tp_thresholds" TBLTPFilters = "tp_filters" - TBLSMCosts = "sm_costs" - TBLCDRs = "cdrs" + SMCostsTBL = "sm_costs" + CDRsTBL = "cdrs" TBLVersions = "versions" TIMINGS_CSV = "Timings.csv" DESTINATIONS_CSV = "Destinations.csv" @@ -481,6 +481,7 @@ const ( StatUpdate = "StatUpdate" ResourceUpdate = "ResourceUpdate" CDR = "CDR" + CDRs = "CDRs" ExpiryTime = "ExpiryTime" AllowNegative = "AllowNegative" Disabled = "Disabled" diff --git a/utils/coreutils.go b/utils/coreutils.go index 070e157d3..b957943e3 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -278,6 +278,17 @@ func ParseDurationWithSecs(durStr string) (d time.Duration, err error) { return time.ParseDuration(durStr) } +// Parses duration, considers s as time unit if not provided, seconds as float to specify subunits +func ParseDurationWithNanosecs(durStr string) (d time.Duration, err error) { + if durStr == "" { + return + } + if _, err = strconv.ParseFloat(durStr, 64); err == nil { // Seconds format considered + durStr += "ns" + } + return time.ParseDuration(durStr) +} + func AccountKey(tenant, account string) string { return fmt.Sprintf("%s:%s", tenant, account) }