From dd6977e43d5e846a93c94fbb77f35d005a010156 Mon Sep 17 00:00:00 2001 From: DanB Date: Sun, 15 Mar 2015 19:16:50 +0100 Subject: [PATCH] Change ReqType to use META(*) as prefix in front of the type for consistency with the rest of the system (eg: prepaid -> *prepaid --- apier/v1/apier_local_test.go | 6 ++-- apier/v1/cdrstatsv1_local_test.go | 8 ++--- apier/v2/cdrs_mysql_local_test.go | 8 ++--- apier/v2/cdrs_psql_local_test.go | 8 ++--- cdrc/cdrc_test.go | 8 ++--- cdre/cdrexporter_test.go | 14 ++++---- cdre/csv_test.go | 8 ++--- cdre/fixedwidth_test.go | 8 ++--- config/cfg_data.json | 2 +- config/config_defaults.go | 2 +- config/config_json_test.go | 4 +-- config/multifiles_local_test.go | 2 +- data/conf/cgrates/cgrates.json | 2 +- data/conf/samples/multifiles/a.json | 2 +- data/conf/samples/multifiles/b/b.json | 4 +-- .../freeswitch/conf/dialplan/cgr_dialplan.xml | 6 ++-- .../conf/directory/default/1000.xml | 2 +- .../etc/kamailio/kamailio-cgrates.cfg | 2 +- data/opensips/etc/opensips/opensips.cfg | 4 +-- data/tariffplans/tutorial/DerivedChargers.csv | 2 +- .../cgrates/etc/cgrates/cgrates.json | 2 +- .../freeswitch/etc/freeswitch_conf.tar.gz | Bin 27450 -> 27494 bytes .../opensips/etc/opensips/opensips.cfg | 8 ++--- engine/fscdr_test.go | 2 +- engine/loader_csv_test.go | 4 +-- engine/mediator.go | 10 +++--- engine/mediator_local_test.go | 14 ++++---- engine/responder.go | 4 +-- engine/responder_test.go | 12 +++---- engine/storage_mysql_local_test.go | 34 +++++++++--------- engine/storage_psql_local_test.go | 34 +++++++++--------- general_tests/fsevcorelate_test.go | 4 +-- general_tests/tutorial_fs_calls_test.go | 4 +-- sessionmanager/fsevent_test.go | 10 +++--- sessionmanager/kamevent_test.go | 10 +++--- sessionmanager/osipsevent_test.go | 10 +++--- utils/apitpdata_test.go | 8 ++--- utils/cgrcdr_test.go | 2 +- utils/consts.go | 4 +++ utils/storedcdr_test.go | 32 ++++++++--------- utils/utils_local_test.go | 2 +- utils/utils_test.go | 4 +-- 42 files changed, 160 insertions(+), 156 deletions(-) diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go index c2caf1116..02a7294b8 100644 --- a/apier/v1/apier_local_test.go +++ b/apier/v1/apier_local_test.go @@ -1383,11 +1383,11 @@ func TestCdrServer(t *testing.T) { return } httpClient := new(http.Client) - cdrForm1 := url.Values{"accid": []string{"dsafdsaf"}, "cdrhost": []string{"192.168.1.1"}, "reqtype": []string{"rated"}, "direction": []string{"*out"}, + cdrForm1 := url.Values{"accid": []string{"dsafdsaf"}, "cdrhost": []string{"192.168.1.1"}, "reqtype": []string{utils.META_RATED}, "direction": []string{"*out"}, "tenant": []string{"cgrates.org"}, "tor": []string{"call"}, "account": []string{"1001"}, "subject": []string{"1001"}, "destination": []string{"1002"}, "setup_time": []string{"2013-11-07T08:42:22Z"}, "answer_time": []string{"2013-11-07T08:42:26Z"}, "duration": []string{"10"}, "field_extr1": []string{"val_extr1"}, "fieldextr2": []string{"valextr2"}} - cdrForm2 := url.Values{"accid": []string{"adsafdsaf"}, "cdrhost": []string{"192.168.1.1"}, "reqtype": []string{"rated"}, "direction": []string{"*out"}, + cdrForm2 := url.Values{"accid": []string{"adsafdsaf"}, "cdrhost": []string{"192.168.1.1"}, "reqtype": []string{utils.META_RATED}, "direction": []string{"*out"}, "tenant": []string{"cgrates.org"}, "tor": []string{"call"}, "account": []string{"1001"}, "subject": []string{"1001"}, "destination": []string{"1002"}, "setup_time": []string{"2013-11-07T08:42:23Z"}, "answer_time": []string{"2013-11-07T08:42:26Z"}, "duration": []string{"10"}, "field_extr1": []string{"val_extr1"}, "fieldextr2": []string{"valextr2"}} @@ -1456,7 +1456,7 @@ func TestLocalProcessCdr(t *testing.T) { } var reply string cdr := utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: 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), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", } diff --git a/apier/v1/cdrstatsv1_local_test.go b/apier/v1/cdrstatsv1_local_test.go index 0f2163c69..cb6a1af86 100644 --- a/apier/v1/cdrstatsv1_local_test.go +++ b/apier/v1/cdrstatsv1_local_test.go @@ -134,26 +134,26 @@ func TestCDRStatsLclPostCdrs(t *testing.T) { httpClient := new(http.Client) storedCdrs := []*utils.StoredCdr{ &utils.StoredCdr{CgrId: utils.Sha1("dsafdsafa", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "+4986517174963", SetupTime: time.Now(), AnswerTime: time.Now(), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dan", }, &utils.StoredCdr{CgrId: utils.Sha1("dsafdsafb", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "+4986517174963", SetupTime: time.Now(), AnswerTime: time.Now(), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(5) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dan", }, &utils.StoredCdr{CgrId: utils.Sha1("dsafdsafc", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "+4986517174963", SetupTime: time.Now(), AnswerTime: time.Now(), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(30) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dan", }, &utils.StoredCdr{CgrId: utils.Sha1("dsafdsafd", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "+4986517174963", SetupTime: time.Now(), AnswerTime: time.Time{}, MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(0) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dan", diff --git a/apier/v2/cdrs_mysql_local_test.go b/apier/v2/cdrs_mysql_local_test.go index 2c4c357c6..49ce35b38 100644 --- a/apier/v2/cdrs_mysql_local_test.go +++ b/apier/v2/cdrs_mysql_local_test.go @@ -84,7 +84,7 @@ func TestV2CdrsMysqlInjectUnratedCdr(t *testing.T) { mysqlDb = d.(*engine.MySQLStorage) } strCdr1 := &utils.StoredCdr{CgrId: utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: "rated", + TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_RATED, Direction: "*out", 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"}, @@ -124,19 +124,19 @@ func TestV2CdrsMysqlProcessCdr(t *testing.T) { var reply string cdrs := []*utils.StoredCdr{ &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: 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), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", Rated: true, }, &utils.StoredCdr{CgrId: utils.Sha1("abcdeftg", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", Destination: "1002", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", 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), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", }, &utils.StoredCdr{CgrId: utils.Sha1("aererfddf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1002", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", 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), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", diff --git a/apier/v2/cdrs_psql_local_test.go b/apier/v2/cdrs_psql_local_test.go index 346924992..ae22bc029 100644 --- a/apier/v2/cdrs_psql_local_test.go +++ b/apier/v2/cdrs_psql_local_test.go @@ -78,7 +78,7 @@ func TestV2CdrsPsqlInjectUnratedCdr(t *testing.T) { psqlDb = d.(*engine.PostgresStorage) } strCdr1 := &utils.StoredCdr{CgrId: utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: "rated", + TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_RATED, Direction: "*out", 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"}, @@ -118,19 +118,19 @@ func TestV2CdrsPsqlProcessCdr(t *testing.T) { var reply string cdrs := []*utils.StoredCdr{ &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: 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), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", Rated: true, }, &utils.StoredCdr{CgrId: utils.Sha1("abcdeftg", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", Destination: "1002", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", 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), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", }, &utils.StoredCdr{CgrId: utils.Sha1("aererfddf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1002", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", 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), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", diff --git a/cdrc/cdrc_test.go b/cdrc/cdrc_test.go index 859847f53..11bc83485 100644 --- a/cdrc/cdrc_test.go +++ b/cdrc/cdrc_test.go @@ -37,7 +37,7 @@ func TestRecordForkCdr(t *testing.T) { if err == nil { t.Error("Failed to corectly detect missing fields from record") } - cdrRow = []string{"ignored", "ignored", utils.VOICE, "acc1", "prepaid", "*out", "cgrates.org", "call", "1001", "1001", "+4986517174963", + cdrRow = []string{"ignored", "ignored", utils.VOICE, "acc1", utils.META_PREPAID, "*out", "cgrates.org", "call", "1001", "1001", "+4986517174963", "2013-02-03 19:50:00", "2013-02-03 19:54:00", "62", "supplier1", "172.16.1.1"} rtCdr, err := cdrc.recordToStoredCdr(cdrRow, cdrc.cdrFields[0]) if err != nil { @@ -132,7 +132,7 @@ func TestDnTdmCdrs(t *testing.T) { AccId: "49773280254", CdrHost: "0.0.0.0", CdrSource: cgrConfig.CdrcSourceId, - ReqType: "rated", + ReqType: utils.META_RATED, Direction: "*out", Tenant: "sip.test.deanconnect.nl", Category: "call", @@ -150,7 +150,7 @@ func TestDnTdmCdrs(t *testing.T) { AccId: "49893252121", CdrHost: "0.0.0.0", CdrSource: cgrConfig.CdrcSourceId, - ReqType: "rated", + ReqType: utils.META_RATED, Direction: "*out", Tenant: "sip.test.deanconnect.nl", Category: "call", @@ -168,7 +168,7 @@ func TestDnTdmCdrs(t *testing.T) { AccId: "49497361022", CdrHost: "0.0.0.0", CdrSource: cgrConfig.CdrcSourceId, - ReqType: "rated", + ReqType: utils.META_RATED, Direction: "*out", Tenant: "sip.test.deanconnect.nl", Category: "call", diff --git a/cdre/cdrexporter_test.go b/cdre/cdrexporter_test.go index 8c2ee91e2..f49dd0100 100644 --- a/cdre/cdrexporter_test.go +++ b/cdre/cdrexporter_test.go @@ -32,23 +32,23 @@ func TestCdreGetCombimedCdrFieldVal(t *testing.T) { cfg, _ := config.NewDefaultCGRConfig() cdrs := []*utils.StoredCdr{ &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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, MediationRunId: "RUN_RTL", Cost: 1.01}, &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf2", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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, MediationRunId: "CUSTOMER1", Cost: 2.01}, &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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, MediationRunId: "CUSTOMER1", Cost: 3.01}, &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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, MediationRunId: utils.DEFAULT_RUNID, Cost: 4.01}, &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1000", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(), Usage: time.Duration(10) * time.Second, MediationRunId: "RETAIL1", Cost: 5.01}, } @@ -78,7 +78,7 @@ func TestCdreGetCombimedCdrFieldVal(t *testing.T) { func TestGetDateTimeFieldVal(t *testing.T) { cdreTst := new(CdrExporter) cdrTst := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.01, ExtraFields: map[string]string{"stop_time": "2014-06-11 19:19:00 +0000 UTC", "fieldextr2": "valextr2"}} @@ -107,7 +107,7 @@ func TestGetDateTimeFieldVal(t *testing.T) { func TestCdreCdrFieldValue(t *testing.T) { cdre := new(CdrExporter) cdr := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.01} val, _ := utils.ParseRSRFields("destination", utils.INFIELD_SEP) diff --git a/cdre/csv_test.go b/cdre/csv_test.go index 0896f8a82..fe0407c8b 100644 --- a/cdre/csv_test.go +++ b/cdre/csv_test.go @@ -35,7 +35,7 @@ func TestCsvCdrWriter(t *testing.T) { cfg, _ := config.NewDefaultCGRConfig() logDb, _ := engine.NewMapStorage() storedCdr1 := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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, MediationRunId: utils.DEFAULT_RUNID, ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01, @@ -49,7 +49,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.0100` + 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.0100` result := strings.TrimSpace(writer.String()) if result != expected { t.Errorf("Expected: \n%s received: \n%s.", expected, result) @@ -64,7 +64,7 @@ func TestAlternativeFieldSeparator(t *testing.T) { cfg, _ := config.NewDefaultCGRConfig() logDb, _ := engine.NewMapStorage() storedCdr1 := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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, MediationRunId: utils.DEFAULT_RUNID, ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01, @@ -77,7 +77,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.0100` + 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.0100` result := strings.TrimSpace(writer.String()) if result != expected { t.Errorf("Expected: \n%s received: \n%s.", expected, result) diff --git a/cdre/fixedwidth_test.go b/cdre/fixedwidth_test.go index 28247a207..835163334 100644 --- a/cdre/fixedwidth_test.go +++ b/cdre/fixedwidth_test.go @@ -121,7 +121,7 @@ func TestWriteCdr(t *testing.T) { } cdr := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), TOR: utils.VOICE, OrderId: 1, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + ReqType: 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), @@ -178,7 +178,7 @@ func TestWriteCdrs(t *testing.T) { TrailerFields: trailerCfgFlds, } cdr1 := &utils.StoredCdr{CgrId: utils.Sha1("aaa1", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), - TOR: utils.VOICE, OrderId: 2, AccId: "aaa1", CdrHost: "192.168.1.1", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + TOR: utils.VOICE, OrderId: 2, AccId: "aaa1", CdrHost: "192.168.1.1", ReqType: utils.META_RATED, Direction: "*out", 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,7 +186,7 @@ func TestWriteCdrs(t *testing.T) { ExtraFields: map[string]string{"productnumber": "12341", "fieldextr2": "valextr2"}, } cdr2 := &utils.StoredCdr{CgrId: utils.Sha1("aaa2", time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC).String()), - TOR: utils.VOICE, OrderId: 4, AccId: "aaa2", CdrHost: "192.168.1.2", ReqType: "prepaid", Direction: "*out", Tenant: "cgrates.org", + TOR: utils.VOICE, OrderId: 4, AccId: "aaa2", CdrHost: "192.168.1.2", ReqType: utils.META_PREPAID, Direction: "*out", 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), @@ -195,7 +195,7 @@ func TestWriteCdrs(t *testing.T) { } cdr3 := &utils.StoredCdr{} cdr4 := &utils.StoredCdr{CgrId: utils.Sha1("aaa3", time.Date(2013, 11, 7, 9, 42, 18, 0, time.UTC).String()), - TOR: utils.VOICE, OrderId: 3, AccId: "aaa4", CdrHost: "192.168.1.4", ReqType: "postpaid", Direction: "*out", Tenant: "cgrates.org", + TOR: utils.VOICE, OrderId: 3, AccId: "aaa4", CdrHost: "192.168.1.4", ReqType: utils.META_POSTPAID, Direction: "*out", 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), diff --git a/config/cfg_data.json b/config/cfg_data.json index 2a9fd8c03..54309fef3 100644 --- a/config/cfg_data.json +++ b/config/cfg_data.json @@ -7,7 +7,7 @@ // This is what you get when you load CGRateS with an empty configuration file. "general": { - "default_reqtype": "pseudoprepaid", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated> + "default_reqtype": "*pseudoprepaid", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated> }, "cdrc": { diff --git a/config/config_defaults.go b/config/config_defaults.go index a55811486..f91717dce 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -32,7 +32,7 @@ const CGRATES_CFG_JSON = ` "rounding_decimals": 10, // system level precision for floats "dbdata_encoding": "msgpack", // encoding used to store object data in strings: "tpexport_dir": "/var/log/cgrates/tpe", // path towards export folder for offline Tariff Plans - "default_reqtype": "rated", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated> + "default_reqtype": "*rated", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated> "default_category": "call", // default Type of Record to consider when missing from requests "default_tenant": "cgrates.org", // default Tenant to consider when missing from requests "default_subject": "cgrates", // default rating Subject to consider when missing from requests diff --git a/config/config_json_test.go b/config/config_json_test.go index 7e7cf265f..3cd0bf424 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -41,7 +41,7 @@ func TestDfGeneralJsonCfg(t *testing.T) { Rounding_decimals: utils.IntPointer(10), Dbdata_encoding: utils.StringPointer("msgpack"), Tpexport_dir: utils.StringPointer("/var/log/cgrates/tpe"), - Default_reqtype: utils.StringPointer("rated"), + Default_reqtype: utils.StringPointer(utils.META_RATED), Default_category: utils.StringPointer("call"), Default_tenant: utils.StringPointer("cgrates.org"), Default_subject: utils.StringPointer("cgrates")} @@ -449,7 +449,7 @@ func TestNewCgrJsonCfgFromFile(t *testing.T) { if err != nil { t.Error(err) } - eCfg := &GeneralJsonCfg{Default_reqtype: utils.StringPointer("pseudoprepaid")} + eCfg := &GeneralJsonCfg{Default_reqtype: utils.StringPointer(utils.META_PSEUDOPREPAID)} if gCfg, err := cgrJsonCfg.GeneralJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfg, gCfg) { diff --git a/config/multifiles_local_test.go b/config/multifiles_local_test.go index fb2c5bbad..ad13fbb2e 100644 --- a/config/multifiles_local_test.go +++ b/config/multifiles_local_test.go @@ -42,7 +42,7 @@ func TestMfGeneralItems(t *testing.T) { if !*testLocal { return } - if mfCgrCfg.DefaultReqType != utils.PSEUDOPREPAID { // Twice reconfigured + if mfCgrCfg.DefaultReqType != utils.META_PSEUDOPREPAID { // Twice reconfigured t.Error("DefaultReqType: ", mfCgrCfg.DefaultReqType) } if mfCgrCfg.DefaultCategory != "call" { // Not configred, should be inherited from default diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index 9318a809f..e7df8f1a9 100644 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -11,7 +11,7 @@ // "rounding_decimals": 10, // system level precision for floats // "dbdata_encoding": "msgpack", // encoding used to store object data in strings: // "tpexport_dir": "/var/log/cgrates/tpe", // path towards export folder for offline Tariff Plans -// "default_reqtype": "rated", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated> +// "default_reqtype": "*rated", // default request type to consider when missing from requests: <""|*prepaid|*postpaid|*pseudoprepaid|*rated> // "default_category": "call", // default Type of Record to consider when missing from requests // "default_tenant": "cgrates.org", // default Tenant to consider when missing from requests // "default_subject": "cgrates", // default rating Subject to consider when missing from requests diff --git a/data/conf/samples/multifiles/a.json b/data/conf/samples/multifiles/a.json index 1834c4631..a822d5966 100644 --- a/data/conf/samples/multifiles/a.json +++ b/data/conf/samples/multifiles/a.json @@ -4,7 +4,7 @@ // Should be the first file loaded "general": { - "default_reqtype": "postpaid", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated> + "default_reqtype": "*postpaid", // default request type to consider when missing from requests: <""|*prepaid|*postpaid|*pseudoprepaid|*rated> }, "cdre": { diff --git a/data/conf/samples/multifiles/b/b.json b/data/conf/samples/multifiles/b/b.json index be845b036..2187cae01 100644 --- a/data/conf/samples/multifiles/b/b.json +++ b/data/conf/samples/multifiles/b/b.json @@ -4,12 +4,12 @@ // Should be the second file loaded "general": { - "default_reqtype": "pseudoprepaid", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated> + "default_reqtype": "*pseudoprepaid", // default request type to consider when missing from requests: <""|*prepaid|*postpaid|*pseudoprepaid|*rated> }, "cdre": { "*default": { - "data_usage_multiply_factor": 1024, // multiply data usage before export (eg: convert from KBytes to Bytes) + "data_usage_multiply_factor": 1024, // multiply data usage before export (eg: convert from KBytes to Bytes) "export_dir": "/tmp/cgrates/cdre", // path where the exported CDRs will be placed }, "export1": { diff --git a/data/freeswitch/conf/dialplan/cgr_dialplan.xml b/data/freeswitch/conf/dialplan/cgr_dialplan.xml index beb03040c..4495f2452 100644 --- a/data/freeswitch/conf/dialplan/cgr_dialplan.xml +++ b/data/freeswitch/conf/dialplan/cgr_dialplan.xml @@ -11,7 +11,7 @@ Ignore include and context defined here for the sake of avoiding errors if direc - + @@ -19,7 +19,7 @@ Ignore include and context defined here for the sake of avoiding errors if direc - + @@ -29,7 +29,7 @@ Ignore include and context defined here for the sake of avoiding errors if direc - + diff --git a/data/freeswitch/conf/directory/default/1000.xml b/data/freeswitch/conf/directory/default/1000.xml index d654f0ef3..5a37a0133 100644 --- a/data/freeswitch/conf/directory/default/1000.xml +++ b/data/freeswitch/conf/directory/default/1000.xml @@ -21,7 +21,7 @@ Make default 1000 user prepaid by adding cgr_reqtype variable to your user. - + diff --git a/data/kamailio/etc/kamailio/kamailio-cgrates.cfg b/data/kamailio/etc/kamailio/kamailio-cgrates.cfg index 4143d33fa..a45514309 100644 --- a/data/kamailio/etc/kamailio/kamailio-cgrates.cfg +++ b/data/kamailio/etc/kamailio/kamailio-cgrates.cfg @@ -32,7 +32,7 @@ route[CGR_AUTH_REQUEST] { sl_send_reply("503","Charging controller unreachable"); exit; } - $dlg_var(cgrReqType) = "postpaid"; + $dlg_var(cgrReqType) = "*postpaid"; $dlg_var(cgrAccount) = $fU; $dlg_var(cgrDestination) = $rU; evapi_async_relay("{\"event\":\"CGR_AUTH_REQUEST\", diff --git a/data/opensips/etc/opensips/opensips.cfg b/data/opensips/etc/opensips/opensips.cfg index 9ad6efbe6..4fb591f86 100644 --- a/data/opensips/etc/opensips/opensips.cfg +++ b/data/opensips/etc/opensips/opensips.cfg @@ -222,11 +222,11 @@ route{ exit; } setflag(CDR); - $avp(cgr_reqtype)="pseudoprepaid"; + $avp(cgr_reqtype)="*pseudoprepaid"; $avp(cgr_account)=$fU; $avp(cgr_subject)=$fU; $avp(cgr_destination)=$rU; - if $avp(cgr_reqtype)=="pseudoprepaid" || $avp(cgr_reqtype)=="prepaid" { #Make sure we got enough balance for the call + if $avp(cgr_reqtype)=="*pseudoprepaid" || $avp(cgr_reqtype)=="*prepaid" { #Make sure we got enough balance for the call $avp(auth_keys) = "cgr_reqtype"; $avp(auth_vals) = $avp(cgr_reqtype); $avp(auth_keys) = "callid"; diff --git a/data/tariffplans/tutorial/DerivedChargers.csv b/data/tariffplans/tutorial/DerivedChargers.csv index 13960bf4f..ddda092f7 100644 --- a/data/tariffplans/tutorial/DerivedChargers.csv +++ b/data/tariffplans/tutorial/DerivedChargers.csv @@ -1,2 +1,2 @@ #Direction,Tenant,Category,Account,Subject,RunId,RunFilter,ReqTypeField,DirectionField,TenantField,CategoryField,AccountField,SubjectField,DestinationField,SetupTimeField,AnswerTimeField,UsageField -*out,cgrates.org,call,1001,1001,derived_run1,,^rated,*default,*default,*default,*default,^1002,*default,*default,*default,*default +*out,cgrates.org,call,1001,1001,derived_run1,,^*rated,*default,*default,*default,*default,^1002,*default,*default,*default,*default diff --git a/data/tutorials/fs_evsock/cgrates/etc/cgrates/cgrates.json b/data/tutorials/fs_evsock/cgrates/etc/cgrates/cgrates.json index 4d7fa8e41..a23401dd2 100644 --- a/data/tutorials/fs_evsock/cgrates/etc/cgrates/cgrates.json +++ b/data/tutorials/fs_evsock/cgrates/etc/cgrates/cgrates.json @@ -12,7 +12,7 @@ // "rounding_decimals": 10, // system level precision for floats // "dbdata_encoding": "msgpack", // encoding used to store object data in strings: // "tpexport_dir": "/var/log/cgrates/tpe", // path towards export folder for offline Tariff Plans -// "default_reqtype": "rated", // default request type to consider when missing from requests: <""|prepaid|postpaid|pseudoprepaid|rated> +// "default_reqtype": "*rated", // default request type to consider when missing from requests: <""|*prepaid|*postpaid|*pseudoprepaid|*rated> // "default_category": "call", // default Type of Record to consider when missing from requests // "default_tenant": "cgrates.org", // default Tenant to consider when missing from requests // "default_subject": "cgrates", // default rating Subject to consider when missing from requests diff --git a/data/tutorials/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz b/data/tutorials/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz index 1c45c6e410c762105b1000ce3743c04759e962a7..b36ba0ccf3a6dcc962a9810abeec5a0cc82fc64e 100644 GIT binary patch delta 27431 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 delta 27362 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 ZKhMwe^ZYzN&(AM<{tuzfC1C(C0sxjN#mWEx diff --git a/data/tutorials/osips_event/opensips/etc/opensips/opensips.cfg b/data/tutorials/osips_event/opensips/etc/opensips/opensips.cfg index d39598a68..d9a888f64 100644 --- a/data/tutorials/osips_event/opensips/etc/opensips/opensips.cfg +++ b/data/tutorials/osips_event/opensips/etc/opensips/opensips.cfg @@ -271,21 +271,21 @@ route[relay] { route[CGR_HANDLER] { # These variables should be populated by script admin on need - $avp(cgr_reqtype)="rated"; + $avp(cgr_reqtype)="*rated"; $avp(cgr_account)=$fU; $avp(cgr_subject)=$fU; $avp(cgr_destination)=$rU; switch ($avp(cgr_account)) { case "1002": - $avp(cgr_reqtype)="postpaid"; + $avp(cgr_reqtype)="*postpaid"; break; case "1003": - $avp(cgr_reqtype)="pseudoprepaid"; + $avp(cgr_reqtype)="*pseudoprepaid"; break; } # End of variables population - if $avp(cgr_reqtype)=="pseudoprepaid" || $avp(cgr_reqtype)=="prepaid" { #Make sure we got enough balance for the call + if $avp(cgr_reqtype)=="*pseudoprepaid" || $avp(cgr_reqtype)=="*prepaid" { #Make sure we got enough balance for the call $avp(auth_keys) = "cgr_reqtype"; $avp(auth_vals) = $avp(cgr_reqtype); diff --git a/engine/fscdr_test.go b/engine/fscdr_test.go index 3ae1aeb29..58d28356f 100644 --- a/engine/fscdr_test.go +++ b/engine/fscdr_test.go @@ -58,7 +58,7 @@ func TestCDRFields(t *testing.T) { setupTime, _ := utils.ParseTimeDetectLayout(fsCdr.vars[FS_SETUP_TIME]) answerTime, _ := utils.ParseTimeDetectLayout(fsCdr.vars[FS_ANSWER_TIME]) expctStoredCdr := &utils.StoredCdr{CgrId: utils.Sha1("01df56f4-d99a-4ef6-b7fe-b924b2415b7f", setupTime.UTC().String()), TOR: utils.VOICE, AccId: "01df56f4-d99a-4ef6-b7fe-b924b2415b7f", - CdrHost: "127.0.0.1", CdrSource: "freeswitch_json", Direction: "*out", Category: "call", ReqType: utils.RATED, Tenant: "ipbx.itsyscom.com", Account: "dan", Subject: "dan", + CdrHost: "127.0.0.1", CdrSource: "freeswitch_json", Direction: "*out", Category: "call", ReqType: utils.META_RATED, Tenant: "ipbx.itsyscom.com", Account: "dan", Subject: "dan", Destination: "+4986517174963", SetupTime: setupTime, AnswerTime: answerTime, Usage: time.Duration(4) * time.Second, ExtraFields: map[string]string{"sip_user_agent": "Jitsi2.2.4603.9615Linux"}, Cost: -1} if storedCdr := fsCdr.AsStoredCdr(); !reflect.DeepEqual(expctStoredCdr, storedCdr) { diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 07a55620b..801120340 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -190,7 +190,7 @@ vdf,emptyY,*out,TOPUP_EMPTY_AT, ` cdrStats = ` #Id,QueueLength,TimeWindow,Metrics,SetupInterval,TOR,CdrHost,CdrSource,ReqType,Direction,Tenant,Category,Account,Subject,DestinationPrefix,UsageInterval,MediationRunIds,RatedAccount,RatedSubject,CostInterval,Triggers -CDRST1,5,60m,ASR,2014-07-29T15:00:00Z;2014-07-29T16:00:00Z,*voice,87.139.12.167,FS_JSON,rated,*out,cgrates.org,call,dan,dan,49,5m;10m,default,rif,rif,0;2,STANDARD_TRIGGERS +CDRST1,5,60m,ASR,2014-07-29T15:00:00Z;2014-07-29T16:00:00Z,*voice,87.139.12.167,FS_JSON,*rated,*out,cgrates.org,call,dan,dan,49,5m;10m,default,rif,rif,0;2,STANDARD_TRIGGERS CDRST1,,,ACD,,,,,,,,,,,,,,,,,STANDARD_TRIGGER CDRST1,,,ACC,,,,,,,,,,,,,,,,, CDRST2,10,10m,ASR,,,,,,,cgrates.org,call,,,,,,,,, @@ -974,7 +974,7 @@ func TestLoadCdrStats(t *testing.T) { TOR: []string{utils.VOICE}, CdrHost: []string{"87.139.12.167"}, CdrSource: []string{"FS_JSON"}, - ReqType: []string{"rated"}, + ReqType: []string{utils.META_RATED}, Direction: []string{utils.OUT}, Tenant: []string{"cgrates.org"}, Category: []string{"call"}, diff --git a/engine/mediator.go b/engine/mediator.go index 45622280c..96f4d008e 100644 --- a/engine/mediator.go +++ b/engine/mediator.go @@ -89,7 +89,7 @@ func (self *Mediator) getCostFromRater(storedCdr *utils.StoredCdr) (*CallCost, e TimeEnd: storedCdr.AnswerTime.Add(storedCdr.Usage), DurationIndex: storedCdr.Usage, } - if utils.IsSliceMember([]string{utils.PSEUDOPREPAID, utils.POSTPAID}, storedCdr.ReqType) { + if utils.IsSliceMember([]string{utils.META_PSEUDOPREPAID, utils.META_POSTPAID, utils.PSEUDOPREPAID, utils.POSTPAID}, storedCdr.ReqType) { err = self.connector.Debit(cd, cc) } else { err = self.connector.GetCost(cd, cc) @@ -106,7 +106,7 @@ func (self *Mediator) getCostFromRater(storedCdr *utils.StoredCdr) (*CallCost, e func (self *Mediator) rateCDR(storedCdr *utils.StoredCdr) error { var qryCC *CallCost var errCost error - if storedCdr.ReqType == utils.PREPAID { + if utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, storedCdr.ReqType) { // ToDo: Get rid of PREPAID as soon as we don't want to support it backwards // Should be previously calculated and stored in DB qryCC, errCost = self.getCostsFromDB(storedCdr.CgrId, storedCdr.MediationRunId) } else { @@ -122,8 +122,8 @@ func (self *Mediator) rateCDR(storedCdr *utils.StoredCdr) error { } func (self *Mediator) RateCdr(storedCdr *utils.StoredCdr, sendToStats bool) error { - storedCdr.MediationRunId = utils.DEFAULT_RUNID - cdrRuns := []*utils.StoredCdr{storedCdr} // Start with initial storCdr, will add here all to be mediated + storedCdr.MediationRunId = utils.META_DEFAULT + cdrRuns := []*utils.StoredCdr{storedCdr} // Start with initial storCdr, will add here all to be mediated attrsDC := utils.AttrDerivedChargers{Tenant: storedCdr.Tenant, Category: storedCdr.Category, Direction: storedCdr.Direction, Account: storedCdr.Account, Subject: storedCdr.Subject} var dcs utils.DerivedChargers @@ -165,7 +165,7 @@ func (self *Mediator) RateCdr(storedCdr *utils.StoredCdr, sendToStats bool) erro } for _, cdr := range cdrRuns { extraInfo := "" - if cdr.MediationRunId != utils.DEFAULT_RUNID || !cdr.Rated { // Do not rate calls which are out of default run and marked as rated already, eg premium SMSes + if cdr.MediationRunId != utils.META_DEFAULT || !cdr.Rated { // Do not rate calls which are out of default run and marked as rated already, eg premium SMSes if err := self.rateCDR(cdr); err != nil { cdr.Cost = -1.0 // If there was an error, mark the CDR as it is extraInfo = err.Error() diff --git a/engine/mediator_local_test.go b/engine/mediator_local_test.go index 22001a717..509840e7f 100644 --- a/engine/mediator_local_test.go +++ b/engine/mediator_local_test.go @@ -139,14 +139,14 @@ func TestMediPostCdrs(t *testing.T) { if !*testLocal { return } - cdrForm1 := url.Values{utils.TOR: []string{utils.VOICE}, utils.ACCID: []string{"dsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{"rated"}, utils.DIRECTION: []string{"*out"}, + cdrForm1 := url.Values{utils.TOR: []string{utils.VOICE}, utils.ACCID: []string{"dsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{utils.META_RATED}, utils.DIRECTION: []string{"*out"}, utils.TENANT: []string{"cgrates.org"}, utils.CATEGORY: []string{"call"}, utils.ACCOUNT: []string{"2001"}, utils.SUBJECT: []string{"2001"}, utils.DESTINATION: []string{"+4986517174963"}, utils.ANSWER_TIME: []string{"2013-11-07T08:42:26Z"}, utils.USAGE: []string{"10"}, "field_extr1": []string{"val_extr1"}, "fieldextr2": []string{"valextr2"}} - cdrForm2 := url.Values{utils.TOR: []string{utils.VOICE}, utils.ACCID: []string{"adsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{"rated"}, utils.DIRECTION: []string{"*out"}, + cdrForm2 := url.Values{utils.TOR: []string{utils.VOICE}, utils.ACCID: []string{"adsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{utils.META_RATED}, utils.DIRECTION: []string{"*out"}, utils.TENANT: []string{"itsyscom.com"}, utils.CATEGORY: []string{"call"}, utils.ACCOUNT: []string{"1003"}, utils.SUBJECT: []string{"1003"}, utils.DESTINATION: []string{"+4986517174964"}, utils.ANSWER_TIME: []string{"2013-11-07T08:42:26Z"}, utils.USAGE: []string{"10"}, "field_extr1": []string{"val_extr1"}, "fieldextr2": []string{"valextr2"}} - cdrFormData1 := url.Values{utils.TOR: []string{utils.DATA}, utils.ACCID: []string{"616350843"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{"rated"}, + cdrFormData1 := url.Values{utils.TOR: []string{utils.DATA}, utils.ACCID: []string{"616350843"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{utils.META_RATED}, utils.DIRECTION: []string{"*out"}, utils.TENANT: []string{"cgrates.org"}, utils.CATEGORY: []string{"data"}, utils.ACCOUNT: []string{"1010"}, utils.SUBJECT: []string{"1010"}, utils.ANSWER_TIME: []string{"2013-11-07T08:42:26Z"}, utils.USAGE: []string{"10"}, "field_extr1": []string{"val_extr1"}, "fieldextr2": []string{"valextr2"}} @@ -174,10 +174,10 @@ func TestMediInjectCdrs(t *testing.T) { if !*testLocal { return } - cgrCdr1 := utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaaaadsafdsaf", "cdrsource": TEST_SQL, utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", + cgrCdr1 := utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaaaadsafdsaf", "cdrsource": TEST_SQL, utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "call", utils.ACCOUNT: "dan", utils.SUBJECT: "dan", utils.DESTINATION: "+4986517174963", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "10"} - cgrCdr2 := utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "baaaadsafdsaf", "cdrsource": TEST_SQL, utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", + cgrCdr2 := utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "baaaadsafdsaf", "cdrsource": TEST_SQL, utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "call", utils.ACCOUNT: "dan", utils.SUBJECT: "dan", utils.DESTINATION: "+4986517173964", utils.ANSWER_TIME: "2013-11-07T09:42:26Z", utils.USAGE: "20"} for _, cdr := range []utils.CgrCdr{cgrCdr1, cgrCdr2} { @@ -256,11 +256,11 @@ func TestMediatePseudoprepaid(t *testing.T) { } else if reply.BalanceMap[engine.CREDIT+attrs.Direction].GetTotalValue() != 11 { t.Errorf("Calling ApierV1.GetBalance expected: 10.0, received: %f", reply.BalanceMap[engine.CREDIT+attrs.Direction].GetTotalValue()) } - voiceCdr := &utils.StoredCdr{TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.PSEUDOPREPAID, Direction: utils.OUT, + voiceCdr := &utils.StoredCdr{TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.META_PSEUDOPREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "+4986517174963", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(5) * time.Second} - dataCdr := &utils.StoredCdr{TOR: utils.DATA, AccId: "6163508432", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.PSEUDOPREPAID, Direction: utils.OUT, + dataCdr := &utils.StoredCdr{TOR: utils.DATA, AccId: "6163508432", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.META_PSEUDOPREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "data", Account: "1003", Subject: "1003", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(10) * time.Second} diff --git a/engine/responder.go b/engine/responder.go index 4d9c56a74..5b4f68792 100644 --- a/engine/responder.go +++ b/engine/responder.go @@ -139,7 +139,7 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev utils.StoredCdr, reply *float64 } dcs, _ = dcs.AppendDefaultRun() for _, dc := range dcs { - if !utils.IsSliceMember([]string{utils.PREPAID, utils.PSEUDOPREPAID}, ev.GetReqType(dc.ReqTypeField)) { // Only consider prepaid and pseudoprepaid for MaxSessionTime + if !utils.IsSliceMember([]string{utils.META_PREPAID, utils.META_PSEUDOPREPAID, utils.PREPAID, utils.PSEUDOPREPAID}, ev.GetReqType(dc.ReqTypeField)) { // Only consider prepaid and pseudoprepaid for MaxSessionTime continue } runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP) @@ -197,7 +197,7 @@ func (rs *Responder) GetSessionRuns(ev utils.StoredCdr, sRuns *[]*SessionRun) er dcs, _ = dcs.AppendDefaultRun() sesRuns := make([]*SessionRun, 0) for _, dc := range dcs { - if ev.GetReqType(dc.ReqTypeField) != utils.PREPAID { + if !utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, ev.GetReqType(dc.ReqTypeField)) { continue // We only consider prepaid sessions } startTime, err := ev.GetAnswerTime(dc.AnswerTimeField) diff --git a/engine/responder_test.go b/engine/responder_test.go index 1decc865e..66c26dcdd 100644 --- a/engine/responder_test.go +++ b/engine/responder_test.go @@ -57,7 +57,7 @@ func TestResponderGetDerivedChargers(t *testing.T) { func TestGetDerivedMaxSessionTime(t *testing.T) { testTenant := "vdf" cdr := utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan", Subject: "dan", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: 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), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dan"} @@ -83,11 +83,11 @@ func TestGetDerivedMaxSessionTime(t *testing.T) { } keyCharger1 := utils.ConcatenatedKey("*out", testTenant, "call", "dan", "dan") charger1 := utils.DerivedChargers{ - &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", + &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^" + utils.META_PREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "^dan", SubjectField: "^dan", DestinationField: "^+49151708707", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"}, &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "^ivo", SubjectField: "^ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"}, - &utils.DerivedCharger{RunId: "extra3", ReqTypeField: "^pseudoprepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", + &utils.DerivedCharger{RunId: "extra3", ReqTypeField: "^" + utils.META_PSEUDOPREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "^rif", SubjectField: "^rif", DestinationField: "^+49151708707", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"}, } if err := accountingStorage.SetDerivedChargers(keyCharger1, charger1); err != nil { @@ -124,18 +124,18 @@ func TestGetDerivedMaxSessionTime(t *testing.T) { func TestGetSessionRuns(t *testing.T) { testTenant := "vdf" cdr := utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "prepaid", Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan2", Subject: "dan2", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: 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), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dan"} keyCharger1 := utils.ConcatenatedKey("*out", testTenant, "call", "dan2", "dan2") dfDC := &utils.DerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "*default", SubjectField: "*default", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"} - extra1DC := &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "^0", + extra1DC := &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^" + utils.META_PREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "^0", AccountField: "^minitsboy", SubjectField: "^rif", DestinationField: "^0256", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"} extra2DC := &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "^ivo", SubjectField: "^ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"} - extra3DC := &utils.DerivedCharger{RunId: "extra3", ReqTypeField: "^pseudoprepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "^0", + extra3DC := &utils.DerivedCharger{RunId: "extra3", ReqTypeField: "^" + utils.META_PSEUDOPREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "^0", AccountField: "^minu", SubjectField: "^rif", DestinationField: "^0256", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"} charger1 := utils.DerivedChargers{extra1DC, extra2DC, extra3DC} if err := accountingStorage.SetDerivedChargers(keyCharger1, charger1); err != nil { diff --git a/engine/storage_mysql_local_test.go b/engine/storage_mysql_local_test.go index e771eb243..72c3b05b5 100644 --- a/engine/storage_mysql_local_test.go +++ b/engine/storage_mysql_local_test.go @@ -212,7 +212,7 @@ func TestMySQLSetGetTPDerivedChargers(t *testing.T) { if !*testLocal { return } - dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^prepaid", AccountField: "^rif", SubjectField: "^rif", UsageField: "cgr_duration"} + dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^" + utils.META_PREPAID, AccountField: "^rif", SubjectField: "^rif", UsageField: "cgr_duration"} dcs := &utils.TPDerivedChargers{TPid: TEST_SQL, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: []*utils.TPDerivedCharger{dc}} DCS_ID := dcs.GetDerivedChargesId() setDCs := map[string][]*utils.TPDerivedCharger{DCS_ID: []*utils.TPDerivedCharger{dc}} @@ -431,22 +431,22 @@ func TestMySQLSetCdr(t *testing.T) { if !*testLocal { return } - cgrCdr1 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr1 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:20Z", utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "10s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: TEST_SQL} - cgrCdr2 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "prepaid", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr2 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_PREPAID, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:22Z", utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "20", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr3 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr3 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "premium_call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "1001", utils.SETUP_TIME: "2013-11-07T08:42:24Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "60s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr4 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: "pseudoprepaid", utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", + cgrCdr4 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_PSEUDOPREPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "+4986517174964", utils.SETUP_TIME: "2013-11-07T08:42:21Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "1m2s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr5 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: "postpaid", utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", + cgrCdr5 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_POSTPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", utils.CATEGORY: "call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "+4986517174963", utils.SETUP_TIME: "2013-11-07T08:42:25Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "15s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} @@ -455,19 +455,19 @@ func TestMySQLSetCdr(t *testing.T) { t.Error(err.Error()) } } - strCdr1 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: "rated", + strCdr1 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_RATED, Direction: "*out", 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"}, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201} strCdr1.CgrId = utils.Sha1(strCdr1.AccId, strCdr1.SetupTime.String()) - strCdr2 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN2", ReqType: "prepaid", + strCdr2 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN2", ReqType: utils.META_PREPAID, Direction: "*out", 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(12) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: utils.DEFAULT_RUNID, Cost: 0.201} strCdr2.CgrId = utils.Sha1(strCdr2.AccId, strCdr2.SetupTime.String()) - strCdr3 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: "rated", + strCdr3 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: utils.META_RATED, Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1000", Destination: "+4986517174963", 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"}, @@ -485,19 +485,19 @@ func TestMySQLSetRatedCdr(t *testing.T) { if !*testLocal { return } - strCdr1 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: "rated", + strCdr1 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_RATED, Direction: "*out", 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"}, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201} strCdr1.CgrId = utils.Sha1(strCdr1.AccId, strCdr1.SetupTime.String()) - strCdr2 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN", ReqType: "prepaid", + strCdr2 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN", ReqType: utils.META_PREPAID, Direction: "*out", 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(12) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: utils.DEFAULT_RUNID, Cost: 0.201} strCdr2.CgrId = utils.Sha1(strCdr2.AccId, strCdr2.SetupTime.String()) - strCdr3 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: "rated", + strCdr3 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: utils.META_RATED, Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1002", Destination: "+4986517174964", 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"}, @@ -608,14 +608,14 @@ func TestMySQLGetStoredCdrs(t *testing.T) { } // Filter on cgrids plus reqType if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{"prepaid"}}); err != nil { + utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{utils.META_PREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Count on multiple filter if _, count, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{"prepaid"}, Count: true}); err != nil { + utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{utils.META_PREPAID}, Count: true}); err != nil { t.Error(err.Error()) } else if count != 1 { t.Error("Unexpected count of StoredCdrs returned: ", count) @@ -663,13 +663,13 @@ func TestMySQLGetStoredCdrs(t *testing.T) { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on reqType - if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{"prepaid"}}); err != nil { + if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_PREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple reqType - if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{"prepaid", "pseudoprepaid"}}); err != nil { + if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 3 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) @@ -795,7 +795,7 @@ func TestMySQLGetStoredCdrs(t *testing.T) { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Combined filter - if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{"rated"}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { + if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) diff --git a/engine/storage_psql_local_test.go b/engine/storage_psql_local_test.go index c9e870345..5c8ae1f08 100644 --- a/engine/storage_psql_local_test.go +++ b/engine/storage_psql_local_test.go @@ -214,7 +214,7 @@ func TestPSQLSetGetTPDerivedChargers(t *testing.T) { if !*testLocal { return } - dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^prepaid", AccountField: "^rif", SubjectField: "^rif", UsageField: "cgr_duration"} + dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^" + utils.META_PREPAID, AccountField: "^rif", SubjectField: "^rif", UsageField: "cgr_duration"} dcs := &utils.TPDerivedChargers{TPid: TEST_SQL, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: []*utils.TPDerivedCharger{dc}} DCS_ID := dcs.GetDerivedChargesId() setDCs := map[string][]*utils.TPDerivedCharger{DCS_ID: []*utils.TPDerivedCharger{dc}} @@ -433,22 +433,22 @@ func TestPSQLSetCdr(t *testing.T) { if !*testLocal { return } - cgrCdr1 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr1 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:20Z", utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "10s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: TEST_SQL} - cgrCdr2 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "prepaid", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr2 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_PREPAID, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:22Z", utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "20", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr3 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr3 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "premium_call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "1001", utils.SETUP_TIME: "2013-11-07T08:42:24Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "60s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr4 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: "pseudoprepaid", utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", + cgrCdr4 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_PSEUDOPREPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "+4986517174964", utils.SETUP_TIME: "2013-11-07T08:42:21Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "1m2s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr5 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: "postpaid", utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", + cgrCdr5 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_POSTPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", utils.CATEGORY: "call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "+4986517174963", utils.SETUP_TIME: "2013-11-07T08:42:25Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "15s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} @@ -457,19 +457,19 @@ func TestPSQLSetCdr(t *testing.T) { t.Error(err.Error()) } } - strCdr1 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: "rated", + strCdr1 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_RATED, Direction: "*out", 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"}, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201} strCdr1.CgrId = utils.Sha1(strCdr1.AccId, strCdr1.SetupTime.String()) - strCdr2 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN2", ReqType: "prepaid", + strCdr2 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN2", ReqType: utils.META_PREPAID, Direction: "*out", 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(12) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: utils.DEFAULT_RUNID, Cost: 0.201} strCdr2.CgrId = utils.Sha1(strCdr2.AccId, strCdr2.SetupTime.String()) - strCdr3 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: "rated", + strCdr3 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: utils.META_RATED, Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1000", Destination: "+4986517174963", 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"}, @@ -531,19 +531,19 @@ func TestPSQLSetRatedCdr(t *testing.T) { if !*testLocal { return } - strCdr1 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: "rated", + strCdr1 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_RATED, Direction: "*out", 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"}, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201} strCdr1.CgrId = utils.Sha1(strCdr1.AccId, strCdr1.SetupTime.String()) - strCdr2 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN", ReqType: "prepaid", + strCdr2 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN", ReqType: utils.META_PREPAID, Direction: "*out", 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(12) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: utils.DEFAULT_RUNID, Cost: 0.201} strCdr2.CgrId = utils.Sha1(strCdr2.AccId, strCdr2.SetupTime.String()) - strCdr3 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: "rated", + strCdr3 := &utils.StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: utils.META_RATED, Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1002", Destination: "+4986517174964", 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"}, @@ -610,14 +610,14 @@ func TestPSQLGetStoredCdrs(t *testing.T) { } // Filter on cgrids plus reqType if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{"prepaid"}}); err != nil { + utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{utils.META_PREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Count on multiple filter if _, count, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{"prepaid"}, Count: true}); err != nil { + utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{utils.META_PREPAID}, Count: true}); err != nil { t.Error(err.Error()) } else if count != 1 { t.Error("Unexpected count of StoredCdrs returned: ", count) @@ -665,13 +665,13 @@ func TestPSQLGetStoredCdrs(t *testing.T) { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on reqType - if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{"prepaid"}}); err != nil { + if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_PREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple reqType - if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{"prepaid", "pseudoprepaid"}}); err != nil { + if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 3 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) @@ -797,7 +797,7 @@ func TestPSQLGetStoredCdrs(t *testing.T) { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Combined filter - if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{"rated"}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { + if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) diff --git a/general_tests/fsevcorelate_test.go b/general_tests/fsevcorelate_test.go index 6630ffadb..d56194b63 100644 --- a/general_tests/fsevcorelate_test.go +++ b/general_tests/fsevcorelate_test.go @@ -134,7 +134,7 @@ variable_effective_caller_id_number: 1001 variable_outbound_caller_id_name: FreeSWITCH variable_outbound_caller_id_number: 0000000000 variable_callgroup: techsupport -variable_cgr_reqtype: prepaid +variable_cgr_reqtype: *prepaid variable_user_name: 1001 variable_domain_name: 192.168.56.66 variable_sip_from_user_stripped: 1001 @@ -211,7 +211,7 @@ variable_read_codec: G722 variable_read_rate: 16000 variable_sip_local_sdp_str: v%3D0%0Ao%3DFreeSWITCH%201396951687%201396951689%20IN%20IP4%20192.168.56.74%0As%3DFreeSWITCH%0Ac%3DIN%20IP4%20192.168.56.74%0At%3D0%200%0Am%3Daudio%2032534%20RTP/AVP%209%20101%0Aa%3Drtpmap%3A9%20G722/8000%0Aa%3Drtpmap%3A101%20telephone-event/8000%0Aa%3Dfmtp%3A101%200-16%0Aa%3Dptime%3A20%0Aa%3Dsendrecv%0A` -var jsonCdr = []byte(`{"core-uuid":"feef0b51-7fdf-4c4a-878e-aff233752de2","channel_data":{"state":"CS_REPORTING","direction":"inbound","state_number":"11","flags":"0=1;1=1;3=1;36=1;37=1;39=1;42=1;47=1;52=1;73=1;75=1;94=1","caps":"1=1;2=1;3=1;4=1;5=1;6=1"},"variables":{"direction":"inbound","uuid":"86cfd6e2-dbda-45a3-b59d-f683ec368e8b","session_id":"5","sip_from_user":"1001","sip_from_uri":"1001@192.168.56.74","sip_from_host":"192.168.56.74","channel_name":"sofia/internal/1001@192.168.56.74","sip_local_network_addr":"192.168.56.74","sip_network_ip":"192.168.56.1","sip_network_port":"5060","sip_received_ip":"192.168.56.1","sip_received_port":"5060","sip_via_protocol":"udp","sip_authorized":"true","Event-Name":"REQUEST_PARAMS","Core-UUID":"feef0b51-7fdf-4c4a-878e-aff233752de2","FreeSWITCH-Hostname":"CGRTest","FreeSWITCH-Switchname":"CGRTest","FreeSWITCH-IPv4":"192.168.178.32","FreeSWITCH-IPv6":"::1","Event-Date-Local":"2014-04-08 21:10:21","Event-Date-GMT":"Tue, 08 Apr 2014 19:10:21 GMT","Event-Date-Timestamp":"1396984221278217","Event-Calling-File":"sofia.c","Event-Calling-Function":"sofia_handle_sip_i_invite","Event-Calling-Line-Number":"8076","Event-Sequence":"1423","sip_number_alias":"1001","sip_auth_username":"1001","sip_auth_realm":"192.168.56.74","number_alias":"1001","requested_domain_name":"192.168.56.66","record_stereo":"true","default_gateway":"example.com","default_areacode":"918","transfer_fallback_extension":"operator","toll_allow":"domestic,international,local","accountcode":"1001","user_context":"default","effective_caller_id_name":"Extension 1001","effective_caller_id_number":"1001","outbound_caller_id_name":"FreeSWITCH","outbound_caller_id_number":"0000000000","callgroup":"techsupport","user_name":"1001","domain_name":"192.168.56.66","sip_from_user_stripped":"1001","sofia_profile_name":"internal","recovery_profile_name":"internal","sip_req_user":"1002","sip_req_uri":"1002@192.168.56.74","sip_req_host":"192.168.56.74","sip_to_user":"1002","sip_to_uri":"1002@192.168.56.74","sip_to_host":"192.168.56.74","sip_contact_params":"transport=udp;registering_acc=192_168_56_74","sip_contact_user":"1001","sip_contact_port":"5060","sip_contact_uri":"1001@192.168.56.1:5060","sip_contact_host":"192.168.56.1","sip_via_host":"192.168.56.1","sip_via_port":"5060","presence_id":"1001@192.168.56.74","ep_codec_string":"G722@8000h@20i@64000b,PCMU@8000h@20i@64000b,PCMA@8000h@20i@64000b,GSM@8000h@20i@13200b","cgr_notify":"+AUTH_OK","max_forwards":"69","transfer_history":"1396984221:caefc538-5da4-4245-8716-112c706383d8:bl_xfer:1002/default/XML","transfer_source":"1396984221:caefc538-5da4-4245-8716-112c706383d8:bl_xfer:1002/default/XML","DP_MATCH":"ARRAY::1002|:1002","call_uuid":"86cfd6e2-dbda-45a3-b59d-f683ec368e8b","RFC2822_DATE":"Tue, 08 Apr 2014 21:10:21 +0200","dialed_extension":"1002","export_vars":"RFC2822_DATE,RFC2822_DATE,dialed_extension","ringback":"%(2000,4000,440,480)","transfer_ringback":"local_stream://moh","call_timeout":"30","hangup_after_bridge":"true","continue_on_fail":"true","called_party_callgroup":"techsupport","current_application_data":"user/1002@192.168.56.66","current_application":"bridge","dialed_user":"1002","dialed_domain":"192.168.56.66","inherit_codec":"true","originated_legs":"ARRAY::402f0929-fa14-4a5f-9642-3a1311bb4ddd;Outbound Call;1002|:402f0929-fa14-4a5f-9642-3a1311bb4ddd;Outbound Call;1002","rtp_use_codec_string":"G722,PCMU,PCMA,GSM","sip_use_codec_name":"G722","sip_use_codec_rate":"8000","sip_use_codec_ptime":"20","write_codec":"G722","write_rate":"16000","video_possible":"true","local_media_ip":"192.168.56.74","local_media_port":"32534","advertised_media_ip":"192.168.56.74","sip_use_pt":"9","rtp_use_ssrc":"1431080133","zrtp_secure_media_confirmed_audio":"true","zrtp_sas1_string_audio":"j6ff","switch_m_sdp":"v=0\r\no=1002 0 0 IN IP4 192.168.56.1\r\ns=-\r\nc=IN IP4 192.168.56.1\r\nt=0 0\r\nm=audio 5020 RTP/AVP 9 0 8 3 101\r\na=rtpmap:9 G722/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:101 telephone-event/8000\r\n","read_codec":"G722","read_rate":"16000","endpoint_disposition":"ANSWER","originate_causes":"ARRAY::402f0929-fa14-4a5f-9642-3a1311bb4ddd;NONE|:402f0929-fa14-4a5f-9642-3a1311bb4ddd;NONE","originate_disposition":"SUCCESS","DIALSTATUS":"SUCCESS","last_bridge_to":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","bridge_channel":"sofia/internal/sip:1002@192.168.56.1:5060","bridge_uuid":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","signal_bond":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","last_sent_callee_id_name":"Outbound Call","last_sent_callee_id_number":"1002","cgr_reqtype":"prepaid","sip_reinvite_sdp":"v=0\r\no=1001 0 1 IN IP4 192.168.56.1\r\ns=-\r\nc=IN IP4 192.168.56.1\r\nt=0 0\r\nm=audio 5016 RTP/AVP 96 97 98 9 100 102 0 8 103 3 104 101\r\na=sendonly\r\na=rtpmap:96 opus/48000/2\r\na=fmtp:96 usedtx=1\r\na=rtpmap:97 SILK/24000\r\na=rtpmap:98 SILK/16000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:100 speex/32000\r\na=rtpmap:102 speex/16000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:103 iLBC/8000\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:104 speex/8000\r\na=rtpmap:101 telephone-event/8000\r\na=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=zrtp-hash:1.10 722d57097aaabea2749ea8938472478f8d88645b23521fa5f8005a7a2bed8286\r\nm=video 0 RTP/AVP 105 99\r\n","switch_r_sdp":"v=0\r\no=1001 0 1 IN IP4 192.168.56.1\r\ns=-\r\nc=IN IP4 192.168.56.1\r\nt=0 0\r\nm=audio 5016 RTP/AVP 96 97 98 9 100 102 0 8 103 3 104 101\r\na=rtpmap:96 opus/48000/2\r\na=fmtp:96 usedtx=1\r\na=rtpmap:97 SILK/24000\r\na=rtpmap:98 SILK/16000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:100 speex/32000\r\na=rtpmap:102 speex/16000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:103 iLBC/8000\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:104 speex/8000\r\na=rtpmap:101 telephone-event/8000\r\na=sendonly\r\na=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=zrtp-hash:1.10 722d57097aaabea2749ea8938472478f8d88645b23521fa5f8005a7a2bed8286\r\nm=video 0 RTP/AVP 105 99\r\n","r_sdp_audio_zrtp_hash":"1.10 722d57097aaabea2749ea8938472478f8d88645b23521fa5f8005a7a2bed8286","remote_media_ip":"192.168.56.1","remote_media_port":"5016","sip_audio_recv_pt":"9","dtmf_type":"rfc2833","sip_2833_send_payload":"101","sip_2833_recv_payload":"101","sip_local_sdp_str":"v=0\no=FreeSWITCH 1396951687 1396951690 IN IP4 192.168.56.74\ns=FreeSWITCH\nc=IN IP4 192.168.56.74\nt=0 0\nm=audio 32534 RTP/AVP 9 101\na=rtpmap:9 G722/8000\na=rtpmap:101 telephone-event/8000\na=fmtp:101 0-16\na=ptime:20\na=sendrecv\n","sip_to_tag":"rXc9vZpv9eFaF","sip_from_tag":"1afc7eca","sip_cseq":"3","sip_call_id":"6691dbf8ffdc02bdacee02bc305d5c71@0:0:0:0:0:0:0:0","sip_full_via":"SIP/2.0/UDP 192.168.56.1:5060;branch=z9hG4bK-323133-5d083abc0d3f327b9101586e71b5fce4","sip_from_display":"1001","sip_full_from":"\"1001\" ;tag=1afc7eca","sip_full_to":";tag=rXc9vZpv9eFaF","sip_term_status":"200","proto_specific_hangup_cause":"sip:200","sip_term_cause":"16","last_bridge_role":"originator","sip_user_agent":"Jitsi2.5.5065Linux","sip_hangup_disposition":"recv_bye","bridge_hangup_cause":"NORMAL_CLEARING","hangup_cause":"NORMAL_CLEARING","hangup_cause_q850":"16","digits_dialed":"none","start_stamp":"2014-04-08 21:10:21","profile_start_stamp":"2014-04-08 21:10:21","answer_stamp":"2014-04-08 21:10:27","bridge_stamp":"2014-04-08 21:10:27","hold_stamp":"2014-04-08 21:10:27","progress_stamp":"2014-04-08 21:10:21","progress_media_stamp":"2014-04-08 21:10:21","hold_events":"{{1396984227824182,1396984242247995}}","end_stamp":"2014-04-08 21:10:42","start_epoch":"1396984221","start_uepoch":"1396984221278217","profile_start_epoch":"1396984221","profile_start_uepoch":"1396984221377035","answer_epoch":"1396984227","answer_uepoch":"1396984227717006","bridge_epoch":"1396984227","bridge_uepoch":"1396984227737268","last_hold_epoch":"1396984227","last_hold_uepoch":"1396984227824167","hold_accum_seconds":"14","hold_accum_usec":"14423816","hold_accum_ms":"14423","resurrect_epoch":"0","resurrect_uepoch":"0","progress_epoch":"1396984221","progress_uepoch":"1396984221497331","progress_media_epoch":"1396984221","progress_media_uepoch":"1396984221517042","end_epoch":"1396984242","end_uepoch":"1396984242257026","last_app":"bridge","last_arg":"user/1002@192.168.56.66","caller_id":"\"1001\" <1001>","duration":"21","billsec":"15","progresssec":"0","answersec":"6","waitsec":"6","progress_mediasec":"0","flow_billsec":"21","mduration":"20979","billmsec":"14540","progressmsec":"219","answermsec":"6439","waitmsec":"6459","progress_mediamsec":"239","flow_billmsec":"20979","uduration":"20978809","billusec":"14540020","progressusec":"219114","answerusec":"6438789","waitusec":"6459051","progress_mediausec":"238825","flow_billusec":"20978809","rtp_audio_in_raw_bytes":"181360","rtp_audio_in_media_bytes":"180304","rtp_audio_in_packet_count":"1031","rtp_audio_in_media_packet_count":"1025","rtp_audio_in_skip_packet_count":"45","rtp_audio_in_jb_packet_count":"0","rtp_audio_in_dtmf_packet_count":"0","rtp_audio_in_cng_packet_count":"0","rtp_audio_in_flush_packet_count":"6","rtp_audio_in_largest_jb_size":"0","rtp_audio_out_raw_bytes":"165780","rtp_audio_out_media_bytes":"165780","rtp_audio_out_packet_count":"942","rtp_audio_out_media_packet_count":"942","rtp_audio_out_skip_packet_count":"0","rtp_audio_out_dtmf_packet_count":"0","rtp_audio_out_cng_packet_count":"0","rtp_audio_rtcp_packet_count":"0","rtp_audio_rtcp_octet_count":"0"},"app_log":{"applications":[{"app_name":"hash","app_data":"insert/192.168.56.66-spymap/1001/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/1001/1002"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/global/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"export","app_data":"RFC2822_DATE=Tue, 08 Apr 2014 21:10:21 +0200"},{"app_name":"park","app_data":""},{"app_name":"hash","app_data":"insert/192.168.56.66-spymap/1001/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/1001/1002"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/global/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"export","app_data":"RFC2822_DATE=Tue, 08 Apr 2014 21:10:21 +0200"},{"app_name":"export","app_data":"dialed_extension=1002"},{"app_name":"bind_meta_app","app_data":"1 b s execute_extension::dx XML features"},{"app_name":"bind_meta_app","app_data":"2 b s record_session::/var/lib/freeswitch/recordings/1001.2014-04-08-21-10-21.wav"},{"app_name":"bind_meta_app","app_data":"3 b s execute_extension::cf XML features"},{"app_name":"bind_meta_app","app_data":"4 b s execute_extension::att_xfer XML features"},{"app_name":"set","app_data":"ringback=%(2000,4000,440,480)"},{"app_name":"set","app_data":"transfer_ringback=local_stream://moh"},{"app_name":"set","app_data":"call_timeout=30"},{"app_name":"set","app_data":"hangup_after_bridge=true"},{"app_name":"set","app_data":"continue_on_fail=true"},{"app_name":"hash","app_data":"insert/192.168.56.66-call_return/1002/1001"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial_ext/1002/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"set","app_data":"called_party_callgroup=techsupport"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial_ext/techsupport/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial_ext/global/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/techsupport/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"bridge","app_data":"user/1002@192.168.56.66"}]},"callflow":{"dialplan":"XML","profile_index":"2","extension":{"name":"global","number":"1002","applications":[{"app_name":"hash","app_data":"insert/${domain_name}-spymap/${caller_id_number}/${uuid}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/${caller_id_number}/${destination_number}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/global/${uuid}"},{"app_name":"export","app_data":"RFC2822_DATE=${strftime(%a, %d %b %Y %T %z)}"},{"app_name":"export","app_data":"dialed_extension=1002"},{"app_name":"bind_meta_app","app_data":"1 b s execute_extension::dx XML features"},{"app_name":"bind_meta_app","app_data":"2 b s record_session::/var/lib/freeswitch/recordings/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"},{"app_name":"bind_meta_app","app_data":"3 b s execute_extension::cf XML features"},{"app_name":"bind_meta_app","app_data":"4 b s execute_extension::att_xfer XML features"},{"app_name":"set","app_data":"ringback=${us-ring}"},{"app_name":"set","app_data":"transfer_ringback=local_stream://moh"},{"app_name":"set","app_data":"call_timeout=30"},{"app_name":"set","app_data":"hangup_after_bridge=true"},{"app_name":"set","app_data":"continue_on_fail=true"},{"app_name":"hash","app_data":"insert/${domain_name}-call_return/${dialed_extension}/${caller_id_number}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial_ext/${dialed_extension}/${uuid}"},{"app_name":"set","app_data":"called_party_callgroup=${user_data(${dialed_extension}@${domain_name} var callgroup)}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial_ext/${called_party_callgroup}/${uuid}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial_ext/global/${uuid}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/${called_party_callgroup}/${uuid}"},{"app_name":"bridge","app_data":"user/${dialed_extension}@${domain_name}"},{"last_executed":"true","app_name":"answer","app_data":""},{"app_name":"sleep","app_data":"1000"},{"app_name":"bridge","app_data":"loopback/app=voicemail:default ${domain_name} ${dialed_extension}"}],"current_app":"answer"},"caller_profile":{"username":"1001","dialplan":"XML","caller_id_name":"1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"192.168.56.1","rdnis":"1002","destination_number":"1002","uuid":"86cfd6e2-dbda-45a3-b59d-f683ec368e8b","source":"mod_sofia","context":"default","chan_name":"sofia/internal/1001@192.168.56.74","originatee":{"originatee_caller_profiles":[{"username":"1001","dialplan":"XML","caller_id_name":"Extension 1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"192.168.56.1","rdnis":"1002","destination_number":"1002","uuid":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","source":"mod_sofia","context":"default","chan_name":"sofia/internal/sip:1002@192.168.56.1:5060"},{"username":"1001","dialplan":"XML","caller_id_name":"Extension 1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"192.168.56.1","rdnis":"1002","destination_number":"1002","uuid":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","source":"mod_sofia","context":"default","chan_name":"sofia/internal/sip:1002@192.168.56.1:5060"}]}},"times":{"created_time":"1396984221278217","profile_created_time":"1396984221377035","progress_time":"1396984221497331","progress_media_time":"1396984221517042","answered_time":"1396984227717006","hangup_time":"1396984242257026","resurrect_time":"0","transfer_time":"0"}},"callflow":{"dialplan":"XML","profile_index":"1","extension":{"name":"global","number":"1002","applications":[{"app_name":"hash","app_data":"insert/${domain_name}-spymap/${caller_id_number}/${uuid}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/${caller_id_number}/${destination_number}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/global/${uuid}"},{"app_name":"export","app_data":"RFC2822_DATE=${strftime(%a, %d %b %Y %T %z)}"},{"app_name":"park","app_data":""}]},"caller_profile":{"username":"1001","dialplan":"XML","caller_id_name":"1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"192.168.56.1","rdnis":"","destination_number":"1002","uuid":"86cfd6e2-dbda-45a3-b59d-f683ec368e8b","source":"mod_sofia","context":"default","chan_name":"sofia/internal/1001@192.168.56.74"},"times":{"created_time":"1396984221278217","profile_created_time":"1396984221278217","progress_time":"0","progress_media_time":"0","answered_time":"0","hangup_time":"0","resurrect_time":"0","transfer_time":"1396984221377035"}}}`) +var jsonCdr = []byte(`{"core-uuid":"feef0b51-7fdf-4c4a-878e-aff233752de2","channel_data":{"state":"CS_REPORTING","direction":"inbound","state_number":"11","flags":"0=1;1=1;3=1;36=1;37=1;39=1;42=1;47=1;52=1;73=1;75=1;94=1","caps":"1=1;2=1;3=1;4=1;5=1;6=1"},"variables":{"direction":"inbound","uuid":"86cfd6e2-dbda-45a3-b59d-f683ec368e8b","session_id":"5","sip_from_user":"1001","sip_from_uri":"1001@192.168.56.74","sip_from_host":"192.168.56.74","channel_name":"sofia/internal/1001@192.168.56.74","sip_local_network_addr":"192.168.56.74","sip_network_ip":"192.168.56.1","sip_network_port":"5060","sip_received_ip":"192.168.56.1","sip_received_port":"5060","sip_via_protocol":"udp","sip_authorized":"true","Event-Name":"REQUEST_PARAMS","Core-UUID":"feef0b51-7fdf-4c4a-878e-aff233752de2","FreeSWITCH-Hostname":"CGRTest","FreeSWITCH-Switchname":"CGRTest","FreeSWITCH-IPv4":"192.168.178.32","FreeSWITCH-IPv6":"::1","Event-Date-Local":"2014-04-08 21:10:21","Event-Date-GMT":"Tue, 08 Apr 2014 19:10:21 GMT","Event-Date-Timestamp":"1396984221278217","Event-Calling-File":"sofia.c","Event-Calling-Function":"sofia_handle_sip_i_invite","Event-Calling-Line-Number":"8076","Event-Sequence":"1423","sip_number_alias":"1001","sip_auth_username":"1001","sip_auth_realm":"192.168.56.74","number_alias":"1001","requested_domain_name":"192.168.56.66","record_stereo":"true","default_gateway":"example.com","default_areacode":"918","transfer_fallback_extension":"operator","toll_allow":"domestic,international,local","accountcode":"1001","user_context":"default","effective_caller_id_name":"Extension 1001","effective_caller_id_number":"1001","outbound_caller_id_name":"FreeSWITCH","outbound_caller_id_number":"0000000000","callgroup":"techsupport","user_name":"1001","domain_name":"192.168.56.66","sip_from_user_stripped":"1001","sofia_profile_name":"internal","recovery_profile_name":"internal","sip_req_user":"1002","sip_req_uri":"1002@192.168.56.74","sip_req_host":"192.168.56.74","sip_to_user":"1002","sip_to_uri":"1002@192.168.56.74","sip_to_host":"192.168.56.74","sip_contact_params":"transport=udp;registering_acc=192_168_56_74","sip_contact_user":"1001","sip_contact_port":"5060","sip_contact_uri":"1001@192.168.56.1:5060","sip_contact_host":"192.168.56.1","sip_via_host":"192.168.56.1","sip_via_port":"5060","presence_id":"1001@192.168.56.74","ep_codec_string":"G722@8000h@20i@64000b,PCMU@8000h@20i@64000b,PCMA@8000h@20i@64000b,GSM@8000h@20i@13200b","cgr_notify":"+AUTH_OK","max_forwards":"69","transfer_history":"1396984221:caefc538-5da4-4245-8716-112c706383d8:bl_xfer:1002/default/XML","transfer_source":"1396984221:caefc538-5da4-4245-8716-112c706383d8:bl_xfer:1002/default/XML","DP_MATCH":"ARRAY::1002|:1002","call_uuid":"86cfd6e2-dbda-45a3-b59d-f683ec368e8b","RFC2822_DATE":"Tue, 08 Apr 2014 21:10:21 +0200","dialed_extension":"1002","export_vars":"RFC2822_DATE,RFC2822_DATE,dialed_extension","ringback":"%(2000,4000,440,480)","transfer_ringback":"local_stream://moh","call_timeout":"30","hangup_after_bridge":"true","continue_on_fail":"true","called_party_callgroup":"techsupport","current_application_data":"user/1002@192.168.56.66","current_application":"bridge","dialed_user":"1002","dialed_domain":"192.168.56.66","inherit_codec":"true","originated_legs":"ARRAY::402f0929-fa14-4a5f-9642-3a1311bb4ddd;Outbound Call;1002|:402f0929-fa14-4a5f-9642-3a1311bb4ddd;Outbound Call;1002","rtp_use_codec_string":"G722,PCMU,PCMA,GSM","sip_use_codec_name":"G722","sip_use_codec_rate":"8000","sip_use_codec_ptime":"20","write_codec":"G722","write_rate":"16000","video_possible":"true","local_media_ip":"192.168.56.74","local_media_port":"32534","advertised_media_ip":"192.168.56.74","sip_use_pt":"9","rtp_use_ssrc":"1431080133","zrtp_secure_media_confirmed_audio":"true","zrtp_sas1_string_audio":"j6ff","switch_m_sdp":"v=0\r\no=1002 0 0 IN IP4 192.168.56.1\r\ns=-\r\nc=IN IP4 192.168.56.1\r\nt=0 0\r\nm=audio 5020 RTP/AVP 9 0 8 3 101\r\na=rtpmap:9 G722/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:101 telephone-event/8000\r\n","read_codec":"G722","read_rate":"16000","endpoint_disposition":"ANSWER","originate_causes":"ARRAY::402f0929-fa14-4a5f-9642-3a1311bb4ddd;NONE|:402f0929-fa14-4a5f-9642-3a1311bb4ddd;NONE","originate_disposition":"SUCCESS","DIALSTATUS":"SUCCESS","last_bridge_to":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","bridge_channel":"sofia/internal/sip:1002@192.168.56.1:5060","bridge_uuid":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","signal_bond":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","last_sent_callee_id_name":"Outbound Call","last_sent_callee_id_number":"1002","cgr_reqtype":"*prepaid","sip_reinvite_sdp":"v=0\r\no=1001 0 1 IN IP4 192.168.56.1\r\ns=-\r\nc=IN IP4 192.168.56.1\r\nt=0 0\r\nm=audio 5016 RTP/AVP 96 97 98 9 100 102 0 8 103 3 104 101\r\na=sendonly\r\na=rtpmap:96 opus/48000/2\r\na=fmtp:96 usedtx=1\r\na=rtpmap:97 SILK/24000\r\na=rtpmap:98 SILK/16000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:100 speex/32000\r\na=rtpmap:102 speex/16000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:103 iLBC/8000\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:104 speex/8000\r\na=rtpmap:101 telephone-event/8000\r\na=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=zrtp-hash:1.10 722d57097aaabea2749ea8938472478f8d88645b23521fa5f8005a7a2bed8286\r\nm=video 0 RTP/AVP 105 99\r\n","switch_r_sdp":"v=0\r\no=1001 0 1 IN IP4 192.168.56.1\r\ns=-\r\nc=IN IP4 192.168.56.1\r\nt=0 0\r\nm=audio 5016 RTP/AVP 96 97 98 9 100 102 0 8 103 3 104 101\r\na=rtpmap:96 opus/48000/2\r\na=fmtp:96 usedtx=1\r\na=rtpmap:97 SILK/24000\r\na=rtpmap:98 SILK/16000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:100 speex/32000\r\na=rtpmap:102 speex/16000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:103 iLBC/8000\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:104 speex/8000\r\na=rtpmap:101 telephone-event/8000\r\na=sendonly\r\na=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=zrtp-hash:1.10 722d57097aaabea2749ea8938472478f8d88645b23521fa5f8005a7a2bed8286\r\nm=video 0 RTP/AVP 105 99\r\n","r_sdp_audio_zrtp_hash":"1.10 722d57097aaabea2749ea8938472478f8d88645b23521fa5f8005a7a2bed8286","remote_media_ip":"192.168.56.1","remote_media_port":"5016","sip_audio_recv_pt":"9","dtmf_type":"rfc2833","sip_2833_send_payload":"101","sip_2833_recv_payload":"101","sip_local_sdp_str":"v=0\no=FreeSWITCH 1396951687 1396951690 IN IP4 192.168.56.74\ns=FreeSWITCH\nc=IN IP4 192.168.56.74\nt=0 0\nm=audio 32534 RTP/AVP 9 101\na=rtpmap:9 G722/8000\na=rtpmap:101 telephone-event/8000\na=fmtp:101 0-16\na=ptime:20\na=sendrecv\n","sip_to_tag":"rXc9vZpv9eFaF","sip_from_tag":"1afc7eca","sip_cseq":"3","sip_call_id":"6691dbf8ffdc02bdacee02bc305d5c71@0:0:0:0:0:0:0:0","sip_full_via":"SIP/2.0/UDP 192.168.56.1:5060;branch=z9hG4bK-323133-5d083abc0d3f327b9101586e71b5fce4","sip_from_display":"1001","sip_full_from":"\"1001\" ;tag=1afc7eca","sip_full_to":";tag=rXc9vZpv9eFaF","sip_term_status":"200","proto_specific_hangup_cause":"sip:200","sip_term_cause":"16","last_bridge_role":"originator","sip_user_agent":"Jitsi2.5.5065Linux","sip_hangup_disposition":"recv_bye","bridge_hangup_cause":"NORMAL_CLEARING","hangup_cause":"NORMAL_CLEARING","hangup_cause_q850":"16","digits_dialed":"none","start_stamp":"2014-04-08 21:10:21","profile_start_stamp":"2014-04-08 21:10:21","answer_stamp":"2014-04-08 21:10:27","bridge_stamp":"2014-04-08 21:10:27","hold_stamp":"2014-04-08 21:10:27","progress_stamp":"2014-04-08 21:10:21","progress_media_stamp":"2014-04-08 21:10:21","hold_events":"{{1396984227824182,1396984242247995}}","end_stamp":"2014-04-08 21:10:42","start_epoch":"1396984221","start_uepoch":"1396984221278217","profile_start_epoch":"1396984221","profile_start_uepoch":"1396984221377035","answer_epoch":"1396984227","answer_uepoch":"1396984227717006","bridge_epoch":"1396984227","bridge_uepoch":"1396984227737268","last_hold_epoch":"1396984227","last_hold_uepoch":"1396984227824167","hold_accum_seconds":"14","hold_accum_usec":"14423816","hold_accum_ms":"14423","resurrect_epoch":"0","resurrect_uepoch":"0","progress_epoch":"1396984221","progress_uepoch":"1396984221497331","progress_media_epoch":"1396984221","progress_media_uepoch":"1396984221517042","end_epoch":"1396984242","end_uepoch":"1396984242257026","last_app":"bridge","last_arg":"user/1002@192.168.56.66","caller_id":"\"1001\" <1001>","duration":"21","billsec":"15","progresssec":"0","answersec":"6","waitsec":"6","progress_mediasec":"0","flow_billsec":"21","mduration":"20979","billmsec":"14540","progressmsec":"219","answermsec":"6439","waitmsec":"6459","progress_mediamsec":"239","flow_billmsec":"20979","uduration":"20978809","billusec":"14540020","progressusec":"219114","answerusec":"6438789","waitusec":"6459051","progress_mediausec":"238825","flow_billusec":"20978809","rtp_audio_in_raw_bytes":"181360","rtp_audio_in_media_bytes":"180304","rtp_audio_in_packet_count":"1031","rtp_audio_in_media_packet_count":"1025","rtp_audio_in_skip_packet_count":"45","rtp_audio_in_jb_packet_count":"0","rtp_audio_in_dtmf_packet_count":"0","rtp_audio_in_cng_packet_count":"0","rtp_audio_in_flush_packet_count":"6","rtp_audio_in_largest_jb_size":"0","rtp_audio_out_raw_bytes":"165780","rtp_audio_out_media_bytes":"165780","rtp_audio_out_packet_count":"942","rtp_audio_out_media_packet_count":"942","rtp_audio_out_skip_packet_count":"0","rtp_audio_out_dtmf_packet_count":"0","rtp_audio_out_cng_packet_count":"0","rtp_audio_rtcp_packet_count":"0","rtp_audio_rtcp_octet_count":"0"},"app_log":{"applications":[{"app_name":"hash","app_data":"insert/192.168.56.66-spymap/1001/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/1001/1002"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/global/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"export","app_data":"RFC2822_DATE=Tue, 08 Apr 2014 21:10:21 +0200"},{"app_name":"park","app_data":""},{"app_name":"hash","app_data":"insert/192.168.56.66-spymap/1001/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/1001/1002"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/global/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"export","app_data":"RFC2822_DATE=Tue, 08 Apr 2014 21:10:21 +0200"},{"app_name":"export","app_data":"dialed_extension=1002"},{"app_name":"bind_meta_app","app_data":"1 b s execute_extension::dx XML features"},{"app_name":"bind_meta_app","app_data":"2 b s record_session::/var/lib/freeswitch/recordings/1001.2014-04-08-21-10-21.wav"},{"app_name":"bind_meta_app","app_data":"3 b s execute_extension::cf XML features"},{"app_name":"bind_meta_app","app_data":"4 b s execute_extension::att_xfer XML features"},{"app_name":"set","app_data":"ringback=%(2000,4000,440,480)"},{"app_name":"set","app_data":"transfer_ringback=local_stream://moh"},{"app_name":"set","app_data":"call_timeout=30"},{"app_name":"set","app_data":"hangup_after_bridge=true"},{"app_name":"set","app_data":"continue_on_fail=true"},{"app_name":"hash","app_data":"insert/192.168.56.66-call_return/1002/1001"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial_ext/1002/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"set","app_data":"called_party_callgroup=techsupport"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial_ext/techsupport/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial_ext/global/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"hash","app_data":"insert/192.168.56.66-last_dial/techsupport/86cfd6e2-dbda-45a3-b59d-f683ec368e8b"},{"app_name":"bridge","app_data":"user/1002@192.168.56.66"}]},"callflow":{"dialplan":"XML","profile_index":"2","extension":{"name":"global","number":"1002","applications":[{"app_name":"hash","app_data":"insert/${domain_name}-spymap/${caller_id_number}/${uuid}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/${caller_id_number}/${destination_number}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/global/${uuid}"},{"app_name":"export","app_data":"RFC2822_DATE=${strftime(%a, %d %b %Y %T %z)}"},{"app_name":"export","app_data":"dialed_extension=1002"},{"app_name":"bind_meta_app","app_data":"1 b s execute_extension::dx XML features"},{"app_name":"bind_meta_app","app_data":"2 b s record_session::/var/lib/freeswitch/recordings/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"},{"app_name":"bind_meta_app","app_data":"3 b s execute_extension::cf XML features"},{"app_name":"bind_meta_app","app_data":"4 b s execute_extension::att_xfer XML features"},{"app_name":"set","app_data":"ringback=${us-ring}"},{"app_name":"set","app_data":"transfer_ringback=local_stream://moh"},{"app_name":"set","app_data":"call_timeout=30"},{"app_name":"set","app_data":"hangup_after_bridge=true"},{"app_name":"set","app_data":"continue_on_fail=true"},{"app_name":"hash","app_data":"insert/${domain_name}-call_return/${dialed_extension}/${caller_id_number}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial_ext/${dialed_extension}/${uuid}"},{"app_name":"set","app_data":"called_party_callgroup=${user_data(${dialed_extension}@${domain_name} var callgroup)}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial_ext/${called_party_callgroup}/${uuid}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial_ext/global/${uuid}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/${called_party_callgroup}/${uuid}"},{"app_name":"bridge","app_data":"user/${dialed_extension}@${domain_name}"},{"last_executed":"true","app_name":"answer","app_data":""},{"app_name":"sleep","app_data":"1000"},{"app_name":"bridge","app_data":"loopback/app=voicemail:default ${domain_name} ${dialed_extension}"}],"current_app":"answer"},"caller_profile":{"username":"1001","dialplan":"XML","caller_id_name":"1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"192.168.56.1","rdnis":"1002","destination_number":"1002","uuid":"86cfd6e2-dbda-45a3-b59d-f683ec368e8b","source":"mod_sofia","context":"default","chan_name":"sofia/internal/1001@192.168.56.74","originatee":{"originatee_caller_profiles":[{"username":"1001","dialplan":"XML","caller_id_name":"Extension 1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"192.168.56.1","rdnis":"1002","destination_number":"1002","uuid":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","source":"mod_sofia","context":"default","chan_name":"sofia/internal/sip:1002@192.168.56.1:5060"},{"username":"1001","dialplan":"XML","caller_id_name":"Extension 1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"192.168.56.1","rdnis":"1002","destination_number":"1002","uuid":"402f0929-fa14-4a5f-9642-3a1311bb4ddd","source":"mod_sofia","context":"default","chan_name":"sofia/internal/sip:1002@192.168.56.1:5060"}]}},"times":{"created_time":"1396984221278217","profile_created_time":"1396984221377035","progress_time":"1396984221497331","progress_media_time":"1396984221517042","answered_time":"1396984227717006","hangup_time":"1396984242257026","resurrect_time":"0","transfer_time":"0"}},"callflow":{"dialplan":"XML","profile_index":"1","extension":{"name":"global","number":"1002","applications":[{"app_name":"hash","app_data":"insert/${domain_name}-spymap/${caller_id_number}/${uuid}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/${caller_id_number}/${destination_number}"},{"app_name":"hash","app_data":"insert/${domain_name}-last_dial/global/${uuid}"},{"app_name":"export","app_data":"RFC2822_DATE=${strftime(%a, %d %b %Y %T %z)}"},{"app_name":"park","app_data":""}]},"caller_profile":{"username":"1001","dialplan":"XML","caller_id_name":"1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"192.168.56.1","rdnis":"","destination_number":"1002","uuid":"86cfd6e2-dbda-45a3-b59d-f683ec368e8b","source":"mod_sofia","context":"default","chan_name":"sofia/internal/1001@192.168.56.74"},"times":{"created_time":"1396984221278217","profile_created_time":"1396984221278217","progress_time":"0","progress_media_time":"0","answered_time":"0","hangup_time":"0","resurrect_time":"0","transfer_time":"1396984221377035"}}}`) func TestEvCorelate(t *testing.T) { cfg, _ := config.NewDefaultCGRConfig() diff --git a/general_tests/tutorial_fs_calls_test.go b/general_tests/tutorial_fs_calls_test.go index 352cc893e..120979b97 100644 --- a/general_tests/tutorial_fs_calls_test.go +++ b/general_tests/tutorial_fs_calls_test.go @@ -173,7 +173,7 @@ func TestTutFsCallsCdrs1001(t *testing.T) { if reply[0].CdrSource != "FS_CHANNEL_HANGUP_COMPLETE" { t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0]) } - if reply[0].ReqType != utils.PREPAID { + if reply[0].ReqType != utils.META_PREPAID { t.Errorf("Unexpected ReqType for CDR: %+v", reply[0]) } if reply[0].Usage != "67" { // Usage as seconds @@ -189,7 +189,7 @@ func TestTutFsCallsCdrs1001(t *testing.T) { } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].ReqType != utils.RATED { + if reply[0].ReqType != utils.META_RATED { t.Errorf("Unexpected ReqType for CDR: %+v", reply[0]) } if reply[0].Subject != "1002" { diff --git a/sessionmanager/fsevent_test.go b/sessionmanager/fsevent_test.go index 770957490..7c24c6547 100644 --- a/sessionmanager/fsevent_test.go +++ b/sessionmanager/fsevent_test.go @@ -236,7 +236,7 @@ variable_last_bridge_to: b7f3d830-b3a4-4e1c-b600-572eeb462c39 variable_bridge_channel: sofia/internal/sip%3A1002%40192.168.56.1%3A5060 variable_bridge_uuid: b7f3d830-b3a4-4e1c-b600-572eeb462c39 variable_signal_bond: b7f3d830-b3a4-4e1c-b600-572eeb462c39 -variable_cgr_reqtype: pseudoprepaid +variable_cgr_reqtype: *pseudoprepaid variable_last_sent_callee_id_name: Outbound%20Call variable_last_sent_callee_id_number: 1002 variable_sip_reinvite_sdp: v%3D0%0D%0Ao%3D1003%200%201%20IN%20IP4%20192.168.56.1%0D%0As%3D-%0D%0Ac%3DIN%20IP4%20192.168.56.1%0D%0At%3D0%200%0D%0Am%3Daudio%205052%20RTP/AVP%2096%2097%2098%209%20100%20102%200%208%20103%203%20104%20101%0D%0Aa%3Dsendonly%0D%0Aa%3Drtpmap%3A96%20opus/48000/2%0D%0Aa%3Dfmtp%3A96%20usedtx%3D1%0D%0Aa%3Drtpmap%3A97%20SILK/24000%0D%0Aa%3Drtpmap%3A98%20SILK/16000%0D%0Aa%3Drtpmap%3A9%20G722/8000%0D%0Aa%3Drtpmap%3A100%20speex/32000%0D%0Aa%3Drtpmap%3A102%20speex/16000%0D%0Aa%3Drtpmap%3A0%20PCMU/8000%0D%0Aa%3Drtpmap%3A8%20PCMA/8000%0D%0Aa%3Drtpmap%3A103%20iLBC/8000%0D%0Aa%3Drtpmap%3A3%20GSM/8000%0D%0Aa%3Drtpmap%3A104%20speex/8000%0D%0Aa%3Drtpmap%3A101%20telephone-event/8000%0D%0Aa%3Dextmap%3A1%20urn%3Aietf%3Aparams%3Artp-hdrext%3Acsrc-audio-level%0D%0Aa%3Dzrtp-hash%3A1.10%20bd7a58a0a6cb4b71870cc776f1901436f82ab3c9f960b9fc9645086206a8a804%0D%0Am%3Dvideo%200%20RTP/AVP%20105%2099%0D%0A @@ -477,7 +477,7 @@ func TestParseFsHangup(t *testing.T) { setupTime, _ := ev.GetSetupTime(utils.META_DEFAULT) answerTime, _ := ev.GetAnswerTime(utils.META_DEFAULT) dur, _ := ev.GetDuration(utils.META_DEFAULT) - if ev.GetReqType(utils.META_DEFAULT) != utils.PSEUDOPREPAID || + if ev.GetReqType(utils.META_DEFAULT) != utils.META_PSEUDOPREPAID || ev.GetDirection(utils.META_DEFAULT) != "*out" || ev.GetTenant(utils.META_DEFAULT) != "cgrates.org" || ev.GetCategory(utils.META_DEFAULT) != "call" || @@ -488,7 +488,7 @@ func TestParseFsHangup(t *testing.T) { answerTime.UTC() != time.Date(2014, 4, 25, 16, 8, 40, 0, time.UTC) || dur != time.Duration(5)*time.Second { t.Error("Default values not matching", - ev.GetReqType(utils.META_DEFAULT) != utils.PSEUDOPREPAID, + ev.GetReqType(utils.META_DEFAULT) != utils.META_PSEUDOPREPAID, ev.GetDirection(utils.META_DEFAULT) != "*out", ev.GetTenant(utils.META_DEFAULT) != "cgrates.org", ev.GetCategory(utils.META_DEFAULT) != "call", @@ -520,7 +520,7 @@ func TestParseEventValue(t *testing.T) { if parsed := ev.ParseEventValue(&utils.RSRField{Id: utils.CDRSOURCE}); parsed != "FS_EVENT" { t.Error("Unexpected result parsed", parsed) } - if parsed := ev.ParseEventValue(&utils.RSRField{Id: utils.REQTYPE}); parsed != utils.PSEUDOPREPAID { + if parsed := ev.ParseEventValue(&utils.RSRField{Id: utils.REQTYPE}); parsed != utils.META_PSEUDOPREPAID { t.Error("Unexpected result parsed", parsed) } if parsed := ev.ParseEventValue(&utils.RSRField{Id: utils.DIRECTION}); parsed != utils.OUT { @@ -619,7 +619,7 @@ func TestFsEvAsStoredCdr(t *testing.T) { setupTime, _ := utils.ParseTimeDetectLayout("1398442107") aTime, _ := utils.ParseTimeDetectLayout("1398442120") eStoredCdr := &utils.StoredCdr{CgrId: utils.Sha1("37e9b766-5256-4e4b-b1ed-3767b930fec8", setupTime.UTC().String()), - TOR: utils.VOICE, AccId: "37e9b766-5256-4e4b-b1ed-3767b930fec8", CdrHost: "10.0.2.15", CdrSource: "FS_CHANNEL_HANGUP_COMPLETE", ReqType: utils.PSEUDOPREPAID, + TOR: utils.VOICE, AccId: "37e9b766-5256-4e4b-b1ed-3767b930fec8", CdrHost: "10.0.2.15", CdrSource: "FS_CHANNEL_HANGUP_COMPLETE", ReqType: utils.META_PSEUDOPREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1002", SetupTime: setupTime, AnswerTime: aTime, Usage: time.Duration(5) * time.Second, ExtraFields: make(map[string]string), Cost: -1} diff --git a/sessionmanager/kamevent_test.go b/sessionmanager/kamevent_test.go index 812d02d6b..48d693b5d 100644 --- a/sessionmanager/kamevent_test.go +++ b/sessionmanager/kamevent_test.go @@ -26,7 +26,7 @@ import ( ) var kamEv = KamEvent{KAM_TR_INDEX: "29223", KAM_TR_LABEL: "698469260", "callid": "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", "from_tag": "eb082607", "to_tag": "4ea9687f", "cgr_account": "dan", - "cgr_reqtype": "prepaid", "cgr_subject": "dan", "cgr_destination": "+4986517174963", "cgr_tenant": "itsyscom.com", + "cgr_reqtype": utils.META_PREPAID, "cgr_subject": "dan", "cgr_destination": "+4986517174963", "cgr_tenant": "itsyscom.com", "cgr_duration": "20", "extra1": "val1", "extra2": "val2"} func TestKamailioEventInterface(t *testing.T) { @@ -38,13 +38,13 @@ func TestNewKamEvent(t *testing.T) { "callid":"46c01a5c249b469e76333fc6bfa87f6a@0:0:0:0:0:0:0:0", "from_tag":"bf71ad59", "to_tag":"7351fecf", - "cgr_reqtype":"postpaid", + "cgr_reqtype":"*postpaid", "cgr_account":"1001", "cgr_destination":"1002", "cgr_answertime":"1419839310", "cgr_duration":"3"}` eKamEv := KamEvent{"event": "CGR_CALL_END", "callid": "46c01a5c249b469e76333fc6bfa87f6a@0:0:0:0:0:0:0:0", "from_tag": "bf71ad59", "to_tag": "7351fecf", - "cgr_reqtype": "postpaid", "cgr_account": "1001", "cgr_destination": "1002", "cgr_answertime": "1419839310", "cgr_duration": "3"} + "cgr_reqtype": utils.META_POSTPAID, "cgr_account": "1001", "cgr_destination": "1002", "cgr_answertime": "1419839310", "cgr_duration": "3"} if kamEv, err := NewKamEvent([]byte(evStr)); err != nil { t.Error(err) } else if !reflect.DeepEqual(eKamEv, kamEv) { @@ -62,7 +62,7 @@ func TestKevAsKamAuthReply(t *testing.T) { } func TestKevMissingParameter(t *testing.T) { - kamEv := KamEvent{"event": "CGR_AUTH_REQUEST", "tr_index": "36045", "tr_label": "612369399", "cgr_reqtype": "postpaid", + kamEv := KamEvent{"event": "CGR_AUTH_REQUEST", "tr_index": "36045", "tr_label": "612369399", "cgr_reqtype": utils.META_POSTPAID, "cgr_account": "1001", "cgr_destination": "1002"} if !kamEv.MissingParameter() { t.Error("Failed detecting missing parameters") @@ -76,7 +76,7 @@ func TestKevMissingParameter(t *testing.T) { t.Error("Failed detecting missing parameters") } kamEv = KamEvent{"event": "CGR_CALL_START", "callid": "9d28ec3ee068babdfe036623f42c0969@0:0:0:0:0:0:0:0", "from_tag": "3131b566", - "cgr_reqtype": "postpaid", "cgr_account": "1001", "cgr_destination": "1002"} + "cgr_reqtype": utils.META_POSTPAID, "cgr_account": "1001", "cgr_destination": "1002"} if !kamEv.MissingParameter() { t.Error("Failed detecting missing parameters") } diff --git a/sessionmanager/osipsevent_test.go b/sessionmanager/osipsevent_test.go index 63e07eec0..72f068f3c 100644 --- a/sessionmanager/osipsevent_test.go +++ b/sessionmanager/osipsevent_test.go @@ -32,7 +32,7 @@ import ( var addr, _ = net.ResolveUDPAddr("udp", "172.16.254.77:42574") var osipsEv = &OsipsEvent{osipsEvent: &osipsdagram.OsipsEvent{Name: "E_ACC_CDR", AttrValues: map[string]string{"to_tag": "4ea9687f", "cgr_account": "dan", "setuptime": "7", "created": "1406370492", "method": "INVITE", "callid": "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", - "sip_reason": "OK", "time": "1406370499", "cgr_reqtype": "prepaid", "cgr_subject": "dan", "cgr_destination": "+4986517174963", "cgr_tenant": "itsyscom.com", "sip_code": "200", + "sip_reason": "OK", "time": "1406370499", "cgr_reqtype": utils.META_PREPAID, "cgr_subject": "dan", "cgr_destination": "+4986517174963", "cgr_tenant": "itsyscom.com", "sip_code": "200", "duration": "20", "from_tag": "eb082607", "extra1": "val1", "extra2": "val2"}, OriginatorAddress: addr}} func TestOsipsEventInterface(t *testing.T) { @@ -86,7 +86,7 @@ func TestOsipsEventGetValues(t *testing.T) { osipsEv.GetCallDestNr(utils.META_DEFAULT) != "+4986517174963" || osipsEv.GetCategory(utils.META_DEFAULT) != cfg.DefaultCategory || osipsEv.GetTenant(utils.META_DEFAULT) != "itsyscom.com" || - osipsEv.GetReqType(utils.META_DEFAULT) != "prepaid" || + osipsEv.GetReqType(utils.META_DEFAULT) != utils.META_PREPAID || !setupTime.Equal(eSetupTime) || !answerTime.Equal(eAnswerTime) || !endTime.Equal(eAnswerTime.Add(dur)) || @@ -102,7 +102,7 @@ func TestOsipsEventGetValues(t *testing.T) { osipsEv.GetCallDestNr(utils.META_DEFAULT) != "+4986517174963", osipsEv.GetCategory(utils.META_DEFAULT) != cfg.DefaultCategory, osipsEv.GetTenant(utils.META_DEFAULT) != "itsyscom.com", - osipsEv.GetReqType(utils.META_DEFAULT) != "prepaid", + osipsEv.GetReqType(utils.META_DEFAULT) != utils.META_PREPAID, !setupTime.Equal(time.Date(2014, 7, 26, 12, 28, 12, 0, time.UTC)), !answerTime.Equal(time.Date(2014, 7, 26, 12, 28, 19, 0, time.Local)), !endTime.Equal(time.Date(2014, 7, 26, 12, 28, 39, 0, time.Local)), @@ -118,7 +118,7 @@ func TestOsipsEventMissingParameter(t *testing.T) { } osipsEv2 := &OsipsEvent{osipsEvent: &osipsdagram.OsipsEvent{Name: "E_ACC_CDR", AttrValues: map[string]string{"to_tag": "4ea9687f", "cgr_account": "dan", "setuptime": "7", "created": "1406370492", "method": "INVITE", "callid": "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", - "sip_reason": "OK", "time": "1406370499", "cgr_reqtype": "prepaid", "cgr_subject": "dan", "cgr_tenant": "itsyscom.com", "sip_code": "200", + "sip_reason": "OK", "time": "1406370499", "cgr_reqtype": utils.META_PREPAID, "cgr_subject": "dan", "cgr_tenant": "itsyscom.com", "sip_code": "200", "duration": "20", "from_tag": "eb082607"}}} if !osipsEv2.MissingParameter() { t.Error("Failed to detect missing parameter.") @@ -129,7 +129,7 @@ func TestOsipsEventAsStoredCdr(t *testing.T) { setupTime, _ := utils.ParseTimeDetectLayout("1406370492") answerTime, _ := utils.ParseTimeDetectLayout("1406370499") eStoredCdr := &utils.StoredCdr{CgrId: utils.Sha1("ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ;eb082607;4ea9687f", setupTime.UTC().String()), - TOR: utils.VOICE, AccId: "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ;eb082607;4ea9687f", CdrHost: "172.16.254.77", CdrSource: "OSIPS_E_ACC_CDR", ReqType: "prepaid", + TOR: utils.VOICE, AccId: "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ;eb082607;4ea9687f", CdrHost: "172.16.254.77", CdrSource: "OSIPS_E_ACC_CDR", ReqType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "itsyscom.com", Category: "call", Account: "dan", Subject: "dan", Destination: "+4986517174963", SetupTime: setupTime, AnswerTime: answerTime, Usage: time.Duration(20) * time.Second, ExtraFields: map[string]string{"extra1": "val1", "extra2": "val2"}, Cost: -1} diff --git a/utils/apitpdata_test.go b/utils/apitpdata_test.go index a3a89b9cc..d269d9b99 100644 --- a/utils/apitpdata_test.go +++ b/utils/apitpdata_test.go @@ -281,7 +281,7 @@ func TestTPCdrStatsAsExportSlice(t *testing.T) { TOR: "*voice", CdrHost: "87.139.12.167", CdrSource: "FS_JSON", - ReqType: "rated", + ReqType: META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", @@ -302,7 +302,7 @@ func TestTPCdrStatsAsExportSlice(t *testing.T) { TOR: "*voice", CdrHost: "87.139.12.167", CdrSource: "FS_JSON", - ReqType: "rated", + ReqType: META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", @@ -318,9 +318,9 @@ func TestTPCdrStatsAsExportSlice(t *testing.T) { }, } expectedSlc := [][]string{ - []string{"CDRST1", "5", "60m", "ASR;ACD", "2014-07-29T15:00:00Z;2014-07-29T16:00:00Z", "*voice", "87.139.12.167", "FS_JSON", "rated", "*out", "cgrates.org", "call", "dan", "dan", "49", "5m;10m", + []string{"CDRST1", "5", "60m", "ASR;ACD", "2014-07-29T15:00:00Z;2014-07-29T16:00:00Z", "*voice", "87.139.12.167", "FS_JSON", META_RATED, "*out", "cgrates.org", "call", "dan", "dan", "49", "5m;10m", "default", "rif", "rif", "0;2", "STANDARD_TRIGGERS"}, - []string{"CDRST1", "5", "60m", "ASR", "2014-07-29T15:00:00Z;2014-07-29T16:00:00Z", "*voice", "87.139.12.167", "FS_JSON", "rated", "*out", "cgrates.org", "call", "dan", "dan", "49", "5m;10m", + []string{"CDRST1", "5", "60m", "ASR", "2014-07-29T15:00:00Z;2014-07-29T16:00:00Z", "*voice", "87.139.12.167", "FS_JSON", META_RATED, "*out", "cgrates.org", "call", "dan", "dan", "49", "5m;10m", "default", "dan", "dan", "0;2", "STANDARD_TRIGGERS"}, } if slc := cdrStats.AsExportSlice(); !reflect.DeepEqual(expectedSlc, slc) { diff --git a/utils/cgrcdr_test.go b/utils/cgrcdr_test.go index 83fca9c4d..35dfea533 100644 --- a/utils/cgrcdr_test.go +++ b/utils/cgrcdr_test.go @@ -33,7 +33,7 @@ func TestCgrCdrInterfaces(t *testing.T) { } func TestCgrCdrAsStoredCdr(t *testing.T) { - cgrCdr := CgrCdr{TOR: VOICE, ACCID: "dsafdsaf", CDRHOST: "192.168.1.1", CDRSOURCE: "internal_test", REQTYPE: "rated", DIRECTION: "*out", TENANT: "cgrates.org", CATEGORY: "call", + cgrCdr := CgrCdr{TOR: VOICE, ACCID: "dsafdsaf", CDRHOST: "192.168.1.1", CDRSOURCE: "internal_test", REQTYPE: META_RATED, DIRECTION: "*out", TENANT: "cgrates.org", CATEGORY: "call", ACCOUNT: "1001", SUBJECT: "1001", DESTINATION: "1002", SETUP_TIME: "2013-11-07T08:42:20Z", ANSWER_TIME: "2013-11-07T08:42:26Z", USAGE: "10", "field_extr1": "val_extr1", "fieldextr2": "valextr2"} setupTime, _ := ParseTimeDetectLayout(cgrCdr["setup_time"]) diff --git a/utils/consts.go b/utils/consts.go index c03afe400..10db745ea 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -11,9 +11,13 @@ const ( FSCDR_HTTP_JSON = "freeswitch_http_json" NOT_IMPLEMENTED = "not implemented" PREPAID = "prepaid" + META_PREPAID = "*prepaid" POSTPAID = "postpaid" + META_POSTPAID = "*postpaid" PSEUDOPREPAID = "pseudoprepaid" + META_PSEUDOPREPAID = "*pseudoprepaid" RATED = "rated" + META_RATED = "*rated" ERR_NOT_IMPLEMENTED = "NOT_IMPLEMENTED" ERR_SERVER_ERROR = "SERVER_ERROR" ERR_NOT_FOUND = "NOT_FOUND" diff --git a/utils/storedcdr_test.go b/utils/storedcdr_test.go index 02c81f3a7..da99e021d 100644 --- a/utils/storedcdr_test.go +++ b/utils/storedcdr_test.go @@ -31,7 +31,7 @@ func TestStoredCdrInterfaces(t *testing.T) { } func TestFieldAsString(t *testing.T) { - cdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + cdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: 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), MediationRunId: DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", } @@ -85,7 +85,7 @@ func TestFieldAsString(t *testing.T) { func TestPassesFieldFilter(t *testing.T) { cdr := &StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: 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), MediationRunId: DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, @@ -245,7 +245,7 @@ func TestFormatUsage(t *testing.T) { func TestStoredCdrAsHttpForm(t *testing.T) { storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrSource: UNIT_TEST, ReqType: 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), MediationRunId: DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, RatedSubject: "dans", Cost: 1.01, } @@ -262,8 +262,8 @@ func TestStoredCdrAsHttpForm(t *testing.T) { if cdrForm.Get(CDRSOURCE) != UNIT_TEST { t.Errorf("Expected: %s, received: %s", UNIT_TEST, cdrForm.Get(CDRSOURCE)) } - if cdrForm.Get(REQTYPE) != "rated" { - t.Errorf("Expected: %s, received: %s", "rated", cdrForm.Get(REQTYPE)) + if cdrForm.Get(REQTYPE) != META_RATED { + t.Errorf("Expected: %s, received: %s", META_RATED, cdrForm.Get(REQTYPE)) } if cdrForm.Get(DIRECTION) != "*out" { t.Errorf("Expected: %s, received: %s", "*out", cdrForm.Get(DIRECTION)) @@ -302,7 +302,7 @@ func TestStoredCdrAsHttpForm(t *testing.T) { func TestStoredCdrForkCdr(t *testing.T) { storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrSource: UNIT_TEST, ReqType: 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), MediationRunId: DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}, Cost: 1.01, RatedSubject: "dans", } @@ -312,7 +312,7 @@ func TestStoredCdrForkCdr(t *testing.T) { if err != nil { t.Error("Unexpected error received", err) } - expctSplRatedCdr := &StoredCdr{CgrId: storCdr.CgrId, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: "rated", + expctSplRatedCdr := &StoredCdr{CgrId: storCdr.CgrId, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: 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, ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}, MediationRunId: "sample_run1", Cost: -1} @@ -323,11 +323,11 @@ func TestStoredCdrForkCdr(t *testing.T) { func TestStoredCdrForkCdrStaticVals(t *testing.T) { storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrSource: UNIT_TEST, ReqType: 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), MediationRunId: DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, } - rsrStPostpaid, _ := NewRSRField("^postpaid") + rsrStPostpaid, _ := NewRSRField("^" + META_POSTPAID) rsrStIn, _ := NewRSRField("^*in") rsrStCgr, _ := NewRSRField("^cgrates.com") rsrStPC, _ := NewRSRField("^premium_call") @@ -342,7 +342,7 @@ func TestStoredCdrForkCdrStaticVals(t *testing.T) { if err != nil { t.Error("Unexpected error received", err) } - expctRatedCdr2 := &StoredCdr{CgrId: storCdr.CgrId, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: "postpaid", + expctRatedCdr2 := &StoredCdr{CgrId: storCdr.CgrId, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: META_POSTPAID, Direction: "*in", 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, @@ -360,11 +360,11 @@ func TestStoredCdrForkCdrStaticVals(t *testing.T) { func TestStoredCdrForkCdrFromMetaDefaults(t *testing.T) { storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrSource: UNIT_TEST, ReqType: 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), MediationRunId: DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, } - expctCdr := &StoredCdr{CgrId: storCdr.CgrId, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: "rated", + expctCdr := &StoredCdr{CgrId: storCdr.CgrId, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: 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, @@ -390,12 +390,12 @@ func TestStoredCdrForkCdrFromMetaDefaults(t *testing.T) { func TestStoredCdrAsCgrExtCdr(t *testing.T) { storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrSource: UNIT_TEST, ReqType: 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), MediationRunId: DEFAULT_RUNID, Usage: time.Duration(10), ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", } expectOutCdr := &CgrExtCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", + CdrSource: UNIT_TEST, ReqType: META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", MediationRunId: DEFAULT_RUNID, Usage: "0.00000001", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", } @@ -406,7 +406,7 @@ func TestStoredCdrAsCgrExtCdr(t *testing.T) { func TestStoredCdrEventFields(t *testing.T) { cdr := &StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", - CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dans", + CdrHost: "192.168.1.1", CdrSource: "test", ReqType: 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), MediationRunId: DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dan"} @@ -443,7 +443,7 @@ func TestStoredCdrEventFields(t *testing.T) { if res := cdr.GetTenant(META_DEFAULT); res != "cgrates.org" { t.Error("Received: ", res) } - if res := cdr.GetReqType(META_DEFAULT); res != "rated" { + if res := cdr.GetReqType(META_DEFAULT); res != META_RATED { t.Error("Received: ", res) } if st, _ := cdr.GetSetupTime(META_DEFAULT); st != time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC) { diff --git a/utils/utils_local_test.go b/utils/utils_local_test.go index d088e8616..7a0b28b79 100644 --- a/utils/utils_local_test.go +++ b/utils/utils_local_test.go @@ -32,7 +32,7 @@ func TestHttpJsonPost(t *testing.T) { return } cdrOut := &CgrExtCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", - CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "account1", Subject: "tgooiscs0014", Destination: "1002", + CdrSource: UNIT_TEST, ReqType: META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "account1", Subject: "tgooiscs0014", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String(), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String(), MediationRunId: DEFAULT_RUNID, Usage: "0.00000001", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, } diff --git a/utils/utils_test.go b/utils/utils_test.go index e18fd3e5d..077d96875 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -274,7 +274,7 @@ func TestMissingStructFieldsCorrect(t *testing.T) { Account string Type string ActionTimingsId string - }{"bevoip.eu", "OUT", "danconns0001", "prepaid", "mama"} + }{"bevoip.eu", "OUT", "danconns0001", META_PREPAID, "mama"} if missing := MissingStructFields(&attr, []string{"Tenant", "Direction", "Account", "Type", "ActionTimingsId"}); len(missing) != 0 { t.Error("Found missing field on correct struct", missing) @@ -288,7 +288,7 @@ func TestMissingStructFieldsIncorrect(t *testing.T) { Account string Type string ActionTimingsId string - }{Tenant: "bevoip.eu", Direction: "OUT", Account: "danconns0001", Type: "prepaid"} + }{Tenant: "bevoip.eu", Direction: "OUT", Account: "danconns0001", Type: META_PREPAID} if missing := MissingStructFields(&attr, []string{"Tenant", "Direction", "Account", "Type", "ActionTimingsId"}); len(missing) != 1 || missing[0] != "ActionTimingsId" { t.Error("Found missing field on correct struct", missing)