diff --git a/agents/dmtagent_it_test.go b/agents/dmtagent_it_test.go
index 6353203d0..2e6d8f707 100644
--- a/agents/dmtagent_it_test.go
+++ b/agents/dmtagent_it_test.go
@@ -140,10 +140,10 @@ func TestDmtAgentCCRAsSMGenericEvent(t *testing.T) {
if ccr.diamMessage, err = ccr.AsDiameterMessage(); err != nil {
t.Error(err)
}
- eSMGE := sessionmanager.SMGenericEvent{"EventName": DIAMETER_CCR, "AccId": "routinga;1442095190;1476802709",
+ eSMGE := sessionmanager.SMGenericEvent{"EventName": DIAMETER_CCR, "OriginID": "routinga;1442095190;1476802709",
"Account": "*users", "AnswerTime": "2015-11-23 12:22:24 +0000 UTC", "Category": "call",
- "Destination": "4986517174964", "Direction": "*out", "ReqType": "*users", "SetupTime": "2015-11-23 12:22:24 +0000 UTC",
- "Subject": "*users", "SubscriberId": "4986517174963", "TOR": "*voice", "Tenant": "*users", "Usage": "300"}
+ "Destination": "4986517174964", "Direction": "*out", "RequestType": "*users", "SetupTime": "2015-11-23 12:22:24 +0000 UTC",
+ "Subject": "*users", "SubscriberId": "4986517174963", "ToR": "*voice", "Tenant": "*users", "Usage": "300"}
if smge, err := ccr.AsSMGenericEvent(cfgDefaults.DiameterAgentCfg().RequestProcessors[0].CCRFields); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eSMGE, smge) {
@@ -186,11 +186,11 @@ func TestDmtAgentSendCCRInit(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- cdr := &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+ cdr := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1004", Supplier: "SUPPL1",
- SetupTime: time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2015, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(0) * time.Second, Pdd: time.Duration(7) * time.Second, ExtraFields: map[string]string{"Service-Context-Id": "voice@huawei.com"},
+ SetupTime: time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2015, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(0) * time.Second, PDD: time.Duration(7) * time.Second, ExtraFields: map[string]string{"Service-Context-Id": "voice@huawei.com"},
}
ccr := storedCdrToCCR(cdr, "UNIT_TEST", daCfg.DiameterAgentCfg().OriginRealm, daCfg.DiameterAgentCfg().VendorId,
daCfg.DiameterAgentCfg().ProductName, utils.DIAMETER_FIRMWARE_REVISION, daCfg.DiameterAgentCfg().DebitInterval, false)
@@ -225,11 +225,11 @@ func TestDmtAgentSendCCRUpdate(t *testing.T) {
if !*testIntegration {
return
}
- cdr := &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+ cdr := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1004", Supplier: "SUPPL1",
- SetupTime: time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2015, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(300) * time.Second, Pdd: time.Duration(7) * time.Second, ExtraFields: map[string]string{"Service-Context-Id": "voice@huawei.com"},
+ SetupTime: time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2015, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(300) * time.Second, PDD: time.Duration(7) * time.Second, ExtraFields: map[string]string{"Service-Context-Id": "voice@huawei.com"},
}
ccr := storedCdrToCCR(cdr, "UNIT_TEST", daCfg.DiameterAgentCfg().OriginRealm, daCfg.DiameterAgentCfg().VendorId,
daCfg.DiameterAgentCfg().ProductName, utils.DIAMETER_FIRMWARE_REVISION, daCfg.DiameterAgentCfg().DebitInterval, false)
@@ -264,11 +264,11 @@ func TestDmtAgentSendCCRUpdate2(t *testing.T) {
if !*testIntegration {
return
}
- cdr := &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+ cdr := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1004", Supplier: "SUPPL1",
- SetupTime: time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2015, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(600) * time.Second, Pdd: time.Duration(7) * time.Second, ExtraFields: map[string]string{"Service-Context-Id": "voice@huawei.com"},
+ SetupTime: time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2015, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(600) * time.Second, PDD: time.Duration(7) * time.Second, ExtraFields: map[string]string{"Service-Context-Id": "voice@huawei.com"},
}
ccr := storedCdrToCCR(cdr, "UNIT_TEST", daCfg.DiameterAgentCfg().OriginRealm, daCfg.DiameterAgentCfg().VendorId,
daCfg.DiameterAgentCfg().ProductName, utils.DIAMETER_FIRMWARE_REVISION, daCfg.DiameterAgentCfg().DebitInterval, false)
@@ -302,11 +302,11 @@ func TestDmtAgentSendCCRTerminate(t *testing.T) {
if !*testIntegration {
return
}
- cdr := &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+ cdr := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1004", Supplier: "SUPPL1",
- SetupTime: time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2015, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(610) * time.Second, Pdd: time.Duration(7) * time.Second, ExtraFields: map[string]string{"Service-Context-Id": "voice@huawei.com"},
+ SetupTime: time.Date(2015, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2015, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(610) * time.Second, PDD: time.Duration(7) * time.Second, ExtraFields: map[string]string{"Service-Context-Id": "voice@huawei.com"},
}
ccr := storedCdrToCCR(cdr, "UNIT_TEST", daCfg.DiameterAgentCfg().OriginRealm, daCfg.DiameterAgentCfg().VendorId,
daCfg.DiameterAgentCfg().ProductName, utils.DIAMETER_FIRMWARE_REVISION, daCfg.DiameterAgentCfg().DebitInterval, true)
@@ -340,8 +340,8 @@ func TestDmtAgentCdrs(t *testing.T) {
if !*testIntegration {
return
}
- var cdrs []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}}
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}}
if err := apierRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
diff --git a/agents/libdmt.go b/agents/libdmt.go
index 9129872dc..642a15024 100644
--- a/agents/libdmt.go
+++ b/agents/libdmt.go
@@ -130,11 +130,11 @@ func usageFromCCR(reqType, reqNr, reqCCTime, usedCCTime int, debitIterval time.D
}
// Utility function to convert from StoredCdr to CCR struct
-func storedCdrToCCR(cdr *engine.StoredCdr, originHost, originRealm string, vendorId int, productName string,
+func storedCdrToCCR(cdr *engine.CDR, originHost, originRealm string, vendorId int, productName string,
firmwareRev int, debitInterval time.Duration, callEnded bool) *CCR {
//sid := "session;" + strconv.Itoa(int(rand.Uint32()))
reqType, reqNr, reqCCTime, usedCCTime := disectUsageForCCR(cdr.Usage, debitInterval, callEnded)
- ccr := &CCR{SessionId: cdr.CgrId, OriginHost: originHost, OriginRealm: originRealm, DestinationHost: originHost, DestinationRealm: originRealm,
+ ccr := &CCR{SessionId: cdr.CGRID, OriginHost: originHost, OriginRealm: originRealm, DestinationHost: originHost, DestinationRealm: originRealm,
AuthApplicationId: 4, ServiceContextId: cdr.ExtraFields["Service-Context-Id"], CCRequestType: reqType, CCRequestNumber: reqNr, EventTimestamp: cdr.AnswerTime,
ServiceIdentifier: 0}
ccr.SubscriptionId = make([]struct {
@@ -152,7 +152,7 @@ func storedCdrToCCR(cdr *engine.StoredCdr, originHost, originRealm string, vendo
ccr.ServiceInformation.INInformation.CallingVlrNumber = cdr.ExtraFields["Calling-Vlr-Number"]
ccr.ServiceInformation.INInformation.CallingCellIDOrSAI = cdr.ExtraFields["Calling-CellID-Or-SAI"]
ccr.ServiceInformation.INInformation.BearerCapability = cdr.ExtraFields["Bearer-Capability"]
- ccr.ServiceInformation.INInformation.CallReferenceNumber = cdr.CgrId
+ ccr.ServiceInformation.INInformation.CallReferenceNumber = cdr.CGRID
ccr.ServiceInformation.INInformation.TimeZone = 0
ccr.ServiceInformation.INInformation.SSPTime = cdr.ExtraFields["SSP-Time"]
return ccr
diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go
index 794445581..36b4fc86e 100644
--- a/apier/v1/apier_local_test.go
+++ b/apier/v1/apier_local_test.go
@@ -79,7 +79,7 @@ func TestApierCreateDirs(t *testing.T) {
if !*testLocal {
return
}
- for _, pathDir := range []string{cfg.CdreProfiles[utils.META_DEFAULT].ExportDir, "/var/log/cgrates/cdrc/in", "/var/log/cgrates/cdrc/out", cfg.HistoryDir} {
+ for _, pathDir := range []string{cfg.CdreProfiles[utils.META_DEFAULT].ExportFolder, "/var/log/cgrates/cdrc/in", "/var/log/cgrates/cdrc/out", cfg.HistoryDir} {
if err := os.RemoveAll(pathDir); err != nil {
t.Fatal("Error removing folder: ", pathDir, err)
@@ -312,7 +312,7 @@ func TestApierTPRate(t *testing.T) {
if err := rater.Call("ApierV1.GetTPRateIds", AttrGetTPRateIds{rt.TPid, utils.Paginator{}}, &rplyRtIds); err != nil {
t.Error("Calling ApierV1.GetTPRateIds, got error: ", err.Error())
} else if !reflect.DeepEqual(expectedRtIds, rplyRtIds) {
- t.Errorf("Calling ApierV1.GetTPDestinationIds expected: %v, received: %v", expectedRtIds, rplyRtIds)
+ t.Errorf("Calling ApierV1.GetTPDestinationIDs expected: %v, received: %v", expectedRtIds, rplyRtIds)
}
}
@@ -1382,7 +1382,7 @@ func TestApierExportCdrsToFile(t *testing.T) {
req.CdrFormat = &dryRun
tm1, _ := utils.ParseTimeDetectLayout("2013-11-07T08:42:22Z")
tm2, _ := utils.ParseTimeDetectLayout("2013-11-07T08:42:23Z")
- expectReply := &utils.ExportedFileCdrs{ExportedFilePath: utils.CDRE_DRYRUN, TotalRecords: 2, ExportedCgrIds: []string{utils.Sha1("dsafdsaf", tm1.String()),
+ expectReply := &utils.ExportedFileCdrs{ExportedFilePath: utils.CDRE_DRYRUN, TotalRecords: 2, ExportedCGRIDs: []string{utils.Sha1("dsafdsaf", tm1.String()),
utils.Sha1("adsafdsaf", tm2.String())}}
if err := rater.Call("ApierV1.ExportCdrsToFile", req, &reply); err != nil {
t.Error(err.Error())
@@ -1410,8 +1410,8 @@ func TestApierLocalGetCdrs(t *testing.T) {
if !*testLocal {
return
}
- var reply []*engine.ExternalCdr
- req := utils.AttrGetCdrs{}
+ var reply []*engine.ExternalCDR
+ req := utils.AttrGetCdrs{MediationRunIds: []string{utils.MetaRaw}}
if err := rater.Call("ApierV1.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
@@ -1424,18 +1424,19 @@ func TestApierLocalProcessCdr(t *testing.T) {
return
}
var reply string
- cdr := engine.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: 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",
+ cdr := engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001",
+ Destination: "1002",
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
if err := rater.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
t.Error("Unexpected reply received: ", reply)
}
- var cdrs []*engine.ExternalCdr
- req := utils.AttrGetCdrs{}
+ var cdrs []*engine.ExternalCDR
+ req := utils.AttrGetCdrs{MediationRunIds: []string{utils.MetaRaw}}
if err := rater.Call("ApierV1.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 3 {
@@ -1448,9 +1449,9 @@ func TestApierLocalSetDC(t *testing.T) {
return
}
dcs1 := []*utils.DerivedCharger{
- &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra1", RequestTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra2", RequestTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
}
attrs := AttrSetDerivedChargers{Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: dcs1, Overwrite: true}
@@ -1467,11 +1468,11 @@ func TestApierLocalGetDC(t *testing.T) {
return
}
attrs := utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "dan", Subject: "dan"}
- eDcs := utils.DerivedChargers{DestinationIds: utils.NewStringMap(),
+ eDcs := utils.DerivedChargers{DestinationIDs: utils.NewStringMap(),
Chargers: []*utils.DerivedCharger{
- &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra1", RequestTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra2", RequestTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
}}
var dcs utils.DerivedChargers
diff --git a/apier/v1/auth.go b/apier/v1/auth.go
index 6d0367487..f462a14d7 100644
--- a/apier/v1/auth.go
+++ b/apier/v1/auth.go
@@ -32,11 +32,11 @@ func (self *ApierV1) GetMaxUsage(usageRecord engine.UsageRecord, maxUsage *float
if err != nil {
return utils.NewErrServerError(err)
}
- if usageRecord.TOR == "" {
- usageRecord.TOR = utils.VOICE
+ if usageRecord.ToR == "" {
+ usageRecord.ToR = utils.VOICE
}
- if usageRecord.ReqType == "" {
- usageRecord.ReqType = self.Config.DefaultReqType
+ if usageRecord.RequestType == "" {
+ usageRecord.RequestType = self.Config.DefaultReqType
}
if usageRecord.Direction == "" {
usageRecord.Direction = utils.OUT
diff --git a/apier/v1/cdre.go b/apier/v1/cdre.go
index 7335f4b28..0079a7ddc 100644
--- a/apier/v1/cdre.go
+++ b/apier/v1/cdre.go
@@ -120,7 +120,7 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
return fmt.Errorf("%s:FieldSeparator:%s", utils.ErrServerError.Error(), "Invalid")
}
}
- exportDir := exportTemplate.ExportDir
+ exportDir := exportTemplate.ExportFolder
if attr.ExportDir != nil && len(*attr.ExportDir) != 0 {
exportDir = *attr.ExportDir
}
@@ -140,7 +140,7 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
if attr.DataUsageMultiplyFactor != nil && *attr.DataUsageMultiplyFactor != 0.0 {
dataUsageMultiplyFactor = *attr.DataUsageMultiplyFactor
}
- smsUsageMultiplyFactor := exportTemplate.SmsUsageMultiplyFactor
+ smsUsageMultiplyFactor := exportTemplate.SMSUsageMultiplyFactor
if attr.SmsUsageMultiplyFactor != nil && *attr.SmsUsageMultiplyFactor != 0.0 {
smsUsageMultiplyFactor = *attr.SmsUsageMultiplyFactor
}
@@ -160,7 +160,7 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
if attr.RoundDecimals != nil {
roundingDecimals = *attr.RoundDecimals
}
- maskDestId := exportTemplate.MaskDestId
+ maskDestId := exportTemplate.MaskDestinationID
if attr.MaskDestinationId != nil && len(*attr.MaskDestinationId) != 0 {
maskDestId = *attr.MaskDestinationId
}
@@ -168,11 +168,11 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
if attr.MaskLength != nil {
maskLen = *attr.MaskLength
}
- cdrsFltr, err := attr.AsCdrsFilter(self.Config.DefaultTimezone)
+ cdrsFltr, err := attr.AsCDRsFilter(self.Config.DefaultTimezone)
if err != nil {
return utils.NewErrServerError(err)
}
- cdrs, _, err := self.CdrDb.GetStoredCdrs(cdrsFltr)
+ cdrs, _, err := self.CdrDb.GetCDRs(cdrsFltr)
if err != nil {
return err
} else if len(cdrs) == 0 {
@@ -204,7 +204,7 @@ func (self *ApierV1) RemCdrs(attrs utils.AttrRemCdrs, reply *string) error {
if len(attrs.CgrIds) == 0 {
return fmt.Errorf("%s:CgrIds", utils.ErrMandatoryIeMissing.Error())
}
- if err := self.CdrDb.RemStoredCdrs(attrs.CgrIds); err != nil {
+ if err := self.CdrDb.RemCDRs(attrs.CgrIds); err != nil {
return utils.NewErrServerError(err)
}
*reply = "OK"
diff --git a/apier/v1/cdrs.go b/apier/v1/cdrs.go
index 909766a0a..c442826ee 100644
--- a/apier/v1/cdrs.go
+++ b/apier/v1/cdrs.go
@@ -31,7 +31,7 @@ func (apier *ApierV1) GetCallCostLog(attrs utils.AttrGetCallCost, reply *engine.
if attrs.RunId == "" {
attrs.RunId = utils.META_DEFAULT
}
- if cc, err := apier.CdrDb.GetCallCostLog(attrs.CgrId, "", attrs.RunId); err != nil {
+ if cc, err := apier.CdrDb.GetCallCostLog(attrs.CgrId, attrs.RunId); err != nil {
return utils.NewErrServerError(err)
} else if cc == nil {
return utils.ErrNotFound
@@ -42,18 +42,18 @@ func (apier *ApierV1) GetCallCostLog(attrs utils.AttrGetCallCost, reply *engine.
}
// Retrieves CDRs based on the filters
-func (apier *ApierV1) GetCdrs(attrs utils.AttrGetCdrs, reply *[]*engine.ExternalCdr) error {
- cdrsFltr, err := attrs.AsCdrsFilter(apier.Config.DefaultTimezone)
+func (apier *ApierV1) GetCdrs(attrs utils.AttrGetCdrs, reply *[]*engine.ExternalCDR) error {
+ cdrsFltr, err := attrs.AsCDRsFilter(apier.Config.DefaultTimezone)
if err != nil {
return utils.NewErrServerError(err)
}
- if cdrs, _, err := apier.CdrDb.GetStoredCdrs(cdrsFltr); err != nil {
+ if cdrs, _, err := apier.CdrDb.GetCDRs(cdrsFltr); err != nil {
return utils.NewErrServerError(err)
} else if len(cdrs) == 0 {
- *reply = make([]*engine.ExternalCdr, 0)
+ *reply = make([]*engine.ExternalCDR, 0)
} else {
for _, cdr := range cdrs {
- *reply = append(*reply, cdr.AsExternalCdr())
+ *reply = append(*reply, cdr.AsExternalCDR())
}
}
return nil
diff --git a/apier/v1/cdrstatsv1_local_test.go b/apier/v1/cdrstatsv1_local_test.go
index 4a4d6d24c..b9a2b7354 100644
--- a/apier/v1/cdrstatsv1_local_test.go
+++ b/apier/v1/cdrstatsv1_local_test.go
@@ -111,31 +111,34 @@ func TestCDRStatsLclPostCdrs(t *testing.T) {
return
}
httpClient := new(http.Client)
- storedCdrs := []*engine.StoredCdr{
- &engine.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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ storedCdrs := []*engine.CDR{
+ &engine.CDR{CGRID: utils.Sha1("dsafdsafa", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "+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",
+ AnswerTime: time.Now(), RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second,
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
},
- &engine.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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ &engine.CDR{CGRID: utils.Sha1("dsafdsafb", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "+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",
+ AnswerTime: time.Now(), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(5) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
},
- &engine.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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ &engine.CDR{CGRID: utils.Sha1("dsafdsafc", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "+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",
+ RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(30) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
},
- &engine.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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ &engine.CDR{CGRID: utils.Sha1("dsafdsafd", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "+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",
+ RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(0) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
},
}
for _, storedCdr := range storedCdrs {
diff --git a/apier/v1/cdrsv1.go b/apier/v1/cdrsv1.go
index c0913766a..21b24ffa0 100644
--- a/apier/v1/cdrsv1.go
+++ b/apier/v1/cdrsv1.go
@@ -19,8 +19,6 @@ along with this program. If not, see
package v1
import (
- "time"
-
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/utils"
)
@@ -31,7 +29,7 @@ type CdrsV1 struct {
}
// Designed for CGR internal usage
-func (self *CdrsV1) ProcessCdr(cdr *engine.StoredCdr, reply *string) error {
+func (self *CdrsV1) ProcessCdr(cdr *engine.CDR, reply *string) error {
if err := self.CdrSrv.LocalProcessCdr(cdr); err != nil {
return utils.NewErrServerError(err)
}
@@ -40,7 +38,7 @@ func (self *CdrsV1) ProcessCdr(cdr *engine.StoredCdr, reply *string) error {
}
// Designed for external programs feeding CDRs to CGRateS
-func (self *CdrsV1) ProcessExternalCdr(cdr *engine.ExternalCdr, reply *string) error {
+func (self *CdrsV1) ProcessExternalCdr(cdr *engine.ExternalCDR, reply *string) error {
if err := self.CdrSrv.ProcessExternalCdr(cdr); err != nil {
return utils.NewErrServerError(err)
}
@@ -50,23 +48,11 @@ func (self *CdrsV1) ProcessExternalCdr(cdr *engine.ExternalCdr, reply *string) e
// Remotely start mediation with specific runid, runs asynchronously, it's status will be displayed in syslog
func (self *CdrsV1) RateCdrs(attrs utils.AttrRateCdrs, reply *string) error {
- var tStart, tEnd time.Time
- var err error
- if len(attrs.TimeStart) != 0 {
- if tStart, err = utils.ParseTimeDetectLayout(attrs.TimeStart, self.CdrSrv.Timezone()); err != nil {
- return err
- }
+ cdrsFltr, err := attrs.AsCDRsFilter(self.CdrSrv.Timezone())
+ if err != nil {
+ return utils.NewErrServerError(err)
}
- if len(attrs.TimeEnd) != 0 {
- if tEnd, err = utils.ParseTimeDetectLayout(attrs.TimeEnd, self.CdrSrv.Timezone()); err != nil {
- return err
- }
- }
- //RateCdrs(cgrIds, runIds, tors, cdrHosts, cdrSources, reqTypes, directions, tenants, categories, accounts, subjects, destPrefixes []string,
- //orderIdStart, orderIdEnd int64, timeStart, timeEnd time.Time, rerateErrors, rerateRated bool)
- if err := self.CdrSrv.RateCdrs(attrs.CgrIds, attrs.MediationRunIds, attrs.TORs, attrs.CdrHosts, attrs.CdrSources, attrs.ReqTypes, attrs.Directions,
- attrs.Tenants, attrs.Categories, attrs.Accounts, attrs.Subjects, attrs.DestinationPrefixes, attrs.RatedAccounts, attrs.RatedSubjects,
- attrs.OrderIdStart, attrs.OrderIdEnd, tStart, tEnd, attrs.RerateErrors, attrs.RerateRated, attrs.SendToStats); err != nil {
+ if err := self.CdrSrv.RateCDRs(cdrsFltr, attrs.SendToStats); err != nil {
return utils.NewErrServerError(err)
}
*reply = utils.OK
diff --git a/apier/v1/debit.go b/apier/v1/debit.go
index c049ac3f3..bd9f53209 100644
--- a/apier/v1/debit.go
+++ b/apier/v1/debit.go
@@ -32,11 +32,11 @@ func (self *ApierV1) DebitUsage(usageRecord engine.UsageRecord, reply *string) e
*reply = err.Error()
return err
}
- if usageRecord.TOR == "" {
- usageRecord.TOR = utils.VOICE
+ if usageRecord.ToR == "" {
+ usageRecord.ToR = utils.VOICE
}
- if usageRecord.ReqType == "" {
- usageRecord.ReqType = self.Config.DefaultReqType
+ if usageRecord.RequestType == "" {
+ usageRecord.RequestType = self.Config.DefaultReqType
}
if usageRecord.Direction == "" {
usageRecord.Direction = utils.OUT
diff --git a/apier/v1/derivedcharging.go b/apier/v1/derivedcharging.go
index 5e74fb00d..0c573f797 100644
--- a/apier/v1/derivedcharging.go
+++ b/apier/v1/derivedcharging.go
@@ -78,7 +78,7 @@ func (self *ApierV1) SetDerivedChargers(attrs AttrSetDerivedChargers, reply *str
}
}
dstIds := strings.Split(attrs.DestinationIds, utils.INFIELD_SEP)
- dcs := &utils.DerivedChargers{DestinationIds: utils.NewStringMap(dstIds...), Chargers: attrs.DerivedChargers}
+ dcs := &utils.DerivedChargers{DestinationIDs: utils.NewStringMap(dstIds...), Chargers: attrs.DerivedChargers}
if err := self.RatingDb.SetDerivedChargers(dcKey, dcs); err != nil {
return utils.NewErrServerError(err)
}
diff --git a/apier/v1/derivedcharging_test.go b/apier/v1/derivedcharging_test.go
index dfc2df07c..87e3d847f 100644
--- a/apier/v1/derivedcharging_test.go
+++ b/apier/v1/derivedcharging_test.go
@@ -49,9 +49,9 @@ func TestGetEmptyDC(t *testing.T) {
func TestSetDC(t *testing.T) {
dcs1 := []*utils.DerivedCharger{
- &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra1", RequestTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra2", RequestTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
}
attrs := AttrSetDerivedChargers{Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: dcs1}
@@ -65,18 +65,18 @@ func TestSetDC(t *testing.T) {
func TestGetDC(t *testing.T) {
attrs := utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "dan", Subject: "dan"}
- eDcs := utils.DerivedChargers{DestinationIds: utils.NewStringMap(),
+ eDcs := utils.DerivedChargers{DestinationIDs: utils.NewStringMap(),
Chargers: []*utils.DerivedCharger{
- &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra1", RequestTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra2", RequestTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
}}
var dcs utils.DerivedChargers
if err := apierDcT.GetDerivedChargers(attrs, &dcs); err != nil {
t.Error("Unexpected error", err.Error())
} else if !reflect.DeepEqual(dcs, eDcs) {
- t.Errorf("Expecting: %v, received: %v", eDcs.DestinationIds, dcs.DestinationIds)
+ t.Errorf("Expecting: %v, received: %v", eDcs.DestinationIDs, dcs.DestinationIDs)
}
}
diff --git a/apier/v2/cdre.go b/apier/v2/cdre.go
index dbeaee933..3bb7b0697 100644
--- a/apier/v2/cdre.go
+++ b/apier/v2/cdre.go
@@ -56,19 +56,19 @@ func (self *ApierV2) ExportCdrsToFile(attr utils.AttrExportCdrsToFile, reply *ut
return fmt.Errorf("%s:FieldSeparator:%s", utils.ErrServerError, "Invalid")
}
}
- exportDir := exportTemplate.ExportDir
- if attr.ExportDir != nil && len(*attr.ExportDir) != 0 {
- exportDir = *attr.ExportDir
+ ExportFolder := exportTemplate.ExportFolder
+ if attr.ExportFolder != nil && len(*attr.ExportFolder) != 0 {
+ ExportFolder = *attr.ExportFolder
}
- exportId := strconv.FormatInt(time.Now().Unix(), 10)
- if attr.ExportId != nil && len(*attr.ExportId) != 0 {
- exportId = *attr.ExportId
+ ExportID := strconv.FormatInt(time.Now().Unix(), 10)
+ if attr.ExportID != nil && len(*attr.ExportID) != 0 {
+ ExportID = *attr.ExportID
}
- fileName := fmt.Sprintf("cdre_%s.%s", exportId, cdrFormat)
+ fileName := fmt.Sprintf("cdre_%s.%s", ExportID, cdrFormat)
if attr.ExportFileName != nil && len(*attr.ExportFileName) != 0 {
fileName = *attr.ExportFileName
}
- filePath := path.Join(exportDir, fileName)
+ filePath := path.Join(ExportFolder, fileName)
if cdrFormat == utils.DRYRUN {
filePath = utils.DRYRUN
}
@@ -76,9 +76,9 @@ func (self *ApierV2) ExportCdrsToFile(attr utils.AttrExportCdrsToFile, reply *ut
if attr.DataUsageMultiplyFactor != nil && *attr.DataUsageMultiplyFactor != 0.0 {
dataUsageMultiplyFactor = *attr.DataUsageMultiplyFactor
}
- smsUsageMultiplyFactor := exportTemplate.SmsUsageMultiplyFactor
- if attr.SmsUsageMultiplyFactor != nil && *attr.SmsUsageMultiplyFactor != 0.0 {
- smsUsageMultiplyFactor = *attr.SmsUsageMultiplyFactor
+ SMSUsageMultiplyFactor := exportTemplate.SMSUsageMultiplyFactor
+ if attr.SMSUsageMultiplyFactor != nil && *attr.SMSUsageMultiplyFactor != 0.0 {
+ SMSUsageMultiplyFactor = *attr.SMSUsageMultiplyFactor
}
genericUsageMultiplyFactor := exportTemplate.GenericUsageMultiplyFactor
if attr.GenericUsageMultiplyFactor != nil && *attr.GenericUsageMultiplyFactor != 0.0 {
@@ -96,26 +96,26 @@ func (self *ApierV2) ExportCdrsToFile(attr utils.AttrExportCdrsToFile, reply *ut
if attr.RoundDecimals != nil {
roundingDecimals = *attr.RoundDecimals
}
- maskDestId := exportTemplate.MaskDestId
- if attr.MaskDestinationId != nil && len(*attr.MaskDestinationId) != 0 {
- maskDestId = *attr.MaskDestinationId
+ maskDestId := exportTemplate.MaskDestinationID
+ if attr.MaskDestinationID != nil && len(*attr.MaskDestinationID) != 0 {
+ maskDestId = *attr.MaskDestinationID
}
maskLen := exportTemplate.MaskLength
if attr.MaskLength != nil {
maskLen = *attr.MaskLength
}
- cdrsFltr, err := attr.RpcCdrsFilter.AsCdrsFilter(self.Config.DefaultTimezone)
+ cdrsFltr, err := attr.RPCCDRsFilter.AsCDRsFilter(self.Config.DefaultTimezone)
if err != nil {
return utils.NewErrServerError(err)
}
- cdrs, _, err := self.CdrDb.GetStoredCdrs(cdrsFltr)
+ cdrs, _, err := self.CdrDb.GetCDRs(cdrsFltr)
if err != nil {
return err
} else if len(cdrs) == 0 {
*reply = utils.ExportedFileCdrs{ExportedFilePath: ""}
return nil
}
- cdrexp, err := cdre.NewCdrExporter(cdrs, self.CdrDb, exportTemplate, cdrFormat, fieldSep, exportId, dataUsageMultiplyFactor, smsUsageMultiplyFactor, genericUsageMultiplyFactor,
+ cdrexp, err := cdre.NewCdrExporter(cdrs, self.CdrDb, exportTemplate, cdrFormat, fieldSep, ExportID, dataUsageMultiplyFactor, SMSUsageMultiplyFactor, genericUsageMultiplyFactor,
costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen, self.Config.HttpSkipTlsVerify, self.Config.DefaultTimezone)
if err != nil {
return utils.NewErrServerError(err)
@@ -128,7 +128,7 @@ func (self *ApierV2) ExportCdrsToFile(attr utils.AttrExportCdrsToFile, reply *ut
return utils.NewErrServerError(err)
}
*reply = utils.ExportedFileCdrs{ExportedFilePath: filePath, TotalRecords: len(cdrs), TotalCost: cdrexp.TotalCost(), FirstOrderId: cdrexp.FirstOrderId(), LastOrderId: cdrexp.LastOrderId()}
- if !attr.SuppressCgrIds {
+ if !attr.Verbose {
reply.ExportedCgrIds = cdrexp.PositiveExports()
reply.UnexportedCgrIds = cdrexp.NegativeExports()
}
diff --git a/apier/v2/cdrs.go b/apier/v2/cdrs.go
index b6fa0f5c8..99d7bb030 100644
--- a/apier/v2/cdrs.go
+++ b/apier/v2/cdrs.go
@@ -26,30 +26,30 @@ import (
)
// Retrieves CDRs based on the filters
-func (apier *ApierV2) GetCdrs(attrs utils.RpcCdrsFilter, reply *[]*engine.ExternalCdr) error {
- cdrsFltr, err := attrs.AsCdrsFilter(apier.Config.DefaultTimezone)
+func (apier *ApierV2) GetCdrs(attrs utils.RPCCDRsFilter, reply *[]*engine.ExternalCDR) error {
+ cdrsFltr, err := attrs.AsCDRsFilter(apier.Config.DefaultTimezone)
if err != nil {
return utils.NewErrServerError(err)
}
- if cdrs, _, err := apier.CdrDb.GetStoredCdrs(cdrsFltr); err != nil {
+ if cdrs, _, err := apier.CdrDb.GetCDRs(cdrsFltr); err != nil {
return utils.NewErrServerError(err)
} else if len(cdrs) == 0 {
- *reply = make([]*engine.ExternalCdr, 0)
+ *reply = make([]*engine.ExternalCDR, 0)
} else {
for _, cdr := range cdrs {
- *reply = append(*reply, cdr.AsExternalCdr())
+ *reply = append(*reply, cdr.AsExternalCDR())
}
}
return nil
}
-func (apier *ApierV2) CountCdrs(attrs utils.RpcCdrsFilter, reply *int64) error {
- cdrsFltr, err := attrs.AsCdrsFilter(apier.Config.DefaultTimezone)
+func (apier *ApierV2) CountCdrs(attrs utils.RPCCDRsFilter, reply *int64) error {
+ cdrsFltr, err := attrs.AsCDRsFilter(apier.Config.DefaultTimezone)
if err != nil {
return utils.NewErrServerError(err)
}
cdrsFltr.Count = true
- if _, count, err := apier.CdrDb.GetStoredCdrs(cdrsFltr); err != nil {
+ if _, count, err := apier.CdrDb.GetCDRs(cdrsFltr); err != nil {
return utils.NewErrServerError(err)
} else {
*reply = count
diff --git a/apier/v2/cdrs_mongo_local_test.go b/apier/v2/cdrs_mongo_local_test.go
index 8ce6186ea..a0e248015 100644
--- a/apier/v2/cdrs_mongo_local_test.go
+++ b/apier/v2/cdrs_mongo_local_test.go
@@ -68,18 +68,18 @@ func TestV2CdrsMongoInjectUnratedCdr(t *testing.T) {
if !*testLocal {
return
}
- mysqlDb, err := engine.NewMongoStorage(cdrsMongoCfg.StorDBHost, cdrsMongoCfg.StorDBPort, cdrsMongoCfg.StorDBName, cdrsMongoCfg.StorDBUser, cdrsMongoCfg.StorDBPass)
+ mongoDb, err := engine.NewMongoStorage(cdrsMongoCfg.StorDBHost, cdrsMongoCfg.StorDBPort, cdrsMongoCfg.StorDBName, cdrsMongoCfg.StorDBUser, cdrsMongoCfg.StorDBPass)
if err != nil {
t.Error("Error on opening database connection: ", err)
return
}
- strCdr1 := &engine.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: utils.META_RATED,
+ strCdr1 := &engine.CDR{CGRID: utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String()), RunID: utils.MetaRaw,
+ ToR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "TestV2CdrsMongoInjectUnratedCdr", RequestType: 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),
+ SetupTime: time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC), AnswerTime: time.Date(2015, 11, 21, 10, 47, 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}
- if err := mysqlDb.SetCdr(strCdr1); err != nil {
+ Cost: -1}
+ if err := mongoDb.SetCDR(strCdr1, false); err != nil {
t.Error(err.Error())
}
}
@@ -105,90 +105,85 @@ func TestV2CdrsMongoRpcConn(t *testing.T) {
}
}
-// Insert some CDRs
-func TestV2CdrsMongoProcessCdr(t *testing.T) {
+func TestV2CdrsMongoProcessCdrRated(t *testing.T) {
if !*testLocal {
return
}
+ cdr := &engine.CDR{
+ CGRID: utils.Sha1("dsafdsaf", time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC).String()), RunID: utils.DEFAULT_RUNID,
+ OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CdrsMongoProcessCdrRated", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call",
+ Account: "1001", Subject: "1001", Destination: "1002",
+ SetupTime: time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC), AnswerTime: time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC),
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Cost: 1.01, CostSource: "TestV2CdrsMongoProcessCdrRated", Rated: true,
+ }
var reply string
- cdrs := []*engine.StoredCdr{
- &engine.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: 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,
- },
- &engine.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: 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",
- },
- &engine.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: 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",
- },
+ if err := cdrsMongoRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if reply != utils.OK {
+ t.Error("Unexpected reply received: ", reply)
}
- for _, cdr := range cdrs {
- if err := cdrsMongoRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if reply != utils.OK {
- t.Error("Unexpected reply received: ", reply)
- }
+}
+
+func TestV2CdrsMongoProcessCdrRaw(t *testing.T) {
+ if !*testLocal {
+ return
}
+ cdr := &engine.CDR{
+ CGRID: utils.Sha1("abcdeftg", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, RunID: utils.MetaRaw,
+ ToR: utils.VOICE, OriginID: "abcdeftg",
+ OriginHost: "192.168.1.1", Source: "TestV2CdrsMongoProcessCdrRaw", RequestType: 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),
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ }
+ var reply string
+ if err := cdrsMongoRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if reply != utils.OK {
+ t.Error("Unexpected reply received: ", reply)
+ }
+ time.Sleep(time.Duration(*waitRater) * time.Millisecond)
}
func TestV2CdrsMongoGetCdrs(t *testing.T) {
if !*testLocal {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{}
if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 4 {
- for _, cdr := range reply {
- t.Logf("CDR: %s %s %s", cdr.CgrId, cdr.CdrSource, cdr.MediationRunId)
- }
+ } else if len(reply) != 4 { // 1 injected, 1 rated, 1 *raw and it's pair in *default run
t.Error("Unexpected number of CDRs returned: ", len(reply))
}
- // CDRs with errors
- req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)}
+ // CDRs with rating errors
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)}
if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 2 {
+ } else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", reply)
}
// CDRs Rated
- req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, MinCost: utils.Float64Pointer(-1.0)}
- if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 4 {
- for _, cdr := range reply {
- t.Logf("CDR: %s %s %s %f", cdr.CgrId, cdr.CdrSource, cdr.MediationRunId, cdr.Cost)
- }
- t.Error("Unexpected number of CDRs returned: ", reply)
- }
- // CDRs non rated OR SkipRated
- req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, MaxCost: utils.Float64Pointer(-1.0)}
- if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 0 {
- for _, cdr := range reply {
- t.Logf("CDR: %s %s %s %f", cdr.CgrId, cdr.CdrSource, cdr.MediationRunId, cdr.Cost)
- }
- t.Error("Unexpected number of CDRs returned: ", reply)
- }
- // Skip Errors
- req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)}
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}}
if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
- for _, cdr := range reply {
- t.Logf("CDR: %s %s %s %f", cdr.CgrId, cdr.CdrSource, cdr.MediationRunId, cdr.Cost)
- }
+ t.Error("Unexpected number of CDRs returned: ", reply)
+ }
+ // Raw CDRs
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}}
+ if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if len(reply) != 2 {
+ t.Error("Unexpected number of CDRs returned: ", reply)
+ }
+ // Skip Errors
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)}
+ if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", reply)
}
}
@@ -198,7 +193,7 @@ func TestV2CdrsMongoCountCdrs(t *testing.T) {
return
}
var reply int64
- req := utils.AttrGetCdrs{CdrSources: []string{"test", "UNKNOWN"}}
+ req := utils.AttrGetCdrs{}
if err := cdrsMongoRpc.Call("ApierV2.CountCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != 4 {
@@ -206,30 +201,30 @@ func TestV2CdrsMongoCountCdrs(t *testing.T) {
}
}
-// Test Prepaid CDRs without previous costs being calculated
+// Make sure *prepaid does not block until finding previous costs
func TestV2CdrsMongoProcessPrepaidCdr(t *testing.T) {
if !*testLocal {
return
}
var reply string
- cdrs := []*engine.StoredCdr{
- &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf2", 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: utils.META_PREPAID, 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,
+ cdrs := []*engine.CDR{
+ &engine.CDR{CGRID: utils.Sha1("dsafdsaf2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CdrsMongoProcessPrepaidCdr1", RequestType: utils.META_PREPAID, Direction: "*out", Tenant: "cgrates.org",
+ Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true,
},
- &engine.StoredCdr{CgrId: utils.Sha1("abcdeftg2", 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: utils.META_PREPAID, 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,
+ &engine.CDR{CGRID: utils.Sha1("abcdeftg2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CdrsMongoProcessPrepaidCdr2", RequestType: utils.META_PREPAID, 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), RunID: 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",
},
- &engine.StoredCdr{CgrId: utils.Sha1("aererfddf2", 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: utils.META_PREPAID, 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,
+ &engine.CDR{CGRID: utils.Sha1("aererfddf2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CdrsMongoProcessPrepaidCdr3", RequestType: utils.META_PREPAID, 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), RunID: 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",
},
}
tStart := time.Now()
@@ -245,6 +240,73 @@ func TestV2CdrsMongoProcessPrepaidCdr(t *testing.T) {
}
}
+func TestV2CdrsMongoRateWithoutTP(t *testing.T) {
+ if !*testLocal {
+ return
+ }
+ rawCdrCGRID := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
+ // Rate the injected CDR, should not rate it since we have no TP loaded
+ attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCGRID}}
+ var reply string
+ if err := cdrsMongoRpc.Call("CdrsV2.RateCdrs", attrs, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if reply != utils.OK {
+ t.Error("Unexpected reply received: ", reply)
+ }
+ time.Sleep(time.Duration(*waitRater) * time.Millisecond)
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{CGRIDs: []string{rawCdrCGRID}, RunIDs: []string{utils.META_DEFAULT}}
+ if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if len(cdrs) != 1 { // Injected CDR did not have a charging run
+ t.Error("Unexpected number of CDRs returned: ", len(cdrs))
+ } else {
+ if cdrs[0].Cost != -1 {
+ t.Errorf("Unexpected CDR returned: %+v", cdrs[0])
+ }
+ }
+}
+
+func TestV2CdrsMongoLoadTariffPlanFromFolder(t *testing.T) {
+ if !*testLocal {
+ return
+ }
+ var loadInst engine.LoadInstance
+ attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")}
+ if err := cdrsMongoRpc.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &loadInst); err != nil {
+ t.Error(err)
+ } else if loadInst.LoadId == "" {
+ t.Error("Empty loadId received, loadInstance: ", loadInst)
+ }
+ time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups
+}
+
+func TestV2CdrsMongoRateWithTP(t *testing.T) {
+ if !*testLocal {
+ return
+ }
+ rawCdrCGRID := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
+ attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCGRID}}
+ var reply string
+ if err := cdrsMongoRpc.Call("CdrsV2.RateCdrs", attrs, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if reply != utils.OK {
+ t.Error("Unexpected reply received: ", reply)
+ }
+ time.Sleep(time.Duration(*waitRater) * time.Millisecond)
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{CGRIDs: []string{rawCdrCGRID}, RunIDs: []string{utils.META_DEFAULT}}
+ if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if len(cdrs) != 1 {
+ t.Error("Unexpected number of CDRs returned: ", len(cdrs))
+ } else {
+ if cdrs[0].Cost != 0.3 {
+ t.Errorf("Unexpected CDR returned: %+v", cdrs[0])
+ }
+ }
+}
+
func TestV2CdrsMongoKillEngine(t *testing.T) {
if !*testLocal {
return
diff --git a/apier/v2/cdrs_mysql_local_test.go b/apier/v2/cdrs_mysql_local_test.go
index 0cadbe1d4..bbbed922e 100644
--- a/apier/v2/cdrs_mysql_local_test.go
+++ b/apier/v2/cdrs_mysql_local_test.go
@@ -39,7 +39,7 @@ var cdrsCfgPath string
var cdrsCfg *config.CGRConfig
var cdrsRpc *rpc.Client
-func TestV2CdrsMysqlInitConfig(t *testing.T) {
+func TestV2CDRsMySQLInitConfig(t *testing.T) {
if !*testLocal {
return
}
@@ -50,7 +50,7 @@ func TestV2CdrsMysqlInitConfig(t *testing.T) {
}
}
-func TestV2CdrsMysqlInitDataDb(t *testing.T) {
+func TestV2CDRsMySQLInitDataDb(t *testing.T) {
if !*testLocal {
return
}
@@ -60,7 +60,7 @@ func TestV2CdrsMysqlInitDataDb(t *testing.T) {
}
// InitDb so we can rely on count
-func TestV2CdrsMysqlInitCdrDb(t *testing.T) {
+func TestV2CDRsMySQLInitCdrDb(t *testing.T) {
if !*testLocal {
return
}
@@ -69,7 +69,7 @@ func TestV2CdrsMysqlInitCdrDb(t *testing.T) {
}
}
-func TestV2CdrsMysqlInjectUnratedCdr(t *testing.T) {
+func TestV2CDRsMySQLInjectUnratedCdr(t *testing.T) {
if !*testLocal {
return
}
@@ -79,18 +79,18 @@ func TestV2CdrsMysqlInjectUnratedCdr(t *testing.T) {
t.Error("Error on opening database connection: ", err)
return
}
- strCdr1 := &engine.StoredCdr{CgrId: utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String()),
- TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_RATED,
+ strCdr1 := &engine.CDR{CGRID: utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String()), RunID: utils.MetaRaw,
+ ToR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "TestV2CDRsMySQLInjectUnratedCdr", RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
SetupTime: time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC), AnswerTime: time.Date(2015, 11, 21, 10, 47, 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}
- if err := mysqlDb.SetCdr(strCdr1); err != nil {
+ Cost: -1}
+ if err := mysqlDb.SetCDR(strCdr1, false); err != nil {
t.Error(err.Error())
}
}
-func TestV2CdrsMysqlStartEngine(t *testing.T) {
+func TestV2CDRsMySQLStartEngine(t *testing.T) {
if !*testLocal {
return
}
@@ -100,7 +100,7 @@ func TestV2CdrsMysqlStartEngine(t *testing.T) {
}
// Connect rpc client to rater
-func TestV2CdrsMysqlRpcConn(t *testing.T) {
+func TestV2CDRsMySQLRpcConn(t *testing.T) {
if !*testLocal {
return
}
@@ -111,83 +111,90 @@ func TestV2CdrsMysqlRpcConn(t *testing.T) {
}
}
-// Insert some CDRs
-func TestV2CdrsMysqlProcessCdr(t *testing.T) {
+func TestV2CDRsMySQLProcessCdrRated(t *testing.T) {
if !*testLocal {
return
}
- var reply string
- cdrs := []*engine.StoredCdr{
- &engine.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: 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,
- },
- &engine.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: 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",
- },
- &engine.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: 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",
- },
+ cdr := &engine.CDR{
+ CGRID: utils.Sha1("dsafdsaf", time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC).String()), RunID: utils.DEFAULT_RUNID,
+ OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsMySQLProcessCdrRated", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call",
+ Account: "1001", Subject: "1001", Destination: "1002",
+ SetupTime: time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC), AnswerTime: time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC),
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Cost: 1.01, CostSource: "TestV2CDRsMySQLProcessCdrRated", Rated: true,
}
- for _, cdr := range cdrs {
- if err := cdrsRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if reply != utils.OK {
- t.Error("Unexpected reply received: ", reply)
- }
+ var reply string
+ if err := cdrsRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if reply != utils.OK {
+ t.Error("Unexpected reply received: ", reply)
}
}
-func TestV2CdrsMysqlGetCdrs(t *testing.T) {
+func TestV2CDRsMySQLProcessCdrRaw(t *testing.T) {
if !*testLocal {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{}
+ cdr := &engine.CDR{
+ CGRID: utils.Sha1("abcdeftg", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, RunID: utils.MetaRaw,
+ ToR: utils.VOICE, OriginID: "abcdeftg",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsMySQLProcessCdrRaw", RequestType: 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),
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ }
+ var reply string
+ if err := cdrsRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if reply != utils.OK {
+ t.Error("Unexpected reply received: ", reply)
+ }
+ time.Sleep(time.Duration(*waitRater) * time.Millisecond)
+}
+
+func TestV2CDRsMySQLGetCdrs(t *testing.T) {
+ if !*testLocal {
+ return
+ }
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{}
if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 4 {
+ } else if len(reply) != 4 { // 1 injected, 1 rated, 1 *raw and it's pair in *default run
t.Error("Unexpected number of CDRs returned: ", len(reply))
}
- // CDRs with errors
- req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)}
- if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 2 {
- t.Error("Unexpected number of CDRs returned: ", reply)
- }
- // CDRs Rated
- req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(-1.0)}
- if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 3 {
- t.Error("Unexpected number of CDRs returned: ", reply)
- }
- // CDRs non rated OR SkipRated
- req = utils.RpcCdrsFilter{MaxCost: utils.Float64Pointer(-1.0)}
+ // CDRs with rating errors
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)}
if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", reply)
}
- // Skip Errors
- req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)}
+ // CDRs Rated
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}}
if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
t.Error("Unexpected number of CDRs returned: ", reply)
}
+ // Raw CDRs
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}}
+ if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if len(reply) != 2 {
+ t.Error("Unexpected number of CDRs returned: ", reply)
+ }
+ // Skip Errors
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)}
+ if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if len(reply) != 1 {
+ t.Error("Unexpected number of CDRs returned: ", reply)
+ }
}
-func TestV2CdrsMysqlCountCdrs(t *testing.T) {
+func TestV2CDRsMySQLCountCdrs(t *testing.T) {
if !*testLocal {
return
}
@@ -200,30 +207,27 @@ func TestV2CdrsMysqlCountCdrs(t *testing.T) {
}
}
-// Test Prepaid CDRs without previous costs being calculated
-func TestV2CdrsMysqlProcessPrepaidCdr(t *testing.T) {
+// Make sure *prepaid does not block until finding previous costs
+func TestV2CDRsMySQLProcessPrepaidCdr(t *testing.T) {
if !*testLocal {
return
}
var reply string
- cdrs := []*engine.StoredCdr{
- &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf2", 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: utils.META_PREPAID, 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,
+ cdrs := []*engine.CDR{
+ &engine.CDR{CGRID: utils.Sha1("dsafdsaf2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsMySQLProcessPrepaidCdr1", RequestType: utils.META_PREPAID, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true,
},
- &engine.StoredCdr{CgrId: utils.Sha1("abcdeftg2", 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: utils.META_PREPAID, 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,
+ &engine.CDR{CGRID: utils.Sha1("abcdeftg2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsMySQLProcessPrepaidCdr2", RequestType: utils.META_PREPAID, 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), RunID: 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",
},
- &engine.StoredCdr{CgrId: utils.Sha1("aererfddf2", 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: utils.META_PREPAID, 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,
+ &engine.CDR{CGRID: utils.Sha1("aererfddf2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsMySQLProcessPrepaidCdr3", RequestType: utils.META_PREPAID, 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), RunID: 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",
},
}
tStart := time.Now()
@@ -239,25 +243,25 @@ func TestV2CdrsMysqlProcessPrepaidCdr(t *testing.T) {
}
}
-func TestV2CdrsMysqlRateWithoutTP(t *testing.T) {
+func TestV2CDRsMySQLRateWithoutTP(t *testing.T) {
if !*testLocal {
return
}
- rawCdrCgrId := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
+ rawCdrCGRID := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
// Rate the injected CDR, should not rate it since we have no TP loaded
- attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCgrId}}
+ attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCGRID}}
var reply string
if err := cdrsRpc.Call("CdrsV2.RateCdrs", attrs, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
t.Error("Unexpected reply received: ", reply)
}
- var cdrs []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{CgrIds: []string{rawCdrCgrId}}
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{CGRIDs: []string{rawCdrCGRID}, RunIDs: []string{utils.META_DEFAULT}}
if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
- } else if len(cdrs) != 1 {
- t.Error("Unexpected number of CDRs returned: ", len(reply))
+ } else if len(cdrs) != 1 { // Injected CDR did not have a charging run
+ t.Error("Unexpected number of CDRs returned: ", len(cdrs))
} else {
if cdrs[0].Cost != -1 {
t.Errorf("Unexpected CDR returned: %+v", cdrs[0])
@@ -265,7 +269,7 @@ func TestV2CdrsMysqlRateWithoutTP(t *testing.T) {
}
}
-func TestV2CdrsMysqloadTariffPlanFromFolder(t *testing.T) {
+func TestV2CDRsMySQLLoadTariffPlanFromFolder(t *testing.T) {
if !*testLocal {
return
}
@@ -279,24 +283,24 @@ func TestV2CdrsMysqloadTariffPlanFromFolder(t *testing.T) {
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups
}
-func TestV2CdrsMysqlRateWithTP(t *testing.T) {
+func TestV2CDRsMySQLRateWithTP(t *testing.T) {
if !*testLocal {
return
}
- rawCdrCgrId := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
- attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCgrId}}
+ rawCdrCGRID := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
+ attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCGRID}}
var reply string
if err := cdrsRpc.Call("CdrsV2.RateCdrs", attrs, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
t.Error("Unexpected reply received: ", reply)
}
- var cdrs []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{CgrIds: []string{rawCdrCgrId}}
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{CGRIDs: []string{rawCdrCGRID}, RunIDs: []string{utils.META_DEFAULT}}
if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
- t.Error("Unexpected number of CDRs returned: ", len(reply))
+ t.Error("Unexpected number of CDRs returned: ", len(cdrs))
} else {
if cdrs[0].Cost != 0.3 {
t.Errorf("Unexpected CDR returned: %+v", cdrs[0])
@@ -306,21 +310,21 @@ func TestV2CdrsMysqlRateWithTP(t *testing.T) {
/*
// Benchmark speed of processing 1000 CDRs
-func TestV2CdrsMysqlProcessRatedExternalCdrBenchmark(t *testing.T) {
+func TestV2CDRsMySQLProcessRatedExternalCdrBenchmark(t *testing.T) {
if !*testLocal {
return
}
- cdr := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "benchratedcdr", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: utils.OUT,
+ cdr := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "benchratedcdr", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1001", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "15", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Usage: "15", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
var reply string
tStart := time.Now()
nrCdrs := 1000
for i := 0; i < nrCdrs; i++ {
- cdr.AccId = "benchratedcdr" + strconv.Itoa(i)
+ cdr.OriginID = "benchratedcdr" + strconv.Itoa(i)
if err := cdrsRpc.Call("CdrsV2.ProcessExternalCdr", cdr, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
@@ -333,7 +337,7 @@ func TestV2CdrsMysqlProcessRatedExternalCdrBenchmark(t *testing.T) {
}
// Benchmark speed of re-rating 1000 CDRs
-func TestV2CdrsMysqlReRateWithTPBenchmark(t *testing.T) {
+func TestV2CDRsMySQLReRateWithTPBenchmark(t *testing.T) {
if !*testLocal {
return
}
@@ -355,21 +359,21 @@ func TestV2CdrsMysqlReRateWithTPBenchmark(t *testing.T) {
}
// Benchmark speed of processing 1000 postpaid CDRs
-func TestV2CdrsMysqlProcessPostpaidExternalCdrBenchmark(t *testing.T) {
+func TestV2CDRsMySQLProcessPostpaidExternalCdrBenchmark(t *testing.T) {
if !*testLocal {
return
}
- cdr := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "benchpostpaidcdr", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_POSTPAID, Direction: utils.OUT,
+ cdr := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "benchpostpaidcdr", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "15", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Usage: "15", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
var reply string
tStart := time.Now()
nrCdrs := 1000
for i := 0; i < nrCdrs; i++ {
- cdr.AccId = "benchpostpaidcdr" + strconv.Itoa(i)
+ cdr.OriginID = "benchpostpaidcdr" + strconv.Itoa(i)
if err := cdrsRpc.Call("CdrsV2.ProcessExternalCdr", cdr, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
@@ -382,7 +386,7 @@ func TestV2CdrsMysqlProcessPostpaidExternalCdrBenchmark(t *testing.T) {
}
*/
-func TestV2CdrsMysqlKillEngine(t *testing.T) {
+func TestV2CDRsMySQLKillEngine(t *testing.T) {
if !*testLocal {
return
}
diff --git a/apier/v2/cdrs_psql_local_test.go b/apier/v2/cdrs_psql_local_test.go
index b02732245..03d387c01 100644
--- a/apier/v2/cdrs_psql_local_test.go
+++ b/apier/v2/cdrs_psql_local_test.go
@@ -36,7 +36,7 @@ var cdrsPsqlCfg *config.CGRConfig
var cdrsPsqlRpc *rpc.Client
var cmdEngineCdrPsql *exec.Cmd
-func TestV2CdrsPsqlInitConfig(t *testing.T) {
+func TestV2CDRsPSQLInitConfig(t *testing.T) {
if !*testLocal {
return
}
@@ -47,7 +47,7 @@ func TestV2CdrsPsqlInitConfig(t *testing.T) {
}
}
-func TestV2CdrsPsqlInitDataDb(t *testing.T) {
+func TestV2CDRsPSQLInitDataDb(t *testing.T) {
if !*testLocal {
return
}
@@ -57,7 +57,7 @@ func TestV2CdrsPsqlInitDataDb(t *testing.T) {
}
// InitDb so we can rely on count
-func TestV2CdrsPsqlInitCdrDb(t *testing.T) {
+func TestV2CDRsPSQLInitCdrDb(t *testing.T) {
if !*testLocal {
return
}
@@ -66,7 +66,7 @@ func TestV2CdrsPsqlInitCdrDb(t *testing.T) {
}
}
-func TestV2CdrsPsqlInjectUnratedCdr(t *testing.T) {
+func TestV2CDRsPSQLInjectUnratedCdr(t *testing.T) {
if !*testLocal {
return
}
@@ -76,29 +76,28 @@ func TestV2CdrsPsqlInjectUnratedCdr(t *testing.T) {
t.Error("Error on opening database connection: ", err)
return
}
- strCdr1 := &engine.StoredCdr{CgrId: utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String()),
- TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_RATED,
+ strCdr1 := &engine.CDR{CGRID: utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String()), RunID: utils.MetaRaw,
+ ToR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "TestV2CDRsPSQLInjectUnratedCdr", RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
SetupTime: time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC), AnswerTime: time.Date(2015, 11, 21, 10, 47, 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}
- if err := psqlDb.SetCdr(strCdr1); err != nil {
+ Cost: -1}
+ if err := psqlDb.SetCDR(strCdr1, false); err != nil {
t.Error(err.Error())
}
}
-func TestV2CdrsPsqlStartEngine(t *testing.T) {
+func TestV2CDRsPSQLStartEngine(t *testing.T) {
if !*testLocal {
return
}
- var err error
- if cmdEngineCdrPsql, err = engine.StartEngine(cdrsPsqlCfgPath, *waitRater); err != nil {
+ if _, err := engine.StopStartEngine(cdrsPsqlCfgPath, *waitRater); err != nil {
t.Fatal(err)
}
}
// Connect rpc client to rater
-func TestV2CdrsPsqlPsqlRpcConn(t *testing.T) {
+func TestV2CDRsPSQLRpcConn(t *testing.T) {
if !*testLocal {
return
}
@@ -109,83 +108,90 @@ func TestV2CdrsPsqlPsqlRpcConn(t *testing.T) {
}
}
-// Insert some CDRs
-func TestV2CdrsPsqlProcessCdr(t *testing.T) {
+func TestV2CDRsPSQLProcessCdrRated(t *testing.T) {
if !*testLocal {
return
}
- var reply string
- cdrs := []*engine.StoredCdr{
- &engine.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: 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,
- },
- &engine.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: 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",
- },
- &engine.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: 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",
- },
+ cdr := &engine.CDR{
+ CGRID: utils.Sha1("dsafdsaf", time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC).String()), RunID: utils.DEFAULT_RUNID,
+ OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsPSQLProcessCdrRated", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call",
+ Account: "1001", Subject: "1001", Destination: "1002",
+ SetupTime: time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC), AnswerTime: time.Date(2015, 12, 13, 18, 15, 26, 0, time.UTC),
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Cost: 1.01, CostSource: "TestV2CDRsPSQLProcessCdrRated", Rated: true,
}
- for _, cdr := range cdrs {
- if err := cdrsPsqlRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if reply != utils.OK {
- t.Error("Unexpected reply received: ", reply)
- }
+ var reply string
+ if err := cdrsPsqlRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if reply != utils.OK {
+ t.Error("Unexpected reply received: ", reply)
}
}
-func TestV2CdrsPsqlGetCdrs(t *testing.T) {
+func TestV2CDRsPSQLProcessCdrRaw(t *testing.T) {
if !*testLocal {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{}
+ cdr := &engine.CDR{
+ CGRID: utils.Sha1("abcdeftg", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, RunID: utils.MetaRaw,
+ ToR: utils.VOICE, OriginID: "abcdeftg",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsPSQLProcessCdrRaw", RequestType: 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),
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ }
+ var reply string
+ if err := cdrsPsqlRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if reply != utils.OK {
+ t.Error("Unexpected reply received: ", reply)
+ }
+ time.Sleep(time.Duration(*waitRater) * time.Millisecond)
+}
+
+func TestV2CDRsPSQLGetCdrs(t *testing.T) {
+ if !*testLocal {
+ return
+ }
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{}
if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 4 {
+ } else if len(reply) != 4 { // 1 injected, 1 rated, 1 *raw and it's pair in *default run
t.Error("Unexpected number of CDRs returned: ", len(reply))
}
- // CDRs with errors
- req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)}
- if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 2 {
- t.Error("Unexpected number of CDRs returned: ", reply)
- }
- // CDRs Rated
- req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(-1.0)}
- if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if len(reply) != 3 {
- t.Error("Unexpected number of CDRs returned: ", reply)
- }
- // CDRs non rated OR SkipRated
- req = utils.RpcCdrsFilter{MaxCost: utils.Float64Pointer(-1.0)}
+ // CDRs with rating errors
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)}
if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", reply)
}
- // Skip Errors
- req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)}
+ // CDRs Rated
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}}
if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
t.Error("Unexpected number of CDRs returned: ", reply)
}
+ // Raw CDRs
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}}
+ if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if len(reply) != 2 {
+ t.Error("Unexpected number of CDRs returned: ", reply)
+ }
+ // Skip Errors
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)}
+ if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
+ t.Error("Unexpected error: ", err.Error())
+ } else if len(reply) != 1 {
+ t.Error("Unexpected number of CDRs returned: ", reply)
+ }
}
-func TestV2CdrsPsqlCountCdrs(t *testing.T) {
+func TestV2CDRsPSQLCountCdrs(t *testing.T) {
if !*testLocal {
return
}
@@ -198,30 +204,27 @@ func TestV2CdrsPsqlCountCdrs(t *testing.T) {
}
}
-// Test Prepaid CDRs without previous costs being calculated
-func TestV2CdrsPsqlProcessPrepaidCdr(t *testing.T) {
+// Make sure *prepaid does not block until finding previous costs
+func TestV2CDRsPSQLProcessPrepaidCdr(t *testing.T) {
if !*testLocal {
return
}
var reply string
- cdrs := []*engine.StoredCdr{
- &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf2", 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: utils.META_PREPAID, 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,
+ cdrs := []*engine.CDR{
+ &engine.CDR{CGRID: utils.Sha1("dsafdsaf2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsPSQLProcessPrepaidCdr1", RequestType: utils.META_PREPAID, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true,
},
- &engine.StoredCdr{CgrId: utils.Sha1("abcdeftg2", 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: utils.META_PREPAID, 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,
+ &engine.CDR{CGRID: utils.Sha1("abcdeftg2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsPSQLProcessPrepaidCdr2", RequestType: utils.META_PREPAID, 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), RunID: 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",
},
- &engine.StoredCdr{CgrId: utils.Sha1("aererfddf2", 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: utils.META_PREPAID, 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,
+ &engine.CDR{CGRID: utils.Sha1("aererfddf2", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "TestV2CDRsPSQLProcessPrepaidCdr3", RequestType: utils.META_PREPAID, 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), RunID: 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",
},
}
tStart := time.Now()
@@ -237,25 +240,25 @@ func TestV2CdrsPsqlProcessPrepaidCdr(t *testing.T) {
}
}
-func TestV2CdrsPsqlRateWithoutTP(t *testing.T) {
+func TestV2CDRsPSQLRateWithoutTP(t *testing.T) {
if !*testLocal {
return
}
- rawCdrCgrId := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
+ rawCdrCGRID := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
// Rate the injected CDR, should not rate it since we have no TP loaded
- attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCgrId}}
+ attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCGRID}}
var reply string
if err := cdrsPsqlRpc.Call("CdrsV2.RateCdrs", attrs, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
t.Error("Unexpected reply received: ", reply)
}
- var cdrs []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{CgrIds: []string{rawCdrCgrId}}
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{CGRIDs: []string{rawCdrCGRID}, RunIDs: []string{utils.META_DEFAULT}}
if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
- } else if len(cdrs) != 1 {
- t.Error("Unexpected number of CDRs returned: ", len(reply))
+ } else if len(cdrs) != 1 { // Injected CDR did not have a charging run
+ t.Error("Unexpected number of CDRs returned: ", len(cdrs))
} else {
if cdrs[0].Cost != -1 {
t.Errorf("Unexpected CDR returned: %+v", cdrs[0])
@@ -263,7 +266,7 @@ func TestV2CdrsPsqlRateWithoutTP(t *testing.T) {
}
}
-func TestV2CdrsPsqlLoadTariffPlanFromFolder(t *testing.T) {
+func TestV2CDRsPSQLLoadTariffPlanFromFolder(t *testing.T) {
if !*testLocal {
return
}
@@ -277,24 +280,24 @@ func TestV2CdrsPsqlLoadTariffPlanFromFolder(t *testing.T) {
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups
}
-func TestV2CdrsPsqlRateWithTP(t *testing.T) {
+func TestV2CDRsPSQLRateWithTP(t *testing.T) {
if !*testLocal {
return
}
- rawCdrCgrId := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
- attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCgrId}}
+ rawCdrCGRID := utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String())
+ attrs := utils.AttrRateCdrs{CgrIds: []string{rawCdrCGRID}}
var reply string
if err := cdrsPsqlRpc.Call("CdrsV2.RateCdrs", attrs, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
t.Error("Unexpected reply received: ", reply)
}
- var cdrs []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{CgrIds: []string{rawCdrCgrId}}
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{CGRIDs: []string{rawCdrCGRID}, RunIDs: []string{utils.META_DEFAULT}}
if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
- t.Error("Unexpected number of CDRs returned: ", len(reply))
+ t.Error("Unexpected number of CDRs returned: ", len(cdrs))
} else {
if cdrs[0].Cost != 0.3 {
t.Errorf("Unexpected CDR returned: %+v", cdrs[0])
@@ -304,21 +307,21 @@ func TestV2CdrsPsqlRateWithTP(t *testing.T) {
/*
// Benchmark speed of processing 1000 CDRs
-func TestV2CdrsPsqlProcessRatedExternalCdrBenchmark(t *testing.T) {
+func TestV2CDRsPSQLProcessRatedExternalCdrBenchmark(t *testing.T) {
if !*testLocal {
return
}
- cdr := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "benchratedcdr", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: utils.OUT,
+ cdr := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "benchratedcdr", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1001", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "15", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Usage: "15", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
var reply string
tStart := time.Now()
nrCdrs := 1000
for i := 0; i < nrCdrs; i++ {
- cdr.AccId = "benchratedcdr" + strconv.Itoa(i)
+ cdr.OriginID = "benchratedcdr" + strconv.Itoa(i)
if err := cdrsPsqlRpc.Call("CdrsV2.ProcessExternalCdr", cdr, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
@@ -331,7 +334,7 @@ func TestV2CdrsPsqlProcessRatedExternalCdrBenchmark(t *testing.T) {
}
// Benchmark speed of re-rating 1000 CDRs
-func TestV2CdrsPsqlReRateWithTPBenchmark(t *testing.T) {
+func TestV2CDRsPSQLReRateWithTPBenchmark(t *testing.T) {
if !*testLocal {
return
}
@@ -353,21 +356,21 @@ func TestV2CdrsPsqlReRateWithTPBenchmark(t *testing.T) {
}
// Benchmark speed of processing 1000 postpaid CDRs
-func TestV2CdrsPsqlProcessPostpaidExternalCdrBenchmark(t *testing.T) {
+func TestV2CDRsPSQLProcessPostpaidExternalCdrBenchmark(t *testing.T) {
if !*testLocal {
return
}
- cdr := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "benchpostpaidcdr", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_POSTPAID, Direction: utils.OUT,
+ cdr := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "benchpostpaidcdr", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "15", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Usage: "15", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
var reply string
tStart := time.Now()
nrCdrs := 1000
for i := 0; i < nrCdrs; i++ {
- cdr.AccId = "benchpostpaidcdr" + strconv.Itoa(i)
+ cdr.OriginID = "benchpostpaidcdr" + strconv.Itoa(i)
if err := cdrsPsqlRpc.Call("CdrsV2.ProcessExternalCdr", cdr, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
@@ -380,7 +383,7 @@ func TestV2CdrsPsqlProcessPostpaidExternalCdrBenchmark(t *testing.T) {
}
*/
-func TestV2CdrsPsqlKillEngine(t *testing.T) {
+func TestV2CDRsPSQLKillEngine(t *testing.T) {
if !*testLocal {
return
}
diff --git a/cdrc/cdrc.go b/cdrc/cdrc.go
index 9d77c941b..a60c073e8 100644
--- a/cdrc/cdrc.go
+++ b/cdrc/cdrc.go
@@ -44,7 +44,7 @@ const (
// Understands and processes a specific format of cdr (eg: .csv or .fwv)
type RecordsProcessor interface {
- ProcessNextRecord() ([]*engine.StoredCdr, error) // Process a single record in the CDR file, return a slice of CDRs since based on configuration we can have more templates
+ ProcessNextRecord() ([]*engine.CDR, error) // Process a single record in the CDR file, return a slice of CDRs since based on configuration we can have more templates
ProcessedRecordsNr() int64
}
diff --git a/cdrc/cdrc_local_test.go b/cdrc/cdrc_local_test.go
index fb3737c32..1fa731eae 100644
--- a/cdrc/cdrc_local_test.go
+++ b/cdrc/cdrc_local_test.go
@@ -121,10 +121,8 @@ func TestCsvLclEmptyTables(t *testing.T) {
return // No point in going further
}
}
- for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
- if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {
- t.Fatal(err.Error())
- }
+ if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", utils.TBL_CDRS)); err != nil {
+ t.Fatal(err.Error())
}
}
diff --git a/cdrc/csv.go b/cdrc/csv.go
index 66d5971d5..c6daaaee0 100644
--- a/cdrc/csv.go
+++ b/cdrc/csv.go
@@ -37,7 +37,7 @@ func NewPartialFlatstoreRecord(record []string, timezone string) (*PartialFlatst
if len(record) < 7 {
return nil, errors.New("MISSING_IE")
}
- pr := &PartialFlatstoreRecord{Method: record[0], AccId: record[3] + record[1] + record[2], Values: record}
+ pr := &PartialFlatstoreRecord{Method: record[0], OriginID: record[3] + record[1] + record[2], Values: record}
var err error
if pr.Timestamp, err = utils.ParseTimeDetectLayout(record[6], timezone); err != nil {
return nil, err
@@ -48,7 +48,7 @@ func NewPartialFlatstoreRecord(record []string, timezone string) (*PartialFlatst
// This is a partial record received from Flatstore, can be INVITE or BYE and it needs to be paired in order to produce duration
type PartialFlatstoreRecord struct {
Method string // INVITE or BYE
- AccId string // Copute here the AccId
+ OriginID string // Copute here the OriginID
Timestamp time.Time // Timestamp of the event, as written by db_flastore module
Values []string // Can contain original values or updated via UpdateValues
}
@@ -100,7 +100,7 @@ type PartialRecordsCache struct {
ttl time.Duration
cdrOutDir string
csvSep rune
- partialRecords map[string]map[string]*PartialFlatstoreRecord // [FileName"][AccId]*PartialRecord
+ partialRecords map[string]map[string]*PartialFlatstoreRecord // [FileName"][OriginID]*PartialRecord
guard *engine.GuardianLock
}
@@ -131,7 +131,7 @@ func (self *PartialRecordsCache) dumpUnpairedRecords(fileName string) error {
}
// Search in cache and return the partial record with accountind id defined, prefFilename is searched at beginning because of better match probability
-func (self *PartialRecordsCache) GetPartialRecord(accId, prefFileName string) (string, *PartialFlatstoreRecord) {
+func (self *PartialRecordsCache) GetPartialRecord(OriginID, prefFileName string) (string, *PartialFlatstoreRecord) {
var cachedFilename string
var cachedPartial *PartialFlatstoreRecord
checkCachedFNames := []string{prefFileName} // Higher probability to match as firstFileName
@@ -143,7 +143,7 @@ func (self *PartialRecordsCache) GetPartialRecord(accId, prefFileName string) (s
for _, fName := range checkCachedFNames { // Need to lock them individually
self.guard.Guard(func() (interface{}, error) {
var hasPartial bool
- if cachedPartial, hasPartial = self.partialRecords[fName][accId]; hasPartial {
+ if cachedPartial, hasPartial = self.partialRecords[fName][OriginID]; hasPartial {
cachedFilename = fName
}
return nil, nil
@@ -158,15 +158,15 @@ func (self *PartialRecordsCache) GetPartialRecord(accId, prefFileName string) (s
func (self *PartialRecordsCache) CachePartial(fileName string, pr *PartialFlatstoreRecord) {
self.guard.Guard(func() (interface{}, error) {
if fileMp, hasFile := self.partialRecords[fileName]; !hasFile {
- self.partialRecords[fileName] = map[string]*PartialFlatstoreRecord{pr.AccId: pr}
+ self.partialRecords[fileName] = map[string]*PartialFlatstoreRecord{pr.OriginID: pr}
if self.ttl != 0 { // Schedule expiry/dump of the just created entry in cache
go func() {
time.Sleep(self.ttl)
self.dumpUnpairedRecords(fileName)
}()
}
- } else if _, hasAccId := fileMp[pr.AccId]; !hasAccId {
- self.partialRecords[fileName][pr.AccId] = pr
+ } else if _, hasOriginID := fileMp[pr.OriginID]; !hasOriginID {
+ self.partialRecords[fileName][pr.OriginID] = pr
}
return nil, nil
}, 0, fileName)
@@ -174,7 +174,7 @@ func (self *PartialRecordsCache) CachePartial(fileName string, pr *PartialFlatst
func (self *PartialRecordsCache) UncachePartial(fileName string, pr *PartialFlatstoreRecord) {
self.guard.Guard(func() (interface{}, error) {
- delete(self.partialRecords[fileName], pr.AccId) // Remove the record out of cache
+ delete(self.partialRecords[fileName], pr.OriginID) // Remove the record out of cache
return nil, nil
}, 0, fileName)
}
@@ -203,7 +203,7 @@ func (self *CsvRecordsProcessor) ProcessedRecordsNr() int64 {
return self.processedRecordsNr
}
-func (self *CsvRecordsProcessor) ProcessNextRecord() ([]*engine.StoredCdr, error) {
+func (self *CsvRecordsProcessor) ProcessNextRecord() ([]*engine.CDR, error) {
record, err := self.csvReader.Read()
if err != nil {
return nil, err
@@ -231,7 +231,7 @@ func (self *CsvRecordsProcessor) processPartialRecord(record []string) ([]string
return nil, err
}
// Retrieve and complete the record from cache
- cachedFilename, cachedPartial := self.partialRecordsCache.GetPartialRecord(pr.AccId, self.fileName)
+ cachedFilename, cachedPartial := self.partialRecordsCache.GetPartialRecord(pr.OriginID, self.fileName)
if cachedPartial == nil { // Not cached, do it here and stop processing
self.partialRecordsCache.CachePartial(self.fileName, pr)
return nil, nil
@@ -245,8 +245,8 @@ func (self *CsvRecordsProcessor) processPartialRecord(record []string) ([]string
}
// Takes the record from a slice and turns it into StoredCdrs, posting them to the cdrServer
-func (self *CsvRecordsProcessor) processRecord(record []string) ([]*engine.StoredCdr, error) {
- recordCdrs := make([]*engine.StoredCdr, 0) // More CDRs based on the number of filters and field templates
+func (self *CsvRecordsProcessor) processRecord(record []string) ([]*engine.CDR, error) {
+ recordCdrs := make([]*engine.CDR, 0) // More CDRs based on the number of filters and field templates
for cdrcId, cdrcCfg := range self.cdrcCfgs { // cdrFields coming from more templates will produce individual storCdr records
// Make sure filters are matching
filterBreak := false
@@ -277,8 +277,8 @@ func (self *CsvRecordsProcessor) processRecord(record []string) ([]*engine.Store
}
// Takes the record out of csv and turns it into storedCdr which can be processed by CDRS
-func (self *CsvRecordsProcessor) recordToStoredCdr(record []string, cdrcId string) (*engine.StoredCdr, error) {
- storedCdr := &engine.StoredCdr{CdrHost: "0.0.0.0", CdrSource: self.cdrcCfgs[cdrcId].CdrSourceId, ExtraFields: make(map[string]string), Cost: -1}
+func (self *CsvRecordsProcessor) recordToStoredCdr(record []string, cdrcId string) (*engine.CDR, error) {
+ storedCdr := &engine.CDR{OriginHost: "0.0.0.0", Source: self.cdrcCfgs[cdrcId].CdrSourceId, ExtraFields: make(map[string]string), Cost: -1}
var err error
var lazyHttpFields []*config.CfgCdrField
for _, cdrFldCfg := range self.cdrcCfgs[cdrcId].ContentFields {
@@ -313,8 +313,8 @@ func (self *CsvRecordsProcessor) recordToStoredCdr(record []string, cdrcId strin
return nil, err
}
}
- storedCdr.CgrId = utils.Sha1(storedCdr.AccId, storedCdr.SetupTime.UTC().String())
- if storedCdr.TOR == utils.DATA && self.cdrcCfgs[cdrcId].DataUsageMultiplyFactor != 0 {
+ storedCdr.CGRID = utils.Sha1(storedCdr.OriginID, storedCdr.SetupTime.UTC().String())
+ if storedCdr.ToR == utils.DATA && self.cdrcCfgs[cdrcId].DataUsageMultiplyFactor != 0 {
storedCdr.Usage = time.Duration(float64(storedCdr.Usage.Nanoseconds()) * self.cdrcCfgs[cdrcId].DataUsageMultiplyFactor)
}
for _, httpFieldCfg := range lazyHttpFields { // Lazy process the http fields
diff --git a/cdrc/csv_test.go b/cdrc/csv_test.go
index 286eb0457..066f564db 100644
--- a/cdrc/csv_test.go
+++ b/cdrc/csv_test.go
@@ -48,13 +48,13 @@ func TestCsvRecordForkCdr(t *testing.T) {
if err != nil {
t.Error("Failed to parse CDR in rated cdr", err)
}
- expectedCdr := &engine.StoredCdr{
- CgrId: utils.Sha1(cdrRow[3], time.Date(2013, 2, 3, 19, 50, 0, 0, time.UTC).String()),
- TOR: cdrRow[2],
- AccId: cdrRow[3],
- CdrHost: "0.0.0.0", // Got it over internal interface
- CdrSource: "TEST_CDRC",
- ReqType: cdrRow[4],
+ expectedCdr := &engine.CDR{
+ CGRID: utils.Sha1(cdrRow[3], time.Date(2013, 2, 3, 19, 50, 0, 0, time.UTC).String()),
+ ToR: cdrRow[2],
+ OriginID: cdrRow[3],
+ OriginHost: "0.0.0.0", // Got it over internal interface
+ Source: "TEST_CDRC",
+ RequestType: cdrRow[4],
Direction: cdrRow[5],
Tenant: cdrRow[6],
Category: cdrRow[7],
@@ -88,11 +88,11 @@ func TestCsvDataMultiplyFactor(t *testing.T) {
t.Error("Failed to parse CDR in rated cdr", err)
}
var sTime time.Time
- expectedCdr := &engine.StoredCdr{
- CgrId: utils.Sha1("", sTime.String()),
- TOR: cdrRow[0],
- CdrHost: "0.0.0.0",
- CdrSource: "TEST_CDRC",
+ expectedCdr := &engine.CDR{
+ CGRID: utils.Sha1("", sTime.String()),
+ ToR: cdrRow[0],
+ OriginHost: "0.0.0.0",
+ Source: "TEST_CDRC",
Usage: time.Duration(1) * time.Second,
ExtraFields: map[string]string{},
Cost: -1,
@@ -101,11 +101,11 @@ func TestCsvDataMultiplyFactor(t *testing.T) {
t.Errorf("Expected: \n%v, \nreceived: \n%v", expectedCdr, rtCdr)
}
csvProcessor.cdrcCfgs["*default"].DataUsageMultiplyFactor = 1024
- expectedCdr = &engine.StoredCdr{
- CgrId: utils.Sha1("", sTime.String()),
- TOR: cdrRow[0],
- CdrHost: "0.0.0.0",
- CdrSource: "TEST_CDRC",
+ expectedCdr = &engine.CDR{
+ CGRID: utils.Sha1("", sTime.String()),
+ ToR: cdrRow[0],
+ OriginHost: "0.0.0.0",
+ Source: "TEST_CDRC",
Usage: time.Duration(1024) * time.Second,
ExtraFields: map[string]string{},
Cost: -1,
@@ -114,11 +114,11 @@ func TestCsvDataMultiplyFactor(t *testing.T) {
t.Errorf("Expected: \n%v, \nreceived: \n%v", expectedCdr, rtCdr)
}
cdrRow = []string{"*voice", "1"}
- expectedCdr = &engine.StoredCdr{
- CgrId: utils.Sha1("", sTime.String()),
- TOR: cdrRow[0],
- CdrHost: "0.0.0.0",
- CdrSource: "TEST_CDRC",
+ expectedCdr = &engine.CDR{
+ CGRID: utils.Sha1("", sTime.String()),
+ ToR: cdrRow[0],
+ OriginHost: "0.0.0.0",
+ Source: "TEST_CDRC",
Usage: time.Duration(1) * time.Second,
ExtraFields: map[string]string{},
Cost: -1,
diff --git a/cdrc/fwv.go b/cdrc/fwv.go
index ddb84241f..b1fffe60d 100644
--- a/cdrc/fwv.go
+++ b/cdrc/fwv.go
@@ -58,11 +58,11 @@ type FwvRecordsProcessor struct {
httpClient *http.Client
httpSkipTlsCheck bool
timezone string
- lineLen int64 // Length of the line in the file
- offset int64 // Index of the next byte to process
- processedRecordsNr int64 // Number of content records in file
- trailerOffset int64 // Index where trailer starts, to be used as boundary when reading cdrs
- headerCdr *engine.StoredCdr // Cache here the general purpose stored CDR
+ lineLen int64 // Length of the line in the file
+ offset int64 // Index of the next byte to process
+ processedRecordsNr int64 // Number of content records in file
+ trailerOffset int64 // Index where trailer starts, to be used as boundary when reading cdrs
+ headerCdr *engine.CDR // Cache here the general purpose stored CDR
}
// Sets the line length based on first line, sets offset back to initial after reading
@@ -83,7 +83,7 @@ func (self *FwvRecordsProcessor) ProcessedRecordsNr() int64 {
return self.processedRecordsNr
}
-func (self *FwvRecordsProcessor) ProcessNextRecord() ([]*engine.StoredCdr, error) {
+func (self *FwvRecordsProcessor) ProcessNextRecord() ([]*engine.CDR, error) {
defer func() { self.offset += self.lineLen }() // Schedule increasing the offset once we are out from processing the record
if self.offset == 0 { // First time, set the necessary offsets
if err := self.setLineLen(); err != nil {
@@ -106,7 +106,7 @@ func (self *FwvRecordsProcessor) ProcessNextRecord() ([]*engine.StoredCdr, error
return nil, nil
}
}
- recordCdrs := make([]*engine.StoredCdr, 0) // More CDRs based on the number of filters and field templates
+ recordCdrs := make([]*engine.CDR, 0) // More CDRs based on the number of filters and field templates
if self.trailerOffset != 0 && self.offset >= self.trailerOffset {
if err := self.processTrailer(); err != nil && err != io.EOF {
utils.Logger.Err(fmt.Sprintf(" Read trailer error: %s ", err.Error()))
@@ -157,24 +157,24 @@ func (self *FwvRecordsProcessor) recordPassesCfgFilter(record, configKey string)
}
// Converts a record (header or normal) to StoredCdr
-func (self *FwvRecordsProcessor) recordToStoredCdr(record string, cfgKey string) (*engine.StoredCdr, error) {
+func (self *FwvRecordsProcessor) recordToStoredCdr(record string, cfgKey string) (*engine.CDR, error) {
var err error
var lazyHttpFields []*config.CfgCdrField
var cfgFields []*config.CfgCdrField
var duMultiplyFactor float64
- var storedCdr *engine.StoredCdr
+ var storedCdr *engine.CDR
if self.headerCdr != nil { // Clone the header CDR so we can use it as base to future processing (inherit fields defined there)
storedCdr = self.headerCdr.Clone()
} else {
- storedCdr = &engine.StoredCdr{CdrHost: "0.0.0.0", ExtraFields: make(map[string]string), Cost: -1}
+ storedCdr = &engine.CDR{OriginHost: "0.0.0.0", ExtraFields: make(map[string]string), Cost: -1}
}
if cfgKey == "*header" {
cfgFields = self.dfltCfg.HeaderFields
- storedCdr.CdrSource = self.dfltCfg.CdrSourceId
+ storedCdr.Source = self.dfltCfg.CdrSourceId
duMultiplyFactor = self.dfltCfg.DataUsageMultiplyFactor
} else {
cfgFields = self.cdrcCfgs[cfgKey].ContentFields
- storedCdr.CdrSource = self.cdrcCfgs[cfgKey].CdrSourceId
+ storedCdr.Source = self.cdrcCfgs[cfgKey].CdrSourceId
duMultiplyFactor = self.cdrcCfgs[cfgKey].DataUsageMultiplyFactor
}
for _, cdrFldCfg := range cfgFields {
@@ -202,10 +202,10 @@ func (self *FwvRecordsProcessor) recordToStoredCdr(record string, cfgKey string)
return nil, err
}
}
- if storedCdr.CgrId == "" && storedCdr.AccId != "" && cfgKey != "*header" {
- storedCdr.CgrId = utils.Sha1(storedCdr.AccId, storedCdr.SetupTime.UTC().String())
+ if storedCdr.CGRID == "" && storedCdr.OriginID != "" && cfgKey != "*header" {
+ storedCdr.CGRID = utils.Sha1(storedCdr.OriginID, storedCdr.SetupTime.UTC().String())
}
- if storedCdr.TOR == utils.DATA && duMultiplyFactor != 0 {
+ if storedCdr.ToR == utils.DATA && duMultiplyFactor != 0 {
storedCdr.Usage = time.Duration(float64(storedCdr.Usage.Nanoseconds()) * duMultiplyFactor)
}
for _, httpFieldCfg := range lazyHttpFields { // Lazy process the http fields
diff --git a/cdre/cdrexporter.go b/cdre/cdrexporter.go
index 0e9fddc81..00fbe67d9 100644
--- a/cdre/cdrexporter.go
+++ b/cdre/cdrexporter.go
@@ -52,7 +52,7 @@ const (
var err error
-func NewCdrExporter(cdrs []*engine.StoredCdr, cdrDb engine.CdrStorage, exportTpl *config.CdreConfig, cdrFormat string, fieldSeparator rune, exportId string,
+func NewCdrExporter(cdrs []*engine.CDR, cdrDb engine.CdrStorage, exportTpl *config.CdreConfig, cdrFormat string, fieldSeparator rune, exportId string,
dataUsageMultiplyFactor, smsUsageMultiplyFactor, genericUsageMultiplyFactor, costMultiplyFactor float64,
costShiftDigits, roundDecimals, cgrPrecision int, maskDestId string, maskLen int, httpSkipTlsCheck bool, timezone string) (*CdrExporter, error) {
if len(cdrs) == 0 { // Nothing to export
@@ -84,7 +84,7 @@ func NewCdrExporter(cdrs []*engine.StoredCdr, cdrDb engine.CdrStorage, exportTpl
}
type CdrExporter struct {
- cdrs []*engine.StoredCdr
+ cdrs []*engine.CDR
cdrDb engine.CdrStorage // Used to extract cost_details if these are requested
exportTemplate *config.CdreConfig
cdrFormat string // csv, fwv
@@ -107,14 +107,14 @@ type CdrExporter struct {
totalCost float64
firstExpOrderId, lastExpOrderId int64
- positiveExports []string // CGRIds of successfully exported CDRs
- negativeExports map[string]string // CgrIds of failed exports
+ positiveExports []string // CGRIDs of successfully exported CDRs
+ negativeExports map[string]string // CGRIDs of failed exports
}
// Return Json marshaled callCost attached to
// Keep it separately so we test only this part in local tests
-func (cdre *CdrExporter) getCdrCostDetails(cgrId, runId string) (string, error) {
- cc, err := cdre.cdrDb.GetCallCostLog(cgrId, "", runId)
+func (cdre *CdrExporter) getCdrCostDetails(CGRID, runId string) (string, error) {
+ cc, err := cdre.cdrDb.GetCallCostLog(CGRID, runId)
if err != nil {
return "", err
} else if cc == nil {
@@ -124,7 +124,7 @@ func (cdre *CdrExporter) getCdrCostDetails(cgrId, runId string) (string, error)
return string(ccJson), nil
}
-func (cdre *CdrExporter) getCombimedCdrFieldVal(processedCdr *engine.StoredCdr, cfgCdrFld *config.CfgCdrField) (string, error) {
+func (cdre *CdrExporter) getCombimedCdrFieldVal(processedCdr *engine.CDR, cfgCdrFld *config.CfgCdrField) (string, error) {
var combinedVal string // Will result as combination of the field values, filters must match
for _, filterRule := range cfgCdrFld.FieldFilter {
fltrPass, ftrPassValue := processedCdr.PassesFieldFilter(filterRule)
@@ -132,7 +132,7 @@ func (cdre *CdrExporter) getCombimedCdrFieldVal(processedCdr *engine.StoredCdr,
return "", nil
}
for _, cdr := range cdre.cdrs {
- if cdr.CgrId != processedCdr.CgrId {
+ if cdr.CGRID != processedCdr.CGRID {
continue // We only care about cdrs with same primary cdr behind
}
if cdr.FieldAsString(&utils.RSRField{Id: filterRule.Id}) == ftrPassValue { // First CDR with filte
@@ -153,7 +153,7 @@ func (cdre *CdrExporter) maskedDestination(destination string) bool {
return false
}
-func (cdre *CdrExporter) getDateTimeFieldVal(cdr *engine.StoredCdr, cfgCdrFld *config.CfgCdrField) (string, error) {
+func (cdre *CdrExporter) getDateTimeFieldVal(cdr *engine.CDR, cfgCdrFld *config.CfgCdrField) (string, error) {
if len(cfgCdrFld.Value) == 0 {
return "", nil
}
@@ -174,7 +174,7 @@ func (cdre *CdrExporter) getDateTimeFieldVal(cdr *engine.StoredCdr, cfgCdrFld *c
}
// Extracts the value specified by cfgHdr out of cdr
-func (cdre *CdrExporter) cdrFieldValue(cdr *engine.StoredCdr, cfgCdrFld *config.CfgCdrField) (string, error) {
+func (cdre *CdrExporter) cdrFieldValue(cdr *engine.CDR, cfgCdrFld *config.CfgCdrField) (string, error) {
for _, fltrRl := range cfgCdrFld.FieldFilter {
if fltrPass, _ := cdr.PassesFieldFilter(fltrRl); !fltrPass {
return "", fmt.Errorf("Field: %s not matching filter rule %v", fltrRl.Id, fltrRl)
@@ -189,7 +189,7 @@ func (cdre *CdrExporter) cdrFieldValue(cdr *engine.StoredCdr, cfgCdrFld *config.
var cdrVal string
switch rsrFld.Id {
case COST_DETAILS: // Special case when we need to further extract cost_details out of logDb
- if cdr.ExtraFields[COST_DETAILS], err = cdre.getCdrCostDetails(cdr.CgrId, cdr.MediationRunId); err != nil {
+ if cdr.ExtraFields[COST_DETAILS], err = cdre.getCdrCostDetails(cdr.CGRID, cdr.RunID); err != nil {
return "", err
} else {
cdrVal = cdr.FieldAsString(rsrFld)
@@ -229,16 +229,16 @@ func (cdre *CdrExporter) metaHandler(tag, arg string) (string, error) {
case META_NRCDRS:
return strconv.Itoa(cdre.numberOfRecords), nil
case META_DURCDRS:
- emulatedCdr := &engine.StoredCdr{TOR: utils.VOICE, Usage: cdre.totalDuration}
+ emulatedCdr := &engine.CDR{ToR: utils.VOICE, Usage: cdre.totalDuration}
return emulatedCdr.FormatUsage(arg), nil
case META_SMSUSAGE:
- emulatedCdr := &engine.StoredCdr{TOR: utils.SMS, Usage: cdre.totalSmsUsage}
+ emulatedCdr := &engine.CDR{ToR: utils.SMS, Usage: cdre.totalSmsUsage}
return emulatedCdr.FormatUsage(arg), nil
case META_GENERICUSAGE:
- emulatedCdr := &engine.StoredCdr{TOR: utils.GENERIC, Usage: cdre.totalGenericUsage}
+ emulatedCdr := &engine.CDR{ToR: utils.GENERIC, Usage: cdre.totalGenericUsage}
return emulatedCdr.FormatUsage(arg), nil
case META_DATAUSAGE:
- emulatedCdr := &engine.StoredCdr{TOR: utils.DATA, Usage: cdre.totalDataUsage}
+ emulatedCdr := &engine.CDR{ToR: utils.DATA, Usage: cdre.totalDataUsage}
return emulatedCdr.FormatUsage(arg), nil
case META_COSTCDRS:
return strconv.FormatFloat(utils.Round(cdre.totalCost, cdre.roundDecimals, utils.ROUNDING_MIDDLE), 'f', -1, 64), nil
@@ -311,18 +311,18 @@ func (cdre *CdrExporter) composeTrailer() error {
}
// Write individual cdr into content buffer, build stats
-func (cdre *CdrExporter) processCdr(cdr *engine.StoredCdr) error {
- if cdr == nil || len(cdr.CgrId) == 0 { // We do not export empty CDRs
+func (cdre *CdrExporter) processCdr(cdr *engine.CDR) error {
+ if cdr == nil || len(cdr.CGRID) == 0 { // We do not export empty CDRs
return nil
} else if cdr.ExtraFields == nil { // Avoid assignment in nil map if not initialized
cdr.ExtraFields = make(map[string]string)
}
// Cost multiply
- if cdre.dataUsageMultiplyFactor != 0.0 && cdr.TOR == utils.DATA {
+ if cdre.dataUsageMultiplyFactor != 0.0 && cdr.ToR == utils.DATA {
cdr.UsageMultiply(cdre.dataUsageMultiplyFactor, cdre.cgrPrecision)
- } else if cdre.smsUsageMultiplyFactor != 0 && cdr.TOR == utils.SMS {
+ } else if cdre.smsUsageMultiplyFactor != 0 && cdr.ToR == utils.SMS {
cdr.UsageMultiply(cdre.smsUsageMultiplyFactor, cdre.cgrPrecision)
- } else if cdre.genericUsageMultiplyFactor != 0 && cdr.TOR == utils.GENERIC {
+ } else if cdre.genericUsageMultiplyFactor != 0 && cdr.ToR == utils.GENERIC {
cdr.UsageMultiply(cdre.genericUsageMultiplyFactor, cdre.cgrPrecision)
}
if cdre.costMultiplyFactor != 0.0 {
@@ -363,12 +363,12 @@ func (cdre *CdrExporter) processCdr(cdr *engine.StoredCdr) error {
}
}
if err != nil {
- utils.Logger.Err(fmt.Sprintf(" Cannot export CDR with cgrid: %s and runid: %s, error: %s", cdr.CgrId, cdr.MediationRunId, err.Error()))
+ utils.Logger.Err(fmt.Sprintf(" Cannot export CDR with CGRID: %s and runid: %s, error: %s", cdr.CGRID, cdr.RunID, err.Error()))
return err
}
fmtOut := outVal
if fmtOut, err = utils.FmtFieldWidth(outVal, cfgFld.Width, cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory); err != nil {
- utils.Logger.Err(fmt.Sprintf(" Cannot export CDR with cgrid: %s, runid: %s, fieldName: %s, fieldValue: %s, error: %s", cdr.CgrId, cdr.MediationRunId, cfgFld.Tag, outVal, err.Error()))
+ utils.Logger.Err(fmt.Sprintf(" Cannot export CDR with CGRID: %s, runid: %s, fieldName: %s, fieldValue: %s, error: %s", cdr.CGRID, cdr.RunID, cfgFld.Tag, outVal, err.Error()))
return err
}
cdrRow[idx] += fmtOut
@@ -386,27 +386,27 @@ func (cdre *CdrExporter) processCdr(cdr *engine.StoredCdr) error {
cdre.lastCdrATime = cdr.AnswerTime
}
cdre.numberOfRecords += 1
- if cdr.TOR == utils.VOICE { // Only count duration for non data cdrs
+ if cdr.ToR == utils.VOICE { // Only count duration for non data cdrs
cdre.totalDuration += cdr.Usage
}
- if cdr.TOR == utils.SMS { // Count usage for SMS
+ if cdr.ToR == utils.SMS { // Count usage for SMS
cdre.totalSmsUsage += cdr.Usage
}
- if cdr.TOR == utils.GENERIC { // Count usage for GENERIC
+ if cdr.ToR == utils.GENERIC { // Count usage for GENERIC
cdre.totalGenericUsage += cdr.Usage
}
- if cdr.TOR == utils.DATA { // Count usage for DATA
+ if cdr.ToR == utils.DATA { // Count usage for DATA
cdre.totalDataUsage += cdr.Usage
}
if cdr.Cost != -1 {
cdre.totalCost += cdr.Cost
cdre.totalCost = utils.Round(cdre.totalCost, cdre.roundDecimals, utils.ROUNDING_MIDDLE)
}
- if cdre.firstExpOrderId > cdr.OrderId || cdre.firstExpOrderId == 0 {
- cdre.firstExpOrderId = cdr.OrderId
+ if cdre.firstExpOrderId > cdr.OrderID || cdre.firstExpOrderId == 0 {
+ cdre.firstExpOrderId = cdr.OrderID
}
- if cdre.lastExpOrderId < cdr.OrderId {
- cdre.lastExpOrderId = cdr.OrderId
+ if cdre.lastExpOrderId < cdr.OrderID {
+ cdre.lastExpOrderId = cdr.OrderID
}
return nil
}
@@ -415,9 +415,9 @@ func (cdre *CdrExporter) processCdr(cdr *engine.StoredCdr) error {
func (cdre *CdrExporter) processCdrs() error {
for _, cdr := range cdre.cdrs {
if err := cdre.processCdr(cdr); err != nil {
- cdre.negativeExports[cdr.CgrId] = err.Error()
+ cdre.negativeExports[cdr.CGRID] = err.Error()
} else {
- cdre.positiveExports = append(cdre.positiveExports, cdr.CgrId)
+ cdre.positiveExports = append(cdre.positiveExports, cdr.CGRID)
}
}
// Process header and trailer after processing cdrs since the metatag functions can access stats out of built cdrs
@@ -524,12 +524,12 @@ func (cdre *CdrExporter) TotalExportedCdrs() int {
return cdre.numberOfRecords
}
-// Return successfully exported CgrIds
+// Return successfully exported CGRIDs
func (cdre *CdrExporter) PositiveExports() []string {
return cdre.positiveExports
}
-// Return failed exported CgrIds together with the reason
+// Return failed exported CGRIDs together with the reason
func (cdre *CdrExporter) NegativeExports() map[string]string {
return cdre.negativeExports
}
diff --git a/cdre/cdrexporter_test.go b/cdre/cdrexporter_test.go
index a2f7f2763..0960c8b8f 100644
--- a/cdre/cdrexporter_test.go
+++ b/cdre/cdrexporter_test.go
@@ -29,34 +29,34 @@ import (
func TestCdreGetCombimedCdrFieldVal(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
- cdrs := []*engine.StoredCdr{
- &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdrs := []*engine.CDR{
+ &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
- Usage: time.Duration(10) * time.Second, MediationRunId: "RUN_RTL", Cost: 1.01},
- &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf2", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ Usage: time.Duration(10) * time.Second, RunID: "RUN_RTL", Cost: 1.01},
+ &engine.CDR{CGRID: utils.Sha1("dsafdsaf2", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
- Usage: time.Duration(10) * time.Second, MediationRunId: "CUSTOMER1", Cost: 2.01},
- &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ Usage: time.Duration(10) * time.Second, RunID: "CUSTOMER1", Cost: 2.01},
+ &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
- Usage: time.Duration(10) * time.Second, MediationRunId: "CUSTOMER1", Cost: 3.01},
- &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ Usage: time.Duration(10) * time.Second, RunID: "CUSTOMER1", Cost: 3.01},
+ &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
- Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 4.01},
- &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 4.01},
+ &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "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},
+ Usage: time.Duration(10) * time.Second, RunID: "RETAIL1", Cost: 5.01},
}
cdre, err := NewCdrExporter(cdrs, nil, cfg.CdreProfiles["*default"], cfg.CdreProfiles["*default"].CdrFormat, cfg.CdreProfiles["*default"].FieldSeparator,
"firstexport", 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "")
if err != nil {
t.Error("Unexpected error received: ", err)
}
- fltrRule, _ := utils.ParseRSRFields("~MediationRunId:s/default/RUN_RTL/", utils.INFIELD_SEP)
+ fltrRule, _ := utils.ParseRSRFields("~RunID:s/default/RUN_RTL/", utils.INFIELD_SEP)
val, _ := utils.ParseRSRFields(utils.COST, utils.INFIELD_SEP)
cfgCdrFld := &config.CfgCdrField{Tag: "cost", Type: "cdrfield", FieldId: utils.COST, Value: val, FieldFilter: fltrRule}
if costVal, err := cdre.getCombimedCdrFieldVal(cdrs[3], cfgCdrFld); err != nil {
@@ -64,7 +64,7 @@ func TestCdreGetCombimedCdrFieldVal(t *testing.T) {
} else if costVal != "1.01" {
t.Error("Expecting: 1.01, received: ", costVal)
}
- fltrRule, _ = utils.ParseRSRFields("~MediationRunId:s/default/RETAIL1/", utils.INFIELD_SEP)
+ fltrRule, _ = utils.ParseRSRFields("~RunID:s/default/RETAIL1/", utils.INFIELD_SEP)
val, _ = utils.ParseRSRFields(utils.ACCOUNT, utils.INFIELD_SEP)
cfgCdrFld = &config.CfgCdrField{Tag: utils.ACCOUNT, Type: "cdrfield", FieldId: utils.ACCOUNT, Value: val, FieldFilter: fltrRule}
if acntVal, err := cdre.getCombimedCdrFieldVal(cdrs[3], cfgCdrFld); err != nil {
@@ -76,10 +76,10 @@ func TestCdreGetCombimedCdrFieldVal(t *testing.T) {
func TestGetDateTimeFieldVal(t *testing.T) {
cdreTst := new(CdrExporter)
- cdrTst := &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdrTst := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
- Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.01,
+ Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 1.01,
ExtraFields: map[string]string{"stop_time": "2014-06-11 19:19:00 +0000 UTC", "fieldextr2": "valextr2"}}
val, _ := utils.ParseRSRFields("stop_time", utils.INFIELD_SEP)
layout := "2006-01-02 15:04:05"
@@ -105,10 +105,10 @@ func TestGetDateTimeFieldVal(t *testing.T) {
func TestCdreCdrFieldValue(t *testing.T) {
cdre := new(CdrExporter)
- cdr := &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdr := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
- Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.01}
+ Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 1.01}
val, _ := utils.ParseRSRFields(utils.DESTINATION, utils.INFIELD_SEP)
cfgCdrFld := &config.CfgCdrField{Tag: "destination", Type: "cdrfield", FieldId: utils.DESTINATION, Value: val}
if val, err := cdre.cdrFieldValue(cdr, cfgCdrFld); err != nil {
diff --git a/cdre/csv_test.go b/cdre/csv_test.go
index 647f8379a..0990c7a80 100644
--- a/cdre/csv_test.go
+++ b/cdre/csv_test.go
@@ -33,13 +33,14 @@ import (
func TestCsvCdrWriter(t *testing.T) {
writer := &bytes.Buffer{}
cfg, _ := config.NewDefaultCGRConfig()
- storedCdr1 := &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ storedCdr1 := &engine.CDR{
+ CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
- Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID,
ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01,
}
- cdre, err := NewCdrExporter([]*engine.StoredCdr{storedCdr1}, nil, cfg.CdreProfiles["*default"], utils.CSV, ',', "firstexport", 0.0, 0.0, 0.0, 0.0, 0, 4,
+ cdre, err := NewCdrExporter([]*engine.CDR{storedCdr1}, nil, cfg.CdreProfiles["*default"], utils.CSV, ',', "firstexport", 0.0, 0.0, 0.0, 0.0, 0, 4,
cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "")
if err != nil {
t.Error("Unexpected error received: ", err)
@@ -61,13 +62,13 @@ func TestCsvCdrWriter(t *testing.T) {
func TestAlternativeFieldSeparator(t *testing.T) {
writer := &bytes.Buffer{}
cfg, _ := config.NewDefaultCGRConfig()
- storedCdr1 := &engine.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
- ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ storedCdr1 := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
- Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID,
ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01,
}
- cdre, err := NewCdrExporter([]*engine.StoredCdr{storedCdr1}, nil, cfg.CdreProfiles["*default"], utils.CSV, '|',
+ cdre, err := NewCdrExporter([]*engine.CDR{storedCdr1}, nil, cfg.CdreProfiles["*default"], utils.CSV, '|',
"firstexport", 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "")
if err != nil {
t.Error("Unexpected error received: ", err)
diff --git a/cdre/fixedwidth_test.go b/cdre/fixedwidth_test.go
index f0e15a71f..ffdd1f747 100644
--- a/cdre/fixedwidth_test.go
+++ b/cdre/fixedwidth_test.go
@@ -118,16 +118,16 @@ func TestWriteCdr(t *testing.T) {
ContentFields: contentCfgFlds,
TrailerFields: trailerCfgFlds,
}
- cdr := &engine.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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdr := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()),
+ ToR: utils.VOICE, OrderID: 1, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
+ RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
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, MediationRunId: utils.DEFAULT_RUNID, Cost: 2.34567,
+ Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 2.34567,
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
- cdre, err := NewCdrExporter([]*engine.StoredCdr{cdr}, nil, cdreCfg, utils.CDRE_FIXED_WIDTH, ',', "fwv_1", 0.0, 0.0, 0.0, 0.0, 0, 4,
+ cdre, err := NewCdrExporter([]*engine.CDR{cdr}, nil, cdreCfg, utils.CDRE_FIXED_WIDTH, ',', "fwv_1", 0.0, 0.0, 0.0, 0.0, 0, 4,
cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify, "")
if err != nil {
t.Error(err)
@@ -176,33 +176,33 @@ func TestWriteCdrs(t *testing.T) {
ContentFields: contentCfgFlds,
TrailerFields: trailerCfgFlds,
}
- cdr1 := &engine.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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdr1 := &engine.CDR{CGRID: utils.Sha1("aaa1", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()),
+ ToR: utils.VOICE, OrderID: 2, OriginID: "aaa1", OriginHost: "192.168.1.1", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
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),
- Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 2.25,
+ Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 2.25,
ExtraFields: map[string]string{"productnumber": "12341", "fieldextr2": "valextr2"},
}
- cdr2 := &engine.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: utils.META_PREPAID, Direction: "*out", Tenant: "cgrates.org",
+ cdr2 := &engine.CDR{CGRID: utils.Sha1("aaa2", time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC).String()),
+ ToR: utils.VOICE, OrderID: 4, OriginID: "aaa2", OriginHost: "192.168.1.2", RequestType: utils.META_PREPAID, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1002", Subject: "1002", Destination: "1011",
SetupTime: time.Date(2013, 11, 7, 7, 42, 20, 0, time.UTC),
AnswerTime: time.Date(2013, 11, 7, 7, 42, 26, 0, time.UTC),
- Usage: time.Duration(5) * time.Minute, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.40001,
+ Usage: time.Duration(5) * time.Minute, RunID: utils.DEFAULT_RUNID, Cost: 1.40001,
ExtraFields: map[string]string{"productnumber": "12342", "fieldextr2": "valextr2"},
}
- cdr3 := &engine.StoredCdr{}
- cdr4 := &engine.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: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
+ cdr3 := &engine.CDR{}
+ cdr4 := &engine.CDR{CGRID: utils.Sha1("aaa3", time.Date(2013, 11, 7, 9, 42, 18, 0, time.UTC).String()),
+ ToR: utils.VOICE, OrderID: 3, OriginID: "aaa4", OriginHost: "192.168.1.4", RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1004", Subject: "1004", Destination: "1013",
SetupTime: time.Date(2013, 11, 7, 9, 42, 18, 0, time.UTC),
AnswerTime: time.Date(2013, 11, 7, 9, 42, 26, 0, time.UTC),
- Usage: time.Duration(20) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 2.34567,
+ Usage: time.Duration(20) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 2.34567,
ExtraFields: map[string]string{"productnumber": "12344", "fieldextr2": "valextr2"},
}
cfg, _ := config.NewDefaultCGRConfig()
- cdre, err := NewCdrExporter([]*engine.StoredCdr{cdr1, cdr2, cdr3, cdr4}, nil, cdreCfg, utils.CDRE_FIXED_WIDTH, ',',
+ cdre, err := NewCdrExporter([]*engine.CDR{cdr1, cdr2, cdr3, cdr4}, nil, cdreCfg, utils.CDRE_FIXED_WIDTH, ',',
"fwv_1", 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify, "")
if err != nil {
t.Error(err)
diff --git a/cmd/cgr-loader/migrator_rc8.go b/cmd/cgr-loader/migrator_rc8.go
index 5f5b29671..421da2e40 100644
--- a/cmd/cgr-loader/migrator_rc8.go
+++ b/cmd/cgr-loader/migrator_rc8.go
@@ -430,7 +430,7 @@ func (mig MigratorRC8) migrateDerivedChargers() error {
}
}
newDcs := &utils.DerivedChargers{
- DestinationIds: make(utils.StringMap),
+ DestinationIDs: make(utils.StringMap),
Chargers: oldDcs,
}
newDcsMap[key] = newDcs
diff --git a/config/cdreconfig.go b/config/cdreconfig.go
index fd1e78ee2..55a98c3b5 100644
--- a/config/cdreconfig.go
+++ b/config/cdreconfig.go
@@ -23,14 +23,14 @@ type CdreConfig struct {
CdrFormat string
FieldSeparator rune
DataUsageMultiplyFactor float64
- SmsUsageMultiplyFactor float64
+ SMSUsageMultiplyFactor float64
GenericUsageMultiplyFactor float64
CostMultiplyFactor float64
CostRoundingDecimals int
CostShiftDigits int
- MaskDestId string
+ MaskDestinationID string
MaskLength int
- ExportDir string
+ ExportFolder string
HeaderFields []*CfgCdrField
ContentFields []*CfgCdrField
TrailerFields []*CfgCdrField
@@ -52,7 +52,7 @@ func (self *CdreConfig) loadFromJsonCfg(jsnCfg *CdreJsonCfg) error {
self.DataUsageMultiplyFactor = *jsnCfg.Data_usage_multiply_factor
}
if jsnCfg.Sms_usage_multiply_factor != nil {
- self.SmsUsageMultiplyFactor = *jsnCfg.Sms_usage_multiply_factor
+ self.SMSUsageMultiplyFactor = *jsnCfg.Sms_usage_multiply_factor
}
if jsnCfg.Generic_usage_multiply_factor != nil {
self.GenericUsageMultiplyFactor = *jsnCfg.Generic_usage_multiply_factor
@@ -67,13 +67,13 @@ func (self *CdreConfig) loadFromJsonCfg(jsnCfg *CdreJsonCfg) error {
self.CostShiftDigits = *jsnCfg.Cost_shift_digits
}
if jsnCfg.Mask_destination_id != nil {
- self.MaskDestId = *jsnCfg.Mask_destination_id
+ self.MaskDestinationID = *jsnCfg.Mask_destination_id
}
if jsnCfg.Mask_length != nil {
self.MaskLength = *jsnCfg.Mask_length
}
- if jsnCfg.Export_dir != nil {
- self.ExportDir = *jsnCfg.Export_dir
+ if jsnCfg.Export_folder != nil {
+ self.ExportFolder = *jsnCfg.Export_folder
}
if jsnCfg.Header_fields != nil {
if self.HeaderFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Header_fields); err != nil {
@@ -99,14 +99,14 @@ func (self *CdreConfig) Clone() *CdreConfig {
clnCdre.CdrFormat = self.CdrFormat
clnCdre.FieldSeparator = self.FieldSeparator
clnCdre.DataUsageMultiplyFactor = self.DataUsageMultiplyFactor
- clnCdre.SmsUsageMultiplyFactor = self.SmsUsageMultiplyFactor
+ clnCdre.SMSUsageMultiplyFactor = self.SMSUsageMultiplyFactor
clnCdre.GenericUsageMultiplyFactor = self.GenericUsageMultiplyFactor
clnCdre.CostMultiplyFactor = self.CostMultiplyFactor
clnCdre.CostRoundingDecimals = self.CostRoundingDecimals
clnCdre.CostShiftDigits = self.CostShiftDigits
- clnCdre.MaskDestId = self.MaskDestId
+ clnCdre.MaskDestinationID = self.MaskDestinationID
clnCdre.MaskLength = self.MaskLength
- clnCdre.ExportDir = self.ExportDir
+ clnCdre.ExportFolder = self.ExportFolder
clnCdre.HeaderFields = make([]*CfgCdrField, len(self.HeaderFields))
for idx, fld := range self.HeaderFields {
clonedVal := *fld
diff --git a/config/cdreconfig_test.go b/config/cdreconfig_test.go
index 84a95d8f4..66e054d34 100644
--- a/config/cdreconfig_test.go
+++ b/config/cdreconfig_test.go
@@ -44,9 +44,9 @@ func TestCdreCfgClone(t *testing.T) {
CostMultiplyFactor: 1.0,
CostRoundingDecimals: -1,
CostShiftDigits: 0,
- MaskDestId: "MASKED_DESTINATIONS",
+ MaskDestinationID: "MASKED_DESTINATIONS",
MaskLength: 0,
- ExportDir: "/var/log/cgrates/cdre",
+ ExportFolder: "/var/log/cgrates/cdre",
ContentFields: initContentFlds,
}
eClnContentFlds := []*CfgCdrField{
@@ -66,9 +66,9 @@ func TestCdreCfgClone(t *testing.T) {
CostMultiplyFactor: 1.0,
CostRoundingDecimals: -1,
CostShiftDigits: 0,
- MaskDestId: "MASKED_DESTINATIONS",
+ MaskDestinationID: "MASKED_DESTINATIONS",
MaskLength: 0,
- ExportDir: "/var/log/cgrates/cdre",
+ ExportFolder: "/var/log/cgrates/cdre",
HeaderFields: emptyFields,
ContentFields: eClnContentFlds,
TrailerFields: emptyFields,
diff --git a/config/cfg_data.json b/config/cfg_data.json
index a6acc1ee6..77f20a7da 100644
--- a/config/cfg_data.json
+++ b/config/cfg_data.json
@@ -33,7 +33,7 @@
"run_delay": 1,
"cdr_source_id": "csv2", // free form field, tag identifying the source of the CDRs within CDRS database
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
- {"field_id": "TOR", "value": "~7:s/^(voice|data|sms|generic)$/*$1/"},
+ {"field_id": "ToR", "value": "~7:s/^(voice|data|sms|generic)$/*$1/"},
{"field_id": "AnswerTime", "value": "1"},
{"field_id": "Usage", "value": "~9:s/^(\\d+)$/${1}s/"},
],
diff --git a/config/cfg_data2.json b/config/cfg_data2.json
index 822dd1f09..67b846168 100644
--- a/config/cfg_data2.json
+++ b/config/cfg_data2.json
@@ -8,7 +8,7 @@
"data_usage_multiply_factor": 0.000976563,
"cdr_source_id": "csv2", // free form field, tag identifying the source of the CDRs within CDRS database
"content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
- {"field_id": "TOR", "value": "~7:s/^(voice|data|sms|generic)$/*$1/"},
+ {"field_id": "ToR", "value": "~7:s/^(voice|data|sms|generic)$/*$1/"},
{"field_id": "AnswerTime", "value": "2"},
],
},
diff --git a/config/config_defaults.go b/config/config_defaults.go
index fa1a60cb8..b3ac16feb 100644
--- a/config/config_defaults.go
+++ b/config/config_defaults.go
@@ -133,20 +133,20 @@ const CGRATES_CFG_JSON = `
"field_separator": ",",
"data_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from KBytes to Bytes)
"sms_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from SMS unit to call duration in some billing systems)
- "generic_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from GENERIC unit to call duration in some billing systems)
+ "generic_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from GENERIC unit to call duration in some billing systems)
"cost_multiply_factor": 1, // multiply cost before export, eg: add VAT
"cost_rounding_decimals": -1, // rounding decimals for Cost values. -1 to disable rounding
"cost_shift_digits": 0, // shift digits in the cost on export (eg: convert from EUR to cents)
"mask_destination_id": "MASKED_DESTINATIONS", // destination id containing called addresses to be masked on export
"mask_length": 0, // length of the destination suffix to be masked
- "export_dir": "/var/log/cgrates/cdre", // path where the exported CDRs will be placed
+ "export_folder": "/var/log/cgrates/cdre", // path where the exported CDRs will be placed
"header_fields": [], // template of the exported header fields
"content_fields": [ // template of the exported content fields
- {"tag": "CgrId", "field_id": "CgrId", "type": "*composed", "value": "CgrId"},
- {"tag":"RunId", "field_id": "MediationRunId", "type": "*composed", "value": "MediationRunId"},
- {"tag":"Tor", "field_id": "TOR", "type": "*composed", "value": "TOR"},
- {"tag":"AccId", "field_id": "AccId", "type": "*composed", "value": "AccId"},
- {"tag":"ReqType", "field_id": "ReqType", "type": "*composed", "value": "ReqType"},
+ {"tag": "CGRID", "field_id": "CGRID", "type": "*composed", "value": "CGRID"},
+ {"tag":"RunID", "field_id": "RunID", "type": "*composed", "value": "RunID"},
+ {"tag":"TOR", "field_id": "ToR", "type": "*composed", "value": "ToR"},
+ {"tag":"OriginID", "field_id": "OriginID", "type": "*composed", "value": "OriginID"},
+ {"tag":"RequestType", "field_id": "RequestType", "type": "*composed", "value": "RequestType"},
{"tag":"Direction", "field_id": "Direction", "type": "*composed", "value": "Direction"},
{"tag":"Tenant", "field_id": "Tenant", "type": "*composed", "value": "Tenant"},
{"tag":"Category", "field_id": "Category", "type": "*composed", "value": "Category"},
@@ -183,18 +183,18 @@ const CGRATES_CFG_JSON = `
"partial_record_cache": "10s", // duration to cache partial records when not pairing
"header_fields": [], // template of the import header fields
"content_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
- {"tag": "tor", "field_id": "TOR", "type": "*composed", "value": "2", "mandatory": true},
- {"tag": "accid", "field_id": "AccId", "type": "*composed", "value": "3", "mandatory": true},
- {"tag": "reqtype", "field_id": "ReqType", "type": "*composed", "value": "4", "mandatory": true},
- {"tag": "direction", "field_id": "Direction", "type": "*composed", "value": "5", "mandatory": true},
- {"tag": "tenant", "field_id": "Tenant", "type": "*composed", "value": "6", "mandatory": true},
- {"tag": "category", "field_id": "Category", "type": "*composed", "value": "7", "mandatory": true},
- {"tag": "account", "field_id": "Account", "type": "*composed", "value": "8", "mandatory": true},
- {"tag": "subject", "field_id": "Subject", "type": "*composed", "value": "9", "mandatory": true},
- {"tag": "destination", "field_id": "Destination", "type": "*composed", "value": "10", "mandatory": true},
- {"tag": "setup_time", "field_id": "SetupTime", "type": "*composed", "value": "11", "mandatory": true},
- {"tag": "answer_time", "field_id": "AnswerTime", "type": "*composed", "value": "12", "mandatory": true},
- {"tag": "usage", "field_id": "Usage", "type": "*composed", "value": "13", "mandatory": true},
+ {"tag": "TOR", "field_id": "ToR", "type": "*composed", "value": "2", "mandatory": true},
+ {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "3", "mandatory": true},
+ {"tag": "RequestType", "field_id": "RequestType", "type": "*composed", "value": "4", "mandatory": true},
+ {"tag": "Direction", "field_id": "Direction", "type": "*composed", "value": "5", "mandatory": true},
+ {"tag": "Tenant", "field_id": "Tenant", "type": "*composed", "value": "6", "mandatory": true},
+ {"tag": "Category", "field_id": "Category", "type": "*composed", "value": "7", "mandatory": true},
+ {"tag": "Account", "field_id": "Account", "type": "*composed", "value": "8", "mandatory": true},
+ {"tag": "Subject", "field_id": "Subject", "type": "*composed", "value": "9", "mandatory": true},
+ {"tag": "Destination", "field_id": "Destination", "type": "*composed", "value": "10", "mandatory": true},
+ {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", "value": "11", "mandatory": true},
+ {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", "value": "12", "mandatory": true},
+ {"tag": "Usage", "field_id": "Usage", "type": "*composed", "value": "13", "mandatory": true},
],
"trailer_fields": [], // template of the import trailer fields
}
@@ -297,10 +297,10 @@ const CGRATES_CFG_JSON = `
"dry_run": false, // do not send the CDRs to CDRS, just parse them
"request_filter": "Subscription-Id>Subscription-Id-Type(0)", // filter requests processed by this processor
"continue_on_success": false, // continue to the next template if executed
- "ccr_fields":[ // fields taken out of CCR and used in internal requests
- {"tag": "TOR", "field_id": "TOR", "type": "*composed", "value": "^*voice", "mandatory": true},
- {"tag": "ACCID", "field_id": "AccId", "type": "*composed", "value": "Session-Id", "mandatory": true},
- {"tag": "RequestType", "field_id": "ReqType", "type": "*composed", "value": "^*users", "mandatory": true},
+ "ccr_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
+ {"tag": "TOR", "field_id": "ToR", "type": "*composed", "value": "^*voice", "mandatory": true},
+ {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "Session-Id", "mandatory": true},
+ {"tag": "RequestType", "field_id": "RequestType", "type": "*composed", "value": "^*users", "mandatory": true},
{"tag": "Direction", "field_id": "Direction", "type": "*composed", "value": "^*out", "mandatory": true},
{"tag": "Tenant", "field_id": "Tenant", "type": "*composed", "value": "^*users", "mandatory": true},
{"tag": "Category", "field_id": "Category", "type": "*composed", "value": "^call", "mandatory": true},
@@ -362,7 +362,7 @@ const CGRATES_CFG_JSON = `
"response_group": "03", // determines how taxes are grouped for the response <03|13>
"response_type": "D4", // determines the granularity of taxes and (optionally) the decimal precision for the tax calculations and amounts in the response
"regulatory_code": "03", // provider type
- "client_tracking": "CgrId", // template extracting client information out of StoredCdr; <$RSRFields>
+ "client_tracking": "CGRID", // template extracting client information out of StoredCdr; <$RSRFields>
"customer_number": "Subject", // template extracting customer number out of StoredCdr; <$RSRFields>
"orig_number": "Subject", // template extracting origination number out of StoredCdr; <$RSRFields>
"term_number": "Destination", // template extracting termination number out of StoredCdr; <$RSRFields>
diff --git a/config/config_json_test.go b/config/config_json_test.go
index dba9f6f9d..da14de246 100644
--- a/config/config_json_test.go
+++ b/config/config_json_test.go
@@ -19,6 +19,7 @@ along with this program. If not, see
package config
import (
+ "encoding/json"
"reflect"
"strings"
"testing"
@@ -181,67 +182,67 @@ func TestDfCdrStatsJsonCfg(t *testing.T) {
func TestDfCdreJsonCfgs(t *testing.T) {
eFields := []*CdrFieldJsonCfg{}
eContentFlds := []*CdrFieldJsonCfg{
- &CdrFieldJsonCfg{Tag: utils.StringPointer("CgrId"),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("CGRID"),
Field_id: utils.StringPointer(utils.CGRID),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.CGRID)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("RunId"),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("RunID"),
Field_id: utils.StringPointer(utils.MEDI_RUNID),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.MEDI_RUNID)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("Tor"),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("TOR"),
Field_id: utils.StringPointer(utils.TOR),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.TOR)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("AccId"),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("OriginID"),
Field_id: utils.StringPointer(utils.ACCID),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.ACCID)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("ReqType"),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"),
Field_id: utils.StringPointer(utils.REQTYPE),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.REQTYPE)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"),
Field_id: utils.StringPointer(utils.DIRECTION),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.DIRECTION)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"),
Field_id: utils.StringPointer(utils.TENANT),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.TENANT)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("Category"),
Field_id: utils.StringPointer(utils.CATEGORY),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.CATEGORY)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("Account"),
Field_id: utils.StringPointer(utils.ACCOUNT),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.ACCOUNT)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"),
Field_id: utils.StringPointer(utils.SUBJECT),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.SUBJECT)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"),
Field_id: utils.StringPointer(utils.DESTINATION),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.DESTINATION)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("SetupTime"),
Field_id: utils.StringPointer(utils.SETUP_TIME),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.SETUP_TIME),
Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")},
&CdrFieldJsonCfg{Tag: utils.StringPointer("AnswerTime"),
Field_id: utils.StringPointer(utils.ANSWER_TIME),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.ANSWER_TIME),
Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")},
&CdrFieldJsonCfg{Tag: utils.StringPointer("Usage"),
Field_id: utils.StringPointer(utils.USAGE),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.USAGE)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("Cost"),
Field_id: utils.StringPointer(utils.COST),
- Type: utils.StringPointer("*composed"),
+ Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer(utils.COST)},
}
eCfg := map[string]*CdreJsonCfg{
@@ -256,7 +257,7 @@ func TestDfCdreJsonCfgs(t *testing.T) {
Cost_shift_digits: utils.IntPointer(0),
Mask_destination_id: utils.StringPointer("MASKED_DESTINATIONS"),
Mask_length: utils.IntPointer(0),
- Export_dir: utils.StringPointer("/var/log/cgrates/cdre"),
+ Export_folder: utils.StringPointer("/var/log/cgrates/cdre"),
Header_fields: &eFields,
Content_fields: &eContentFlds,
Trailer_fields: &eFields,
@@ -265,36 +266,38 @@ func TestDfCdreJsonCfgs(t *testing.T) {
if cfg, err := dfCgrJsonCfg.CdreJsonCfgs(); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCfg, cfg) {
- t.Error("Received: ", cfg)
+ expect, _ := json.Marshal(eCfg)
+ received, _ := json.Marshal(cfg)
+ t.Errorf("Expecting: %s, received: %s", string(expect), string(received))
}
}
func TestDfCdrcJsonCfg(t *testing.T) {
eFields := []*CdrFieldJsonCfg{}
cdrFields := []*CdrFieldJsonCfg{
- &CdrFieldJsonCfg{Tag: utils.StringPointer("tor"), Field_id: utils.StringPointer(utils.TOR), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("TOR"), Field_id: utils.StringPointer(utils.TOR), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("2"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("accid"), Field_id: utils.StringPointer(utils.ACCID), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("OriginID"), Field_id: utils.StringPointer(utils.ACCID), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("3"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("reqtype"), Field_id: utils.StringPointer(utils.REQTYPE), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"), Field_id: utils.StringPointer(utils.REQTYPE), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("4"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("direction"), Field_id: utils.StringPointer(utils.DIRECTION), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), Field_id: utils.StringPointer(utils.DIRECTION), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("5"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("tenant"), Field_id: utils.StringPointer(utils.TENANT), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), Field_id: utils.StringPointer(utils.TENANT), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("6"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("category"), Field_id: utils.StringPointer(utils.CATEGORY), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("Category"), Field_id: utils.StringPointer(utils.CATEGORY), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("7"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("account"), Field_id: utils.StringPointer(utils.ACCOUNT), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("Account"), Field_id: utils.StringPointer(utils.ACCOUNT), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("8"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("subject"), Field_id: utils.StringPointer(utils.SUBJECT), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"), Field_id: utils.StringPointer(utils.SUBJECT), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("9"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("destination"), Field_id: utils.StringPointer(utils.DESTINATION), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"), Field_id: utils.StringPointer(utils.DESTINATION), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("10"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("setup_time"), Field_id: utils.StringPointer(utils.SETUP_TIME), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("SetupTime"), Field_id: utils.StringPointer(utils.SETUP_TIME), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("11"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("answer_time"), Field_id: utils.StringPointer(utils.ANSWER_TIME), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("AnswerTime"), Field_id: utils.StringPointer(utils.ANSWER_TIME), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("12"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("usage"), Field_id: utils.StringPointer(utils.USAGE), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("Usage"), Field_id: utils.StringPointer(utils.USAGE), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("13"), Mandatory: utils.BoolPointer(true)},
}
eCfg := map[string]*CdrcJsonCfg{
@@ -466,7 +469,7 @@ func TestDiameterAgentJsonCfg(t *testing.T) {
CCR_fields: &[]*CdrFieldJsonCfg{
&CdrFieldJsonCfg{Tag: utils.StringPointer("TOR"), Field_id: utils.StringPointer(utils.TOR), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("^*voice"), Mandatory: utils.BoolPointer(true)},
- &CdrFieldJsonCfg{Tag: utils.StringPointer("ACCID"), Field_id: utils.StringPointer(utils.ACCID), Type: utils.StringPointer(utils.META_COMPOSED),
+ &CdrFieldJsonCfg{Tag: utils.StringPointer("OriginID"), Field_id: utils.StringPointer(utils.ACCID), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("Session-Id"), Mandatory: utils.BoolPointer(true)},
&CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"), Field_id: utils.StringPointer(utils.REQTYPE), Type: utils.StringPointer(utils.META_COMPOSED),
Value: utils.StringPointer("^*users"), Mandatory: utils.BoolPointer(true)},
@@ -579,7 +582,7 @@ func TestDfSureTaxJsonCfg(t *testing.T) {
Response_group: utils.StringPointer("03"),
Response_type: utils.StringPointer("D4"),
Regulatory_code: utils.StringPointer("03"),
- Client_tracking: utils.StringPointer("CgrId"),
+ Client_tracking: utils.StringPointer(utils.CGRID),
Customer_number: utils.StringPointer("Subject"),
Orig_number: utils.StringPointer("Subject"),
Term_number: utils.StringPointer("Destination"),
diff --git a/config/configcdrc_test.go b/config/configcdrc_test.go
index 7acc357cf..621a07b70 100644
--- a/config/configcdrc_test.go
+++ b/config/configcdrc_test.go
@@ -51,29 +51,29 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
PartialRecordCache: time.Duration(10) * time.Second,
HeaderFields: make([]*CfgCdrField, 0),
ContentFields: []*CfgCdrField{
- &CfgCdrField{Tag: "tor", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "accid", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "reqtype", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "setup_time", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "answer_time", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
},
TrailerFields: make([]*CfgCdrField, 0),
@@ -94,29 +94,29 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
CdrFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP),
HeaderFields: make([]*CfgCdrField, 0),
ContentFields: []*CfgCdrField{
- &CfgCdrField{Tag: "tor", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "accid", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "reqtype", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "setup_time", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "answer_time", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
},
TrailerFields: make([]*CfgCdrField, 0),
@@ -160,29 +160,29 @@ func TestLoadCdrcConfigMultipleFiles(t *testing.T) {
CdrFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP),
HeaderFields: make([]*CfgCdrField, 0),
ContentFields: []*CfgCdrField{
- &CfgCdrField{Tag: "tor", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "TOR", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "accid", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "OriginID", Type: utils.META_COMPOSED, FieldId: utils.ACCID, Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "reqtype", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "RequestType", Type: utils.META_COMPOSED, FieldId: utils.REQTYPE, Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Direction", Type: utils.META_COMPOSED, FieldId: utils.DIRECTION, Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Tenant", Type: utils.META_COMPOSED, FieldId: utils.TENANT, Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Category", Type: utils.META_COMPOSED, FieldId: utils.CATEGORY, Value: utils.ParseRSRFieldsMustCompile("7", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Account", Type: utils.META_COMPOSED, FieldId: utils.ACCOUNT, Value: utils.ParseRSRFieldsMustCompile("8", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Subject", Type: utils.META_COMPOSED, FieldId: utils.SUBJECT, Value: utils.ParseRSRFieldsMustCompile("9", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("10", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "setup_time", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "SetupTime", Type: utils.META_COMPOSED, FieldId: utils.SETUP_TIME, Value: utils.ParseRSRFieldsMustCompile("11", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "answer_time", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "AnswerTime", Type: utils.META_COMPOSED, FieldId: utils.ANSWER_TIME, Value: utils.ParseRSRFieldsMustCompile("12", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
- &CfgCdrField{Tag: "usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
+ &CfgCdrField{Tag: "Usage", Type: utils.META_COMPOSED, FieldId: utils.USAGE, Value: utils.ParseRSRFieldsMustCompile("13", utils.INFIELD_SEP),
FieldFilter: utils.ParseRSRFieldsMustCompile("", utils.INFIELD_SEP), Width: 0, Strip: "", Padding: "", Layout: "", Mandatory: true},
},
TrailerFields: make([]*CfgCdrField, 0),
diff --git a/config/libconfig_json.go b/config/libconfig_json.go
index 556d3be69..3804ec076 100644
--- a/config/libconfig_json.go
+++ b/config/libconfig_json.go
@@ -132,7 +132,7 @@ type CdreJsonCfg struct {
Cost_shift_digits *int
Mask_destination_id *string
Mask_length *int
- Export_dir *string
+ Export_folder *string
Header_fields *[]*CdrFieldJsonCfg
Content_fields *[]*CdrFieldJsonCfg
Trailer_fields *[]*CdrFieldJsonCfg
diff --git a/data/conf/samples/storage/mongo/cgrates.json b/data/conf/samples/storage/mongo/cgrates.json
new file mode 100644
index 000000000..7bd989d5e
--- /dev/null
+++ b/data/conf/samples/storage/mongo/cgrates.json
@@ -0,0 +1,10 @@
+{
+// CGRateS Configuration file used for testing mongo implementation
+
+"stor_db": {
+ "db_type": "mongo", // stor database type to use:
+ "db_port": 27017, // the port to reach the stordb
+},
+
+
+}
diff --git a/data/conf/samples/storage/mysql/cgrates.json b/data/conf/samples/storage/mysql/cgrates.json
new file mode 100644
index 000000000..fd8b92330
--- /dev/null
+++ b/data/conf/samples/storage/mysql/cgrates.json
@@ -0,0 +1,13 @@
+{
+// CGRateS Configuration file used for testing mysql implementation
+
+"stor_db": { // database used to store offline tariff plans and CDRs
+ "db_type": "mysql", // stor database type to use:
+ "db_host": "127.0.0.1", // the host to connect to
+ "db_port": 3306, // the port to reach the stordb
+ "db_name": "cgrates", // stor database name
+ "db_user": "cgrates", // username to use when connecting to stordb
+ "db_passwd": "CGRateS.org", // password to use when connecting to stordb
+},
+
+}
diff --git a/data/conf/samples/storage/postgres/cgrates.json b/data/conf/samples/storage/postgres/cgrates.json
new file mode 100644
index 000000000..d1d700a9d
--- /dev/null
+++ b/data/conf/samples/storage/postgres/cgrates.json
@@ -0,0 +1,13 @@
+{
+// CGRateS Configuration file used for testing mysql implementation
+
+"stor_db": { // database used to store offline tariff plans and CDRs
+ "db_type": "postgres", // stor database type to use:
+ "db_host": "127.0.0.1", // the host to connect to
+ "db_port": 5432, // the port to reach the stordb
+ "db_name": "cgrates", // stor database name
+ "db_user": "cgrates", // username to use when connecting to stordb
+ "db_passwd": "CGRateS.org", // password to use when connecting to stordb
+},
+
+}
diff --git a/data/storage/mongo/create_user.js b/data/storage/mongo/create_user.js
new file mode 100644
index 000000000..bcdf06d43
--- /dev/null
+++ b/data/storage/mongo/create_user.js
@@ -0,0 +1,9 @@
+
+db = db.getSiblingDB('admin')
+db.createUser(
+ {
+ user: "cgrates",
+ pwd: "CGRateS.org",
+ roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
+ }
+)
diff --git a/data/storage/mongo/setup_cgr_db.sh b/data/storage/mongo/setup_cgr_db.sh
new file mode 100755
index 000000000..4cbc93516
--- /dev/null
+++ b/data/storage/mongo/setup_cgr_db.sh
@@ -0,0 +1,14 @@
+#! /usr/bin/env sh
+
+
+mongo --quiet create_user.js
+cu=$?
+
+if [ $cu = 0 ]; then
+ echo ""
+ echo "\t+++ CGR-DB successfully set-up! +++"
+ echo ""
+ exit 0
+fi
+
+
diff --git a/data/storage/mysql/create_cdrs_tables.sql b/data/storage/mysql/create_cdrs_tables.sql
index ac7dc3088..3f5e0269d 100644
--- a/data/storage/mysql/create_cdrs_tables.sql
+++ b/data/storage/mysql/create_cdrs_tables.sql
@@ -1,90 +1,17 @@
-
--
--- Table structure for table `cdrs_primary`
+-- Table structure for table `cdrs`
--
-DROP TABLE IF EXISTS cdrs_primary;
-CREATE TABLE cdrs_primary (
+DROP TABLE IF EXISTS cdrs;
+CREATE TABLE cdrs (
id int(11) NOT NULL AUTO_INCREMENT,
cgrid char(40) NOT NULL,
- tor varchar(16) NOT NULL,
- accid varchar(64) NOT NULL,
- cdrhost varchar(64) NOT NULL,
- cdrsource varchar(64) NOT NULL,
- reqtype varchar(24) NOT NULL,
- direction varchar(8) NOT NULL,
- tenant varchar(64) NOT NULL,
- category varchar(32) NOT NULL,
- account varchar(128) NOT NULL,
- subject varchar(128) NOT NULL,
- destination varchar(128) NOT NULL,
- setup_time datetime NOT NULL,
- pdd DECIMAL(12,9) NOT NULL,
- answer_time datetime NOT NULL,
- `usage` DECIMAL(30,9) NOT NULL,
- supplier varchar(128) NOT NULL,
- disconnect_cause varchar(64) NOT NULL,
- created_at TIMESTAMP,
- deleted_at TIMESTAMP,
- PRIMARY KEY (id),
- UNIQUE KEY cgrid (cgrid),
- KEY answer_time_idx (answer_time),
- KEY deleted_at_idx (deleted_at)
-
-);
-
---
--- Table structure for table `cdrs_extra`
---
-
-DROP TABLE IF EXISTS cdrs_extra;
-CREATE TABLE cdrs_extra (
- id int(11) NOT NULL AUTO_INCREMENT,
- cgrid char(40) NOT NULL,
- extra_fields text NOT NULL,
- created_at TIMESTAMP,
- deleted_at TIMESTAMP,
- PRIMARY KEY (id),
- UNIQUE KEY cgrid (cgrid),
- KEY deleted_at_idx (deleted_at)
-);
-
---
--- Table structure for table `cost_details`
---
-
-DROP TABLE IF EXISTS cost_details;
-CREATE TABLE cost_details (
- id int(11) NOT NULL AUTO_INCREMENT,
- cgrid char(40) NOT NULL,
- runid varchar(64) NOT NULL,
+ run_id varchar(64) NOT NULL,
+ origin_host varchar(64) NOT NULL,
+ source varchar(64) NOT NULL,
+ origin_id varchar(64) NOT NULL,
tor varchar(16) NOT NULL,
- direction varchar(8) NOT NULL,
- tenant varchar(128) NOT NULL,
- category varchar(32) NOT NULL,
- account varchar(128) NOT NULL,
- subject varchar(128) NOT NULL,
- destination varchar(128) NOT NULL,
- cost DECIMAL(20,4) NOT NULL,
- timespans text,
- cost_source varchar(64) NOT NULL,
- created_at TIMESTAMP,
- updated_at TIMESTAMP,
- deleted_at TIMESTAMP,
- PRIMARY KEY (`id`),
- UNIQUE KEY `costid` (`cgrid`,`runid`),
- KEY deleted_at_idx (deleted_at)
-);
-
---
--- Table structure for table `rated_cdrs`
---
-DROP TABLE IF EXISTS rated_cdrs;
-CREATE TABLE `rated_cdrs` (
- id int(11) NOT NULL AUTO_INCREMENT,
- cgrid char(40) NOT NULL,
- runid varchar(64) NOT NULL,
- reqtype varchar(24) NOT NULL,
+ request_type varchar(24) NOT NULL,
direction varchar(8) NOT NULL,
tenant varchar(64) NOT NULL,
category varchar(32) NOT NULL,
@@ -97,12 +24,28 @@ CREATE TABLE `rated_cdrs` (
`usage` DECIMAL(30,9) NOT NULL,
supplier varchar(128) NOT NULL,
disconnect_cause varchar(64) NOT NULL,
- cost DECIMAL(20,4) DEFAULT NULL,
+ extra_fields text NOT NULL,
+ cost_source varchar(64) NOT NULL,
+ cost DECIMAL(20,4) NOT NULL,
+ cost_details text,
extra_info text,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP,
+ PRIMARY KEY (id),
+ UNIQUE KEY cdrrun (cgrid, run_id)
+);
+
+DROP TABLE IF EXISTS sm_costs;
+CREATE TABLE sm_costs (
+ id int(11) NOT NULL AUTO_INCREMENT,
+ cgrid char(40) NOT NULL,
+ run_id varchar(64) NOT NULL,
+ cost_source varchar(64) NOT NULL,
+ cost_details text,
+ created_at TIMESTAMP,
+ deleted_at TIMESTAMP,
PRIMARY KEY (`id`),
- UNIQUE KEY `costid` (`cgrid`,`runid`),
+ UNIQUE KEY costid (cgrid,run_id),
KEY deleted_at_idx (deleted_at)
-);
\ No newline at end of file
+);
diff --git a/data/storage/postgres/create_cdrs_tables.sql b/data/storage/postgres/create_cdrs_tables.sql
index 4aa36828f..3d386ec7e 100644
--- a/data/storage/postgres/create_cdrs_tables.sql
+++ b/data/storage/postgres/create_cdrs_tables.sql
@@ -1,103 +1,54 @@
-
--
--- Table structure for table `cdrs_primary`
+-- Table structure for table `cdrs`
--
-DROP TABLE IF EXISTS cdrs_primary;
-CREATE TABLE cdrs_primary (
- id SERIAL PRIMARY KEY,
- cgrid CHAR(40) NOT NULL,
- tor VARCHAR(16) NOT NULL,
- accid VARCHAR(64) NOT NULL,
- cdrhost VARCHAR(64) NOT NULL,
- cdrsource VARCHAR(64) NOT NULL,
- reqtype VARCHAR(24) NOT NULL,
- direction VARCHAR(8) NOT NULL,
- tenant VARCHAR(64) NOT NULL,
- category VARCHAR(32) NOT NULL,
- account VARCHAR(128) NOT NULL,
- subject VARCHAR(128) NOT NULL,
- destination VARCHAR(128) NOT NULL,
- setup_time TIMESTAMP NOT NULL,
- pdd NUMERIC(12,9) NOT NULL,
- answer_time TIMESTAMP NOT NULL,
- usage NUMERIC(30,9) NOT NULL,
- supplier VARCHAR(128) NOT NULL,
- disconnect_cause VARCHAR(64) NOT NULL,
- created_at TIMESTAMP,
- deleted_at TIMESTAMP,
- UNIQUE (cgrid)
+DROP TABLE IF EXISTS cdrs;
+CREATE TABLE cdrs (
+ id SERIAL PRIMARY KEY,
+ cgrid CHAR(40) NOT NULL,
+ run_id VARCHAR(64) NOT NULL,
+ origin_host VARCHAR(64) NOT NULL,
+ source VARCHAR(64) NOT NULL,
+ origin_id VARCHAR(64) NOT NULL,
+ tor VARCHAR(16) NOT NULL,
+ request_type VARCHAR(24) NOT NULL,
+ direction VARCHAR(8) NOT NULL,
+ tenant VARCHAR(64) NOT NULL,
+ category VARCHAR(32) NOT NULL,
+ account VARCHAR(128) NOT NULL,
+ subject VARCHAR(128) NOT NULL,
+ destination VARCHAR(128) NOT NULL,
+ setup_time TIMESTAMP NOT NULL,
+ pdd NUMERIC(12,9) NOT NULL,
+ answer_time TIMESTAMP NOT NULL,
+ usage NUMERIC(30,9) NOT NULL,
+ supplier VARCHAR(128) NOT NULL,
+ disconnect_cause VARCHAR(64) NOT NULL,
+ extra_fields jsonb,
+ cost_source VARCHAR(64) NOT NULL,
+ cost NUMERIC(20,4) DEFAULT NULL,
+ cost_details jsonb,
+ extra_info text,
+ created_at TIMESTAMP,
+ updated_at TIMESTAMP,
+ deleted_at TIMESTAMP,
+ UNIQUE (cgrid, run_id)
);
-CREATE INDEX answer_time_idx ON cdrs_primary (answer_time);
+;
+DROP INDEX IF EXISTS deleted_at_cp_idx;
CREATE INDEX deleted_at_cp_idx ON cdrs_primary (deleted_at);
---
--- Table structure for table `cdrs_extra`
---
-DROP TABLE IF EXISTS cdrs_extra;
-CREATE TABLE cdrs_extra (
+DROP TABLE IF EXISTS sm_costs;
+CREATE TABLE sm_costs (
id SERIAL PRIMARY KEY,
cgrid CHAR(40) NOT NULL,
- extra_fields jsonb NOT NULL,
- created_at TIMESTAMP,
- deleted_at TIMESTAMP,
- UNIQUE (cgrid)
-);
-CREATE INDEX deleted_at_ce_idx ON cdrs_extra (deleted_at);
-
---
--- Table structure for table `cost_details`
---
-
-DROP TABLE IF EXISTS cost_details;
-CREATE TABLE cost_details (
- id SERIAL PRIMARY KEY,
- cgrid CHAR(40) NOT NULL,
- runid VARCHAR(64) NOT NULL,
- tor VARCHAR(16) NOT NULL,
- direction VARCHAR(8) NOT NULL,
- tenant VARCHAR(128) NOT NULL,
- category VARCHAR(32) NOT NULL,
- account VARCHAR(128) NOT NULL,
- subject VARCHAR(128) NOT NULL,
- destination VARCHAR(128) NOT NULL,
- cost NUMERIC(20,4) NOT NULL,
- timespans jsonb,
+ run_id VARCHAR(64) NOT NULL,
cost_source VARCHAR(64) NOT NULL,
+ cost_details jsonb,
created_at TIMESTAMP,
- updated_at TIMESTAMP,
deleted_at TIMESTAMP,
- UNIQUE (cgrid, runid)
+ UNIQUE (cgrid, run_id)
);
-CREATE INDEX deleted_at_cd_idx ON cost_details (deleted_at);
-
---
--- Table structure for table `rated_cdrs`
---
-DROP TABLE IF EXISTS rated_cdrs;
-CREATE TABLE rated_cdrs (
- id SERIAL PRIMARY KEY,
- cgrid CHAR(40) NOT NULL,
- runid VARCHAR(64) NOT NULL,
- reqtype VARCHAR(24) NOT NULL,
- direction VARCHAR(8) NOT NULL,
- tenant VARCHAR(64) NOT NULL,
- category VARCHAR(32) NOT NULL,
- account VARCHAR(128) NOT NULL,
- subject VARCHAR(128) NOT NULL,
- destination VARCHAR(128) NOT NULL,
- setup_time TIMESTAMP NOT NULL,
- pdd NUMERIC(12,9) NOT NULL,
- answer_time TIMESTAMP NOT NULL,
- usage NUMERIC(30,9) NOT NULL,
- supplier VARCHAR(128) NOT NULL,
- disconnect_cause VARCHAR(64) NOT NULL,
- cost NUMERIC(20,4) DEFAULT NULL,
- extra_info text,
- created_at TIMESTAMP,
- updated_at TIMESTAMP,
- deleted_at TIMESTAMP,
- UNIQUE (cgrid, runid)
-);
-CREATE INDEX deleted_at_rc_idx ON rated_cdrs (deleted_at);
+DROP INDEX IF EXISTS deleted_at_smcost_idx;
+CREATE INDEX deleted_at_smcost_idx ON sm_costs (deleted_at);
diff --git a/data/tariffplans/tutorial/Users.csv b/data/tariffplans/tutorial/Users.csv
index 699dec1e2..63b36ff9f 100644
--- a/data/tariffplans/tutorial/Users.csv
+++ b/data/tariffplans/tutorial/Users.csv
@@ -6,7 +6,7 @@ cgrates.org,1001,,Account,1001,10
cgrates.org,1001,,Subject,1001,10
cgrates.org,1001,,Uuid,388539dfd4f5cefee8f488b78c6c244b9e19138e,10
cgrates.org,1001,,SubscriberId,1001,10
-cgrates.org,1001,,ReqType,*prepaid,10
+cgrates.org,1001,,RequestType,*prepaid,10
cgrates.org,1002,,SysUserName,rif,10
cgrates.org,1002,,RifAttr,RifVal,10
cgrates.org,1002,,Account,1002,10
@@ -18,5 +18,5 @@ cgrates.org,1004,,SysPassword,hisPass321,10
cgrates.org,1004,,Cli,+4986517174964,10
cgrates.org,1004,,Account,1004,10
cgrates.org,1004,,Subject,1004,10
-cgrates.org,1004,,ReqType,*rated,10
+cgrates.org,1004,,RequestType,*rated,10
cgrates.org,1004,,SubscriberId,1004,10
diff --git a/engine/account.go b/engine/account.go
index 92d10f48e..747722756 100644
--- a/engine/account.go
+++ b/engine/account.go
@@ -499,7 +499,6 @@ func (ub *Account) executeActionTriggers(a *Action) {
}
switch at.ThresholdType {
case utils.TRIGGER_MAX_BALANCE:
-
if b.MatchActionTrigger(at) && b.GetValue() >= at.ThresholdValue {
at.Execute(ub, nil)
}
diff --git a/engine/account_test.go b/engine/account_test.go
index 8209a5b36..3f59e332d 100644
--- a/engine/account_test.go
+++ b/engine/account_test.go
@@ -867,9 +867,9 @@ func TestAccountAddMinuteNil(t *testing.T) {
}
func TestAccountAddMinutBucketEmpty(t *testing.T) {
- mb1 := &Balance{Value: -10, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.StringMap{utils.OUT: true}}
- mb2 := &Balance{Value: -10, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.StringMap{utils.OUT: true}}
- mb3 := &Balance{Value: -10, DestinationIds: utils.StringMap{"OTHER": true}, Directions: utils.StringMap{utils.OUT: true}}
+ mb1 := &Balance{Value: -10, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.NewStringMap(utils.OUT)}
+ mb2 := &Balance{Value: -10, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.NewStringMap(utils.OUT)}
+ mb3 := &Balance{Value: -10, DestinationIds: utils.StringMap{"OTHER": true}, Directions: utils.NewStringMap(utils.OUT)}
ub := &Account{}
a := &Action{BalanceType: utils.VOICE, Balance: mb1}
ub.debitBalanceAction(a, false)
diff --git a/engine/action.go b/engine/action.go
index f3d605ec8..e7e265cb9 100644
--- a/engine/action.go
+++ b/engine/action.go
@@ -197,15 +197,15 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action)
func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) {
defaultTemplate := map[string]utils.RSRFields{
- "TOR": utils.ParseRSRFieldsMustCompile("balance_type", utils.INFIELD_SEP),
- "CdrHost": utils.ParseRSRFieldsMustCompile("^127.0.0.1", utils.INFIELD_SEP),
- "Direction": utils.ParseRSRFieldsMustCompile("direction", utils.INFIELD_SEP),
- "ReqType": utils.ParseRSRFieldsMustCompile("^"+utils.META_PREPAID, utils.INFIELD_SEP),
- "Tenant": utils.ParseRSRFieldsMustCompile("tenant", utils.INFIELD_SEP),
- "Account": utils.ParseRSRFieldsMustCompile("account", utils.INFIELD_SEP),
- "Subject": utils.ParseRSRFieldsMustCompile("account", utils.INFIELD_SEP),
- "Cost": utils.ParseRSRFieldsMustCompile("balance_value", utils.INFIELD_SEP),
- "MediationRunId": utils.ParseRSRFieldsMustCompile("^"+utils.META_DEFAULT, utils.INFIELD_SEP),
+ utils.TOR: utils.ParseRSRFieldsMustCompile("balance_type", utils.INFIELD_SEP),
+ utils.CDRHOST: utils.ParseRSRFieldsMustCompile("^127.0.0.1", utils.INFIELD_SEP),
+ utils.DIRECTION: utils.ParseRSRFieldsMustCompile("direction", utils.INFIELD_SEP),
+ utils.REQTYPE: utils.ParseRSRFieldsMustCompile("^"+utils.META_PREPAID, utils.INFIELD_SEP),
+ utils.TENANT: utils.ParseRSRFieldsMustCompile("tenant", utils.INFIELD_SEP),
+ utils.ACCOUNT: utils.ParseRSRFieldsMustCompile("account", utils.INFIELD_SEP),
+ utils.SUBJECT: utils.ParseRSRFieldsMustCompile("account", utils.INFIELD_SEP),
+ utils.COST: utils.ParseRSRFieldsMustCompile("balance_value", utils.INFIELD_SEP),
+ utils.MEDI_RUNID: utils.ParseRSRFieldsMustCompile("^"+utils.META_DEFAULT, utils.INFIELD_SEP),
}
template := make(map[string]string)
@@ -223,13 +223,13 @@ func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions)
}
// set stored cdr values
- var cdrs []*StoredCdr
+ var cdrs []*CDR
for _, action := range acs {
if !utils.IsSliceMember([]string{DEBIT, DEBIT_RESET}, action.ActionType) || action.Balance == nil {
continue // Only log specific actions
}
- cdr := &StoredCdr{CdrSource: CDRLOG, SetupTime: time.Now(), AnswerTime: time.Now(), AccId: utils.GenUUID(), ExtraFields: make(map[string]string)}
- cdr.CgrId = utils.Sha1(cdr.AccId, cdr.SetupTime.String())
+ cdr := &CDR{Source: CDRLOG, SetupTime: time.Now(), AnswerTime: time.Now(), OriginID: utils.GenUUID(), ExtraFields: make(map[string]string)}
+ cdr.CGRID = utils.Sha1(cdr.OriginID, cdr.SetupTime.String())
cdr.Usage = time.Duration(1) * time.Second
elem := reflect.ValueOf(cdr).Elem()
for key, rsrFlds := range defaultTemplate {
@@ -255,10 +255,7 @@ func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions)
if cdrStorage == nil { // Only save if the cdrStorage is defined
continue
}
- if err := cdrStorage.SetCdr(cdr); err != nil {
- return err
- }
- if err := cdrStorage.SetRatedCdr(cdr); err != nil {
+ if err := cdrStorage.SetCDR(cdr, true); err != nil {
return err
}
// FixMe
diff --git a/engine/actions_local_test.go b/engine/actions_local_test.go
index eea4919f8..c5d30e126 100644
--- a/engine/actions_local_test.go
+++ b/engine/actions_local_test.go
@@ -19,6 +19,7 @@ along with this program. If not, see
package engine
import (
+ "flag"
"net/rpc"
"net/rpc/jsonrpc"
"path"
@@ -33,6 +34,8 @@ var actsLclCfg *config.CGRConfig
var actsLclRpc *rpc.Client
var actsLclCfgPath = path.Join(*dataDir, "conf", "samples", "actions")
+var waitRater = flag.Int("wait_rater", 100, "Number of miliseconds to wait for rater to start and cache")
+
func TestActionsLocalInitCfg(t *testing.T) {
if !*testLocal {
return
@@ -61,7 +64,7 @@ func TestActionsLocalStartEngine(t *testing.T) {
if !*testLocal {
return
}
- if _, err := StartEngine(actsLclCfgPath, waitRater); err != nil {
+ if _, err := StartEngine(actsLclCfgPath, *waitRater); err != nil {
t.Fatal(err)
}
}
@@ -105,20 +108,20 @@ func TestActionsLocalSetCdrlogActions(t *testing.T) {
} else if reply != utils.OK {
t.Errorf("Calling ApierV1.ExecuteAction received: %s", reply)
}
- var rcvedCdrs []*ExternalCdr
- if err := actsLclRpc.Call("ApierV2.GetCdrs", utils.RpcCdrsFilter{CdrSources: []string{CDRLOG}}, &rcvedCdrs); err != nil {
+ var rcvedCdrs []*ExternalCDR
+ if err := actsLclRpc.Call("ApierV2.GetCdrs", utils.RPCCDRsFilter{Sources: []string{CDRLOG}}, &rcvedCdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(rcvedCdrs) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(rcvedCdrs))
- } else if rcvedCdrs[0].TOR != utils.MONETARY ||
- rcvedCdrs[0].CdrHost != "127.0.0.1" ||
- rcvedCdrs[0].CdrSource != CDRLOG ||
- rcvedCdrs[0].ReqType != utils.META_PREPAID ||
+ } else if rcvedCdrs[0].ToR != utils.MONETARY ||
+ rcvedCdrs[0].OriginHost != "127.0.0.1" ||
+ rcvedCdrs[0].Source != CDRLOG ||
+ rcvedCdrs[0].RequestType != utils.META_PREPAID ||
rcvedCdrs[0].Tenant != "cgrates.org" ||
rcvedCdrs[0].Account != "dan2904" ||
rcvedCdrs[0].Subject != "dan2904" ||
rcvedCdrs[0].Usage != "1" ||
- rcvedCdrs[0].MediationRunId != utils.META_DEFAULT ||
+ rcvedCdrs[0].RunID != utils.META_DEFAULT ||
rcvedCdrs[0].Cost != attrsAA.Actions[0].Units {
t.Errorf("Received: %+v", rcvedCdrs[0])
}
@@ -129,7 +132,7 @@ func TestActionsLocalStopCgrEngine(t *testing.T) {
if !*testLocal {
return
}
- if err := KillEngine(waitRater); err != nil {
+ if err := KillEngine(*waitRater); err != nil {
t.Error(err)
}
}
diff --git a/engine/actions_test.go b/engine/actions_test.go
index 75b6ef9b9..2b3f7614c 100644
--- a/engine/actions_test.go
+++ b/engine/actions_test.go
@@ -1174,9 +1174,9 @@ func TestActionCdrlogEmpty(t *testing.T) {
if err != nil {
t.Error("Error performing cdrlog action: ", err)
}
- cdrs := make([]*StoredCdr, 0)
+ cdrs := make([]*CDR, 0)
json.Unmarshal([]byte(cdrlog.ExpirationString), &cdrs)
- if len(cdrs) != 1 || cdrs[0].CdrSource != CDRLOG {
+ if len(cdrs) != 1 || cdrs[0].Source != CDRLOG {
t.Errorf("Wrong cdrlogs: %+v", cdrs[0])
}
}
@@ -1200,7 +1200,7 @@ func TestActionCdrlogWithParams(t *testing.T) {
if err != nil {
t.Error("Error performing cdrlog action: ", err)
}
- cdrs := make([]*StoredCdr, 0)
+ cdrs := make([]*CDR, 0)
json.Unmarshal([]byte(cdrlog.ExpirationString), &cdrs)
if len(cdrs) != 2 ||
cdrs[0].Subject != "rif" {
@@ -1212,7 +1212,7 @@ func TestActionCdrLogParamsWithOverload(t *testing.T) {
acnt := &Account{Id: "cgrates.org:dan2904"}
cdrlog := &Action{
ActionType: CDRLOG,
- ExtraParameters: `{"Subject":"^rif","Destination":"^1234","TOR":"~action_tag:s/^at(.)$/0$1/","AccountId":"~account_id:s/^\\*(.*)$/$1/"}`,
+ ExtraParameters: `{"Subject":"^rif","Destination":"^1234","ToR":"~action_tag:s/^at(.)$/0$1/","AccountId":"~account_id:s/^\\*(.*)$/$1/"}`,
}
err := cdrLogAction(acnt, nil, cdrlog, Actions{
&Action{
@@ -1227,7 +1227,7 @@ func TestActionCdrLogParamsWithOverload(t *testing.T) {
if err != nil {
t.Error("Error performing cdrlog action: ", err)
}
- cdrs := make([]*StoredCdr, 0)
+ cdrs := make([]*CDR, 0)
json.Unmarshal([]byte(cdrlog.ExpirationString), &cdrs)
expectedExtraFields := map[string]string{
"AccountId": "cgrates.org:dan2904",
diff --git a/engine/storedcdr.go b/engine/cdr.go
similarity index 50%
rename from engine/storedcdr.go
rename to engine/cdr.go
index fba8ac848..599de20de 100644
--- a/engine/storedcdr.go
+++ b/engine/cdr.go
@@ -31,56 +31,55 @@ import (
"github.com/cgrates/cgrates/utils"
)
-func NewStoredCdrFromExternalCdr(extCdr *ExternalCdr, timezone string) (*StoredCdr, error) {
+func NewCDRFromExternalCDR(extCdr *ExternalCDR, timezone string) (*CDR, error) {
var err error
- storedCdr := &StoredCdr{CgrId: extCdr.CgrId, OrderId: extCdr.OrderId, TOR: extCdr.TOR, AccId: extCdr.AccId, CdrHost: extCdr.CdrHost, CdrSource: extCdr.CdrSource,
- ReqType: extCdr.ReqType, Direction: extCdr.Direction, Tenant: extCdr.Tenant, Category: extCdr.Category, Account: extCdr.Account, Subject: extCdr.Subject,
- Destination: extCdr.Destination, Supplier: extCdr.Supplier, DisconnectCause: extCdr.DisconnectCause,
- MediationRunId: extCdr.MediationRunId, RatedAccount: extCdr.RatedAccount, RatedSubject: extCdr.RatedSubject, Cost: extCdr.Cost, Rated: extCdr.Rated}
- if storedCdr.SetupTime, err = utils.ParseTimeDetectLayout(extCdr.SetupTime, timezone); err != nil {
+ cdr := &CDR{CGRID: extCdr.CGRID, RunID: extCdr.RunID, OrderID: extCdr.OrderID, ToR: extCdr.ToR, OriginID: extCdr.OriginID, OriginHost: extCdr.OriginHost,
+ Source: extCdr.Source, RequestType: extCdr.RequestType, Direction: extCdr.Direction, Tenant: extCdr.Tenant, Category: extCdr.Category,
+ Account: extCdr.Account, Subject: extCdr.Subject, Destination: extCdr.Destination, Supplier: extCdr.Supplier,
+ DisconnectCause: extCdr.DisconnectCause, CostSource: extCdr.CostSource, Cost: extCdr.Cost, Rated: extCdr.Rated}
+ if cdr.SetupTime, err = utils.ParseTimeDetectLayout(extCdr.SetupTime, timezone); err != nil {
return nil, err
}
- if len(storedCdr.CgrId) == 0 { // Populate CgrId if not present
- storedCdr.CgrId = utils.Sha1(storedCdr.AccId, storedCdr.SetupTime.UTC().String())
+ if len(cdr.CGRID) == 0 { // Populate CGRID if not present
+ cdr.CGRID = utils.Sha1(cdr.OriginID, cdr.SetupTime.UTC().String())
}
- if storedCdr.AnswerTime, err = utils.ParseTimeDetectLayout(extCdr.AnswerTime, timezone); err != nil {
+ if cdr.AnswerTime, err = utils.ParseTimeDetectLayout(extCdr.AnswerTime, timezone); err != nil {
return nil, err
}
- if storedCdr.Usage, err = utils.ParseDurationWithSecs(extCdr.Usage); err != nil {
+ if cdr.Usage, err = utils.ParseDurationWithSecs(extCdr.Usage); err != nil {
return nil, err
}
- if storedCdr.Pdd, err = utils.ParseDurationWithSecs(extCdr.Pdd); err != nil {
+ if cdr.PDD, err = utils.ParseDurationWithSecs(extCdr.PDD); err != nil {
return nil, err
}
if len(extCdr.CostDetails) != 0 {
- if err = json.Unmarshal([]byte(extCdr.CostDetails), storedCdr.CostDetails); err != nil {
+ if err = json.Unmarshal([]byte(extCdr.CostDetails), cdr.CostDetails); err != nil {
return nil, err
}
}
if extCdr.ExtraFields != nil {
- storedCdr.ExtraFields = make(map[string]string)
+ cdr.ExtraFields = make(map[string]string)
}
for k, v := range extCdr.ExtraFields {
- storedCdr.ExtraFields[k] = v
+ cdr.ExtraFields[k] = v
}
- return storedCdr, nil
+ return cdr, nil
}
-// ToDo: split config to only add here general section
-func NewStoredCdrWithDefaults(cfg *config.CGRConfig) *StoredCdr {
- return &StoredCdr{TOR: utils.VOICE, ReqType: cfg.DefaultReqType, Direction: utils.OUT, Tenant: cfg.DefaultTenant, Category: cfg.DefaultCategory,
+func NewCDRWithDefaults(cfg *config.CGRConfig) *CDR {
+ return &CDR{ToR: utils.VOICE, RequestType: cfg.DefaultReqType, Direction: utils.OUT, Tenant: cfg.DefaultTenant, Category: cfg.DefaultCategory,
ExtraFields: make(map[string]string), Cost: -1}
}
-// Kinda standard of internal CDR, complies to CDR interface also
-type StoredCdr struct {
- CgrId string
- OrderId int64 // Stor order id used as export order id
- TOR string // type of record, meta-field, should map to one of the TORs hardcoded inside the server <*voice|*data|*sms|*generic>
- AccId string // represents the unique accounting id given by the telecom switch generating the CDR
- CdrHost string // represents the IP address of the host generating the CDR (automatically populated by the server)
- CdrSource string // formally identifies the source of the CDR (free form field)
- ReqType string // matching the supported request types by the **CGRateS**, accepted values are hardcoded in the server .
+type CDR struct {
+ CGRID string
+ RunID string
+ OrderID int64 // Stor order id used as export order id
+ OriginHost string // represents the IP address of the host generating the CDR (automatically populated by the server)
+ Source string // formally identifies the source of the CDR (free form field)
+ OriginID string // represents the unique accounting id given by the telecom switch generating the CDR
+ ToR string // type of record, meta-field, should map to one of the TORs hardcoded inside the server <*voice|*data|*sms|*generic>
+ RequestType string // matching the supported request types by the **CGRateS**, accepted values are hardcoded in the server .
Direction string // matching the supported direction identifiers of the CGRateS <*out>
Tenant string // tenant whom this record belongs
Category string // free-form filter for this record, matching the category defined in rating profiles.
@@ -88,42 +87,37 @@ type StoredCdr struct {
Subject string // rating subject (rating subsystem) this record should be attached to
Destination string // destination to be charged
SetupTime time.Time // set-up time of the event. Supported formats: datetime RFC3339 compatible, SQL datetime (eg: MySQL), unix timestamp.
- Pdd time.Duration // PDD value
+ PDD time.Duration // PDD value
AnswerTime time.Time // answer time of the event. Supported formats: datetime RFC3339 compatible, SQL datetime (eg: MySQL), unix timestamp.
Usage time.Duration // event usage information (eg: in case of tor=*voice this will represent the total duration of a call)
Supplier string // Supplier information when available
DisconnectCause string // Disconnect cause of the event
ExtraFields map[string]string // Extra fields to be stored in CDR
- MediationRunId string
- RatedAccount string // Populated out of rating data
- RatedSubject string
+ CostSource string // The source of this cost
Cost float64
- ExtraInfo string // Container for extra information related to this CDR, eg: populated with error reason in case of error on calculation
CostDetails *CallCost // Attach the cost details to CDR when possible
- Rated bool // Mark the CDR as rated so we do not process it during mediation
+ ExtraInfo string // Container for extra information related to this CDR, eg: populated with error reason in case of error on calculation
+ Rated bool // Mark the CDR as rated so we do not process it during rating
}
-func (storedCdr *StoredCdr) CostDetailsJson() string {
- if storedCdr.CostDetails == nil {
- return ""
- }
- mrshled, _ := json.Marshal(storedCdr.CostDetails)
+func (cdr *CDR) CostDetailsJson() string {
+ mrshled, _ := json.Marshal(cdr.CostDetails)
return string(mrshled)
}
// Used to multiply usage on export
-func (storedCdr *StoredCdr) UsageMultiply(multiplyFactor float64, roundDecimals int) {
- storedCdr.Usage = time.Duration(int(utils.Round(float64(storedCdr.Usage.Nanoseconds())*multiplyFactor, roundDecimals, utils.ROUNDING_MIDDLE))) // Rounding down could introduce a slight loss here but only at nanoseconds level
+func (cdr *CDR) UsageMultiply(multiplyFactor float64, roundDecimals int) {
+ cdr.Usage = time.Duration(int(utils.Round(float64(cdr.Usage.Nanoseconds())*multiplyFactor, roundDecimals, utils.ROUNDING_MIDDLE))) // Rounding down could introduce a slight loss here but only at nanoseconds level
}
// Used to multiply cost on export
-func (storedCdr *StoredCdr) CostMultiply(multiplyFactor float64, roundDecimals int) {
- storedCdr.Cost = utils.Round(storedCdr.Cost*multiplyFactor, roundDecimals, utils.ROUNDING_MIDDLE)
+func (cdr *CDR) CostMultiply(multiplyFactor float64, roundDecimals int) {
+ cdr.Cost = utils.Round(cdr.Cost*multiplyFactor, roundDecimals, utils.ROUNDING_MIDDLE)
}
// Format cost as string on export
-func (storedCdr *StoredCdr) FormatCost(shiftDecimals, roundDecimals int) string {
- cost := storedCdr.Cost
+func (cdr *CDR) FormatCost(shiftDecimals, roundDecimals int) string {
+ cost := cdr.Cost
if shiftDecimals != 0 {
cost = cost * math.Pow10(shiftDecimals)
}
@@ -131,216 +125,204 @@ func (storedCdr *StoredCdr) FormatCost(shiftDecimals, roundDecimals int) string
}
// Formats usage on export
-func (storedCdr *StoredCdr) FormatUsage(layout string) string {
- if utils.IsSliceMember([]string{utils.DATA, utils.SMS, utils.GENERIC}, storedCdr.TOR) {
- return strconv.FormatFloat(utils.Round(storedCdr.Usage.Seconds(), 0, utils.ROUNDING_MIDDLE), 'f', -1, 64)
+func (cdr *CDR) FormatUsage(layout string) string {
+ if utils.IsSliceMember([]string{utils.DATA, utils.SMS, utils.GENERIC}, cdr.ToR) {
+ return strconv.FormatFloat(utils.Round(cdr.Usage.Seconds(), 0, utils.ROUNDING_MIDDLE), 'f', -1, 64)
}
switch layout {
default:
- return strconv.FormatFloat(float64(storedCdr.Usage.Nanoseconds())/1000000000, 'f', -1, 64)
+ return strconv.FormatFloat(float64(cdr.Usage.Nanoseconds())/1000000000, 'f', -1, 64)
}
}
// Used to retrieve fields as string, primary fields are const labeled
-func (storedCdr *StoredCdr) FieldAsString(rsrFld *utils.RSRField) string {
+func (cdr *CDR) FieldAsString(rsrFld *utils.RSRField) string {
if rsrFld.IsStatic() { // Static values do not care about headers
return rsrFld.ParseValue("")
}
switch rsrFld.Id {
case utils.CGRID:
- return rsrFld.ParseValue(storedCdr.CgrId)
+ return rsrFld.ParseValue(cdr.CGRID)
case utils.ORDERID:
- return rsrFld.ParseValue(strconv.FormatInt(storedCdr.OrderId, 10))
+ return rsrFld.ParseValue(strconv.FormatInt(cdr.OrderID, 10))
case utils.TOR:
- return rsrFld.ParseValue(storedCdr.TOR)
+ return rsrFld.ParseValue(cdr.ToR)
case utils.ACCID:
- return rsrFld.ParseValue(storedCdr.AccId)
+ return rsrFld.ParseValue(cdr.OriginID)
case utils.CDRHOST:
- return rsrFld.ParseValue(storedCdr.CdrHost)
+ return rsrFld.ParseValue(cdr.OriginHost)
case utils.CDRSOURCE:
- return rsrFld.ParseValue(storedCdr.CdrSource)
+ return rsrFld.ParseValue(cdr.Source)
case utils.REQTYPE:
- return rsrFld.ParseValue(storedCdr.ReqType)
+ return rsrFld.ParseValue(cdr.RequestType)
case utils.DIRECTION:
- return rsrFld.ParseValue(storedCdr.Direction)
+ return rsrFld.ParseValue(cdr.Direction)
case utils.TENANT:
- return rsrFld.ParseValue(storedCdr.Tenant)
+ return rsrFld.ParseValue(cdr.Tenant)
case utils.CATEGORY:
- return rsrFld.ParseValue(storedCdr.Category)
+ return rsrFld.ParseValue(cdr.Category)
case utils.ACCOUNT:
- return rsrFld.ParseValue(storedCdr.Account)
+ return rsrFld.ParseValue(cdr.Account)
case utils.SUBJECT:
- return rsrFld.ParseValue(storedCdr.Subject)
+ return rsrFld.ParseValue(cdr.Subject)
case utils.DESTINATION:
- return rsrFld.ParseValue(storedCdr.Destination)
+ return rsrFld.ParseValue(cdr.Destination)
case utils.SETUP_TIME:
- return rsrFld.ParseValue(storedCdr.SetupTime.Format(time.RFC3339))
+ return rsrFld.ParseValue(cdr.SetupTime.Format(time.RFC3339))
case utils.PDD:
- return strconv.FormatFloat(storedCdr.Pdd.Seconds(), 'f', -1, 64)
+ return strconv.FormatFloat(cdr.PDD.Seconds(), 'f', -1, 64)
case utils.ANSWER_TIME:
- return rsrFld.ParseValue(storedCdr.AnswerTime.Format(time.RFC3339))
+ return rsrFld.ParseValue(cdr.AnswerTime.Format(time.RFC3339))
case utils.USAGE:
- return strconv.FormatFloat(storedCdr.Usage.Seconds(), 'f', -1, 64)
+ return strconv.FormatFloat(cdr.Usage.Seconds(), 'f', -1, 64)
case utils.SUPPLIER:
- return rsrFld.ParseValue(storedCdr.Supplier)
+ return rsrFld.ParseValue(cdr.Supplier)
case utils.DISCONNECT_CAUSE:
- return rsrFld.ParseValue(storedCdr.DisconnectCause)
+ return rsrFld.ParseValue(cdr.DisconnectCause)
case utils.MEDI_RUNID:
- return rsrFld.ParseValue(storedCdr.MediationRunId)
- case utils.RATED_ACCOUNT:
- return rsrFld.ParseValue(storedCdr.RatedAccount)
- case utils.RATED_SUBJECT:
- return rsrFld.ParseValue(storedCdr.RatedSubject)
+ return rsrFld.ParseValue(cdr.RunID)
case utils.RATED_FLD:
- return rsrFld.ParseValue(strconv.FormatBool(storedCdr.Rated))
+ return rsrFld.ParseValue(strconv.FormatBool(cdr.Rated))
case utils.COST:
- return rsrFld.ParseValue(strconv.FormatFloat(storedCdr.Cost, 'f', -1, 64)) // Recommended to use FormatCost
+ return rsrFld.ParseValue(strconv.FormatFloat(cdr.Cost, 'f', -1, 64)) // Recommended to use FormatCost
case utils.COST_DETAILS:
- return rsrFld.ParseValue(storedCdr.CostDetailsJson())
+ return rsrFld.ParseValue(cdr.CostDetailsJson())
default:
- return rsrFld.ParseValue(storedCdr.ExtraFields[rsrFld.Id])
+ return rsrFld.ParseValue(cdr.ExtraFields[rsrFld.Id])
}
}
// Populates the field with id from value; strings are appended to original one
-func (storedCdr *StoredCdr) ParseFieldValue(fieldId, fieldVal, timezone string) error {
+func (cdr *CDR) ParseFieldValue(fieldId, fieldVal, timezone string) error {
var err error
switch fieldId {
case utils.TOR:
- storedCdr.TOR += fieldVal
+ cdr.ToR += fieldVal
case utils.ACCID:
- storedCdr.AccId += fieldVal
+ cdr.OriginID += fieldVal
case utils.REQTYPE:
- storedCdr.ReqType += fieldVal
+ cdr.RequestType += fieldVal
case utils.DIRECTION:
- storedCdr.Direction += fieldVal
+ cdr.Direction += fieldVal
case utils.TENANT:
- storedCdr.Tenant += fieldVal
+ cdr.Tenant += fieldVal
case utils.CATEGORY:
- storedCdr.Category += fieldVal
+ cdr.Category += fieldVal
case utils.ACCOUNT:
- storedCdr.Account += fieldVal
+ cdr.Account += fieldVal
case utils.SUBJECT:
- storedCdr.Subject += fieldVal
+ cdr.Subject += fieldVal
case utils.DESTINATION:
- storedCdr.Destination += fieldVal
+ cdr.Destination += fieldVal
case utils.RATED_FLD:
- storedCdr.Rated, _ = strconv.ParseBool(fieldVal)
+ cdr.Rated, _ = strconv.ParseBool(fieldVal)
case utils.SETUP_TIME:
- if storedCdr.SetupTime, err = utils.ParseTimeDetectLayout(fieldVal, timezone); err != nil {
+ if cdr.SetupTime, err = utils.ParseTimeDetectLayout(fieldVal, timezone); err != nil {
return fmt.Errorf("Cannot parse answer time field with value: %s, err: %s", fieldVal, err.Error())
}
case utils.PDD:
- if storedCdr.Pdd, err = utils.ParseDurationWithSecs(fieldVal); err != nil {
+ if cdr.PDD, err = utils.ParseDurationWithSecs(fieldVal); err != nil {
return fmt.Errorf("Cannot parse answer time field with value: %s, err: %s", fieldVal, err.Error())
}
case utils.ANSWER_TIME:
- if storedCdr.AnswerTime, err = utils.ParseTimeDetectLayout(fieldVal, timezone); err != nil {
+ if cdr.AnswerTime, err = utils.ParseTimeDetectLayout(fieldVal, timezone); err != nil {
return fmt.Errorf("Cannot parse answer time field with value: %s, err: %s", fieldVal, err.Error())
}
case utils.USAGE:
- if storedCdr.Usage, err = utils.ParseDurationWithSecs(fieldVal); err != nil {
+ if cdr.Usage, err = utils.ParseDurationWithSecs(fieldVal); err != nil {
return fmt.Errorf("Cannot parse duration field with value: %s, err: %s", fieldVal, err.Error())
}
case utils.SUPPLIER:
- storedCdr.Supplier += fieldVal
+ cdr.Supplier += fieldVal
case utils.DISCONNECT_CAUSE:
- storedCdr.DisconnectCause += fieldVal
+ cdr.DisconnectCause += fieldVal
case utils.COST:
- if storedCdr.Cost, err = strconv.ParseFloat(fieldVal, 64); err != nil {
+ if cdr.Cost, err = strconv.ParseFloat(fieldVal, 64); err != nil {
return fmt.Errorf("Cannot parse cost field with value: %s, err: %s", fieldVal, err.Error())
}
default: // Extra fields will not match predefined so they all show up here
- storedCdr.ExtraFields[fieldId] += fieldVal
+ cdr.ExtraFields[fieldId] += fieldVal
}
return nil
}
// concatenates values of multiple fields defined in template, used eg in CDR templates
-func (storedCdr *StoredCdr) FieldsAsString(rsrFlds utils.RSRFields) string {
+func (cdr *CDR) FieldsAsString(rsrFlds utils.RSRFields) string {
var fldVal string
for _, rsrFld := range rsrFlds {
- fldVal += storedCdr.FieldAsString(rsrFld)
+ fldVal += cdr.FieldAsString(rsrFld)
}
return fldVal
}
-func (storedCdr *StoredCdr) PassesFieldFilter(fieldFilter *utils.RSRField) (bool, string) {
+func (cdr *CDR) PassesFieldFilter(fieldFilter *utils.RSRField) (bool, string) {
if fieldFilter == nil {
return true, ""
}
- if fieldFilter.IsStatic() && storedCdr.FieldAsString(&utils.RSRField{Id: fieldFilter.Id}) == storedCdr.FieldAsString(fieldFilter) {
- return true, storedCdr.FieldAsString(&utils.RSRField{Id: fieldFilter.Id})
+ if fieldFilter.IsStatic() && cdr.FieldAsString(&utils.RSRField{Id: fieldFilter.Id}) == cdr.FieldAsString(fieldFilter) {
+ return true, cdr.FieldAsString(&utils.RSRField{Id: fieldFilter.Id})
}
preparedFilter := &utils.RSRField{Id: fieldFilter.Id, RSRules: make([]*utils.ReSearchReplace, len(fieldFilter.RSRules))} // Reset rules so they do not point towards same structures as original fieldFilter
for idx := range fieldFilter.RSRules {
// Hardcode the template with maximum of 5 groups ordered
preparedFilter.RSRules[idx] = &utils.ReSearchReplace{SearchRegexp: fieldFilter.RSRules[idx].SearchRegexp, ReplaceTemplate: utils.FILTER_REGEXP_TPL}
}
- preparedVal := storedCdr.FieldAsString(preparedFilter)
- filteredValue := storedCdr.FieldAsString(fieldFilter)
+ preparedVal := cdr.FieldAsString(preparedFilter)
+ filteredValue := cdr.FieldAsString(fieldFilter)
if preparedFilter.RegexpMatched() && (len(preparedVal) == 0 || preparedVal == filteredValue) {
return true, filteredValue
}
return false, ""
}
-func (storedCdr *StoredCdr) AsStoredCdr(timezone string) *StoredCdr {
- return storedCdr
+func (cdr *CDR) AsStoredCdr(timezone string) *CDR {
+ return cdr
}
-func (storedCdr *StoredCdr) Clone() *StoredCdr {
- clnCdr := *storedCdr
- clnCdr.ExtraFields = make(map[string]string)
- clnCdr.CostDetails = nil // Clean old reference
- for k, v := range storedCdr.ExtraFields {
- clnCdr.ExtraFields[k] = v
- }
- if storedCdr.CostDetails != nil {
- cDetails := *storedCdr.CostDetails
- clnCdr.CostDetails = &cDetails
- }
- return &clnCdr
+func (cdr *CDR) Clone() *CDR {
+ var clnedCDR CDR
+ utils.Clone(cdr, &clnedCDR)
+ return &clnedCDR
}
// Ability to send the CgrCdr remotely to another CDR server, we do not include rating variables for now
-func (storedCdr *StoredCdr) AsHttpForm() url.Values {
+func (cdr *CDR) AsHttpForm() url.Values {
v := url.Values{}
- for fld, val := range storedCdr.ExtraFields {
+ for fld, val := range cdr.ExtraFields {
v.Set(fld, val)
}
- v.Set(utils.TOR, storedCdr.TOR)
- v.Set(utils.ACCID, storedCdr.AccId)
- v.Set(utils.CDRHOST, storedCdr.CdrHost)
- v.Set(utils.CDRSOURCE, storedCdr.CdrSource)
- v.Set(utils.REQTYPE, storedCdr.ReqType)
- v.Set(utils.DIRECTION, storedCdr.Direction)
- v.Set(utils.TENANT, storedCdr.Tenant)
- v.Set(utils.CATEGORY, storedCdr.Category)
- v.Set(utils.ACCOUNT, storedCdr.Account)
- v.Set(utils.SUBJECT, storedCdr.Subject)
- v.Set(utils.DESTINATION, storedCdr.Destination)
- v.Set(utils.SETUP_TIME, storedCdr.SetupTime.Format(time.RFC3339))
- v.Set(utils.PDD, storedCdr.FieldAsString(&utils.RSRField{Id: utils.PDD}))
- v.Set(utils.ANSWER_TIME, storedCdr.AnswerTime.Format(time.RFC3339))
- v.Set(utils.USAGE, storedCdr.FormatUsage(utils.SECONDS))
- v.Set(utils.SUPPLIER, storedCdr.Supplier)
- v.Set(utils.DISCONNECT_CAUSE, storedCdr.DisconnectCause)
- if storedCdr.CostDetails != nil {
- v.Set(utils.COST_DETAILS, storedCdr.CostDetailsJson())
+ v.Set(utils.TOR, cdr.ToR)
+ v.Set(utils.ACCID, cdr.OriginID)
+ v.Set(utils.CDRHOST, cdr.OriginHost)
+ v.Set(utils.CDRSOURCE, cdr.Source)
+ v.Set(utils.REQTYPE, cdr.RequestType)
+ v.Set(utils.DIRECTION, cdr.Direction)
+ v.Set(utils.TENANT, cdr.Tenant)
+ v.Set(utils.CATEGORY, cdr.Category)
+ v.Set(utils.ACCOUNT, cdr.Account)
+ v.Set(utils.SUBJECT, cdr.Subject)
+ v.Set(utils.DESTINATION, cdr.Destination)
+ v.Set(utils.SETUP_TIME, cdr.SetupTime.Format(time.RFC3339))
+ v.Set(utils.PDD, cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}))
+ v.Set(utils.ANSWER_TIME, cdr.AnswerTime.Format(time.RFC3339))
+ v.Set(utils.USAGE, cdr.FormatUsage(utils.SECONDS))
+ v.Set(utils.SUPPLIER, cdr.Supplier)
+ v.Set(utils.DISCONNECT_CAUSE, cdr.DisconnectCause)
+ if cdr.CostDetails != nil {
+ v.Set(utils.COST_DETAILS, cdr.CostDetailsJson())
}
return v
}
// Used in mediation, primaryMandatory marks whether missing field out of request represents error or can be ignored
-func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, pddFld,
+func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, PDDFld,
answerTimeFld, durationFld, supplierFld, disconnectCauseFld, ratedFld, costFld *utils.RSRField,
- extraFlds []*utils.RSRField, primaryMandatory bool, timezone string) (*StoredCdr, error) {
- if reqTypeFld == nil {
- reqTypeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
+ extraFlds []*utils.RSRField, primaryMandatory bool, timezone string) (*CDR, error) {
+ if RequestTypeFld == nil {
+ RequestTypeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
}
- if reqTypeFld.Id == utils.META_DEFAULT {
- reqTypeFld.Id = utils.REQTYPE
+ if RequestTypeFld.Id == utils.META_DEFAULT {
+ RequestTypeFld.Id = utils.REQTYPE
}
if directionFld == nil {
directionFld, _ = utils.NewRSRField(utils.META_DEFAULT)
@@ -396,11 +378,11 @@ func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tena
if durationFld.Id == utils.META_DEFAULT {
durationFld.Id = utils.USAGE
}
- if pddFld == nil {
- pddFld, _ = utils.NewRSRField(utils.META_DEFAULT)
+ if PDDFld == nil {
+ PDDFld, _ = utils.NewRSRField(utils.META_DEFAULT)
}
- if pddFld.Id == utils.META_DEFAULT {
- pddFld.Id = utils.PDD
+ if PDDFld.Id == utils.META_DEFAULT {
+ PDDFld.Id = utils.PDD
}
if supplierFld == nil {
supplierFld, _ = utils.NewRSRField(utils.META_DEFAULT)
@@ -427,75 +409,75 @@ func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tena
costFld.Id = utils.COST
}
var err error
- frkStorCdr := new(StoredCdr)
- frkStorCdr.CgrId = storedCdr.CgrId
- frkStorCdr.TOR = storedCdr.TOR
- frkStorCdr.MediationRunId = runId
+ frkStorCdr := new(CDR)
+ frkStorCdr.CGRID = cdr.CGRID
+ frkStorCdr.ToR = cdr.ToR
+ frkStorCdr.RunID = runId
frkStorCdr.Cost = -1.0 // Default for non-rated CDR
- frkStorCdr.AccId = storedCdr.AccId
- frkStorCdr.CdrHost = storedCdr.CdrHost
- frkStorCdr.CdrSource = storedCdr.CdrSource
- frkStorCdr.ReqType = storedCdr.FieldAsString(reqTypeFld)
- if primaryMandatory && len(frkStorCdr.ReqType) == 0 {
- return nil, utils.NewErrMandatoryIeMissing(utils.REQTYPE, reqTypeFld.Id)
+ frkStorCdr.OriginID = cdr.OriginID
+ frkStorCdr.OriginHost = cdr.OriginHost
+ frkStorCdr.Source = cdr.Source
+ frkStorCdr.RequestType = cdr.FieldAsString(RequestTypeFld)
+ if primaryMandatory && len(frkStorCdr.RequestType) == 0 {
+ return nil, utils.NewErrMandatoryIeMissing(utils.REQTYPE, RequestTypeFld.Id)
}
- frkStorCdr.Direction = storedCdr.FieldAsString(directionFld)
+ frkStorCdr.Direction = cdr.FieldAsString(directionFld)
if primaryMandatory && len(frkStorCdr.Direction) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.DIRECTION, directionFld.Id)
}
- frkStorCdr.Tenant = storedCdr.FieldAsString(tenantFld)
+ frkStorCdr.Tenant = cdr.FieldAsString(tenantFld)
if primaryMandatory && len(frkStorCdr.Tenant) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.TENANT, tenantFld.Id)
}
- frkStorCdr.Category = storedCdr.FieldAsString(categFld)
+ frkStorCdr.Category = cdr.FieldAsString(categFld)
if primaryMandatory && len(frkStorCdr.Category) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.CATEGORY, categFld.Id)
}
- frkStorCdr.Account = storedCdr.FieldAsString(accountFld)
+ frkStorCdr.Account = cdr.FieldAsString(accountFld)
if primaryMandatory && len(frkStorCdr.Account) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.ACCOUNT, accountFld.Id)
}
- frkStorCdr.Subject = storedCdr.FieldAsString(subjectFld)
+ frkStorCdr.Subject = cdr.FieldAsString(subjectFld)
if primaryMandatory && len(frkStorCdr.Subject) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.SUBJECT, subjectFld.Id)
}
- frkStorCdr.Destination = storedCdr.FieldAsString(destFld)
- if primaryMandatory && len(frkStorCdr.Destination) == 0 && frkStorCdr.TOR == utils.VOICE {
+ frkStorCdr.Destination = cdr.FieldAsString(destFld)
+ if primaryMandatory && len(frkStorCdr.Destination) == 0 && frkStorCdr.ToR == utils.VOICE {
return nil, utils.NewErrMandatoryIeMissing(utils.DESTINATION, destFld.Id)
}
- sTimeStr := storedCdr.FieldAsString(setupTimeFld)
+ sTimeStr := cdr.FieldAsString(setupTimeFld)
if primaryMandatory && len(sTimeStr) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.SETUP_TIME, setupTimeFld.Id)
} else if frkStorCdr.SetupTime, err = utils.ParseTimeDetectLayout(sTimeStr, timezone); err != nil {
return nil, err
}
- aTimeStr := storedCdr.FieldAsString(answerTimeFld)
+ aTimeStr := cdr.FieldAsString(answerTimeFld)
if primaryMandatory && len(aTimeStr) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.ANSWER_TIME, answerTimeFld.Id)
} else if frkStorCdr.AnswerTime, err = utils.ParseTimeDetectLayout(aTimeStr, timezone); err != nil {
return nil, err
}
- durStr := storedCdr.FieldAsString(durationFld)
+ durStr := cdr.FieldAsString(durationFld)
if primaryMandatory && len(durStr) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.USAGE, durationFld.Id)
} else if frkStorCdr.Usage, err = utils.ParseDurationWithSecs(durStr); err != nil {
return nil, err
}
- pddStr := storedCdr.FieldAsString(pddFld)
- if primaryMandatory && len(pddStr) == 0 {
- return nil, utils.NewErrMandatoryIeMissing(utils.PDD, pddFld.Id)
- } else if frkStorCdr.Pdd, err = utils.ParseDurationWithSecs(pddStr); err != nil {
+ PDDStr := cdr.FieldAsString(PDDFld)
+ if primaryMandatory && len(PDDStr) == 0 {
+ return nil, utils.NewErrMandatoryIeMissing(utils.PDD, PDDFld.Id)
+ } else if frkStorCdr.PDD, err = utils.ParseDurationWithSecs(PDDStr); err != nil {
return nil, err
}
- frkStorCdr.Supplier = storedCdr.FieldAsString(supplierFld)
- frkStorCdr.DisconnectCause = storedCdr.FieldAsString(disconnectCauseFld)
- ratedStr := storedCdr.FieldAsString(ratedFld)
+ frkStorCdr.Supplier = cdr.FieldAsString(supplierFld)
+ frkStorCdr.DisconnectCause = cdr.FieldAsString(disconnectCauseFld)
+ ratedStr := cdr.FieldAsString(ratedFld)
if primaryMandatory && len(ratedStr) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.RATED_FLD, ratedFld.Id)
} else if frkStorCdr.Rated, err = strconv.ParseBool(ratedStr); err != nil {
return nil, err
}
- costStr := storedCdr.FieldAsString(costFld)
+ costStr := cdr.FieldAsString(costFld)
if primaryMandatory && len(costStr) == 0 {
return nil, utils.NewErrMandatoryIeMissing(utils.COST, costFld.Id)
} else if frkStorCdr.Cost, err = strconv.ParseFloat(costStr, 64); err != nil {
@@ -503,226 +485,228 @@ func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tena
}
frkStorCdr.ExtraFields = make(map[string]string, len(extraFlds))
for _, fld := range extraFlds {
- frkStorCdr.ExtraFields[fld.Id] = storedCdr.FieldAsString(fld)
+ frkStorCdr.ExtraFields[fld.Id] = cdr.FieldAsString(fld)
}
return frkStorCdr, nil
}
-func (storedCdr *StoredCdr) AsExternalCdr() *ExternalCdr {
- return &ExternalCdr{CgrId: storedCdr.CgrId,
- OrderId: storedCdr.OrderId,
- TOR: storedCdr.TOR,
- AccId: storedCdr.AccId,
- CdrHost: storedCdr.CdrHost,
- CdrSource: storedCdr.CdrSource,
- ReqType: storedCdr.ReqType,
- Direction: storedCdr.Direction,
- Tenant: storedCdr.Tenant,
- Category: storedCdr.Category,
- Account: storedCdr.Account,
- Subject: storedCdr.Subject,
- Destination: storedCdr.Destination,
- SetupTime: storedCdr.SetupTime.Format(time.RFC3339),
- AnswerTime: storedCdr.AnswerTime.Format(time.RFC3339),
- Usage: storedCdr.FormatUsage(utils.SECONDS),
- Pdd: storedCdr.FieldAsString(&utils.RSRField{Id: utils.PDD}),
- Supplier: storedCdr.Supplier,
- DisconnectCause: storedCdr.DisconnectCause,
- ExtraFields: storedCdr.ExtraFields,
- MediationRunId: storedCdr.MediationRunId,
- RatedAccount: storedCdr.RatedAccount,
- RatedSubject: storedCdr.RatedSubject,
- Cost: storedCdr.Cost,
- CostDetails: storedCdr.CostDetailsJson(),
+func (cdr *CDR) AsExternalCDR() *ExternalCDR {
+ return &ExternalCDR{CGRID: cdr.CGRID,
+ RunID: cdr.RunID,
+ OrderID: cdr.OrderID,
+ OriginHost: cdr.OriginHost,
+ Source: cdr.Source,
+ OriginID: cdr.OriginID,
+ ToR: cdr.ToR,
+ RequestType: cdr.RequestType,
+ Direction: cdr.Direction,
+ Tenant: cdr.Tenant,
+ Category: cdr.Category,
+ Account: cdr.Account,
+ Subject: cdr.Subject,
+ Destination: cdr.Destination,
+ SetupTime: cdr.SetupTime.Format(time.RFC3339),
+ PDD: cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}),
+ AnswerTime: cdr.AnswerTime.Format(time.RFC3339),
+ Usage: cdr.FormatUsage(utils.SECONDS),
+ Supplier: cdr.Supplier,
+ DisconnectCause: cdr.DisconnectCause,
+ ExtraFields: cdr.ExtraFields,
+ CostSource: cdr.CostSource,
+ Cost: cdr.Cost,
+ CostDetails: cdr.CostDetailsJson(),
+ ExtraInfo: cdr.ExtraInfo,
+ Rated: cdr.Rated,
}
}
// Implementation of Event interface, used in tests
-func (storedCdr *StoredCdr) AsEvent(ignored string) Event {
- return Event(storedCdr)
+func (cdr *CDR) AsEvent(ignored string) Event {
+ return Event(cdr)
}
-func (storedCdr *StoredCdr) ComputeLcr() bool {
+func (cdr *CDR) ComputeLcr() bool {
return false
}
-func (storedCdr *StoredCdr) GetName() string {
- return storedCdr.CdrSource
+func (cdr *CDR) GetName() string {
+ return cdr.Source
}
-func (storedCdr *StoredCdr) GetCgrId(timezone string) string {
- return storedCdr.CgrId
+func (cdr *CDR) GetCgrId(timezone string) string {
+ return cdr.CGRID
}
-func (storedCdr *StoredCdr) GetUUID() string {
- return storedCdr.AccId
+func (cdr *CDR) GetUUID() string {
+ return cdr.OriginID
}
-func (storedCdr *StoredCdr) GetSessionIds() []string {
- return []string{storedCdr.GetUUID()}
+func (cdr *CDR) GetSessionIds() []string {
+ return []string{cdr.GetUUID()}
}
-func (storedCdr *StoredCdr) GetDirection(fieldName string) string {
+func (cdr *CDR) GetDirection(fieldName string) string {
if utils.IsSliceMember([]string{utils.DIRECTION, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Direction
+ return cdr.Direction
}
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetSubject(fieldName string) string {
+func (cdr *CDR) GetSubject(fieldName string) string {
if utils.IsSliceMember([]string{utils.SUBJECT, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Subject
+ return cdr.Subject
}
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetAccount(fieldName string) string {
+func (cdr *CDR) GetAccount(fieldName string) string {
if utils.IsSliceMember([]string{utils.ACCOUNT, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Account
+ return cdr.Account
}
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetDestination(fieldName string) string {
+func (cdr *CDR) GetDestination(fieldName string) string {
if utils.IsSliceMember([]string{utils.DESTINATION, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Destination
+ return cdr.Destination
}
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetCallDestNr(fieldName string) string {
+func (cdr *CDR) GetCallDestNr(fieldName string) string {
if utils.IsSliceMember([]string{utils.DESTINATION, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Destination
+ return cdr.Destination
}
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetCategory(fieldName string) string {
+func (cdr *CDR) GetCategory(fieldName string) string {
if utils.IsSliceMember([]string{utils.CATEGORY, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Category
+ return cdr.Category
}
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetTenant(fieldName string) string {
+func (cdr *CDR) GetTenant(fieldName string) string {
if utils.IsSliceMember([]string{utils.TENANT, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Tenant
+ return cdr.Tenant
}
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetReqType(fieldName string) string {
+func (cdr *CDR) GetReqType(fieldName string) string {
if utils.IsSliceMember([]string{utils.REQTYPE, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.ReqType
+ return cdr.RequestType
}
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetSetupTime(fieldName, timezone string) (time.Time, error) {
+func (cdr *CDR) GetSetupTime(fieldName, timezone string) (time.Time, error) {
if utils.IsSliceMember([]string{utils.SETUP_TIME, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.SetupTime, nil
+ return cdr.SetupTime, nil
}
var sTimeVal string
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
sTimeVal = fieldName[len(utils.STATIC_VALUE_PREFIX):]
} else {
- sTimeVal = storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ sTimeVal = cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
return utils.ParseTimeDetectLayout(sTimeVal, timezone)
}
-func (storedCdr *StoredCdr) GetAnswerTime(fieldName, timezone string) (time.Time, error) {
+func (cdr *CDR) GetAnswerTime(fieldName, timezone string) (time.Time, error) {
if utils.IsSliceMember([]string{utils.ANSWER_TIME, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.AnswerTime, nil
+ return cdr.AnswerTime, nil
}
var aTimeVal string
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
aTimeVal = fieldName[len(utils.STATIC_VALUE_PREFIX):]
} else {
- aTimeVal = storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ aTimeVal = cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
return utils.ParseTimeDetectLayout(aTimeVal, timezone)
}
-func (storedCdr *StoredCdr) GetEndTime(fieldName, timezone string) (time.Time, error) {
- return storedCdr.AnswerTime.Add(storedCdr.Usage), nil
+func (cdr *CDR) GetEndTime(fieldName, timezone string) (time.Time, error) {
+ return cdr.AnswerTime.Add(cdr.Usage), nil
}
-func (storedCdr *StoredCdr) GetDuration(fieldName string) (time.Duration, error) {
+func (cdr *CDR) GetDuration(fieldName string) (time.Duration, error) {
if utils.IsSliceMember([]string{utils.USAGE, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Usage, nil
+ return cdr.Usage, nil
}
var durVal string
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
durVal = fieldName[len(utils.STATIC_VALUE_PREFIX):]
} else {
- durVal = storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ durVal = cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
return utils.ParseDurationWithSecs(durVal)
}
-func (storedCdr *StoredCdr) GetPdd(fieldName string) (time.Duration, error) {
+func (cdr *CDR) GetPdd(fieldName string) (time.Duration, error) {
if utils.IsSliceMember([]string{utils.PDD, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Pdd, nil
+ return cdr.PDD, nil
}
- var pddVal string
+ var PDDVal string
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
- pddVal = fieldName[len(utils.STATIC_VALUE_PREFIX):]
+ PDDVal = fieldName[len(utils.STATIC_VALUE_PREFIX):]
} else {
- pddVal = storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ PDDVal = cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
- return utils.ParseDurationWithSecs(pddVal)
+ return utils.ParseDurationWithSecs(PDDVal)
}
-func (storedCdr *StoredCdr) GetSupplier(fieldName string) string {
+func (cdr *CDR) GetSupplier(fieldName string) string {
if utils.IsSliceMember([]string{utils.SUPPLIER, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.Supplier
+ return cdr.Supplier
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetDisconnectCause(fieldName string) string {
+func (cdr *CDR) GetDisconnectCause(fieldName string) string {
if utils.IsSliceMember([]string{utils.DISCONNECT_CAUSE, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.DisconnectCause
+ return cdr.DisconnectCause
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetOriginatorIP(fieldName string) string {
+func (cdr *CDR) GetOriginatorIP(fieldName string) string {
if utils.IsSliceMember([]string{utils.CDRHOST, utils.META_DEFAULT, ""}, fieldName) {
- return storedCdr.CdrHost
+ return cdr.OriginHost
}
- return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
+ return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
-func (storedCdr *StoredCdr) GetExtraFields() map[string]string {
- return storedCdr.ExtraFields
+func (cdr *CDR) GetExtraFields() map[string]string {
+ return cdr.ExtraFields
}
-func (storedCdr *StoredCdr) MissingParameter(timezone string) bool {
- return len(storedCdr.AccId) == 0 ||
- len(storedCdr.Category) == 0 ||
- len(storedCdr.Tenant) == 0 ||
- len(storedCdr.Account) == 0 ||
- len(storedCdr.Destination) == 0
+func (cdr *CDR) MissingParameter(timezone string) bool {
+ return len(cdr.OriginID) == 0 ||
+ len(cdr.Category) == 0 ||
+ len(cdr.Tenant) == 0 ||
+ len(cdr.Account) == 0 ||
+ len(cdr.Destination) == 0
}
-func (storedCdr *StoredCdr) ParseEventValue(rsrFld *utils.RSRField, timezone string) string {
- return storedCdr.FieldAsString(rsrFld)
+func (cdr *CDR) ParseEventValue(rsrFld *utils.RSRField, timezone string) string {
+ return cdr.FieldAsString(rsrFld)
}
-func (storedCdr *StoredCdr) String() string {
- mrsh, _ := json.Marshal(storedCdr)
+func (cdr *CDR) String() string {
+ mrsh, _ := json.Marshal(cdr)
return string(mrsh)
}
-type ExternalCdr struct {
- CgrId string
- OrderId int64
- TOR string
- AccId string
- CdrHost string
- CdrSource string
- ReqType string
+type ExternalCDR struct {
+ CGRID string
+ RunID string
+ OrderID int64
+ OriginHost string
+ Source string
+ OriginID string
+ ToR string
+ RequestType string
Direction string
Tenant string
Category string
@@ -730,24 +714,23 @@ type ExternalCdr struct {
Subject string
Destination string
SetupTime string
+ PDD string
AnswerTime string
Usage string
- Pdd string
Supplier string
DisconnectCause string
ExtraFields map[string]string
- MediationRunId string
- RatedAccount string
- RatedSubject string
+ CostSource string
Cost float64
CostDetails string
+ ExtraInfo string
Rated bool // Mark the CDR as rated so we do not process it during mediation
}
// Used when authorizing requests from outside, eg ApierV1.GetMaxUsage
type UsageRecord struct {
- TOR string
- ReqType string
+ ToR string
+ RequestType string
Direction string
Tenant string
Category string
@@ -760,33 +743,32 @@ type UsageRecord struct {
ExtraFields map[string]string
}
-func (self *UsageRecord) AsStoredCdr(timezone string) (*StoredCdr, error) {
+func (self *UsageRecord) AsStoredCdr(timezone string) (*CDR, error) {
var err error
- storedCdr := &StoredCdr{CgrId: self.GetId(), TOR: self.TOR, ReqType: self.ReqType, Direction: self.Direction, Tenant: self.Tenant, Category: self.Category,
- Account: self.Account, Subject: self.Subject, Destination: self.Destination}
- if storedCdr.SetupTime, err = utils.ParseTimeDetectLayout(self.SetupTime, timezone); err != nil {
+ cdr := &CDR{CGRID: self.GetId(), ToR: self.ToR, RequestType: self.RequestType, Direction: self.Direction, Tenant: self.Tenant, Category: self.Category, Account: self.Account, Subject: self.Subject, Destination: self.Destination}
+ if cdr.SetupTime, err = utils.ParseTimeDetectLayout(self.SetupTime, timezone); err != nil {
return nil, err
}
- if storedCdr.AnswerTime, err = utils.ParseTimeDetectLayout(self.AnswerTime, timezone); err != nil {
+ if cdr.AnswerTime, err = utils.ParseTimeDetectLayout(self.AnswerTime, timezone); err != nil {
return nil, err
}
- if storedCdr.Usage, err = utils.ParseDurationWithSecs(self.Usage); err != nil {
+ if cdr.Usage, err = utils.ParseDurationWithSecs(self.Usage); err != nil {
return nil, err
}
if self.ExtraFields != nil {
- storedCdr.ExtraFields = make(map[string]string)
+ cdr.ExtraFields = make(map[string]string)
}
for k, v := range self.ExtraFields {
- storedCdr.ExtraFields[k] = v
+ cdr.ExtraFields[k] = v
}
- return storedCdr, nil
+ return cdr, nil
}
func (self *UsageRecord) AsCallDescriptor(timezone string) (*CallDescriptor, error) {
var err error
cd := &CallDescriptor{
CgrId: self.GetId(),
- TOR: self.TOR,
+ TOR: self.ToR,
Direction: self.Direction,
Tenant: self.Tenant,
Category: self.Category,
@@ -816,5 +798,5 @@ func (self *UsageRecord) AsCallDescriptor(timezone string) (*CallDescriptor, err
}
func (self *UsageRecord) GetId() string {
- return utils.Sha1(self.TOR, self.ReqType, self.Direction, self.Tenant, self.Category, self.Account, self.Subject, self.Destination, self.SetupTime, self.AnswerTime, self.Usage)
+ return utils.Sha1(self.ToR, self.RequestType, self.Direction, self.Tenant, self.Category, self.Account, self.Subject, self.Destination, self.SetupTime, self.AnswerTime, self.Usage)
}
diff --git a/engine/storedcdr_local_test.go b/engine/cdr_local_test.go
similarity index 77%
rename from engine/storedcdr_local_test.go
rename to engine/cdr_local_test.go
index 78598d20c..823e8f6d5 100644
--- a/engine/storedcdr_local_test.go
+++ b/engine/cdr_local_test.go
@@ -34,13 +34,13 @@ func TestHttpJsonPost(t *testing.T) {
if !*testLocal {
return
}
- cdrOut := &ExternalCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
- CdrHost: "192.168.1.1",
- CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdrOut := &ExternalCDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1",
+ Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "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: utils.DEFAULT_RUNID,
- Usage: "0.00000001", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
+ RunID: utils.DEFAULT_RUNID,
+ Usage: "0.00000001", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
if _, err := utils.HttpJsonPost("http://localhost:8000", false, cdrOut); err == nil {
t.Error(err)
diff --git a/engine/storedcdr_test.go b/engine/cdr_test.go
similarity index 66%
rename from engine/storedcdr_test.go
rename to engine/cdr_test.go
index 670c3bdee..013e0c8dc 100644
--- a/engine/storedcdr_test.go
+++ b/engine/cdr_test.go
@@ -26,38 +26,38 @@ import (
"github.com/cgrates/cgrates/utils"
)
-func TestStoredCdrInterfaces(t *testing.T) {
- storedCdr := new(StoredCdr)
- var _ RawCdr = storedCdr
- var _ Event = storedCdr
+func TestCDRInterfaces(t *testing.T) {
+ CDR := new(CDR)
+ var _ RawCdr = CDR
+ var _ Event = CDR
}
-func TestNewStoredCdrFromExternalCdr(t *testing.T) {
- extCdr := &ExternalCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+func TestNewCDRFromExternalCDR(t *testing.T) {
+ extCdr := &ExternalCDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1",
- SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", MediationRunId: utils.DEFAULT_RUNID,
- Usage: "0.00000001", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", Rated: true,
+ SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.DEFAULT_RUNID,
+ Usage: "0.00000001", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true,
}
- eStorCdr := &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+ eStorCdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1",
- SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(10), Pdd: time.Duration(7) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", Rated: true,
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10), PDD: time.Duration(7) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true,
}
- if storedCdr, err := NewStoredCdrFromExternalCdr(extCdr, ""); err != nil {
+ if CDR, err := NewCDRFromExternalCDR(extCdr, ""); err != nil {
t.Error(err)
- } else if !reflect.DeepEqual(eStorCdr, storedCdr) {
- t.Errorf("Expected: %+v, received: %+v", eStorCdr, storedCdr)
+ } else if !reflect.DeepEqual(eStorCdr, CDR) {
+ t.Errorf("Expected: %+v, received: %+v", eStorCdr, CDR)
}
}
-func TestStoredCdrClone(t *testing.T) {
- storCdr := &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+func TestCDRClone(t *testing.T) {
+ storCdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1",
- SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(10), Pdd: time.Duration(7) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", Rated: true,
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10), PDD: time.Duration(7) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true,
}
if clnStorCdr := storCdr.Clone(); !reflect.DeepEqual(storCdr, clnStorCdr) {
t.Errorf("Expecting: %+v, received: %+v", storCdr, clnStorCdr)
@@ -65,20 +65,21 @@ func TestStoredCdrClone(t *testing.T) {
}
func TestFieldAsString(t *testing.T) {
- cdr := 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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
- AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(10) * time.Second, Pdd: time.Duration(5) * time.Second, Supplier: "SUPPL1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans",
+ AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, PDD: time.Duration(5) * time.Second, Supplier: "SUPPL1",
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Cost: 1.01,
}
- if cdr.FieldAsString(&utils.RSRField{Id: utils.CGRID}) != cdr.CgrId ||
+ if cdr.FieldAsString(&utils.RSRField{Id: utils.CGRID}) != cdr.CGRID ||
cdr.FieldAsString(&utils.RSRField{Id: utils.ORDERID}) != "123" ||
cdr.FieldAsString(&utils.RSRField{Id: utils.TOR}) != utils.VOICE ||
- cdr.FieldAsString(&utils.RSRField{Id: utils.ACCID}) != cdr.AccId ||
- cdr.FieldAsString(&utils.RSRField{Id: utils.CDRHOST}) != cdr.CdrHost ||
- cdr.FieldAsString(&utils.RSRField{Id: utils.CDRSOURCE}) != cdr.CdrSource ||
- cdr.FieldAsString(&utils.RSRField{Id: utils.REQTYPE}) != cdr.ReqType ||
+ cdr.FieldAsString(&utils.RSRField{Id: utils.ACCID}) != cdr.OriginID ||
+ cdr.FieldAsString(&utils.RSRField{Id: utils.CDRHOST}) != cdr.OriginHost ||
+ cdr.FieldAsString(&utils.RSRField{Id: utils.CDRSOURCE}) != cdr.Source ||
+ cdr.FieldAsString(&utils.RSRField{Id: utils.REQTYPE}) != cdr.RequestType ||
cdr.FieldAsString(&utils.RSRField{Id: utils.DIRECTION}) != cdr.Direction ||
cdr.FieldAsString(&utils.RSRField{Id: utils.CATEGORY}) != cdr.Category ||
cdr.FieldAsString(&utils.RSRField{Id: utils.ACCOUNT}) != cdr.Account ||
@@ -89,21 +90,19 @@ func TestFieldAsString(t *testing.T) {
cdr.FieldAsString(&utils.RSRField{Id: utils.USAGE}) != "10" ||
cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}) != "5" ||
cdr.FieldAsString(&utils.RSRField{Id: utils.SUPPLIER}) != cdr.Supplier ||
- cdr.FieldAsString(&utils.RSRField{Id: utils.MEDI_RUNID}) != cdr.MediationRunId ||
+ cdr.FieldAsString(&utils.RSRField{Id: utils.MEDI_RUNID}) != cdr.RunID ||
cdr.FieldAsString(&utils.RSRField{Id: utils.COST}) != "1.01" ||
- cdr.FieldAsString(&utils.RSRField{Id: utils.RATED_ACCOUNT}) != "dan" ||
- cdr.FieldAsString(&utils.RSRField{Id: utils.RATED_SUBJECT}) != "dans" ||
cdr.FieldAsString(&utils.RSRField{Id: "field_extr1"}) != cdr.ExtraFields["field_extr1"] ||
cdr.FieldAsString(&utils.RSRField{Id: "fieldextr2"}) != cdr.ExtraFields["fieldextr2"] ||
cdr.FieldAsString(&utils.RSRField{Id: "dummy_field"}) != "" {
t.Error("Unexpected filed value received",
- cdr.FieldAsString(&utils.RSRField{Id: utils.CGRID}) != cdr.CgrId,
+ cdr.FieldAsString(&utils.RSRField{Id: utils.CGRID}) != cdr.CGRID,
cdr.FieldAsString(&utils.RSRField{Id: utils.ORDERID}) != "123",
cdr.FieldAsString(&utils.RSRField{Id: utils.TOR}) != utils.VOICE,
- cdr.FieldAsString(&utils.RSRField{Id: utils.ACCID}) != cdr.AccId,
- cdr.FieldAsString(&utils.RSRField{Id: utils.CDRHOST}) != cdr.CdrHost,
- cdr.FieldAsString(&utils.RSRField{Id: utils.CDRSOURCE}) != cdr.CdrSource,
- cdr.FieldAsString(&utils.RSRField{Id: utils.REQTYPE}) != cdr.ReqType,
+ cdr.FieldAsString(&utils.RSRField{Id: utils.ACCID}) != cdr.OriginID,
+ cdr.FieldAsString(&utils.RSRField{Id: utils.CDRHOST}) != cdr.OriginHost,
+ cdr.FieldAsString(&utils.RSRField{Id: utils.CDRSOURCE}) != cdr.Source,
+ cdr.FieldAsString(&utils.RSRField{Id: utils.REQTYPE}) != cdr.RequestType,
cdr.FieldAsString(&utils.RSRField{Id: utils.DIRECTION}) != cdr.Direction,
cdr.FieldAsString(&utils.RSRField{Id: utils.CATEGORY}) != cdr.Category,
cdr.FieldAsString(&utils.RSRField{Id: utils.ACCOUNT}) != cdr.Account,
@@ -114,9 +113,7 @@ func TestFieldAsString(t *testing.T) {
cdr.FieldAsString(&utils.RSRField{Id: utils.USAGE}) != "10",
cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}) != "5",
cdr.FieldAsString(&utils.RSRField{Id: utils.SUPPLIER}) != cdr.Supplier,
- cdr.FieldAsString(&utils.RSRField{Id: utils.MEDI_RUNID}) != cdr.MediationRunId,
- cdr.FieldAsString(&utils.RSRField{Id: utils.RATED_ACCOUNT}) != "dan",
- cdr.FieldAsString(&utils.RSRField{Id: utils.RATED_SUBJECT}) != "dans",
+ cdr.FieldAsString(&utils.RSRField{Id: utils.MEDI_RUNID}) != cdr.RunID,
cdr.FieldAsString(&utils.RSRField{Id: utils.COST}) != "1.01",
cdr.FieldAsString(&utils.RSRField{Id: "field_extr1"}) != cdr.ExtraFields["field_extr1"],
cdr.FieldAsString(&utils.RSRField{Id: "fieldextr2"}) != cdr.ExtraFields["fieldextr2"],
@@ -125,12 +122,12 @@ func TestFieldAsString(t *testing.T) {
}
func TestFieldsAsString(t *testing.T) {
- cdr := 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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
- AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(10) * time.Second, Pdd: time.Duration(5) * time.Second, Supplier: "SUPPL1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans",
+ AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, PDD: time.Duration(5) * time.Second, Supplier: "SUPPL1",
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
eVal := "call_from_1001"
if val := cdr.FieldsAsString(utils.ParseRSRFieldsMustCompile("Category;^_from_;Account", utils.INFIELD_SEP)); val != eVal {
@@ -139,10 +136,10 @@ func TestFieldsAsString(t *testing.T) {
}
func TestPassesFieldFilter(t *testing.T) {
- cdr := &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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+ cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
- AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
+ AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
if pass, _ := cdr.PassesFieldFilter(nil); !pass {
@@ -168,7 +165,7 @@ func TestPassesFieldFilter(t *testing.T) {
if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
t.Error("Passing filter")
}
- torFltr, _ := utils.NewRSRField(`^TOR::*voice/`)
+ torFltr, _ := utils.NewRSRField(`^ToR::*voice/`)
if pass, _ := cdr.PassesFieldFilter(torFltr); !pass {
t.Error("Not passing filter")
}
@@ -183,7 +180,7 @@ func TestPassesFieldFilter(t *testing.T) {
}
func TestPassesFieldFilterDn1(t *testing.T) {
- cdr := &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "futurem0005",
+ cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "futurem0005",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
acntPrefxFltr, _ := utils.NewRSRField(`~Account:s/^\w+[shmp]\d{4}$//`)
@@ -191,13 +188,13 @@ func TestPassesFieldFilterDn1(t *testing.T) {
t.Error("Not passing valid filter")
}
- cdr = &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "futurem00005",
+ cdr = &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "futurem00005",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
t.Error("Should not pass filter")
}
- cdr = &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "0402129281",
+ cdr = &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "0402129281",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
acntPrefxFltr, _ = utils.NewRSRField(`~Account:s/^0\d{9}$//`)
@@ -208,13 +205,13 @@ func TestPassesFieldFilterDn1(t *testing.T) {
if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
t.Error("Should not pass filter")
}
- cdr = &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "04021292812",
+ cdr = &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "04021292812",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
t.Error("Should not pass filter")
}
- cdr = &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "0162447222",
+ cdr = &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "0162447222",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
if acntPrefxFltr, err := utils.NewRSRField(`~Account:s/^0\d{9}$//`); err != nil {
@@ -234,11 +231,11 @@ func TestPassesFieldFilterDn1(t *testing.T) {
}
func TestUsageMultiply(t *testing.T) {
- cdr := StoredCdr{Usage: time.Duration(10) * time.Second}
+ cdr := CDR{Usage: time.Duration(10) * time.Second}
if cdr.UsageMultiply(1024.0, 0); cdr.Usage != time.Duration(10240)*time.Second {
t.Errorf("Unexpected usage after multiply: %v", cdr.Usage.Nanoseconds())
}
- cdr = StoredCdr{Usage: time.Duration(10240) * time.Second} // Simulate conversion back, gives out a bit odd result but this can be rounded on export
+ cdr = CDR{Usage: time.Duration(10240) * time.Second} // Simulate conversion back, gives out a bit odd result but this can be rounded on export
expectDuration, _ := time.ParseDuration("10.000005120s")
if cdr.UsageMultiply(0.000976563, 0); cdr.Usage != expectDuration {
t.Errorf("Unexpected usage after multiply: %v", cdr.Usage.Nanoseconds())
@@ -246,22 +243,22 @@ func TestUsageMultiply(t *testing.T) {
}
func TestCostMultiply(t *testing.T) {
- cdr := StoredCdr{Cost: 1.01}
+ cdr := CDR{Cost: 1.01}
if cdr.CostMultiply(1.19, 4); cdr.Cost != 1.2019 {
t.Errorf("Unexpected cost after multiply: %v", cdr.Cost)
}
- cdr = StoredCdr{Cost: 1.01}
+ cdr = CDR{Cost: 1.01}
if cdr.CostMultiply(1000, 0); cdr.Cost != 1010 {
t.Errorf("Unexpected cost after multiply: %v", cdr.Cost)
}
}
func TestFormatCost(t *testing.T) {
- cdr := StoredCdr{Cost: 1.01}
+ cdr := CDR{Cost: 1.01}
if cdr.FormatCost(0, 4) != "1.0100" {
t.Error("Unexpected format of the cost: ", cdr.FormatCost(0, 4))
}
- cdr = StoredCdr{Cost: 1.01001}
+ cdr = CDR{Cost: 1.01001}
if cdr.FormatCost(0, 4) != "1.0100" {
t.Error("Unexpected format of the cost: ", cdr.FormatCost(0, 4))
}
@@ -277,34 +274,34 @@ func TestFormatCost(t *testing.T) {
}
func TestFormatUsage(t *testing.T) {
- cdr := StoredCdr{Usage: time.Duration(10) * time.Second}
+ cdr := CDR{Usage: time.Duration(10) * time.Second}
if cdr.FormatUsage(utils.SECONDS) != "10" {
t.Error("Wrong usage format: ", cdr.FormatUsage(utils.SECONDS))
}
if cdr.FormatUsage("default") != "10" {
t.Error("Wrong usage format: ", cdr.FormatUsage("default"))
}
- cdr = StoredCdr{TOR: utils.DATA, Usage: time.Duration(1640113000000000)}
+ cdr = CDR{ToR: utils.DATA, Usage: time.Duration(1640113000000000)}
if cdr.FormatUsage("default") != "1640113" {
t.Error("Wrong usage format: ", cdr.FormatUsage("default"))
}
- cdr = StoredCdr{Usage: time.Duration(2) * time.Millisecond}
+ cdr = CDR{Usage: time.Duration(2) * time.Millisecond}
if cdr.FormatUsage("default") != "0.002" {
t.Error("Wrong usage format: ", cdr.FormatUsage("default"))
}
- cdr = StoredCdr{Usage: time.Duration(1002) * time.Millisecond}
+ cdr = CDR{Usage: time.Duration(1002) * time.Millisecond}
if cdr.FormatUsage("default") != "1.002" {
t.Error("Wrong usage format: ", cdr.FormatUsage("default"))
}
}
-func TestStoredCdrAsHttpForm(t *testing.T) {
- storCdr := 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: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+func TestCDRAsHttpForm(t *testing.T) {
+ storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
- SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
Usage: time.Duration(10) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, RatedSubject: "dans", Cost: 1.01,
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
cdrForm := storCdr.AsHttpForm()
if cdrForm.Get(utils.TOR) != utils.VOICE {
@@ -360,13 +357,14 @@ func TestStoredCdrAsHttpForm(t *testing.T) {
}
}
-func TestStoredCdrForkCdr(t *testing.T) {
- storCdr := 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: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+func TestCDRForkCdr(t *testing.T) {
+ storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
- SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), Pdd: time.Duration(200) * time.Millisecond, AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(10) * time.Second, Supplier: "suppl1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"},
- Cost: 1.01, RatedSubject: "dans"}
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), PDD: time.Duration(200) * time.Millisecond,
+ AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, Supplier: "suppl1",
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}, Cost: 1.01}
rtSampleCdrOut, err := storCdr.ForkCdr("sample_run1", &utils.RSRField{Id: utils.REQTYPE}, &utils.RSRField{Id: utils.DIRECTION}, &utils.RSRField{Id: utils.TENANT},
&utils.RSRField{Id: utils.CATEGORY}, &utils.RSRField{Id: utils.ACCOUNT}, &utils.RSRField{Id: utils.SUBJECT}, &utils.RSRField{Id: utils.DESTINATION},
&utils.RSRField{Id: utils.SETUP_TIME}, &utils.RSRField{Id: utils.PDD}, &utils.RSRField{Id: utils.ANSWER_TIME}, &utils.RSRField{Id: utils.USAGE},
@@ -375,21 +373,21 @@ func TestStoredCdrForkCdr(t *testing.T) {
if err != nil {
t.Error("Unexpected error received", err)
}
- expctSplRatedCdr := &StoredCdr{CgrId: storCdr.CgrId, TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED,
+ expctSplRatedCdr := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
- SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), Pdd: time.Duration(200) * time.Millisecond, AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), PDD: time.Duration(200) * time.Millisecond, AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
Usage: time.Duration(10) * time.Second, Supplier: "suppl1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"},
- MediationRunId: "sample_run1", Rated: false, Cost: 1.01}
+ RunID: "sample_run1", Rated: false, Cost: 1.01}
if !reflect.DeepEqual(expctSplRatedCdr, rtSampleCdrOut) {
t.Errorf("Expected: %v, received: %v", expctSplRatedCdr, rtSampleCdrOut)
}
}
-func TestStoredCdrForkCdrStaticVals(t *testing.T) {
- storCdr := StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
- CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+func TestCDRForkCdrStaticVals(t *testing.T) {
+ storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
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: utils.DEFAULT_RUNID,
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
rsrStPostpaid, _ := utils.NewRSRField("^" + utils.META_POSTPAID)
@@ -403,20 +401,20 @@ func TestStoredCdrForkCdrStaticVals(t *testing.T) {
rsrStDur, _ := utils.NewRSRField("^12s")
rsrStSuppl, _ := utils.NewRSRField("^supplier1")
rsrStDCause, _ := utils.NewRSRField("^HANGUP_COMPLETE")
- rsrPdd, _ := utils.NewRSRField("^3")
+ rsrPDD, _ := utils.NewRSRField("^3")
rsrStRated, _ := utils.NewRSRField("^true")
rsrStCost, _ := utils.NewRSRField("^1.2")
rtCdrOut2, err := storCdr.ForkCdr("wholesale_run", rsrStPostpaid, rsrStIn, rsrStCgr, rsrStPC, rsrStFA, rsrStFS, &utils.RSRField{Id: utils.DESTINATION},
- rsrStST, rsrPdd, rsrStAT, rsrStDur, rsrStSuppl, rsrStDCause, rsrStRated, rsrStCost, []*utils.RSRField{}, true, "")
+ rsrStST, rsrPDD, rsrStAT, rsrStDur, rsrStSuppl, rsrStDCause, rsrStRated, rsrStCost, []*utils.RSRField{}, true, "")
if err != nil {
t.Error("Unexpected error received", err)
}
- expctRatedCdr2 := &StoredCdr{CgrId: storCdr.CgrId, TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_POSTPAID,
+ expctRatedCdr2 := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID,
Direction: "*in", Tenant: "cgrates.com", Category: "premium_call", Account: "first_account", Subject: "first_subject", Destination: "1002",
SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC),
- AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(12) * time.Second, Pdd: time.Duration(3) * time.Second,
+ AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(12) * time.Second, PDD: time.Duration(3) * time.Second,
Supplier: "supplier1", DisconnectCause: "HANGUP_COMPLETE", Rated: true, Cost: 1.2,
- ExtraFields: map[string]string{}, MediationRunId: "wholesale_run"}
+ ExtraFields: map[string]string{}, RunID: "wholesale_run"}
if !reflect.DeepEqual(rtCdrOut2, expctRatedCdr2) {
t.Errorf("Received: %v, expected: %v", rtCdrOut2, expctRatedCdr2)
}
@@ -430,19 +428,19 @@ func TestStoredCdrForkCdrStaticVals(t *testing.T) {
}
}
-func TestStoredCdrForkCdrFromMetaDefaults(t *testing.T) {
- storCdr := StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
- CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
+func TestCDRForkCdrFromMetaDefaults(t *testing.T) {
+ storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
- SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(10) * time.Second, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL3",
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10) * time.Second, PDD: time.Duration(4) * time.Second, Supplier: "SUPPL3",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
}
- expctCdr := &StoredCdr{CgrId: storCdr.CgrId, TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED,
+ expctCdr := &CDR{CGRID: storCdr.CGRID, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
- Usage: time.Duration(10) * time.Second, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL3", Cost: 1.01,
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: "wholesale_run"}
+ Usage: time.Duration(10) * time.Second, PDD: time.Duration(4) * time.Second, Supplier: "SUPPL3", Cost: 1.01,
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, RunID: "wholesale_run"}
cdrOut, err := storCdr.ForkCdr("wholesale_run", &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT},
&utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT},
&utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT},
@@ -464,32 +462,30 @@ func TestStoredCdrForkCdrFromMetaDefaults(t *testing.T) {
}
}
-func TestStoredCdrAsExternalCdr(t *testing.T) {
- storCdr := StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+func TestCDRAsExternalCDR(t *testing.T) {
+ storCdr := CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
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: utils.DEFAULT_RUNID,
- Usage: time.Duration(10), Pdd: time.Duration(7) * time.Second, Supplier: "SUPPL1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans",
- }
- expectOutCdr := &ExternalCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(10), PDD: time.Duration(7) * time.Second, Supplier: "SUPPL1",
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01}
+ expectOutCdr := &ExternalCDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
- SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", MediationRunId: utils.DEFAULT_RUNID,
- Usage: "0.00000001", Pdd: "7", Supplier: "SUPPL1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans",
- }
- if cdrOut := storCdr.AsExternalCdr(); !reflect.DeepEqual(expectOutCdr, cdrOut) {
+ SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.DEFAULT_RUNID,
+ Usage: "0.00000001", PDD: "7", Supplier: "SUPPL1",
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, CostDetails: "null"}
+ if cdrOut := storCdr.AsExternalCDR(); !reflect.DeepEqual(expectOutCdr, cdrOut) {
t.Errorf("Expected: %+v, received: %+v", expectOutCdr, cdrOut)
}
}
-func TestStoredCdrEventFields(t *testing.T) {
- cdr := &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: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dans",
+func TestCDREventFields(t *testing.T) {
+ cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dans",
Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 27, 0, time.UTC),
- MediationRunId: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, Supplier: "suppl1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dan"}
+ RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, Supplier: "suppl1",
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01}
if ev := cdr.AsEvent(""); ev != Event(cdr) {
t.Error("Received: ", ev)
@@ -542,7 +538,7 @@ func TestStoredCdrEventFields(t *testing.T) {
if suppl := cdr.GetSupplier(utils.META_DEFAULT); suppl != cdr.Supplier {
t.Error("Received: ", suppl)
}
- if res := cdr.GetOriginatorIP(utils.META_DEFAULT); res != cdr.CdrHost {
+ if res := cdr.GetOriginatorIP(utils.META_DEFAULT); res != cdr.OriginHost {
t.Error("Received: ", res)
}
if extraFlds := cdr.GetExtraFields(); !reflect.DeepEqual(cdr.ExtraFields, extraFlds) {
@@ -550,29 +546,27 @@ func TestStoredCdrEventFields(t *testing.T) {
}
}
-func TesUsageReqAsStoredCdr(t *testing.T) {
- setupReq := &UsageRecord{TOR: utils.VOICE, ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call",
+func TesUsageReqAsCDR(t *testing.T) {
+ setupReq := &UsageRecord{ToR: utils.VOICE, RequestType: utils.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", Usage: "0.00000001",
}
- eStorCdr := &StoredCdr{TOR: utils.VOICE, ReqType: utils.META_RATED, Direction: "*out",
+ eStorCdr := &CDR{ToR: utils.VOICE, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(10)}
- if storedCdr, err := setupReq.AsStoredCdr(""); err != nil {
+ if CDR, err := setupReq.AsStoredCdr(""); err != nil {
t.Error(err)
- } else if !reflect.DeepEqual(eStorCdr, storedCdr) {
- t.Errorf("Expected: %+v, received: %+v", eStorCdr, storedCdr)
+ } else if !reflect.DeepEqual(eStorCdr, CDR) {
+ t.Errorf("Expected: %+v, received: %+v", eStorCdr, CDR)
}
}
func TestUsageReqAsCD(t *testing.T) {
- req := &UsageRecord{TOR: utils.VOICE, ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call",
+ req := &UsageRecord{ToR: utils.VOICE, RequestType: utils.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", Usage: "0.00000001",
}
- eCD := &CallDescriptor{CgrId: "9473e7b2e075d168b9da10ae957ee68fe5a217e4", TOR: req.TOR, Direction: req.Direction,
- Tenant: req.Tenant, Category: req.Category, Account: req.Account, Subject: req.Subject, Destination: req.Destination,
- TimeStart: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), TimeEnd: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).Add(time.Duration(10))}
+ eCD := &CallDescriptor{CgrId: "9473e7b2e075d168b9da10ae957ee68fe5a217e4", TOR: req.ToR, Direction: req.Direction, Tenant: req.Tenant, Category: req.Category, Account: req.Account, Subject: req.Subject, Destination: req.Destination, TimeStart: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), TimeEnd: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).Add(time.Duration(10))}
if cd, err := req.AsCallDescriptor(""); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCD, cd) {
diff --git a/engine/cdrs.go b/engine/cdrs.go
index 6eeeb0c14..8b603111d 100644
--- a/engine/cdrs.go
+++ b/engine/cdrs.go
@@ -107,8 +107,8 @@ func (self *CdrServer) RegisterHandlersToServer(server *utils.Server) {
server.RegisterHttpFunc("/freeswitch_json", fsCdrHandler)
}
-func (self *CdrServer) ProcessCdr(cdr *StoredCdr, reply *string) error {
- cacheKey := "ProcessCdr" + cdr.CgrId
+func (self *CdrServer) ProcessCdr(cdr *CDR, reply *string) error {
+ cacheKey := "ProcessCdr" + cdr.CGRID
if item, err := self.getCache().Get(cacheKey); err == nil && item != nil {
*reply = item.Value.(string)
return item.Err
@@ -123,17 +123,17 @@ func (self *CdrServer) ProcessCdr(cdr *StoredCdr, reply *string) error {
}
// RPC method, used to internally process CDR
-func (self *CdrServer) LocalProcessCdr(cdr *StoredCdr) error {
+func (self *CdrServer) LocalProcessCdr(cdr *CDR) error {
return self.processCdr(cdr)
}
// RPC method, used to process external CDRs
-func (self *CdrServer) ProcessExternalCdr(cdr *ExternalCdr) error {
- storedCdr, err := NewStoredCdrFromExternalCdr(cdr, self.cgrCfg.DefaultTimezone)
+func (self *CdrServer) ProcessExternalCdr(eCDR *ExternalCDR) error {
+ cdr, err := NewCDRFromExternalCDR(eCDR, self.cgrCfg.DefaultTimezone)
if err != nil {
return err
}
- return self.processCdr(storedCdr)
+ return self.processCdr(cdr)
}
func (self *CdrServer) LogCallCost(ccl *CallCostLog, reply *string) error {
@@ -155,44 +155,27 @@ func (self *CdrServer) LogCallCost(ccl *CallCostLog, reply *string) error {
func (self *CdrServer) LocalLogCallCost(ccl *CallCostLog) error {
if ccl.CheckDuplicate {
_, err := self.guard.Guard(func() (interface{}, error) {
- cc, err := self.cdrDb.GetCallCostLog(ccl.CgrId, ccl.Source, ccl.RunId)
+ cc, err := self.cdrDb.GetCallCostLog(ccl.CgrId, ccl.RunId)
if err != nil && err != gorm.RecordNotFound && err != mgov2.ErrNotFound {
return nil, err
}
if cc != nil {
return nil, utils.ErrExists
}
- return nil, self.cdrDb.LogCallCost(ccl.CgrId, ccl.Source, ccl.RunId, ccl.CallCost)
+ return nil, self.cdrDb.LogCallCost(ccl.CgrId, ccl.RunId, ccl.Source, ccl.CallCost)
}, 0, ccl.CgrId)
return err
}
- return self.cdrDb.LogCallCost(ccl.CgrId, ccl.Source, ccl.RunId, ccl.CallCost)
+ return self.cdrDb.LogCallCost(ccl.CgrId, ccl.RunId, ccl.Source, ccl.CallCost)
}
// Called by rate/re-rate API
-func (self *CdrServer) RateCdrs(cgrIds, runIds, tors, cdrHosts, cdrSources, reqTypes, directions, tenants, categories, accounts, subjects, destPrefixes, ratedAccounts, ratedSubjects []string,
- orderIdStart, orderIdEnd int64, timeStart, timeEnd time.Time, rerateErrors, rerateRated, sendToStats bool) error {
- var costStart, costEnd *float64
- if rerateErrors {
- costStart = utils.Float64Pointer(-1.0)
- if !rerateRated {
- costEnd = utils.Float64Pointer(0.0)
- }
- } else if rerateRated {
- costStart = utils.Float64Pointer(0.0)
- }
- cdrs, _, err := self.cdrDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: cgrIds, RunIds: runIds, Tors: tors, CdrHosts: cdrHosts, CdrSources: cdrSources,
- ReqTypes: reqTypes, Directions: directions, Tenants: tenants, Categories: categories, Accounts: accounts,
- Subjects: subjects, DestPrefixes: destPrefixes, RatedAccounts: ratedAccounts, RatedSubjects: ratedSubjects,
- OrderIdStart: orderIdStart, OrderIdEnd: orderIdEnd, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd,
- MinCost: costStart, MaxCost: costEnd})
+func (self *CdrServer) RateCDRs(cdrFltr *utils.CDRsFilter, sendToStats bool) error {
+ cdrs, _, err := self.cdrDb.GetCDRs(cdrFltr)
if err != nil {
return err
}
for _, cdr := range cdrs {
- if cdr.MediationRunId == "" { // raw CDRs which were not calculated before
- cdr.MediationRunId = utils.META_DEFAULT
- }
// replace aliases for cases they were loaded after CDR received
if err := LoadAlias(&AttrMatchingAlias{
Destination: cdr.Destination,
@@ -209,7 +192,7 @@ func (self *CdrServer) RateCdrs(cgrIds, runIds, tors, cdrHosts, cdrSources, reqT
if err := LoadUserProfile(cdr, utils.EXTRA_FIELDS); err != nil {
return err
}
- if err := self.rateStoreStatsReplicate(cdr); err != nil {
+ if err := self.rateStoreStatsReplicate(cdr, sendToStats); err != nil {
utils.Logger.Err(fmt.Sprintf(" Processing CDR %+v, got error: %s", cdr, err.Error()))
}
}
@@ -217,79 +200,66 @@ func (self *CdrServer) RateCdrs(cgrIds, runIds, tors, cdrHosts, cdrSources, reqT
}
// Returns error if not able to properly store the CDR, mediation is async since we can always recover offline
-func (self *CdrServer) processCdr(storedCdr *StoredCdr) (err error) {
- if storedCdr.Direction == "" {
- storedCdr.Direction = utils.OUT
+func (self *CdrServer) processCdr(cdr *CDR) (err error) {
+ if cdr.Direction == "" {
+ cdr.Direction = utils.OUT
}
- if storedCdr.ReqType == "" {
- storedCdr.ReqType = self.cgrCfg.DefaultReqType
+ if cdr.RequestType == "" {
+ cdr.RequestType = self.cgrCfg.DefaultReqType
}
- if storedCdr.Tenant == "" {
- storedCdr.Tenant = self.cgrCfg.DefaultTenant
+ if cdr.Tenant == "" {
+ cdr.Tenant = self.cgrCfg.DefaultTenant
}
- if storedCdr.Category == "" {
- storedCdr.Category = self.cgrCfg.DefaultCategory
+ if cdr.Category == "" {
+ cdr.Category = self.cgrCfg.DefaultCategory
}
- if storedCdr.Subject == "" { // Use account information as rating subject if missing
- storedCdr.Subject = storedCdr.Account
+ if cdr.Subject == "" { // Use account information as rating subject if missing
+ cdr.Subject = cdr.Account
}
- // replace aliases
- if err := LoadAlias(&AttrMatchingAlias{
- Destination: storedCdr.Destination,
- Direction: storedCdr.Direction,
- Tenant: storedCdr.Tenant,
- Category: storedCdr.Category,
- Account: storedCdr.Account,
- Subject: storedCdr.Subject,
- Context: utils.ALIAS_CONTEXT_RATING,
- }, storedCdr, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound {
- return err
- }
- // replace user profile fields
- if err := LoadUserProfile(storedCdr, utils.EXTRA_FIELDS); err != nil {
- return err
+ if !cdr.Rated {
+ cdr.RunID = utils.MetaRaw
}
if self.cgrCfg.CDRSStoreCdrs { // Store RawCDRs, this we do sync so we can reply with the status
- if err := self.cdrDb.SetCdr(storedCdr); err != nil { // Only original CDR stored in primary table, no derived
- utils.Logger.Err(fmt.Sprintf(" Storing primary CDR %+v, got error: %s", storedCdr, err.Error()))
+ if err := self.cdrDb.SetCDR(cdr, false); err != nil { // Only original CDR stored in primary table, no derived
+ utils.Logger.Err(fmt.Sprintf(" Storing primary CDR %+v, got error: %s", cdr, err.Error()))
return err // Error is propagated back and we don't continue processing the CDR if we cannot store it
}
-
}
- go self.deriveRateStoreStatsReplicate(storedCdr)
+ go self.deriveRateStoreStatsReplicate(cdr)
return nil
}
// Returns error if not able to properly store the CDR, mediation is async since we can always recover offline
-func (self *CdrServer) deriveRateStoreStatsReplicate(storedCdr *StoredCdr) error {
- cdrRuns, err := self.deriveCdrs(storedCdr)
+func (self *CdrServer) deriveRateStoreStatsReplicate(cdr *CDR) error {
+ cdrRuns, err := self.deriveCdrs(cdr)
if err != nil {
return err
}
- for _, cdr := range cdrRuns {
- if err := self.rateStoreStatsReplicate(cdr); err != nil {
+ for _, cdrRun := range cdrRuns {
+ if err := self.rateStoreStatsReplicate(cdrRun, true); err != nil {
return err
}
}
return nil
}
-func (self *CdrServer) rateStoreStatsReplicate(cdr *StoredCdr) error {
- if cdr.MediationRunId != utils.META_DEFAULT { // Process Aliases and Users for derived CDRs
- if err := LoadAlias(&AttrMatchingAlias{
- Destination: cdr.Destination,
- Direction: cdr.Direction,
- Tenant: cdr.Tenant,
- Category: cdr.Category,
- Account: cdr.Account,
- Subject: cdr.Subject,
- Context: utils.ALIAS_CONTEXT_RATING,
- }, cdr, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound {
- return err
- }
- if err := LoadUserProfile(cdr, utils.EXTRA_FIELDS); err != nil {
- return err
- }
+func (self *CdrServer) rateStoreStatsReplicate(cdr *CDR, sendToStats bool) error {
+ if cdr.RunID == utils.MetaRaw { // Overwrite *raw with *default for rating
+ cdr.RunID = utils.META_DEFAULT
+ }
+ if err := LoadAlias(&AttrMatchingAlias{
+ Destination: cdr.Destination,
+ Direction: cdr.Direction,
+ Tenant: cdr.Tenant,
+ Category: cdr.Category,
+ Account: cdr.Account,
+ Subject: cdr.Subject,
+ Context: utils.ALIAS_CONTEXT_RATING,
+ }, cdr, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound {
+ return err
+ }
+ if err := LoadUserProfile(cdr, utils.EXTRA_FIELDS); err != nil {
+ return err
}
// Rate CDR
if self.client != nil && !cdr.Rated {
@@ -298,7 +268,7 @@ func (self *CdrServer) rateStoreStatsReplicate(cdr *StoredCdr) error {
cdr.ExtraInfo = err.Error()
}
}
- if cdr.MediationRunId == utils.META_SURETAX { // Request should be processed by SureTax
+ if cdr.RunID == utils.META_SURETAX { // Request should be processed by SureTax
if err := SureTaxProcessCdr(cdr); err != nil {
cdr.Cost = -1.0
cdr.ExtraInfo = err.Error() // Something failed, write the error in the ExtraInfo
@@ -306,18 +276,12 @@ func (self *CdrServer) rateStoreStatsReplicate(cdr *StoredCdr) error {
}
if self.cgrCfg.CDRSStoreCdrs { // Store CDRs
// Store RatedCDR
- if err := self.cdrDb.SetRatedCdr(cdr); err != nil {
+ if err := self.cdrDb.SetCDR(cdr, true); err != nil {
utils.Logger.Err(fmt.Sprintf(" Storing rated CDR %+v, got error: %s", cdr, err.Error()))
}
- // Store CostDetails
- if cdr.Rated || utils.IsSliceMember([]string{utils.RATED, utils.META_RATED}, cdr.ReqType) { // Account related CDRs are saved automatically, so save the others here if requested
- if err := self.cdrDb.LogCallCost(cdr.CgrId, utils.CDRS_SOURCE, cdr.MediationRunId, cdr.CostDetails); err != nil {
- utils.Logger.Err(fmt.Sprintf(" Storing costs for CDR %+v, costDetails: %+v, got error: %s", cdr, cdr.CostDetails, err.Error()))
- }
- }
}
// Attach CDR to stats
- if self.stats != nil { // Send CDR to stats
+ if self.stats != nil && sendToStats { // Send CDR to stats
var out int
if err := self.stats.Call("CDRStatsV1.AppendCDR", cdr, &out); err != nil {
utils.Logger.Err(fmt.Sprintf(" Could not append cdr to stats: %s", err.Error()))
@@ -329,35 +293,31 @@ func (self *CdrServer) rateStoreStatsReplicate(cdr *StoredCdr) error {
return nil
}
-func (self *CdrServer) deriveCdrs(storedCdr *StoredCdr) ([]*StoredCdr, error) {
- if len(storedCdr.MediationRunId) == 0 {
- storedCdr.MediationRunId = utils.META_DEFAULT
- }
- cdrRuns := []*StoredCdr{storedCdr}
- if storedCdr.Rated { // Do not derive already rated CDRs since they should be already derived
+func (self *CdrServer) deriveCdrs(cdr *CDR) ([]*CDR, error) {
+ cdrRuns := []*CDR{cdr}
+ if cdr.RunID != utils.MetaRaw { // Only derive *raw CDRs
return cdrRuns, nil
}
- attrsDC := &utils.AttrDerivedChargers{Tenant: storedCdr.Tenant, Category: storedCdr.Category, Direction: storedCdr.Direction,
- Account: storedCdr.Account, Subject: storedCdr.Subject, Destination: storedCdr.Destination}
+ attrsDC := &utils.AttrDerivedChargers{Tenant: cdr.Tenant, Category: cdr.Category, Direction: cdr.Direction,
+ Account: cdr.Account, Subject: cdr.Subject, Destination: cdr.Destination}
var dcs utils.DerivedChargers
if err := self.client.Call("Responder.GetDerivedChargers", attrsDC, &dcs); err != nil {
- utils.Logger.Err(fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", storedCdr.CgrId, err.Error()))
+ utils.Logger.Err(fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", cdr.CGRID, err.Error()))
return nil, err
}
for _, dc := range dcs.Chargers {
runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
matchingAllFilters := true
for _, dcRunFilter := range runFilters {
- if fltrPass, _ := storedCdr.PassesFieldFilter(dcRunFilter); !fltrPass {
+ if fltrPass, _ := cdr.PassesFieldFilter(dcRunFilter); !fltrPass {
matchingAllFilters = false
break
}
}
if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
-
continue
}
- dcReqTypeFld, _ := utils.NewRSRField(dc.ReqTypeField)
+ dcRequestTypeFld, _ := utils.NewRSRField(dc.RequestTypeField)
dcDirFld, _ := utils.NewRSRField(dc.DirectionField)
dcTenantFld, _ := utils.NewRSRField(dc.TenantField)
dcCategoryFld, _ := utils.NewRSRField(dc.CategoryField)
@@ -365,17 +325,17 @@ func (self *CdrServer) deriveCdrs(storedCdr *StoredCdr) ([]*StoredCdr, error) {
dcSubjFld, _ := utils.NewRSRField(dc.SubjectField)
dcDstFld, _ := utils.NewRSRField(dc.DestinationField)
dcSTimeFld, _ := utils.NewRSRField(dc.SetupTimeField)
- dcPddFld, _ := utils.NewRSRField(dc.PddField)
+ dcPddFld, _ := utils.NewRSRField(dc.PDDField)
dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField)
dcDurFld, _ := utils.NewRSRField(dc.UsageField)
dcSupplFld, _ := utils.NewRSRField(dc.SupplierField)
dcDCauseFld, _ := utils.NewRSRField(dc.DisconnectCauseField)
dcRatedFld, _ := utils.NewRSRField(dc.RatedField)
dcCostFld, _ := utils.NewRSRField(dc.CostField)
- forkedCdr, err := storedCdr.ForkCdr(dc.RunId, dcReqTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld,
+ forkedCdr, err := cdr.ForkCdr(dc.RunID, dcRequestTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld,
dcSTimeFld, dcPddFld, dcATimeFld, dcDurFld, dcSupplFld, dcDCauseFld, dcRatedFld, dcCostFld, []*utils.RSRField{}, true, self.cgrCfg.DefaultTimezone)
if err != nil {
- utils.Logger.Err(fmt.Sprintf("Could not fork CGR with cgrid %s, run: %s, error: %s", storedCdr.CgrId, dc.RunId, err.Error()))
+ utils.Logger.Err(fmt.Sprintf("Could not fork CGR with cgrid %s, run: %s, error: %s", cdr.CGRID, dc.RunID, err.Error()))
continue // do not add it to the forked CDR list
}
if !forkedCdr.Rated {
@@ -386,30 +346,61 @@ func (self *CdrServer) deriveCdrs(storedCdr *StoredCdr) ([]*StoredCdr, error) {
return cdrRuns, nil
}
+func (self *CdrServer) rateCDR(cdr *CDR) error {
+ var qryCC *CallCost
+ var err error
+ if cdr.RequestType == utils.META_NONE {
+ return nil
+ }
+ if utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, cdr.RequestType) && cdr.Usage != 0 { // ToDo: Get rid of PREPAID as soon as we don't want to support it backwards
+ // Should be previously calculated and stored in DB
+ delay := utils.Fib()
+ for i := 0; i < 4; i++ {
+ qryCC, err = self.cdrDb.GetCallCostLog(cdr.CGRID, cdr.RunID)
+ if err == nil {
+ break
+ }
+ time.Sleep(delay())
+ }
+ if err != nil && (err == gorm.RecordNotFound || err == mgov2.ErrNotFound) { //calculate CDR as for pseudoprepaid
+ utils.Logger.Warning(fmt.Sprintf(" WARNING: Could not find CallCostLog for cgrid: %s, source: %s, runid: %s, will recalculate", cdr.CGRID, utils.SESSION_MANAGER_SOURCE, cdr.RunID))
+ qryCC, err = self.getCostFromRater(cdr)
+ }
+
+ } else {
+ qryCC, err = self.getCostFromRater(cdr)
+ }
+ if err != nil {
+ return err
+ } else if qryCC != nil {
+ cdr.Cost = qryCC.Cost
+ cdr.CostDetails = qryCC
+ }
+ return nil
+}
+
// Retrive the cost from engine
-func (self *CdrServer) getCostFromRater(storedCdr *StoredCdr) (*CallCost, error) {
+func (self *CdrServer) getCostFromRater(cdr *CDR) (*CallCost, error) {
cc := new(CallCost)
var err error
- timeStart := storedCdr.AnswerTime
+ timeStart := cdr.AnswerTime
if timeStart.IsZero() { // Fix for FreeSWITCH unanswered calls
- timeStart = storedCdr.SetupTime
+ timeStart = cdr.SetupTime
}
cd := &CallDescriptor{
- TOR: storedCdr.TOR,
- Direction: storedCdr.Direction,
- Tenant: storedCdr.Tenant,
- Category: storedCdr.Category,
- Subject: storedCdr.Subject,
- Account: storedCdr.Account,
- Destination: storedCdr.Destination,
+ TOR: cdr.ToR,
+ Direction: cdr.Direction,
+ Tenant: cdr.Tenant,
+ Category: cdr.Category,
+ Subject: cdr.Subject,
+ Account: cdr.Account,
+ Destination: cdr.Destination,
TimeStart: timeStart,
- TimeEnd: timeStart.Add(storedCdr.Usage),
- DurationIndex: storedCdr.Usage,
+ TimeEnd: timeStart.Add(cdr.Usage),
+ DurationIndex: cdr.Usage,
}
- if utils.IsSliceMember([]string{utils.META_PSEUDOPREPAID, utils.META_POSTPAID, utils.META_PREPAID, utils.PSEUDOPREPAID, utils.POSTPAID, utils.PREPAID}, storedCdr.ReqType) { // Prepaid - Cost can be recalculated in case of missing records from SM
- if err = self.client.Call("Responder.Debit", cd, cc); err == nil { // Debit has occured, we are forced to write the log, even if CDR store is disabled
- self.cdrDb.LogCallCost(storedCdr.CgrId, utils.CDRS_SOURCE, storedCdr.MediationRunId, cc)
- }
+ if utils.IsSliceMember([]string{utils.META_PSEUDOPREPAID, utils.META_POSTPAID, utils.META_PREPAID, utils.PSEUDOPREPAID, utils.POSTPAID, utils.PREPAID}, cdr.RequestType) { // Prepaid - Cost can be recalculated in case of missing records from SM
+ err = self.client.Call("Responder.Debit", cd, cc)
} else {
err = self.client.Call("Responder.GetCost", cd, cc)
}
@@ -419,41 +410,8 @@ func (self *CdrServer) getCostFromRater(storedCdr *StoredCdr) (*CallCost, error)
return cc, nil
}
-func (self *CdrServer) rateCDR(storedCdr *StoredCdr) error {
- var qryCC *CallCost
- var err error
- if storedCdr.ReqType == utils.META_NONE {
- return nil
- }
- if utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, storedCdr.ReqType) && storedCdr.Usage != 0 { // ToDo: Get rid of PREPAID as soon as we don't want to support it backwards
- // Should be previously calculated and stored in DB
- delay := utils.Fib()
- for i := 0; i < 4; i++ {
- qryCC, err = self.cdrDb.GetCallCostLog(storedCdr.CgrId, utils.SESSION_MANAGER_SOURCE, storedCdr.MediationRunId)
- if err == nil {
- break
- }
- time.Sleep(delay())
- }
- if err != nil && (err == gorm.RecordNotFound || err == mgov2.ErrNotFound) { //calculate CDR as for pseudoprepaid
- utils.Logger.Warning(fmt.Sprintf(" WARNING: Could not find CallCostLog for cgrid: %s, source: %s, runid: %s, will recalculate", storedCdr.CgrId, utils.SESSION_MANAGER_SOURCE, storedCdr.MediationRunId))
- qryCC, err = self.getCostFromRater(storedCdr)
- }
-
- } else {
- qryCC, err = self.getCostFromRater(storedCdr)
- }
- if err != nil {
- return err
- } else if qryCC != nil {
- storedCdr.Cost = qryCC.Cost
- storedCdr.CostDetails = qryCC
- }
- return nil
-}
-
// ToDo: Add websocket support
-func (self *CdrServer) replicateCdr(cdr *StoredCdr) error {
+func (self *CdrServer) replicateCdr(cdr *CDR) error {
for _, rplCfg := range self.cgrCfg.CDRSCdrReplication {
passesFilters := true
for _, cdfFltr := range rplCfg.CdrFilter {
@@ -475,7 +433,6 @@ func (self *CdrServer) replicateCdr(cdr *StoredCdr) error {
content = utils.CONTENT_JSON
body = cdr
}
-
errChan := make(chan error)
go func(body interface{}, rplCfg *config.CdrReplicationCfg, content string, errChan chan error) {
fallbackPath := path.Join(
diff --git a/engine/cdrstats.go b/engine/cdrstats.go
index 6ff1dae4c..94d17cf51 100644
--- a/engine/cdrstats.go
+++ b/engine/cdrstats.go
@@ -64,7 +64,7 @@ type CdrStats struct {
TOR []string // CDRFieldFilter on TORs
CdrHost []string // CDRFieldFilter on CdrHosts
CdrSource []string // CDRFieldFilter on CdrSources
- ReqType []string // CDRFieldFilter on ReqTypes
+ ReqType []string // CDRFieldFilter on RequestTypes
Direction []string // CDRFieldFilter on Directions
Tenant []string // CDRFieldFilter on Tenants
Category []string // CDRFieldFilter on Categories
@@ -82,7 +82,7 @@ type CdrStats struct {
Triggers ActionTriggers
}
-func (cs *CdrStats) AcceptCdr(cdr *StoredCdr) bool {
+func (cs *CdrStats) AcceptCdr(cdr *CDR) bool {
if cdr == nil {
return false
}
@@ -94,16 +94,16 @@ func (cs *CdrStats) AcceptCdr(cdr *StoredCdr) bool {
return false
}
}
- if len(cs.TOR) > 0 && !utils.IsSliceMember(cs.TOR, cdr.TOR) {
+ if len(cs.TOR) > 0 && !utils.IsSliceMember(cs.TOR, cdr.ToR) {
return false
}
- if len(cs.CdrHost) > 0 && !utils.IsSliceMember(cs.CdrHost, cdr.CdrHost) {
+ if len(cs.CdrHost) > 0 && !utils.IsSliceMember(cs.CdrHost, cdr.OriginHost) {
return false
}
- if len(cs.CdrSource) > 0 && !utils.IsSliceMember(cs.CdrSource, cdr.CdrSource) {
+ if len(cs.CdrSource) > 0 && !utils.IsSliceMember(cs.CdrSource, cdr.Source) {
return false
}
- if len(cs.ReqType) > 0 && !utils.IsSliceMember(cs.ReqType, cdr.ReqType) {
+ if len(cs.ReqType) > 0 && !utils.IsSliceMember(cs.ReqType, cdr.RequestType) {
return false
}
if len(cs.Direction) > 0 && !utils.IsSliceMember(cs.Direction, cdr.Direction) {
@@ -153,10 +153,10 @@ func (cs *CdrStats) AcceptCdr(cdr *StoredCdr) bool {
}
}
if len(cs.PddInterval) > 0 {
- if cdr.Pdd < cs.PddInterval[0] {
+ if cdr.PDD < cs.PddInterval[0] {
return false
}
- if len(cs.PddInterval) > 1 && cdr.Pdd >= cs.PddInterval[1] {
+ if len(cs.PddInterval) > 1 && cdr.PDD >= cs.PddInterval[1] {
return false
}
}
@@ -166,7 +166,7 @@ func (cs *CdrStats) AcceptCdr(cdr *StoredCdr) bool {
if len(cs.DisconnectCause) > 0 && !utils.IsSliceMember(cs.DisconnectCause, cdr.DisconnectCause) {
return false
}
- if len(cs.MediationRunIds) > 0 && !utils.IsSliceMember(cs.MediationRunIds, cdr.MediationRunId) {
+ if len(cs.MediationRunIds) > 0 && !utils.IsSliceMember(cs.MediationRunIds, cdr.RunID) {
return false
}
if len(cs.CostInterval) > 0 {
@@ -177,12 +177,6 @@ func (cs *CdrStats) AcceptCdr(cdr *StoredCdr) bool {
return false
}
}
- if len(cs.RatedAccount) > 0 && !utils.IsSliceMember(cs.RatedAccount, cdr.RatedAccount) {
- return false
- }
- if len(cs.RatedSubject) > 0 && !utils.IsSliceMember(cs.RatedSubject, cdr.RatedSubject) {
- return false
- }
return true
}
diff --git a/engine/cgrcdr.go b/engine/cgrcdr.go
index db33e4020..7121070dc 100644
--- a/engine/cgrcdr.go
+++ b/engine/cgrcdr.go
@@ -31,7 +31,7 @@ func NewCgrCdrFromHttpReq(req *http.Request, timezone string) (CgrCdr, error) {
}
}
cgrCdr := make(CgrCdr)
- cgrCdr[utils.CDRHOST] = req.RemoteAddr
+ cgrCdr[utils.CDRSOURCE] = req.RemoteAddr
for k, vals := range req.Form {
cgrCdr[k] = vals[0] // We only support the first value for now, if more are provided it is considered remote's fault
}
@@ -40,9 +40,9 @@ func NewCgrCdrFromHttpReq(req *http.Request, timezone string) (CgrCdr, error) {
type CgrCdr map[string]string
-func (cgrCdr CgrCdr) getCgrId(timezone string) string {
- if cgrId, hasIt := cgrCdr[utils.CGRID]; hasIt {
- return cgrId
+func (cgrCdr CgrCdr) getCGRID(timezone string) string {
+ if CGRID, hasIt := cgrCdr[utils.CGRID]; hasIt {
+ return CGRID
}
setupTime, _ := utils.ParseTimeDetectLayout(cgrCdr[utils.SETUP_TIME], timezone)
return utils.Sha1(cgrCdr[utils.ACCID], setupTime.UTC().String())
@@ -58,22 +58,22 @@ func (cgrCdr CgrCdr) getExtraFields() map[string]string {
return extraFields
}
-func (cgrCdr CgrCdr) AsStoredCdr(timezone string) *StoredCdr {
- storCdr := new(StoredCdr)
- storCdr.CgrId = cgrCdr.getCgrId(timezone)
- storCdr.TOR = cgrCdr[utils.TOR]
- storCdr.AccId = cgrCdr[utils.ACCID]
- storCdr.CdrHost = cgrCdr[utils.CDRHOST]
- storCdr.CdrSource = cgrCdr[utils.CDRSOURCE]
- storCdr.ReqType = cgrCdr[utils.REQTYPE]
- storCdr.Direction = "*out"
+func (cgrCdr CgrCdr) AsStoredCdr(timezone string) *CDR {
+ storCdr := new(CDR)
+ storCdr.CGRID = cgrCdr.getCGRID(timezone)
+ storCdr.ToR = cgrCdr[utils.TOR]
+ storCdr.OriginID = cgrCdr[utils.ACCID]
+ storCdr.OriginHost = cgrCdr[utils.CDRHOST]
+ storCdr.Source = cgrCdr[utils.CDRSOURCE]
+ storCdr.RequestType = cgrCdr[utils.REQTYPE]
+ storCdr.Direction = utils.OUT
storCdr.Tenant = cgrCdr[utils.TENANT]
storCdr.Category = cgrCdr[utils.CATEGORY]
storCdr.Account = cgrCdr[utils.ACCOUNT]
storCdr.Subject = cgrCdr[utils.SUBJECT]
storCdr.Destination = cgrCdr[utils.DESTINATION]
storCdr.SetupTime, _ = utils.ParseTimeDetectLayout(cgrCdr[utils.SETUP_TIME], timezone) // Not interested to process errors, should do them if necessary in a previous step
- storCdr.Pdd, _ = utils.ParseDurationWithSecs(cgrCdr[utils.PDD])
+ storCdr.PDD, _ = utils.ParseDurationWithSecs(cgrCdr[utils.PDD])
storCdr.AnswerTime, _ = utils.ParseTimeDetectLayout(cgrCdr[utils.ANSWER_TIME], timezone)
storCdr.Usage, _ = utils.ParseDurationWithSecs(cgrCdr[utils.USAGE])
storCdr.Supplier = cgrCdr[utils.SUPPLIER]
diff --git a/engine/cgrcdr_test.go b/engine/cgrcdr_test.go
index 5aa544ca1..82648affe 100644
--- a/engine/cgrcdr_test.go
+++ b/engine/cgrcdr_test.go
@@ -26,45 +26,45 @@ import (
)
/*
-curl --data "accid=asbfdsaf&cdrhost=192.168.1.1&reqtype=rated&direction=*out&tenant=cgrates.org&tor=call&account=1001&subject=1001&destination=1002&time_answer=1383813746&duration=10&field_extr1=val_extr1&fieldextr2=valextr2" http://ipbxdev:2080/cgr
+curl --data "OriginID=asbfdsaf&OriginHost=192.168.1.1&RequestType=rated&direction=*out&tenant=cgrates.org&tor=call&account=1001&subject=1001&destination=1002&time_answer=1383813746&duration=10&field_extr1=val_extr1&fieldextr2=valextr2" http://ipbxdev:2080/cgr
*/
func TestCgrCdrInterfaces(t *testing.T) {
var _ RawCdr = make(CgrCdr)
}
-func TestCgrCdrAsStoredCdr(t *testing.T) {
+func TestCgrCdrAsCDR(t *testing.T) {
cgrCdr := CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "dsafdsaf", utils.CDRHOST: "192.168.1.1", utils.CDRSOURCE: "internal_test", utils.REQTYPE: utils.META_RATED,
utils.DIRECTION: utils.OUT,
utils.TENANT: "cgrates.org", utils.CATEGORY: "call",
utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-07T08:42:20Z", utils.ANSWER_TIME: "2013-11-07T08:42:26Z",
utils.USAGE: "10", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2"}
setupTime, _ := utils.ParseTimeDetectLayout(cgrCdr[utils.SETUP_TIME], "")
- expctRtCdr := &StoredCdr{CgrId: utils.Sha1(cgrCdr[utils.ACCID], setupTime.String()), TOR: utils.VOICE, AccId: cgrCdr[utils.ACCID], CdrHost: cgrCdr[utils.CDRHOST],
- CdrSource: cgrCdr[utils.CDRSOURCE],
- ReqType: cgrCdr[utils.REQTYPE],
- Direction: cgrCdr[utils.DIRECTION], Tenant: cgrCdr[utils.TENANT], Category: cgrCdr[utils.CATEGORY], Account: cgrCdr[utils.ACCOUNT], Subject: cgrCdr[utils.SUBJECT],
+ expctRtCdr := &CDR{CGRID: utils.Sha1(cgrCdr[utils.ACCID], setupTime.String()), ToR: utils.VOICE, OriginID: cgrCdr[utils.ACCID], OriginHost: cgrCdr[utils.CDRHOST],
+ Source: cgrCdr[utils.CDRSOURCE],
+ RequestType: cgrCdr[utils.REQTYPE],
+ Direction: cgrCdr[utils.DIRECTION], Tenant: cgrCdr[utils.TENANT], Category: cgrCdr[utils.CATEGORY], Account: cgrCdr[utils.ACCOUNT], Subject: cgrCdr[utils.SUBJECT],
Destination: cgrCdr[utils.DESTINATION], SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
Usage: time.Duration(10) * time.Second, Supplier: "SUPPL1",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: -1}
- if storedCdr := cgrCdr.AsStoredCdr(""); !reflect.DeepEqual(expctRtCdr, storedCdr) {
- t.Errorf("Expecting %v, received: %v", expctRtCdr, storedCdr)
+ if CDR := cgrCdr.AsStoredCdr(""); !reflect.DeepEqual(expctRtCdr, CDR) {
+ t.Errorf("Expecting %v, received: %v", expctRtCdr, CDR)
}
}
-// Make sure the replicated CDR matches the expected StoredCdr
-func TestReplicatedCgrCdrAsStoredCdr(t *testing.T) {
+// Make sure the replicated CDR matches the expected CDR
+func TestReplicatedCgrCdrAsCDR(t *testing.T) {
cgrCdr := CgrCdr{utils.CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41", utils.TOR: utils.VOICE, utils.ACCID: "dsafdsaf", utils.CDRHOST: "192.168.1.1",
utils.CDRSOURCE: "internal_test", utils.REQTYPE: utils.META_RATED,
utils.DIRECTION: utils.OUT, utils.TENANT: "cgrates.org", utils.CATEGORY: "call",
utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-07T08:42:20Z", utils.PDD: "0.200", utils.ANSWER_TIME: "2013-11-07T08:42:26Z",
utils.USAGE: "10", utils.SUPPLIER: "SUPPL1", utils.DISCONNECT_CAUSE: "NORMAL_CLEARING", utils.COST: "0.12", utils.RATED: "true", "field_extr1": "val_extr1", "fieldextr2": "valextr2"}
- expctRtCdr := &StoredCdr{CgrId: cgrCdr[utils.CGRID],
- TOR: cgrCdr[utils.TOR],
- AccId: cgrCdr[utils.ACCID],
- CdrHost: cgrCdr[utils.CDRHOST],
- CdrSource: cgrCdr[utils.CDRSOURCE],
- ReqType: cgrCdr[utils.REQTYPE],
+ expctRtCdr := &CDR{CGRID: cgrCdr[utils.CGRID],
+ ToR: cgrCdr[utils.TOR],
+ OriginID: cgrCdr[utils.ACCID],
+ OriginHost: cgrCdr[utils.CDRHOST],
+ Source: cgrCdr[utils.CDRSOURCE],
+ RequestType: cgrCdr[utils.REQTYPE],
Direction: cgrCdr[utils.DIRECTION],
Tenant: cgrCdr[utils.TENANT],
Category: cgrCdr[utils.CATEGORY],
@@ -72,7 +72,7 @@ func TestReplicatedCgrCdrAsStoredCdr(t *testing.T) {
Subject: cgrCdr[utils.SUBJECT],
Destination: cgrCdr[utils.DESTINATION],
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC),
- Pdd: time.Duration(200) * time.Millisecond,
+ PDD: time.Duration(200) * time.Millisecond,
AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
Usage: time.Duration(10) * time.Second,
Supplier: cgrCdr[utils.SUPPLIER],
@@ -81,7 +81,7 @@ func TestReplicatedCgrCdrAsStoredCdr(t *testing.T) {
Cost: 0.12,
Rated: true,
}
- if storedCdr := cgrCdr.AsStoredCdr(""); !reflect.DeepEqual(expctRtCdr, storedCdr) {
- t.Errorf("Expecting %v, received: %v", expctRtCdr, storedCdr)
+ if CDR := cgrCdr.AsStoredCdr(""); !reflect.DeepEqual(expctRtCdr, CDR) {
+ t.Errorf("Expecting %v, received: %v", expctRtCdr, CDR)
}
}
diff --git a/engine/event.go b/engine/event.go
index e6a9627f7..91803856f 100644
--- a/engine/event.go
+++ b/engine/event.go
@@ -33,6 +33,7 @@ type Event interface {
GetAccount(string) string
GetDestination(string) string
GetCallDestNr(string) string
+ GetOriginatorIP(string) string
GetCategory(string) string
GetTenant(string) string
GetReqType(string) string
@@ -43,12 +44,11 @@ type Event interface {
GetPdd(string) (time.Duration, error)
GetSupplier(string) string
GetDisconnectCause(string) string
- GetOriginatorIP(string) string
GetExtraFields() map[string]string
MissingParameter(string) bool
ParseEventValue(*utils.RSRField, string) string
PassesFieldFilter(*utils.RSRField) (bool, string)
- AsStoredCdr(timezone string) *StoredCdr
+ AsStoredCdr(timezone string) *CDR
String() string
AsEvent(string) Event
ComputeLcr() bool
diff --git a/engine/fscdr.go b/engine/fscdr.go
index b4fb36306..8ab7ad753 100644
--- a/engine/fscdr.go
+++ b/engine/fscdr.go
@@ -70,7 +70,7 @@ type FSCdr struct {
body map[string]interface{} // keeps the loaded body for extra field search
}
-func (fsCdr FSCdr) getCgrId(timezone string) string {
+func (fsCdr FSCdr) getCGRID(timezone string) string {
setupTime, _ := utils.ParseTimeDetectLayout(fsCdr.vars[FS_SETUP_TIME], timezone)
return utils.Sha1(fsCdr.vars[FS_UUID], setupTime.UTC().String())
}
@@ -118,14 +118,14 @@ func (fsCdr FSCdr) searchExtraField(field string, body map[string]interface{}) (
return
}
-func (fsCdr FSCdr) AsStoredCdr(timezone string) *StoredCdr {
- storCdr := new(StoredCdr)
- storCdr.CgrId = fsCdr.getCgrId(timezone)
- storCdr.TOR = utils.VOICE
- storCdr.AccId = fsCdr.vars[FS_UUID]
- storCdr.CdrHost = fsCdr.vars[FS_IP]
- storCdr.CdrSource = FS_CDR_SOURCE
- storCdr.ReqType = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_REQTYPE], fsCdr.cgrCfg.DefaultReqType)
+func (fsCdr FSCdr) AsStoredCdr(timezone string) *CDR {
+ storCdr := new(CDR)
+ storCdr.CGRID = fsCdr.getCGRID(timezone)
+ storCdr.ToR = utils.VOICE
+ storCdr.OriginID = fsCdr.vars[FS_UUID]
+ storCdr.OriginHost = fsCdr.vars[FS_IP]
+ storCdr.Source = FS_CDR_SOURCE
+ storCdr.RequestType = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_REQTYPE], fsCdr.cgrCfg.DefaultReqType)
storCdr.Direction = utils.OUT
storCdr.Tenant = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_TENANT], fsCdr.cgrCfg.DefaultTenant)
storCdr.Category = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_CATEGORY], fsCdr.cgrCfg.DefaultCategory)
@@ -134,8 +134,8 @@ func (fsCdr FSCdr) AsStoredCdr(timezone string) *StoredCdr {
storCdr.Destination = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_DESTINATION], fsCdr.vars[FS_CALL_DEST_NR], fsCdr.vars[FS_SIP_REQUSER])
storCdr.SetupTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_SETUP_TIME], timezone) // Not interested to process errors, should do them if necessary in a previous step
pddStr := utils.FirstNonEmpty(fsCdr.vars[FS_PROGRESS_MEDIAMSEC], fsCdr.vars[FS_PROGRESSMS])
- pddStr = pddStr + "ms"
- storCdr.Pdd, _ = time.ParseDuration(pddStr)
+ pddStr += "ms"
+ storCdr.PDD, _ = time.ParseDuration(pddStr)
storCdr.AnswerTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_ANSWER_TIME], timezone)
storCdr.Usage, _ = utils.ParseDurationWithSecs(fsCdr.vars[FS_DURATION])
storCdr.Supplier = fsCdr.vars[utils.CGR_SUPPLIER]
diff --git a/engine/fscdr_test.go b/engine/fscdr_test.go
index 521d7b5f0..bdd7ffa50 100644
--- a/engine/fscdr_test.go
+++ b/engine/fscdr_test.go
@@ -55,12 +55,12 @@ func TestCDRFields(t *testing.T) {
}
setupTime, _ := utils.ParseTimeDetectLayout("1436280728", "")
answerTime, _ := utils.ParseTimeDetectLayout("1436280728", "")
- expctStoredCdr := &StoredCdr{CgrId: "164b0422fdc6a5117031b427439482c6a4f90e41", TOR: utils.VOICE, AccId: "e3133bf7-dcde-4daf-9663-9a79ffcef5ad",
- CdrHost: "127.0.0.1", CdrSource: "freeswitch_json", Direction: utils.OUT, Category: "call", ReqType: utils.META_PREPAID, Tenant: "cgrates.org", Account: "1001", Subject: "1001",
- Destination: "1003", SetupTime: setupTime, Pdd: time.Duration(28) * time.Millisecond, AnswerTime: answerTime, Usage: time.Duration(66) * time.Second, Supplier: "supplier1",
+ expctCDR := &CDR{CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41", ToR: utils.VOICE, OriginID: "e3133bf7-dcde-4daf-9663-9a79ffcef5ad",
+ OriginHost: "127.0.0.1", Source: "freeswitch_json", Direction: utils.OUT, Category: "call", RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Account: "1001", Subject: "1001",
+ Destination: "1003", SetupTime: setupTime, PDD: time.Duration(28) * time.Millisecond, AnswerTime: answerTime, Usage: time.Duration(66) * time.Second, Supplier: "supplier1",
DisconnectCause: "NORMAL_CLEARING", ExtraFields: map[string]string{"sip_user_agent": "PJSUA v2.3 Linux-3.2.0.4/x86_64/glibc-2.13"}, Cost: -1}
- if storedCdr := fsCdr.AsStoredCdr(""); !reflect.DeepEqual(expctStoredCdr, storedCdr) {
- t.Errorf("Expecting: %v, received: %v", expctStoredCdr, storedCdr)
+ if CDR := fsCdr.AsStoredCdr(""); !reflect.DeepEqual(expctCDR, CDR) {
+ t.Errorf("Expecting: %v, received: %v", expctCDR, CDR)
}
}
diff --git a/engine/handler_derivedcharging.go b/engine/handler_derivedcharging.go
index d5dc087f8..52f48eb03 100644
--- a/engine/handler_derivedcharging.go
+++ b/engine/handler_derivedcharging.go
@@ -43,14 +43,14 @@ func HandleGetDerivedChargers(ratingStorage RatingStorage, attrs *utils.AttrDeri
}
func DerivedChargersMatchesDest(dcs *utils.DerivedChargers, dest string) bool {
- if len(dcs.DestinationIds) == 0 || dcs.DestinationIds[utils.ANY] {
+ if len(dcs.DestinationIDs) == 0 || dcs.DestinationIDs[utils.ANY] {
return true
}
// check destination ids
for _, p := range utils.SplitPrefix(dest, MIN_PREFIX_MATCH) {
if x, err := cache2go.Get(utils.DESTINATION_PREFIX + p); err == nil {
destIds := x.(map[interface{}]struct{})
- for value := range dcs.DestinationIds {
+ for value := range dcs.DestinationIDs {
for idId := range destIds {
dId := idId.(string)
if value == dId {
diff --git a/engine/handler_derivedcharging_test.go b/engine/handler_derivedcharging_test.go
index 83a4d2e54..8a2c98f54 100644
--- a/engine/handler_derivedcharging_test.go
+++ b/engine/handler_derivedcharging_test.go
@@ -95,7 +95,7 @@ func TestHandleGetStoredDC(t *testing.T) {
func TestHandleDeivedChargersMatchDestRet(t *testing.T) {
dcs := &utils.DerivedChargers{
- DestinationIds: utils.NewStringMap("RET"),
+ DestinationIDs: utils.NewStringMap("RET"),
}
if !DerivedChargersMatchesDest(dcs, "0723045326") {
t.Error("Derived charger failed to match dest")
@@ -104,7 +104,7 @@ func TestHandleDeivedChargersMatchDestRet(t *testing.T) {
func TestHandleDeivedChargersMatchDestNat(t *testing.T) {
dcs := &utils.DerivedChargers{
- DestinationIds: utils.NewStringMap("NAT"),
+ DestinationIDs: utils.NewStringMap("NAT"),
}
if !DerivedChargersMatchesDest(dcs, "0723045326") {
t.Error("Derived charger failed to match dest")
@@ -113,7 +113,7 @@ func TestHandleDeivedChargersMatchDestNat(t *testing.T) {
func TestHandleDeivedChargersMatchDestNatRet(t *testing.T) {
dcs := &utils.DerivedChargers{
- DestinationIds: utils.NewStringMap("NAT", "RET"),
+ DestinationIDs: utils.NewStringMap("NAT", "RET"),
}
if !DerivedChargersMatchesDest(dcs, "0723045326") {
t.Error("Derived charger failed to match dest")
diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go
index ab922c9e0..fc8d985dc 100644
--- a/engine/loader_csv_test.go
+++ b/engine/loader_csv_test.go
@@ -210,7 +210,7 @@ cgrates.org,alodis,TOPUP_EMPTY_AT,,true,true
`
derivedCharges = `
-#Direction,Tenant,Category,Account,Subject,DestinationIds,RunId,RunFilter,ReqTypeField,DirectionField,TenantField,TorField,AccountField,SubjectField,DestinationField,SetupTimeField,PddField,AnswerTimeField,UsageField,SupplierField,DisconnectCauseField,CostField,RatedField
+#Direction,Tenant,Category,Account,Subject,DestinationIds,RunId,RunFilter,RequestTypeField,DirectionField,TenantField,TorField,AccountField,SubjectField,DestinationField,SetupTimeField,PddField,AnswerTimeField,UsageField,SupplierField,DisconnectCauseField,CostField,RatedField
*out,cgrates.org,call,dan,dan,,extra1,^filteredHeader1/filterValue1/,^prepaid,,,,rif,rif,,,,,,,,,
*out,cgrates.org,call,dan,dan,,extra2,,,,,,ivo,ivo,,,,,,,,,
*out,cgrates.org,call,dan,*any,,extra1,,,,,,rif2,rif2,,,,,,,,,
@@ -1122,15 +1122,15 @@ func TestLoadDerivedChargers(t *testing.T) {
t.Error("Failed to load derivedChargers: ", csvr.derivedChargers)
}
expCharger1 := &utils.DerivedChargers{
- DestinationIds: utils.StringMap{},
+ DestinationIDs: utils.StringMap{},
Chargers: []*utils.DerivedCharger{
- &utils.DerivedCharger{RunId: "extra1", RunFilters: "^filteredHeader1/filterValue1/", ReqTypeField: "^prepaid", DirectionField: utils.META_DEFAULT,
+ &utils.DerivedCharger{RunID: "extra1", RunFilters: "^filteredHeader1/filterValue1/", RequestTypeField: "^prepaid", DirectionField: utils.META_DEFAULT,
TenantField: utils.META_DEFAULT, CategoryField: utils.META_DEFAULT, AccountField: "rif", SubjectField: "rif", DestinationField: utils.META_DEFAULT,
- SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
+ SetupTimeField: utils.META_DEFAULT, PDDField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT},
- &utils.DerivedCharger{RunId: "extra2", ReqTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
+ &utils.DerivedCharger{RunID: "extra2", RequestTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
CategoryField: utils.META_DEFAULT, AccountField: "ivo", SubjectField: "ivo", DestinationField: utils.META_DEFAULT,
- SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
+ SetupTimeField: utils.META_DEFAULT, PDDField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT},
}}
keyCharger1 := utils.DerivedChargersKey("*out", "cgrates.org", "call", "dan", "dan")
diff --git a/engine/models.go b/engine/models.go
index 99d8c505b..ead7492dc 100644
--- a/engine/models.go
+++ b/engine/models.go
@@ -1,14 +1,14 @@
/*
-Rating system designed to be used in VoIP Carriers World
-Copyright (C) 2012-2015 ITsysCOM
+Real-time Charging System for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
-This program is free software: you can redistribute it and/or modify
+This program is free software: you can Storagetribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
+but WITH*out ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
@@ -392,74 +392,15 @@ func (ta *TpAlias) GetId() string {
return utils.ConcatenatedKey(ta.Direction, ta.Tenant, ta.Category, ta.Account, ta.Subject, ta.Context)
}
-type TblCdrsPrimary struct {
- Id int64
+type TBLCDRs struct {
+ ID int64
Cgrid string
+ RunID string
+ OriginHost string
+ Source string
+ OriginID string
Tor string
- Accid string
- Cdrhost string
- Cdrsource string
- Reqtype string
- Direction string
- Tenant string
- Category string
- Account string
- Subject string
- Destination string
- SetupTime time.Time
- Pdd float64
- AnswerTime time.Time
- Usage float64
- Supplier string
- DisconnectCause string
- CreatedAt time.Time
- DeletedAt time.Time
-}
-
-func (t TblCdrsPrimary) TableName() string {
- return utils.TBL_CDRS_PRIMARY
-}
-
-type TblCdrsExtra struct {
- Id int64
- Cgrid string
- ExtraFields string
- CreatedAt time.Time
- DeletedAt time.Time
-}
-
-func (t TblCdrsExtra) TableName() string {
- return utils.TBL_CDRS_EXTRA
-}
-
-type TblCostDetail struct {
- Id int64
- Cgrid string
- Runid string
- Tor string
- Direction string
- Tenant string
- Category string
- Account string
- Subject string
- Destination string
- Cost float64
- Timespans string
- CostSource string
- CreatedAt time.Time
- UpdatedAt time.Time
- DeletedAt time.Time
-}
-
-func (t TblCostDetail) TableName() string {
- return utils.TBL_COST_DETAILS
-}
-
-type TblRatedCdr struct {
- Id int64
- Cgrid string
- Runid string
- Reqtype string
+ RequestType string
Direction string
Tenant string
Category string
@@ -472,13 +413,30 @@ type TblRatedCdr struct {
Usage float64
Supplier string
DisconnectCause string
+ ExtraFields string
Cost float64
+ CostDetails string
+ CostSource string
ExtraInfo string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt time.Time
}
-func (t TblRatedCdr) TableName() string {
- return utils.TBL_RATED_CDRS
+func (t TBLCDRs) TableName() string {
+ return utils.TBL_CDRS
+}
+
+type TBLSMCosts struct {
+ ID int64
+ Cgrid string
+ RunID string
+ CostSource string
+ CostDetails string
+ CreatedAt time.Time
+ DeletedAt time.Time
+}
+
+func (t TBLSMCosts) TableName() string {
+ return utils.TBLSMCosts
}
diff --git a/engine/rawcdr.go b/engine/rawcdr.go
index 472ecd175..f186c8bc2 100644
--- a/engine/rawcdr.go
+++ b/engine/rawcdr.go
@@ -20,5 +20,5 @@ package engine
// RawCDR is the original CDR received from external sources (eg: FreeSWITCH)
type RawCdr interface {
- AsStoredCdr(string) *StoredCdr // Convert the inbound Cdr into internally used one, CgrCdr
+ AsStoredCdr(string) *CDR // Convert the inbound Cdr into internally used one, CgrCdr
}
diff --git a/engine/responder.go b/engine/responder.go
index 7843c609a..00a605356 100644
--- a/engine/responder.go
+++ b/engine/responder.go
@@ -260,8 +260,8 @@ func (rs *Responder) GetMaxSessionTime(arg *CallDescriptor, reply *float64) (err
}
// Returns MaxSessionTime for an event received in SessionManager, considering DerivedCharging for it
-func (rs *Responder) GetDerivedMaxSessionTime(ev *StoredCdr, reply *float64) error {
- cacheKey := "GetDerivedMaxSessionTime" + ev.CgrId
+func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) error {
+ cacheKey := "GetDerivedMaxSessionTime" + ev.CGRID
if item, err := rs.getCache().Get(cacheKey); err == nil && item != nil {
*reply = item.Value.(float64)
return item.Err
@@ -303,7 +303,7 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *StoredCdr, reply *float64) err
}
dcs, _ = dcs.AppendDefaultRun()
for _, dc := range dcs.Chargers {
- if utils.IsSliceMember([]string{utils.META_RATED, utils.RATED}, ev.GetReqType(dc.ReqTypeField)) { // Only consider prepaid and pseudoprepaid for MaxSessionTime
+ if utils.IsSliceMember([]string{utils.META_RATED, utils.RATED}, ev.GetReqType(dc.RequestTypeField)) { // Only consider prepaid and pseudoprepaid for MaxSessionTime
continue
}
runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
@@ -347,7 +347,7 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *StoredCdr, reply *float64) err
rs.getCache().Cache(cacheKey, &cache2go.CacheItem{Err: err})
return err
}
- if utils.IsSliceMember([]string{utils.META_POSTPAID, utils.POSTPAID}, ev.GetReqType(dc.ReqTypeField)) {
+ if utils.IsSliceMember([]string{utils.META_POSTPAID, utils.POSTPAID}, ev.GetReqType(dc.RequestTypeField)) {
// Only consider prepaid and pseudoprepaid for MaxSessionTime, do it here for unauthorized destination error check
continue
}
@@ -364,8 +364,8 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *StoredCdr, reply *float64) err
}
// Used by SM to get all the prepaid CallDescriptors attached to a session
-func (rs *Responder) GetSessionRuns(ev *StoredCdr, sRuns *[]*SessionRun) error {
- cacheKey := "GetSessionRuns" + ev.CgrId
+func (rs *Responder) GetSessionRuns(ev *CDR, sRuns *[]*SessionRun) error {
+ cacheKey := "GetSessionRuns" + ev.CGRID
if item, err := rs.getCache().Get(cacheKey); err == nil && item != nil {
*sRuns = item.Value.([]*SessionRun)
return item.Err
@@ -407,7 +407,7 @@ func (rs *Responder) GetSessionRuns(ev *StoredCdr, sRuns *[]*SessionRun) error {
dcs, _ = dcs.AppendDefaultRun()
sesRuns := make([]*SessionRun, 0)
for _, dc := range dcs.Chargers {
- if !utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, ev.GetReqType(dc.ReqTypeField)) {
+ if !utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, ev.GetReqType(dc.RequestTypeField)) {
continue // We only consider prepaid sessions
}
startTime, err := ev.GetAnswerTime(dc.AnswerTimeField, rs.Timezone)
@@ -613,7 +613,6 @@ func (rs *Responder) Call(serviceMethod string, args interface{}, reply interfac
if !method.IsValid() {
return utils.ErrNotImplemented
}
-
// construct the params
params := []reflect.Value{reflect.ValueOf(args), reflect.ValueOf(reply)}
diff --git a/engine/responder_test.go b/engine/responder_test.go
index 1e7a23889..94235c95a 100644
--- a/engine/responder_test.go
+++ b/engine/responder_test.go
@@ -35,8 +35,8 @@ func init() {
// Test internal abilites of GetDerivedChargers
func TestResponderGetDerivedChargers(t *testing.T) {
-
- cfgedDC := &utils.DerivedChargers{DestinationIds: utils.StringMap{}, Chargers: []*utils.DerivedCharger{&utils.DerivedCharger{RunId: "responder1", ReqTypeField: utils.META_DEFAULT, DirectionField: "test", TenantField: "test",
+ cfgedDC := &utils.DerivedChargers{DestinationIDs: utils.StringMap{}, Chargers: []*utils.DerivedCharger{&utils.DerivedCharger{RunID: "responder1",
+ RequestTypeField: utils.META_DEFAULT, DirectionField: "test", TenantField: "test",
CategoryField: "test", AccountField: "test", SubjectField: "test", DestinationField: "test", SetupTimeField: "test", AnswerTimeField: "test", UsageField: "test"}}}
rsponder = &Responder{}
attrs := &utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "responder_test", Subject: "responder_test"}
@@ -56,11 +56,11 @@ func TestResponderGetDerivedChargers(t *testing.T) {
func TestResponderGetDerivedMaxSessionTime(t *testing.T) {
testTenant := "vdf"
- cdr := &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: utils.META_RATED, Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan", Subject: "dan",
+ cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_RATED, Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan", Subject: "dan",
Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
- 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"}
+ RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Cost: 1.01}
var maxSessionTime float64
if err := rsponder.GetDerivedMaxSessionTime(cdr, &maxSessionTime); err != nil {
t.Error(err)
@@ -83,11 +83,11 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) {
}
keyCharger1 := utils.ConcatenatedKey("*out", testTenant, "call", "dan", "dan")
charger1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{
- &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^" + utils.META_PREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra1", RequestTypeField: "^" + 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",
+ &utils.DerivedCharger{RunID: "extra2", RequestTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "^ivo", SubjectField: "^ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- &utils.DerivedCharger{RunId: "extra3", ReqTypeField: "^" + utils.META_PSEUDOPREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra3", RequestTypeField: "^" + utils.META_PSEUDOPREPAID, DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "^rif", SubjectField: "^rif", DestinationField: "^+49151708707", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
}}
if err := ratingStorage.SetDerivedChargers(keyCharger1, charger1); err != nil {
@@ -122,25 +122,26 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) {
func TestResponderGetSessionRuns(t *testing.T) {
testTenant := "vdf"
- cdr := &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: utils.META_PREPAID, Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan2", Subject: "dan2",
- Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Pdd: 3 * time.Second, AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Supplier: "suppl1",
- 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"}
+ cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
+ OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_PREPAID, Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan2", Subject: "dan2",
+ Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), PDD: 3 * time.Second,
+ AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Supplier: "suppl1",
+ RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second,
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01}
keyCharger1 := utils.ConcatenatedKey("*out", testTenant, "call", "dan2", "dan2")
- dfDC := &utils.DerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
+ dfDC := &utils.DerivedCharger{RunID: utils.DEFAULT_RUNID, RequestTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
CategoryField: utils.META_DEFAULT, AccountField: utils.META_DEFAULT, SubjectField: utils.META_DEFAULT, DestinationField: utils.META_DEFAULT,
- SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT,
+ SetupTimeField: utils.META_DEFAULT, PDDField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT,
DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT}
- extra1DC := &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^" + utils.META_PREPAID, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
+ extra1DC := &utils.DerivedCharger{RunID: "extra1", RequestTypeField: "^" + utils.META_PREPAID, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
CategoryField: "^0", AccountField: "^minitsboy", SubjectField: "^rif", DestinationField: "^0256",
- SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT}
- extra2DC := &utils.DerivedCharger{RunId: "extra2", ReqTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
+ SetupTimeField: utils.META_DEFAULT, PDDField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT}
+ extra2DC := &utils.DerivedCharger{RunID: "extra2", RequestTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
CategoryField: utils.META_DEFAULT, AccountField: "^ivo", SubjectField: "^ivo", DestinationField: utils.META_DEFAULT,
SetupTimeField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT}
- extra3DC := &utils.DerivedCharger{RunId: "extra3", ReqTypeField: "^" + utils.META_PSEUDOPREPAID, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
+ extra3DC := &utils.DerivedCharger{RunID: "extra3", RequestTypeField: "^" + utils.META_PSEUDOPREPAID, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
CategoryField: "^0", AccountField: "^minu", SubjectField: "^rif", DestinationField: "^0256",
- SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT,
+ SetupTimeField: utils.META_DEFAULT, PDDField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT,
DisconnectCauseField: utils.META_DEFAULT}
charger1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{extra1DC, extra2DC, extra3DC}}
if err := ratingStorage.SetDerivedChargers(keyCharger1, charger1); err != nil {
@@ -489,9 +490,10 @@ func TestResponderGetLCR(t *testing.T) {
} else if !reflect.DeepEqual(eQTLcr.SupplierCosts, lcrQT.SupplierCosts) {
t.Errorf("Expecting: %+v, received: %+v", eQTLcr.SupplierCosts, lcrQT.SupplierCosts)
}
- cdr := &StoredCdr{Supplier: "rif12", AnswerTime: time.Now(), Usage: 3 * time.Minute, Cost: 1}
+
+ cdr := &CDR{Supplier: "rif12", AnswerTime: time.Now(), Usage: 3 * time.Minute, Cost: 1}
rsponder.Stats.Call("CDRStatsV1.AppendCDR", cdr, &r)
- cdr = &StoredCdr{Supplier: "dan12", AnswerTime: time.Now(), Usage: 5 * time.Minute, Cost: 2}
+ cdr = &CDR{Supplier: "dan12", AnswerTime: time.Now(), Usage: 5 * time.Minute, Cost: 2}
rsponder.Stats.Call("CDRStatsV1.AppendCDR", cdr, &r)
eQTLcr = &LCRCost{
diff --git a/engine/stats.go b/engine/stats.go
index 62ff95c48..e130a4e25 100644
--- a/engine/stats.go
+++ b/engine/stats.go
@@ -257,7 +257,7 @@ func (s *Stats) setupQueueSaver(sq *StatsQueue) {
}
}
-func (s *Stats) AppendCDR(cdr *StoredCdr, out *int) error {
+func (s *Stats) AppendCDR(cdr *CDR, out *int) error {
s.mux.RLock()
defer s.mux.RUnlock()
for _, sq := range s.queues {
diff --git a/engine/stats_queue.go b/engine/stats_queue.go
index c9bd1619f..bfc07356d 100644
--- a/engine/stats_queue.go
+++ b/engine/stats_queue.go
@@ -111,7 +111,7 @@ func (sq *StatsQueue) Load(saved *StatsQueue) {
}
}
-func (sq *StatsQueue) AppendCDR(cdr *StoredCdr) {
+func (sq *StatsQueue) AppendCDR(cdr *CDR) {
sq.mux.Lock()
defer sq.mux.Unlock()
if sq.conf.AcceptCdr(cdr) {
@@ -162,11 +162,11 @@ func (sq *StatsQueue) removeFromMetrics(cdr *QCdr) {
}
}
-func (sq *StatsQueue) simplifyCdr(cdr *StoredCdr) *QCdr {
+func (sq *StatsQueue) simplifyCdr(cdr *CDR) *QCdr {
return &QCdr{
SetupTime: cdr.SetupTime,
AnswerTime: cdr.AnswerTime,
- Pdd: cdr.Pdd,
+ Pdd: cdr.PDD,
Usage: cdr.Usage,
Cost: cdr.Cost,
Dest: cdr.Destination,
diff --git a/engine/stats_test.go b/engine/stats_test.go
index 2823fad38..def739f13 100644
--- a/engine/stats_test.go
+++ b/engine/stats_test.go
@@ -34,7 +34,7 @@ func TestStatsQueueInit(t *testing.T) {
func TestStatsValue(t *testing.T) {
sq := NewStatsQueue(&CdrStats{Metrics: []string{ASR, ACD, TCD, ACC, TCC}})
- cdr := &StoredCdr{
+ cdr := &CDR{
AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
Usage: 10 * time.Second,
Cost: 1,
@@ -55,22 +55,22 @@ func TestStatsValue(t *testing.T) {
}
func TestStatsSimplifyCDR(t *testing.T) {
- cdr := &StoredCdr{
- TOR: "tor",
- AccId: "accid",
- CdrHost: "cdrhost",
- CdrSource: "cdrsource",
- ReqType: "reqtype",
- Direction: "direction",
- Tenant: "tenant",
- Category: "category",
- Account: "account",
- Subject: "subject",
- Destination: "12345678",
- SetupTime: time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC),
- Usage: 10 * time.Second,
- MediationRunId: "mri",
- Cost: 10,
+ cdr := &CDR{
+ ToR: "tor",
+ OriginID: "accid",
+ OriginHost: "cdrhost",
+ Source: "cdrsource",
+ RequestType: "reqtype",
+ Direction: "direction",
+ Tenant: "tenant",
+ Category: "category",
+ Account: "account",
+ Subject: "subject",
+ Destination: "12345678",
+ SetupTime: time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC),
+ Usage: 10 * time.Second,
+ RunID: "mri",
+ Cost: 10,
}
sq := &StatsQueue{}
qcdr := sq.simplifyCdr(cdr)
@@ -84,12 +84,12 @@ func TestStatsSimplifyCDR(t *testing.T) {
func TestAcceptCdr(t *testing.T) {
sq := NewStatsQueue(nil)
- cdr := &StoredCdr{
- TOR: "tor",
- AccId: "accid",
- CdrHost: "cdrhost",
- CdrSource: "cdrsource",
- ReqType: "reqtype",
+ cdr := &CDR{
+ ToR: "tor",
+ OriginID: "accid",
+ OriginHost: "cdrhost",
+ Source: "cdrsource",
+ RequestType: "reqtype",
Direction: "direction",
Tenant: "tenant",
Category: "category",
@@ -98,10 +98,10 @@ func TestAcceptCdr(t *testing.T) {
Destination: "0723045326",
SetupTime: time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC),
Usage: 10 * time.Second,
- Pdd: 7 * time.Second,
+ PDD: 7 * time.Second,
Supplier: "supplier1",
DisconnectCause: "normal",
- MediationRunId: "mri",
+ RunID: "mri",
Cost: 10,
}
sq.conf = &CdrStats{}
@@ -148,14 +148,6 @@ func TestAcceptCdr(t *testing.T) {
if sq.conf.AcceptCdr(cdr) == true {
t.Errorf("Should have NOT accepted this CDR: %+v", cdr)
}
- sq.conf = &CdrStats{RatedAccount: []string{"test"}}
- if sq.conf.AcceptCdr(cdr) == true {
- t.Errorf("Should have NOT accepted this CDR: %+v", cdr)
- }
- sq.conf = &CdrStats{RatedSubject: []string{"test"}}
- if sq.conf.AcceptCdr(cdr) == true {
- t.Errorf("Should have NOT accepted this CDR: %+v", cdr)
- }
sq.conf = &CdrStats{DestinationIds: []string{"test"}}
if sq.conf.AcceptCdr(cdr) == true {
t.Errorf("Should have NOT accepted this CDR: %+v", cdr)
@@ -217,7 +209,7 @@ func TestStatsQueueIds(t *testing.T) {
func TestStatsAppendCdr(t *testing.T) {
cdrStats := NewStats(ratingStorage, accountingStorage, 0)
- cdr := &StoredCdr{
+ cdr := &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
@@ -241,7 +233,7 @@ func TestStatsAppendCdr(t *testing.T) {
func TestStatsGetValues(t *testing.T) {
cdrStats := NewStats(ratingStorage, accountingStorage, 0)
- cdr := &StoredCdr{
+ cdr := &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
@@ -250,7 +242,7 @@ func TestStatsGetValues(t *testing.T) {
Cost: 10,
}
cdrStats.AppendCDR(cdr, nil)
- cdr = &StoredCdr{
+ cdr = &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
@@ -270,7 +262,7 @@ func TestStatsGetValues(t *testing.T) {
func TestStatsReloadQueues(t *testing.T) {
cdrStats := NewStats(ratingStorage, accountingStorage, 0)
- cdr := &StoredCdr{
+ cdr := &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
@@ -305,7 +297,7 @@ func TestStatsReloadQueuesWithDefault(t *testing.T) {
cdrStats.AddQueue(&CdrStats{
Id: utils.META_DEFAULT,
}, nil)
- cdr := &StoredCdr{
+ cdr := &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
@@ -338,7 +330,7 @@ func TestStatsReloadQueuesWithDefault(t *testing.T) {
func TestStatsReloadQueuesWithIds(t *testing.T) {
cdrStats := NewStats(ratingStorage, accountingStorage, 0)
- cdr := &StoredCdr{
+ cdr := &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
@@ -370,7 +362,7 @@ func TestStatsReloadQueuesWithIds(t *testing.T) {
func TestStatsSaveQueues(t *testing.T) {
cdrStats := NewStats(ratingStorage, accountingStorage, 0)
- cdr := &StoredCdr{
+ cdr := &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
@@ -388,7 +380,7 @@ func TestStatsSaveQueues(t *testing.T) {
func TestStatsResetQueues(t *testing.T) {
cdrStats := NewStats(ratingStorage, accountingStorage, 0)
- cdr := &StoredCdr{
+ cdr := &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
@@ -420,7 +412,7 @@ func TestStatsResetQueues(t *testing.T) {
func TestStatsResetQueuesWithIds(t *testing.T) {
cdrStats := NewStats(ratingStorage, accountingStorage, 0)
- cdr := &StoredCdr{
+ cdr := &CDR{
Tenant: "cgrates.org",
Category: "call",
AnswerTime: time.Now(),
diff --git a/engine/storage_cdrs_it_test.go b/engine/storage_cdrs_it_test.go
new file mode 100644
index 000000000..5f886aa4e
--- /dev/null
+++ b/engine/storage_cdrs_it_test.go
@@ -0,0 +1,780 @@
+/*
+Rating system designed to be used in VoIP Carriers World
+Copyright (C) 2012-2015 ITsysCOM
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package engine
+
+import (
+ "flag"
+ "fmt"
+ "path"
+ //"reflect"
+ "testing"
+ "time"
+
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/utils"
+)
+
+var testIntegration = flag.Bool("integration", false, "Perform the tests in integration mode, not by default.") // This flag will be passed here via "go test -local" args
+
+func TestITCDRsMySQL(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ cfg, err := config.NewCGRConfigFromFolder(path.Join(*dataDir, "conf", "samples", "storage", "mysql"))
+ if err != nil {
+ t.Error(err)
+ }
+ if err := testGetCDRs(cfg); err != nil {
+ t.Error(err)
+ }
+ if err := testSetCDR(cfg); err != nil {
+ t.Error(err)
+ }
+ if err := testSMCosts(cfg); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestITCDRsPSQL(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ cfg, err := config.NewCGRConfigFromFolder(path.Join(*dataDir, "conf", "samples", "storage", "postgres"))
+ if err != nil {
+ t.Error(err)
+ }
+ if err := testGetCDRs(cfg); err != nil {
+ t.Error(err)
+ }
+ if err := testSetCDR(cfg); err != nil {
+ t.Error(err)
+ }
+ if err := testSMCosts(cfg); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestITCDRsMongo(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ cfg, err := config.NewCGRConfigFromFolder(path.Join(*dataDir, "conf", "samples", "storage", "mongo"))
+ if err != nil {
+ t.Error(err)
+ }
+ if err := testGetCDRs(cfg); err != nil {
+ t.Error(err)
+ }
+ if err := testSetCDR(cfg); err != nil {
+ t.Error(err)
+ }
+ if err := testSMCosts(cfg); err != nil {
+ t.Error(err)
+ }
+}
+
+// helper function to populate CDRs and check if they were stored in storDb
+func testSetCDR(cfg *config.CGRConfig) error {
+ if err := InitStorDb(cfg); err != nil {
+ return err
+ }
+ cdrStorage, err := ConfigureCdrStorage(cfg.StorDBType, cfg.StorDBHost, cfg.StorDBPort, cfg.StorDBName, cfg.StorDBUser, cfg.StorDBPass,
+ cfg.StorDBMaxOpenConns, cfg.StorDBMaxIdleConns)
+ if err != nil {
+ return err
+ }
+ rawCDR := &CDR{
+ CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ RunID: utils.MetaRaw,
+ OrderID: time.Now().UnixNano(),
+ OriginHost: "127.0.0.1",
+ Source: "testSetCDRs",
+ OriginID: "testevent1",
+ ToR: utils.VOICE,
+ RequestType: utils.META_PREPAID,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "call",
+ Account: "1004",
+ Subject: "1004",
+ Destination: "1007",
+ SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC),
+ PDD: time.Duration(20) * time.Millisecond,
+ AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC),
+ Usage: time.Duration(35) * time.Second,
+ Supplier: "SUPPLIER1",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"},
+ Cost: -1,
+ }
+ if err := cdrStorage.SetCDR(rawCDR, false); err != nil {
+ return fmt.Errorf("rawCDR: %+v, SetCDR err: %s", rawCDR, err.Error())
+ }
+ if cdrs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{rawCDR.CGRID}, RunIDs: []string{utils.MetaRaw}}); err != nil {
+ return fmt.Errorf("rawCDR: %+v, GetCDRs err: %s", rawCDR, err.Error())
+ } else if len(cdrs) != 1 {
+ return fmt.Errorf("rawCDR %+v, Unexpected number of CDRs returned: %d", rawCDR, len(cdrs))
+ }
+ ratedCDR := &CDR{
+ CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ RunID: utils.META_DEFAULT,
+ OriginHost: "127.0.0.1",
+ Source: "testSetCDRs",
+ OriginID: "testevent1",
+ ToR: utils.VOICE,
+ RequestType: utils.META_PREPAID,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "call",
+ Account: "1004",
+ Subject: "1004",
+ Destination: "1007",
+ SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC),
+ PDD: time.Duration(20) * time.Millisecond,
+ AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC),
+ Usage: time.Duration(35) * time.Second,
+ Supplier: "SUPPLIER1",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"},
+ CostSource: "testSetCDRs",
+ Cost: 0.17,
+ }
+ if err := cdrStorage.SetCDR(ratedCDR, false); err != nil {
+ return fmt.Errorf("ratedCDR: %+v, SetCDR err: %s", ratedCDR, err.Error())
+ }
+ if cdrs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{ratedCDR.CGRID}, RunIDs: []string{ratedCDR.RunID}}); err != nil {
+ return fmt.Errorf("ratedCDR: %+v, GetCDRs err: %s", ratedCDR, err.Error())
+ } else if len(cdrs) != 1 {
+ return fmt.Errorf("ratedCDR %+v, Unexpected number of CDRs returned: %d", ratedCDR, len(cdrs))
+ } else {
+ if cdrs[0].RunID != ratedCDR.RunID {
+ return fmt.Errorf("Unexpected ratedCDR received: %+v", cdrs[0])
+ }
+ if cdrs[0].RequestType != ratedCDR.RequestType {
+ return fmt.Errorf("Unexpected ratedCDR received: %+v", cdrs[0])
+ }
+ if cdrs[0].Cost != ratedCDR.Cost {
+ return fmt.Errorf("Unexpected ratedCDR received: %+v", cdrs[0])
+ }
+ }
+ // Make sure duplicating does not work
+ if err := cdrStorage.SetCDR(ratedCDR, false); err == nil {
+ return fmt.Errorf("Duplicating ratedCDR: %+v works", ratedCDR)
+ }
+ ratedCDR.RequestType = utils.META_RATED
+ ratedCDR.Cost = 0.34
+ if err := cdrStorage.SetCDR(ratedCDR, true); err != nil {
+ return fmt.Errorf("Rerating ratedCDR: %+v, SetCDR err: %s", ratedCDR, err.Error())
+ }
+ if cdrs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{ratedCDR.CGRID}, RunIDs: []string{ratedCDR.RunID}}); err != nil {
+ return fmt.Errorf("Rerating ratedCDR: %+v, GetCDRs err: %s", ratedCDR, err.Error())
+ } else if len(cdrs) != 1 {
+ return fmt.Errorf("Rerating ratedCDR %+v, Unexpected number of CDRs returned: %d", ratedCDR, len(cdrs))
+ } else {
+ if cdrs[0].RunID != ratedCDR.RunID {
+ return fmt.Errorf("Unexpected ratedCDR received after rerating: %+v", cdrs[0])
+ }
+ if cdrs[0].RequestType != ratedCDR.RequestType {
+ return fmt.Errorf("Unexpected ratedCDR received after rerating: %+v", cdrs[0])
+ }
+ if cdrs[0].Cost != ratedCDR.Cost {
+ return fmt.Errorf("Unexpected ratedCDR received after rerating: %+v", cdrs[0])
+ }
+ }
+ return nil
+}
+
+func testSMCosts(cfg *config.CGRConfig) error {
+ if err := InitStorDb(cfg); err != nil {
+ return err
+ }
+ cdrStorage, err := ConfigureCdrStorage(cfg.StorDBType, cfg.StorDBHost, cfg.StorDBPort, cfg.StorDBName, cfg.StorDBUser, cfg.StorDBPass,
+ cfg.StorDBMaxOpenConns, cfg.StorDBMaxIdleConns)
+ if err != nil {
+ return err
+ }
+ cc := &CallCost{
+ Direction: utils.OUT,
+ Destination: "+4986517174963",
+ Timespans: []*TimeSpan{
+ &TimeSpan{
+ TimeStart: time.Date(2015, 12, 28, 8, 53, 0, 0, time.UTC).Local(), // MongoDB saves timestamps in local timezone
+ TimeEnd: time.Date(2015, 12, 28, 8, 54, 40, 0, time.UTC).Local(),
+ DurationIndex: 0,
+ RateInterval: &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 100, RateIncrement: 10 * time.Second, RateUnit: time.Second}}}},
+ },
+ },
+ TOR: utils.VOICE,
+ }
+ if err := cdrStorage.LogCallCost("164b0422fdc6a5117031b427439482c6a4f90e41", utils.META_DEFAULT, utils.UNIT_TEST, cc); err != nil {
+ return err
+ }
+ if rcvCC, err := cdrStorage.GetCallCostLog("164b0422fdc6a5117031b427439482c6a4f90e41", utils.META_DEFAULT); err != nil {
+ return err
+ } else if len(cc.Timespans) != len(rcvCC.Timespans) { // cc.Timespans[0].RateInterval.Rating.Rates[0], rcvCC.Timespans[0].RateInterval.Rating.Rates[0])
+ return fmt.Errorf("Expecting: %+v, received: %+v", cc, rcvCC)
+ }
+ return nil
+}
+
+func testGetCDRs(cfg *config.CGRConfig) error {
+ if err := InitStorDb(cfg); err != nil {
+ return err
+ }
+ cdrStorage, err := ConfigureCdrStorage(cfg.StorDBType, cfg.StorDBHost, cfg.StorDBPort, cfg.StorDBName, cfg.StorDBUser, cfg.StorDBPass,
+ cfg.StorDBMaxOpenConns, cfg.StorDBMaxIdleConns)
+ if err != nil {
+ return err
+ }
+ // All CDRs, no filter
+ if CDRs, _, err := cdrStorage.GetCDRs(new(utils.CDRsFilter)); err != nil {
+ return err
+ } else if len(CDRs) != 0 {
+ return fmt.Errorf("Unexpected number of CDRs returned: ", CDRs)
+ }
+ cdrs := []*CDR{
+ &CDR{
+ CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ RunID: utils.MetaRaw,
+ OriginHost: "127.0.0.1",
+ Source: "testGetCDRs",
+ OriginID: "testevent1",
+ ToR: utils.VOICE,
+ RequestType: utils.META_PREPAID,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "call",
+ Account: "1001",
+ Subject: "1001",
+ Destination: "1002",
+ SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC),
+ PDD: time.Duration(20) * time.Millisecond,
+ AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC),
+ Usage: time.Duration(35) * time.Second,
+ Supplier: "SUPPLIER1",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"},
+ CostSource: "",
+ Cost: -1,
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ RunID: utils.META_DEFAULT,
+ OriginHost: "127.0.0.1",
+ Source: "testGetCDRs",
+ OriginID: "testevent1",
+ ToR: utils.VOICE,
+ RequestType: utils.META_PREPAID,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "call",
+ Account: "1001",
+ Subject: "1001",
+ Destination: "1002",
+ SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC),
+ PDD: time.Duration(20) * time.Millisecond,
+ AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC),
+ Usage: time.Duration(35) * time.Second,
+ Supplier: "SUPPLIER1",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"},
+ CostSource: "testGetCDRs",
+ Cost: 0.17,
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ RunID: "run2",
+ OriginHost: "127.0.0.1",
+ Source: "testGetCDRs",
+ OriginID: "testevent1",
+ ToR: utils.VOICE,
+ RequestType: utils.META_RATED,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "call_derived",
+ Account: "1001",
+ Subject: "1002",
+ Destination: "1002",
+ SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC),
+ PDD: time.Duration(20) * time.Millisecond,
+ AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC),
+ Usage: time.Duration(35) * time.Second,
+ Supplier: "SUPPLIER1",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"},
+ CostSource: "testGetCDRs",
+ Cost: 0.17,
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent2", time.Date(2015, 12, 29, 12, 58, 0, 0, time.UTC).String()),
+ RunID: utils.META_DEFAULT,
+ OriginHost: "192.168.1.12",
+ Source: "testGetCDRs",
+ OriginID: "testevent2",
+ ToR: utils.VOICE,
+ RequestType: utils.META_POSTPAID,
+ Direction: utils.OUT,
+ Tenant: "itsyscom.com",
+ Category: "call",
+ Account: "1004",
+ Subject: "1004",
+ Destination: "1007",
+ SetupTime: time.Date(2015, 12, 29, 12, 58, 0, 0, time.UTC),
+ PDD: time.Duration(10) * time.Millisecond,
+ AnswerTime: time.Date(2015, 12, 29, 12, 59, 0, 0, time.UTC),
+ Usage: time.Duration(0) * time.Second,
+ Supplier: "SUPPLIER1",
+ DisconnectCause: "NO_ANSWER",
+ ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"},
+ CostSource: "rater1",
+ Cost: 0,
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()),
+ RunID: utils.MetaRaw,
+ OriginHost: "192.168.1.13",
+ Source: "testGetCDRs3",
+ OriginID: "testevent3",
+ ToR: utils.VOICE,
+ RequestType: utils.META_PSEUDOPREPAID,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "call",
+ Account: "1002",
+ Subject: "1002",
+ Destination: "1003",
+ SetupTime: time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC),
+ PDD: time.Duration(20) * time.Millisecond,
+ AnswerTime: time.Date(2015, 12, 28, 12, 58, 30, 0, time.UTC),
+ Usage: time.Duration(125) * time.Second,
+ Supplier: "SUPPLIER2",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{},
+ CostSource: "",
+ Cost: -1,
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()),
+ RunID: utils.META_DEFAULT,
+ OriginHost: "192.168.1.13",
+ Source: "testGetCDRs3",
+ OriginID: "testevent3",
+ ToR: utils.VOICE,
+ RequestType: utils.META_RATED,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "call",
+ Account: "1002",
+ Subject: "1002",
+ Destination: "1003",
+ SetupTime: time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC),
+ PDD: time.Duration(20) * time.Millisecond,
+ AnswerTime: time.Date(2015, 12, 28, 12, 58, 30, 0, time.UTC),
+ Usage: time.Duration(125) * time.Second,
+ Supplier: "SUPPLIER2",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{},
+ CostSource: "testSetCDRs",
+ Cost: -1,
+ ExtraInfo: "AccountNotFound",
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent4", time.Date(2015, 12, 14, 14, 52, 0, 0, time.UTC).String()),
+ RunID: utils.MetaRaw,
+ OriginHost: "192.168.1.14",
+ Source: "testGetCDRs",
+ OriginID: "testevent4",
+ ToR: utils.VOICE,
+ RequestType: utils.META_PSEUDOPREPAID,
+ Direction: utils.OUT,
+ Tenant: "itsyscom.com",
+ Category: "call",
+ Account: "1003",
+ Subject: "1003",
+ Destination: "1007",
+ SetupTime: time.Date(2015, 12, 14, 14, 52, 0, 0, time.UTC),
+ PDD: time.Duration(2) * time.Second,
+ AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC),
+ Usage: time.Duration(64) * time.Second,
+ Supplier: "SUPPLIER1",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{"ExtraHeader3": "ExtraVal3"},
+ CostSource: "",
+ Cost: -1,
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent4", time.Date(2015, 12, 14, 14, 52, 0, 0, time.UTC).String()),
+ RunID: utils.META_DEFAULT,
+ OriginHost: "192.168.1.14",
+ Source: "testGetCDRs",
+ OriginID: "testevent4",
+ ToR: utils.VOICE,
+ RequestType: utils.META_RATED,
+ Direction: utils.OUT,
+ Tenant: "itsyscom.com",
+ Category: "call",
+ Account: "1003",
+ Subject: "1003",
+ Destination: "1007",
+ SetupTime: time.Date(2015, 12, 14, 14, 52, 0, 0, time.UTC),
+ PDD: time.Duration(2) * time.Second,
+ AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC),
+ Usage: time.Duration(64) * time.Second,
+ Supplier: "SUPPLIER1",
+ DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{"ExtraHeader3": "ExtraVal3"},
+ CostSource: "testSetCDRs",
+ Cost: 1.205,
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent5", time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC).String()),
+ RunID: utils.MetaRaw,
+ OriginHost: "127.0.0.1",
+ Source: "testGetCDRs5",
+ OriginID: "testevent5",
+ ToR: utils.SMS,
+ RequestType: utils.META_PREPAID,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "sms",
+ Account: "1001",
+ Subject: "1001",
+ Destination: "1002",
+ SetupTime: time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC),
+ PDD: time.Duration(0),
+ AnswerTime: time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC),
+ Usage: time.Duration(1) * time.Second,
+ Supplier: "SUPPLIER3",
+ DisconnectCause: "SENT_OK",
+ ExtraFields: map[string]string{"Hdr4": "HdrVal4"},
+ CostSource: "",
+ Cost: -1,
+ },
+ &CDR{
+ CGRID: utils.Sha1("testevent5", time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC).String()),
+ RunID: utils.META_DEFAULT,
+ OriginHost: "127.0.0.1",
+ Source: "testGetCDRs5",
+ OriginID: "testevent5",
+ ToR: utils.SMS,
+ RequestType: utils.META_PREPAID,
+ Direction: utils.OUT,
+ Tenant: "cgrates.org",
+ Category: "sms",
+ Account: "1001",
+ Subject: "1001",
+ Destination: "1002",
+ SetupTime: time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC),
+ PDD: time.Duration(0),
+ AnswerTime: time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC),
+ Usage: time.Duration(1) * time.Second,
+ Supplier: "SUPPLIER3",
+ DisconnectCause: "SENT_OK",
+ ExtraFields: map[string]string{"Hdr4": "HdrVal4"},
+ CostSource: "rater",
+ Cost: 0.15,
+ },
+ }
+ // Store all CDRs
+ for _, cdr := range cdrs {
+ if err := cdrStorage.SetCDR(cdr, false); err != nil {
+ return fmt.Errorf("CDR: %+v, SetCDR err: %s", cdr, err.Error())
+ }
+ }
+ // All CDRs, no filter
+ if CDRs, _, err := cdrStorage.GetCDRs(new(utils.CDRsFilter)); err != nil {
+ return err
+ } else if len(CDRs) != 10 {
+ return fmt.Errorf("GetCDRs, unexpected number of CDRs returned: %d", len(CDRs))
+ }
+ // Count ALL
+ if CDRs, count, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Count: true}); err != nil {
+ return err
+ } else if len(CDRs) != 0 {
+ return fmt.Errorf("CountCDRs, unexpected number of CDRs returned: %+v", CDRs)
+ } else if count != 10 {
+ return fmt.Errorf("CountCDRs, unexpected count of CDRs returned: %+v", count)
+ }
+ // Limit 5
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil {
+ return err
+ } else if len(CDRs) != 5 {
+ return fmt.Errorf("Limit 5, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Offset 5
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil {
+ return err
+ } else if len(CDRs) != 5 {
+ return fmt.Errorf("Offset 5, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Offset with limit 2
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}); err != nil {
+ return err
+ } else if len(CDRs) != 2 {
+ return fmt.Errorf("Offset with limit 2, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on cgrids
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{
+ utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()),
+ }}); err != nil {
+ return err
+ } else if len(CDRs) != 5 {
+ return fmt.Errorf("Filter on CGRIDs, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Count on CGRIDS
+ if _, count, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{
+ utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()),
+ }, Count: true}); err != nil {
+ return err
+ } else if count != 5 {
+ return fmt.Errorf("Count on CGRIDs, unexpected count of CDRs returned: %d", count)
+ }
+ // Filter on cgrids plus reqType
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{
+ utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()),
+ }, RequestTypes: []string{utils.META_PREPAID}}); err != nil {
+ return err
+ } else if len(CDRs) != 2 {
+ return fmt.Errorf("Filter on cgrids plus reqType, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Count on multiple filter
+ if _, count, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{
+ utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()),
+ utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()),
+ }, RequestTypes: []string{utils.META_PREPAID}, Count: true}); err != nil {
+ return err
+ } else if count != 2 {
+ return fmt.Errorf("Count on multiple filter, unexpected count of CDRs returned: %d", count)
+ }
+ // Filter on RunID
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RunIDs: []string{utils.DEFAULT_RUNID}}); err != nil {
+ return err
+ } else if len(CDRs) != 5 {
+ return fmt.Errorf("Filter on RunID, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on TOR
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{ToRs: []string{utils.SMS}}); err != nil {
+ return err
+ } else if len(CDRs) != 2 {
+ return fmt.Errorf("Filter on TOR, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on multiple TOR
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{ToRs: []string{utils.SMS, utils.VOICE}}); err != nil {
+ return err
+ } else if len(CDRs) != 10 {
+ return fmt.Errorf("Filter on multiple TOR, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on OriginHost
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"127.0.0.1"}}); err != nil {
+ return err
+ } else if len(CDRs) != 5 {
+ return fmt.Errorf("Filter on OriginHost, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on multiple OriginHost
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"127.0.0.1", "192.168.1.12"}}); err != nil {
+ return err
+ } else if len(CDRs) != 6 {
+ return fmt.Errorf("Filter on OriginHosts, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on Source
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Sources: []string{"testGetCDRs"}}); err != nil {
+ return err
+ } else if len(CDRs) != 6 {
+ return fmt.Errorf("Filter on Source, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on multiple Sources
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Sources: []string{"testGetCDRs", "testGetCDRs5"}}); err != nil {
+ return err
+ } else if len(CDRs) != 8 {
+ return fmt.Errorf("Filter on Sources, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on reqType
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID}}); err != nil {
+ return err
+ } else if len(CDRs) != 4 {
+ return fmt.Errorf("Filter on RequestType, unexpected number of CDRs returned: %+v", len(CDRs))
+ }
+ // Filter on multiple reqType
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}); err != nil {
+ return err
+ } else if len(CDRs) != 6 {
+ return fmt.Errorf("Filter on RequestTypes, unexpected number of CDRs returned: %+v", CDRs)
+ }
+
+ // Filter on direction
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Directions: []string{utils.OUT}}); err != nil {
+ return err
+ } else if len(CDRs) != 10 {
+ return fmt.Errorf("Filter on Direction, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on Tenant
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com"}}); err != nil {
+ return err
+ } else if len(CDRs) != 3 {
+ return fmt.Errorf("Filter on Tenant, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on multiple tenants
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}); err != nil {
+ return err
+ } else if len(CDRs) != 10 {
+ return fmt.Errorf("Filter on Tenants, Unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on Category
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Categories: []string{"call"}}); err != nil {
+ return err
+ } else if len(CDRs) != 7 {
+ return fmt.Errorf("Filter on Category, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on multiple categories
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Categories: []string{"sms", "call_derived"}}); err != nil {
+ return err
+ } else if len(CDRs) != 3 {
+ return fmt.Errorf("Filter on Categories, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on account
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1002"}}); err != nil {
+ return err
+ } else if len(CDRs) != 2 {
+ return fmt.Errorf("Filter on Account, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on multiple account
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1001", "1002"}}); err != nil {
+ return err
+ } else if len(CDRs) != 7 {
+ return fmt.Errorf("Filter on Accounts, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on subject
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1004"}}); err != nil {
+ return err
+ } else if len(CDRs) != 1 {
+ return fmt.Errorf("Filter on Subject, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on multiple subject
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1002", "1003"}}); err != nil {
+ return err
+ } else if len(CDRs) != 5 {
+ return fmt.Errorf("Filter on Subjects, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on destPrefix
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"10"}}); err != nil {
+ return err
+ } else if len(CDRs) != 10 {
+ return fmt.Errorf("Filter on DestinationPrefix, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on multiple destPrefixes
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"1002", "1003"}}); err != nil {
+ return err
+ } else if len(CDRs) != 7 {
+ return fmt.Errorf("Filter on DestinationPrefix, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on not destPrefix
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{NotDestinationPrefixes: []string{"10"}}); err != nil {
+ return err
+ } else if len(CDRs) != 0 {
+ return fmt.Errorf("Filter on NotDestinationPrefix, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on not destPrefixes
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{NotDestinationPrefixes: []string{"1001", "1002"}}); err != nil {
+ return err
+ } else if len(CDRs) != 5 {
+ return fmt.Errorf("Filter on NotDestinationPrefix, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on hasPrefix and not HasPrefix
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"1002", "1003"},
+ NotDestinationPrefixes: []string{"1002"}}); err != nil {
+ return err
+ } else if len(CDRs) != 2 {
+ return fmt.Errorf("Filter on DestinationPrefix and NotDestinationPrefix, unexpected number of CDRs returned: %+v", CDRs)
+ }
+
+ // Filter on MaxCost
+ var orderIdStart, orderIdEnd int64 // Capture also orderIds for the next test
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{MaxCost: utils.Float64Pointer(0.0)}); err != nil {
+ return err
+ } else if len(CDRs) != 5 {
+ return fmt.Errorf("Filter on MaxCost, unexpected number of CDRs returned: ", CDRs)
+ } else {
+ for i, cdr := range CDRs {
+ if i == 0 {
+ orderIdStart = cdr.OrderID
+ }
+ if cdr.OrderID < orderIdStart {
+ orderIdStart = cdr.OrderID
+ }
+ if cdr.OrderID > orderIdEnd {
+ orderIdEnd = cdr.OrderID
+ }
+ }
+ }
+ // Filter on orderIdStart
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{OrderIDStart: &orderIdStart}); err != nil {
+ return err
+ } else if len(CDRs) != 10 {
+ return fmt.Errorf("Filter on OrderIDStart, unexpected number of CDRs returned: %d", len(CDRs))
+ }
+ // Filter on orderIdStart and orderIdEnd
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{OrderIDStart: &orderIdStart, OrderIDEnd: &orderIdEnd}); err != nil {
+ return err
+ } else if len(CDRs) != 8 {
+ return fmt.Errorf("Filter on OrderIDStart OrderIDEnd, unexpected number of CDRs returned: %d", len(CDRs))
+ }
+ var timeStart, timeEnd time.Time
+ // Filter on timeStart
+ timeStart = time.Date(2015, 12, 28, 0, 0, 0, 0, time.UTC)
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart}); err != nil {
+ return err
+ } else if len(CDRs) != 3 {
+ return fmt.Errorf("Filter on AnswerTimeStart, unexpected number of CDRs returned: %d", len(CDRs))
+ }
+ // Filter on timeStart and timeEnd
+ timeEnd = time.Date(2015, 12, 29, 0, 0, 0, 0, time.UTC)
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil {
+ return err
+ } else if len(CDRs) != 2 {
+ return fmt.Errorf("Filter on AnswerTimeStart AnswerTimeEnd, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on MinPDD
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{MinPDD: "20ms"}); err != nil {
+ return err
+ } else if len(CDRs) != 7 {
+ return fmt.Errorf("Filter on MinPDD, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on maxPdd
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{MaxPDD: "1s"}); err != nil {
+ return err
+ } else if len(CDRs) != 8 {
+ return fmt.Errorf("Filter on MaxPDD, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Filter on minPdd, maxPdd
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{MinPDD: "10ms", MaxPDD: "1s"}); err != nil {
+ return err
+ } else if len(CDRs) != 6 {
+ return fmt.Errorf("Filter on MinPDD MaxPDD, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ // Combined filter
+ if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil {
+ return err
+ } else if len(CDRs) != 1 {
+ return fmt.Errorf("Filter on RequestTypes AnswerTimeStart AnswerTimeEnd, unexpected number of CDRs returned: %+v", CDRs)
+ }
+ return nil
+}
diff --git a/engine/storage_interface.go b/engine/storage_interface.go
index ee67ad681..0f10bc6a5 100644
--- a/engine/storage_interface.go
+++ b/engine/storage_interface.go
@@ -96,12 +96,11 @@ type AccountingStorage interface {
type CdrStorage interface {
Storage
- SetCdr(*StoredCdr) error
- SetRatedCdr(*StoredCdr) error
- LogCallCost(cgrid, source, runid string, cc *CallCost) error
- GetCallCostLog(cgrid, source, runid string) (*CallCost, error)
- GetStoredCdrs(*utils.CdrsFilter) ([]*StoredCdr, int64, error)
- RemStoredCdrs([]string) error
+ SetCDR(*CDR, bool) error
+ LogCallCost(cgrid, runid, source string, cc *CallCost) error
+ GetCallCostLog(cgrid, runid string) (*CallCost, error)
+ GetCDRs(*utils.CDRsFilter) ([]*CDR, int64, error)
+ RemCDRs([]string) error
}
type LogStorage interface {
diff --git a/engine/storage_mongo.go b/engine/storage_mongo_datadb.go
similarity index 95%
rename from engine/storage_mongo.go
rename to engine/storage_mongo_datadb.go
index a45efc1cf..ad6fc6e75 100644
--- a/engine/storage_mongo.go
+++ b/engine/storage_mongo_datadb.go
@@ -24,37 +24,61 @@ import (
"errors"
"fmt"
"io/ioutil"
+ "strings"
"github.com/cgrates/cgrates/cache2go"
"github.com/cgrates/cgrates/utils"
-
"gopkg.in/mgo.v2"
-
"gopkg.in/mgo.v2/bson"
)
const (
colDst = "destinations"
colAct = "actions"
- colApl = "actionplans"
+ colApl = "action_plans"
colTsk = "tasks"
- colAtr = "actiontriggers"
- colRpl = "ratingplans"
- colRpf = "ratingprofiles"
+ colAtr = "action_triggers"
+ colRpl = "rating_plans"
+ colRpf = "rating_profiles"
colAcc = "accounts"
- colShg = "sharedgroups"
- colLcr = "lcrrules"
- colDcs = "derivedchargers"
+ colShg = "shared_groups"
+ colLcr = "lcr_rules"
+ colDcs = "derived_chargers"
colAls = "aliases"
- colStq = "statsqeues"
+ colStq = "stat_qeues"
colPbs = "pubsub"
colUsr = "users"
- colCrs = "cdrstats"
- colLht = "loadhistory"
- colLogAtr = "actiontriggerslogs"
- colLogApl = "actionplanlogs"
- colLogErr = "errorlogs"
- colCdrs = "cdrs"
+ colCrs = "cdr_stats"
+ colLht = "load_history"
+ colLogAtr = "action_trigger_logs"
+ colLogApl = "action_plan_logs"
+ colLogErr = "error_logs"
+)
+
+var (
+ CGRIDLow = strings.ToLower(utils.CGRID)
+ RunIDLow = strings.ToLower(utils.MEDI_RUNID)
+ OrderIDLow = strings.ToLower(utils.ORDERID)
+ ToRLow = strings.ToLower(utils.TOR)
+ CDRHostLow = strings.ToLower(utils.CDRHOST)
+ CDRSourceLow = strings.ToLower(utils.CDRSOURCE)
+ RequestTypeLow = strings.ToLower(utils.REQTYPE)
+ DirectionLow = strings.ToLower(utils.DIRECTION)
+ TenantLow = strings.ToLower(utils.TENANT)
+ CategoryLow = strings.ToLower(utils.CATEGORY)
+ AccountLow = strings.ToLower(utils.ACCOUNT)
+ SubjectLow = strings.ToLower(utils.SUBJECT)
+ SupplierLow = strings.ToLower(utils.SUPPLIER)
+ DisconnectCauseLow = strings.ToLower(utils.DISCONNECT_CAUSE)
+ SetupTimeLow = strings.ToLower(utils.SETUP_TIME)
+ AnswerTimeLow = strings.ToLower(utils.ANSWER_TIME)
+ CreatedAtLow = strings.ToLower(utils.CreatedAt)
+ UpdatedAtLow = strings.ToLower(utils.UpdatedAt)
+ UsageLow = strings.ToLower(utils.USAGE)
+ PDDLow = strings.ToLower(utils.PDD)
+ CostDetailsLow = strings.ToLower(utils.COST_DETAILS)
+ DestinationLow = strings.ToLower(utils.DESTINATION)
+ CostLow = strings.ToLower(utils.COST)
)
type MongoStorage struct {
@@ -192,13 +216,13 @@ func NewMongoStorage(host, port, db, user, pass string) (*MongoStorage, error) {
}
}
index = mgo.Index{
- Key: []string{"cgrid", "cdrsource", "mediationrunid"},
+ Key: []string{CGRIDLow, RunIDLow},
Unique: true,
DropDups: false,
Background: false,
Sparse: false,
}
- collections = []string{colCdrs}
+ collections = []string{utils.TBL_CDRS}
for _, col := range collections {
if err = ndb.C(col).EnsureIndex(index); err != nil {
return nil, err
diff --git a/engine/storage_mongo_local_test.go b/engine/storage_mongo_local_test.go
deleted file mode 100644
index 917559f67..000000000
--- a/engine/storage_mongo_local_test.go
+++ /dev/null
@@ -1,973 +0,0 @@
-/*
-Rating system designed to be used in VoIP Carriers World
-Copyright (C) 2012-2015 ITsysCOM
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see
-*/
-
-package engine
-
-import (
- "reflect"
- "testing"
- "time"
-
- "github.com/cgrates/cgrates/config"
- "github.com/cgrates/cgrates/utils"
-)
-
-var mongoDb *MongoStorage
-
-func TestMongoCreateTables(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrConfig, _ := config.NewDefaultCGRConfig()
- var err error
- if mongoDb, err = NewMongoStorage("localhost", "27017", cgrConfig.StorDBName, cgrConfig.StorDBUser, cgrConfig.StorDBPass); err != nil {
- t.Error("Error on opening database connection: ", err)
- }
-}
-
-func TestMongoSetGetTPTiming(t *testing.T) {
- if !*testLocal {
- return
- }
- tm := TpTiming{Tpid: utils.TEST_SQL, Tag: "ALWAYS", Time: "00:00:00"}
- if err := mongoDb.SetTpTimings([]TpTiming{tm}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.Tag); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(tm, tmgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[0])
- }
- // Update
- tm.Time = "00:00:01"
- if err := mongoDb.SetTpTimings([]TpTiming{tm}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.Tag); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(tm, tmgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[0])
- }
-}
-
-func TestMongoSetGetTPDestination(t *testing.T) {
- if !*testLocal {
- return
- }
- dst := []TpDestination{
- TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49"},
- TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49151"},
- TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49176"},
- }
- if err := mongoDb.SetTpDestinations(dst); err != nil {
- t.Error(err.Error())
- }
- storData, err := mongoDb.GetTpDestinations(utils.TEST_SQL, utils.TEST_SQL)
- dsts, err := TpDestinations(storData).GetDestinations()
- expected := &Destination{Id: utils.TEST_SQL, Prefixes: []string{"+49", "+49151", "+49176"}}
- if err != nil {
- t.Error(err.Error())
- } else if !modelEqual(*expected, *dsts[utils.TEST_SQL]) {
- t.Errorf("Expecting: %+v, received: %+v", expected, dsts[utils.TEST_SQL])
- }
-}
-
-func TestMongoSetGetTPRates(t *testing.T) {
- if !*testLocal {
- return
- }
- RT_ID := "RT_1"
- rtSlots := []*utils.RateSlot{
- &utils.RateSlot{ConnectFee: 0.02, Rate: 0.01, RateUnit: "60s", RateIncrement: "60s", GroupIntervalStart: "0s"},
- &utils.RateSlot{ConnectFee: 0.00, Rate: 0.005, RateUnit: "60s", RateIncrement: "1s", GroupIntervalStart: "60s"},
- }
- for _, rs := range rtSlots {
- rs.SetDurations()
- }
- rates := &utils.TPRate{
- TPid: utils.TEST_SQL,
- RateId: RT_ID,
- RateSlots: rtSlots,
- }
- mRates := APItoModelRate(rates)
- if err := mongoDb.SetTpRates(mRates); err != nil {
- t.Error(err.Error())
- }
- if rts, err := mongoDb.GetTpRates(utils.TEST_SQL, RT_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mRates[0], rts[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mRates, rts)
- }
-}
-
-func TestMongoSetGetTPDestinationRates(t *testing.T) {
- if !*testLocal {
- return
- }
- DR_ID := "DR_1"
- dr := &utils.DestinationRate{DestinationId: "DST_1", RateId: "RT_1", RoundingMethod: "*up", RoundingDecimals: 4}
-
- eDrs := &utils.TPDestinationRate{TPid: utils.TEST_SQL, DestinationRateId: DR_ID, DestinationRates: []*utils.DestinationRate{dr}}
- mdrs := APItoModelDestinationRate(eDrs)
- if err := mongoDb.SetTpDestinationRates(mdrs); err != nil {
- t.Error(err.Error())
- }
- if drs, err := mongoDb.GetTpDestinationRates(utils.TEST_SQL, DR_ID, nil); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mdrs[0], drs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mdrs, drs)
- }
-}
-
-func TestMongoSetGetTPRatingPlans(t *testing.T) {
- if !*testLocal {
- return
- }
- RP_ID := "RP_1"
- rbBinding := &utils.TPRatingPlanBinding{DestinationRatesId: "DR_1", TimingId: "TM_1", Weight: 10.0}
- rp := &utils.TPRatingPlan{
- TPid: utils.TEST_SQL,
- RatingPlanId: RP_ID,
- RatingPlanBindings: []*utils.TPRatingPlanBinding{rbBinding},
- }
- mrp := APItoModelRatingPlan(rp)
- if err := mongoDb.SetTpRatingPlans(mrp); err != nil {
- t.Error(err.Error())
- }
- if drps, err := mongoDb.GetTpRatingPlans(utils.TEST_SQL, RP_ID, nil); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mrp[0], drps[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mrp, drps)
- }
-}
-
-func TestMongoSetGetTPRatingProfiles(t *testing.T) {
- if !*testLocal {
- return
- }
- ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RP_1"}}
- rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras}
- mrp := APItoModelRatingProfile(rp)
- if err := mongoDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mrp[0], rps[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mrp, rps)
- }
-
-}
-
-func TestMongoSetGetTPSharedGroups(t *testing.T) {
- if !*testLocal {
- return
- }
- SG_ID := "SG_1"
- tpSgs := &utils.TPSharedGroups{
- TPid: utils.TEST_SQL,
- SharedGroupsId: SG_ID,
- SharedGroups: []*utils.TPSharedGroup{
- &utils.TPSharedGroup{Account: "dan", Strategy: "*lowest_first", RatingSubject: "lowest_rates"},
- },
- }
- mSgs := APItoModelSharedGroup(tpSgs)
- if err := mongoDb.SetTpSharedGroups(mSgs); err != nil {
- t.Error(err.Error())
- }
- if sgs, err := mongoDb.GetTpSharedGroups(utils.TEST_SQL, SG_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mSgs[0], sgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mSgs, sgs)
- }
-}
-
-func TestMongoSetGetTPCdrStats(t *testing.T) {
- if !*testLocal {
- return
- }
- CS_ID := "CDRSTATS_1"
- setCS := &utils.TPCdrStats{
- TPid: utils.TEST_SQL,
- CdrStatsId: CS_ID,
- CdrStats: []*utils.TPCdrStat{
- &utils.TPCdrStat{QueueLength: "10", TimeWindow: "10m", Metrics: "ASR", Tenants: "cgrates.org", Categories: "call"},
- },
- }
- mcs := APItoModelCdrStat(setCS)
- if err := mongoDb.SetTpCdrStats(mcs); err != nil {
- t.Error(err.Error())
- }
- if cs, err := mongoDb.GetTpCdrStats(utils.TEST_SQL, CS_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mcs[0], cs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mcs, cs)
- }
-}
-
-func TestMongoSetGetTPDerivedChargers(t *testing.T) {
- if !*testLocal {
- return
- }
- dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^" + utils.META_PREPAID, AccountField: "^rif", SubjectField: "^rif",
- UsageField: "cgr_duration", SupplierField: "^supplier1"}
- dcs := &utils.TPDerivedChargers{TPid: utils.TEST_SQL, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: []*utils.TPDerivedCharger{dc}}
-
- mdcs := APItoModelDerivedCharger(dcs)
- if err := mongoDb.SetTpDerivedChargers(mdcs); err != nil {
- t.Error(err.Error())
- }
- if rDCs, err := mongoDb.GetTpDerivedChargers(&mdcs[0]); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mdcs[0], rDCs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mdcs, rDCs)
- }
-}
-
-func TestMongoSetGetTPActions(t *testing.T) {
- if !*testLocal {
- return
- }
- ACTS_ID := "PREPAID_10"
- acts := []*utils.TPAction{
- &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited",
- DestinationIds: "*any", BalanceWeight: 10, Weight: 10}}
- tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts}
- mas := APItoModelAction(tpActions)
- if err := mongoDb.SetTpActions(mas); err != nil {
- t.Error(err.Error())
- }
- if rTpActs, err := mongoDb.GetTpActions(utils.TEST_SQL, ACTS_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mas[0], rTpActs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mas, rTpActs)
- }
-}
-
-func TestMongoTPActionTimings(t *testing.T) {
- if !*testLocal {
- return
- }
- AP_ID := "AP_1"
- ap := &utils.TPActionPlan{
- TPid: utils.TEST_SQL,
- ActionPlanId: AP_ID,
- ActionPlan: []*utils.TPActionTiming{&utils.TPActionTiming{ActionsId: "ACTS_1", TimingId: "TM_1", Weight: 10.0}},
- }
- maps := APItoModelActionPlan(ap)
- if err := mongoDb.SetTpActionPlans(maps); err != nil {
- t.Error(err.Error())
- }
- if rAP, err := mongoDb.GetTpActionPlans(utils.TEST_SQL, AP_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(maps[0], rAP[0]) {
- t.Errorf("Expecting: %+v, received: %+v", maps, rAP)
- }
-}
-
-func TestMongoSetGetTPActionTriggers(t *testing.T) {
- if !*testLocal {
- return
- }
- atrg := &utils.TPActionTrigger{
- Id: "MY_FIRST_ATGR",
- BalanceType: "*monetary",
- BalanceDirections: "*out",
- ThresholdType: "*min_balance",
- ThresholdValue: 2.0,
- Recurrent: true,
- BalanceDestinationIds: "*any",
- Weight: 10.0,
- ActionsId: "LOG_BALANCE",
- }
- atrgs := &utils.TPActionTriggers{
- TPid: utils.TEST_SQL,
- ActionTriggersId: "MY_FIRST_ATGR",
- ActionTriggers: []*utils.TPActionTrigger{atrg},
- }
- matrg := APItoModelActionTrigger(atrgs)
- if err := mongoDb.SetTpActionTriggers(matrg); err != nil {
- t.Error("Unexpected error: ", err.Error())
- }
- if rcvMpAtrgs, err := mongoDb.GetTpActionTriggers(utils.TEST_SQL, "MY_FIRST_ATGR"); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if !modelEqual(matrg[0], rcvMpAtrgs[0]) {
- t.Errorf("Expecting: %v, received: %v", matrg, rcvMpAtrgs)
- }
-}
-
-func TestMongoSetGetTpAccountActions(t *testing.T) {
- if !*testLocal {
- return
- }
- aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
- maa := APItoModelAccountAction(aa)
- if err := mongoDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := mongoDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(*maa, aas[0]) {
- t.Errorf("Expecting: %+v, received: %+v", maa, aas)
- }
-}
-
-func TestMongoGetTPIds(t *testing.T) {
- if !*testLocal {
- return
- }
- eTPIds := []string{utils.TEST_SQL}
- if tpIds, err := mongoDb.GetTpIds(); err != nil {
- t.Error(err.Error())
- } else if !reflect.DeepEqual(eTPIds, tpIds) {
- t.Errorf("Expecting: %+v, received: %+v", eTPIds, tpIds)
- }
-}
-
-func TestMongoRemoveTPData(t *testing.T) {
- if !*testLocal {
- return
- }
- // Create Timings
- tm := &utils.ApierTPTiming{TPid: utils.TEST_SQL, TimingId: "ALWAYS", Time: "00:00:00"}
- tms := APItoModelTiming(tm)
- if err := mongoDb.SetTpTimings([]TpTiming{*tms}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err.Error())
- } else if len(tmgs) == 0 {
- t.Error("Could not store TPTiming")
- }
- // Remove Timings
- if err := mongoDb.RemTpData(utils.TBL_TP_TIMINGS, utils.TEST_SQL, map[string]string{"tag": tm.TimingId}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err)
- } else if len(tmgs) != 0 {
- t.Errorf("Timings should be empty, got instead: %+v", tmgs)
- }
- // Create RatingProfile
- ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1"}}
- rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras}
- mrp := APItoModelRatingProfile(rp)
- if err := mongoDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if len(rps) == 0 {
- t.Error("Could not store TPRatingProfile")
- }
- // Remove RatingProfile
- if err := mongoDb.RemTpData(utils.TBL_TP_RATE_PROFILES, rp.TPid, map[string]string{"loadid": rp.LoadId, "direction": rp.Direction, "tenant": rp.Tenant, "category": rp.Category, "subject": rp.Subject}); err != nil {
- t.Error(err.Error())
- }
- if rps, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err)
- } else if len(rps) != 0 {
- t.Errorf("RatingProfiles different than 0: %+v", rps)
- }
- // Create AccountActions
- aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
- maa := APItoModelAccountAction(aa)
- if err := mongoDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := mongoDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if len(aas) == 0 {
- t.Error("Could not create TPAccountActions")
- }
- // Remove AccountActions
- if err := mongoDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := mongoDb.GetTpAccountActions(maa); err != nil {
- t.Error(err)
- } else if len(aas) != 0 {
- t.Errorf("Non empty account actions: %+v", aas)
- }
- // Create again so we can test complete TP removal
- if err := mongoDb.SetTpTimings([]TpTiming{*tms}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err.Error())
- } else if len(tmgs) == 0 {
- t.Error("Could not store TPTiming")
- }
- // Create RatingProfile
- if err := mongoDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if len(rps) == 0 {
- t.Error("Could not store TPRatingProfile")
- }
- // Create AccountActions
- if err := mongoDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := mongoDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if len(aas) == 0 {
- t.Error("Could not create TPAccountActions")
- }
- // Remove TariffPlan completely
- if err := mongoDb.RemTpData("", utils.TEST_SQL, nil); err != nil {
- t.Error(err.Error())
- }
- // Make sure we have removed it
- if tms, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err)
- } else if len(tms) != 0 {
- t.Errorf("Non empty timings: %+v", tms)
- }
- if rpfs, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err)
- } else if len(rpfs) != 0 {
- t.Errorf("Non empty rpfs: %+v", rpfs)
- }
- if aas, err := mongoDb.GetTpAccountActions(maa); err != nil {
- t.Error(err)
- } else if len(aas) != 0 {
- t.Errorf("Non empty account actions: %+v", aas)
- }
-}
-
-func TestMongoSetCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrCdr1 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: utils.TEST_SQL}
-
- cgrCdr2 := &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", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr3 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr4 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr5 := &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", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- for _, cdr := range []*CgrCdr{cgrCdr1, cgrCdr2, cgrCdr3, cgrCdr4, cgrCdr5} {
- if err := mongoDb.SetCdr(cdr.AsStoredCdr("")); err != nil {
- t.Error(err.Error())
- }
- }
- strCdr1 := &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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- 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 := &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, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL1",
- 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 := &StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: utils.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, Pdd: time.Duration(2) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201}
- strCdr3.CgrId = utils.Sha1(strCdr3.AccId, strCdr3.SetupTime.String())
-
- for _, cdr := range []*StoredCdr{strCdr1, strCdr2, strCdr3} {
- if err := mongoDb.SetCdr(cdr); err != nil {
- t.Error(err.Error())
- }
- }
-}
-
-func TestMongoSetRatedCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- strCdr1 := &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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- 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 := &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, Pdd: time.Duration(7) * time.Second, Supplier: "SUPPL1",
- 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 := &StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: utils.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, Pdd: time.Duration(2) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: "wholesale_run", Cost: 1.201}
- strCdr3.CgrId = utils.Sha1(strCdr3.AccId, strCdr3.SetupTime.String())
-
- for _, cdr := range []*StoredCdr{strCdr1, strCdr2, strCdr3} {
- if err := mongoDb.SetRatedCdr(cdr); err != nil {
- t.Error(err.Error())
- }
- }
-}
-
-func TestMongoCallCost(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrId := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- cc := &CallCost{
- Direction: "*out",
- Category: "call",
- Tenant: "cgrates.org",
- Subject: "91001",
- Account: "8001",
- Destination: "1002",
- TOR: utils.VOICE,
- Timespans: []*TimeSpan{
- &TimeSpan{
- TimeStart: time.Date(2013, 9, 10, 13, 40, 0, 0, time.UTC),
- TimeEnd: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC),
- },
- &TimeSpan{
- TimeStart: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC),
- TimeEnd: time.Date(2013, 9, 10, 13, 41, 30, 0, time.UTC),
- },
- },
- }
- if err := mongoDb.LogCallCost(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil {
- t.Error(err.Error())
- }
- if ccRcv, err := mongoDb.GetCallCostLog(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil {
- t.Error(err.Error())
- } else if cc.Cost != ccRcv.Cost {
- t.Errorf("Expecting call cost:\n%+v,\nreceived:\n%+v", cc.Timespans[0], ccRcv.Timespans[0])
- }
- // UPDATE test here
- cc.Category = "premium_call"
- if err := mongoDb.LogCallCost(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil {
- t.Error(err.Error())
- }
- if ccRcv, err := mongoDb.GetCallCostLog(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil {
- t.Error(err.Error())
- } else if cc.Cost != ccRcv.Cost {
- t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv)
- }
-}
-
-func TestMongoGetStoredCdrs(t *testing.T) {
- if !*testLocal {
- return
- }
- var timeStart, timeEnd time.Time
- // All CDRs, no filter
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 20 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Count ALL
- if storedCdrs, count, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Count: true}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- } else if count != 20 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // Limit 5
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Offset 5
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Offset with limit 2
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on cgrids
- if storedCdrs, _, err := mongoDb.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())}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Count on CGRIDS
- if _, count, err := mongoDb.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())}, Count: true}); err != nil {
- t.Error(err.Error())
- } else if count != 3 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // Filter on cgrids plus reqType
- if storedCdrs, _, err := mongoDb.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{utils.META_PREPAID}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Count on multiple filter
- if _, count, err := mongoDb.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{utils.META_PREPAID}, Count: true}); err != nil {
- t.Error(err.Error())
- } else if count != 1 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // Filter on runId
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{RunIds: []string{utils.DEFAULT_RUNID}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 14 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on TOR
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Tors: []string{utils.SMS}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple TOR
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Tors: []string{utils.SMS, utils.VOICE}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 15 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on cdrHost
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{CdrHosts: []string{"192.168.1.2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple cdrHost
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{CdrHosts: []string{"192.168.1.1", "192.168.1.2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 15 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on cdrSource
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{CdrSources: []string{"UNKNOWN"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple cdrSource
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{CdrSources: []string{"UNKNOWN", "UNKNOWN2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on reqType
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_PREPAID}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple reqType
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 6 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on direction
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Directions: []string{"*out"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 15 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on tenant
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Tenants: []string{"itsyscom.com"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 4 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple tenants
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 15 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on category
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Categories: []string{"premium_call"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple categories
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Categories: []string{"premium_call", "call"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 15 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on account
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Accounts: []string{"1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 6 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple account
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Accounts: []string{"1001", "1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 13 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on subject
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Subjects: []string{"1000"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple subject
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{Subjects: []string{"1000", "1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 6 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on destPrefix
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{DestPrefixes: []string{"+498651"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 4 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on multiple destPrefixes
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{DestPrefixes: []string{"1001", "+498651"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on ratedAccount
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{RatedAccounts: []string{"8001"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on ratedSubject
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{RatedSubjects: []string{"91001"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on ignoreRated
- var orderIdStart, orderIdEnd int64 // Capture also orderIds for the next test
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{MaxCost: utils.Float64Pointer(0.0)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 7 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- } else {
- for _, cdr := range storedCdrs {
- if cdr.OrderId < orderIdStart {
- orderIdStart = cdr.OrderId
- }
- if cdr.OrderId > orderIdEnd {
- orderIdEnd = cdr.OrderId
- }
- }
- }
- // Filter on orderIdStart
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 20 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on orderIdStart and orderIdEnd
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart, OrderIdEnd: orderIdEnd}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 20 { // TODO: find mongo equivalent
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on timeStart
- timeStart = time.Date(2013, 11, 8, 8, 0, 0, 0, time.UTC)
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 6 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on timeStart and timeEnd
- timeEnd = time.Date(2013, 12, 1, 8, 0, 0, 0, time.UTC)
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on minPdd
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(float64(3 * time.Second))}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 7 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on maxPdd
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{MaxPdd: utils.Float64Pointer(float64(3 * time.Second))}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 13 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on minPdd, maxPdd
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(float64(3 * time.Second)), MaxPdd: utils.Float64Pointer(float64(5 * time.Second))}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 4 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Combined filter
- if storedCdrs, _, err := mongoDb.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: ", len(storedCdrs))
- }
- // Filter on ignoreDerived
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, FilterOnRated: true}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 { // ToDo: Recheck this value
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
-}
-
-func TestMongoRemStoredCdrs(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrIdB1 := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- if err := mongoDb.RemStoredCdrs([]string{cgrIdB1}); err != nil {
- t.Error(err.Error())
- }
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 20 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- tm, _ := utils.ParseTimeDetectLayout("2013-11-08T08:42:20Z", "")
- cgrIdA1 := utils.Sha1("aaa1", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-08T08:42:22Z", "")
- cgrIdA2 := utils.Sha1("aaa2", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:24Z", "")
- cgrIdA3 := utils.Sha1("aaa3", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:21Z", "")
- cgrIdA4 := utils.Sha1("aaa4", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:25Z", "")
- cgrIdA5 := utils.Sha1("aaa5", tm.String())
- cgrIdB2 := utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- cgrIdB3 := utils.Sha1("bbb3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- if err := mongoDb.RemStoredCdrs([]string{cgrIdA1, cgrIdA2, cgrIdA3, cgrIdA4, cgrIdA5,
- cgrIdB2, cgrIdB3}); err != nil {
- t.Error(err.Error())
- }
- if storedCdrs, _, err := mongoDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 20 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
-}
-
-// Make sure that what we get is what we set
-func TestMongoStoreRestoreCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- strCdr := &StoredCdr{TOR: utils.VOICE, AccId: "ccc1", CdrHost: "192.168.1.1", CdrSource: "TEST_CDR", 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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201}
- strCdr.CgrId = utils.Sha1(strCdr.AccId, strCdr.SetupTime.String())
- if err := mongoDb.SetCdr(strCdr); err != nil {
- t.Error(err.Error())
- }
- if err := mongoDb.SetRatedCdr(strCdr); err != nil {
- t.Error(err.Error())
- }
- // Check RawCdr
- if rcvCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{strCdr.CgrId}}); err != nil {
- t.Error(err.Error())
- } else if len(rcvCdrs) != 1 {
- t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs)
- } else {
- rcvCdr := rcvCdrs[0]
- if strCdr.CgrId != rcvCdr.CgrId ||
- strCdr.TOR != rcvCdr.TOR ||
- strCdr.AccId != rcvCdr.AccId ||
- strCdr.CdrHost != rcvCdr.CdrHost ||
- strCdr.ReqType != rcvCdr.ReqType ||
- strCdr.Direction != rcvCdr.Direction ||
- strCdr.Tenant != rcvCdr.Tenant ||
- strCdr.Category != rcvCdr.Category ||
- strCdr.Account != rcvCdr.Account ||
- strCdr.Subject != rcvCdr.Subject ||
- strCdr.Destination != rcvCdr.Destination ||
- !strCdr.SetupTime.Equal(rcvCdr.SetupTime) ||
- !strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) ||
- strCdr.Usage != rcvCdr.Usage ||
- strCdr.Pdd != rcvCdr.Pdd ||
- strCdr.Supplier != rcvCdr.Supplier ||
- strCdr.DisconnectCause != rcvCdr.DisconnectCause ||
- !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) {
- t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0])
- }
- }
- // Check RatedCdr
- if rcvCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{strCdr.CgrId}, FilterOnRated: true}); err != nil {
- t.Error(err.Error())
- } else if len(rcvCdrs) != 1 {
- t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs)
- } else {
- rcvCdr := rcvCdrs[0]
- if strCdr.CgrId != rcvCdr.CgrId ||
- strCdr.TOR != rcvCdr.TOR ||
- strCdr.AccId != rcvCdr.AccId ||
- strCdr.CdrHost != rcvCdr.CdrHost ||
- strCdr.ReqType != rcvCdr.ReqType ||
- strCdr.Direction != rcvCdr.Direction ||
- strCdr.Tenant != rcvCdr.Tenant ||
- strCdr.Category != rcvCdr.Category ||
- strCdr.Account != rcvCdr.Account ||
- strCdr.Subject != rcvCdr.Subject ||
- strCdr.Destination != rcvCdr.Destination ||
- //!strCdr.SetupTime.Equal(rcvCdr.SetupTime) || // FixMe
- //!strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || // FixMe
- strCdr.Usage != rcvCdr.Usage ||
- strCdr.Pdd != rcvCdr.Pdd ||
- strCdr.Supplier != rcvCdr.Supplier ||
- strCdr.DisconnectCause != rcvCdr.DisconnectCause ||
- strCdr.Cost != rcvCdr.Cost ||
- !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) {
- t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0])
- }
- }
-}
diff --git a/engine/storage_mongo_tp.go b/engine/storage_mongo_stordb.go
similarity index 79%
rename from engine/storage_mongo_tp.go
rename to engine/storage_mongo_stordb.go
index 7a1eda6b4..9ef4333a9 100644
--- a/engine/storage_mongo_tp.go
+++ b/engine/storage_mongo_stordb.go
@@ -698,46 +698,46 @@ func (ms *MongoStorage) LogActionTiming(source string, at *ActionTiming, as Acti
}{at, as, time.Now(), source})
}
-func (ms *MongoStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) error {
- s := &StoredCdr{
- CgrId: cgrid,
- CdrSource: source,
- MediationRunId: runid,
- CostDetails: cc,
+func (ms *MongoStorage) LogCallCost(cgrid, runid, source string, cc *CallCost) error {
+ return ms.db.C(utils.TBLSMCosts).Insert(&SMCost{CGRID: cgrid, RunID: runid, CostSource: source, CostDetails: cc})
+}
+
+func (ms *MongoStorage) GetCallCostLog(cgrid, runid string) (cc *CallCost, err error) {
+ var result SMCost
+ if err = ms.db.C(utils.TBLSMCosts).Find(bson.M{CGRIDLow: cgrid, RunIDLow: runid}).One(&result); err != nil {
+ return nil, err
}
- _, err := ms.db.C(colCdrs).Upsert(bson.M{"cgrid": cgrid, "cdrsource": source, "mediationrunid": runid}, s)
- return err
+ return result.CostDetails, nil
}
-func (ms *MongoStorage) GetCallCostLog(cgrid, source, runid string) (cc *CallCost, err error) {
- result := StoredCdr{}
- err = ms.db.C(colCdrs).Find(bson.M{"cgrid": cgrid, "cdrsource": source, "mediationrunid": runid}).One(&result)
- cc = result.CostDetails
- return
-}
-
-func (ms *MongoStorage) SetCdr(cdr *StoredCdr) error {
- _, err := ms.db.C(colCdrs).Upsert(bson.M{"cgrid": cdr.CgrId, "mediationrunid": cdr.MediationRunId}, cdr)
- return err
-}
-
-func (ms *MongoStorage) SetRatedCdr(storedCdr *StoredCdr) error {
- _, err := ms.db.C(colCdrs).Upsert(bson.M{"cgrid": storedCdr.CgrId, "mediationrunid": storedCdr.MediationRunId}, storedCdr)
+func (ms *MongoStorage) SetCDR(cdr *CDR, allowUpdate bool) (err error) {
+ if cdr.OrderID == 0 {
+ cdr.OrderID = time.Now().UnixNano()
+ }
+ if allowUpdate {
+ _, err = ms.db.C(utils.TBL_CDRS).Upsert(bson.M{CGRIDLow: cdr.CGRID, RunIDLow: cdr.RunID}, cdr)
+ } else {
+ err = ms.db.C(utils.TBL_CDRS).Insert(cdr)
+ }
return err
}
// Remove CDR data out of all CDR tables based on their cgrid
-func (ms *MongoStorage) RemStoredCdrs(cgrIds []string) error {
+func (ms *MongoStorage) RemCDRs(cgrIds []string) error {
if len(cgrIds) == 0 {
return nil
}
- _, err := ms.db.C(colCdrs).UpdateAll(bson.M{"cgrid": bson.M{"$in": cgrIds}}, bson.M{"$set": bson.M{"deleted_at": time.Now()}})
+ _, err := ms.db.C(utils.TBL_CDRS).UpdateAll(bson.M{CGRIDLow: bson.M{"$in": cgrIds}}, bson.M{"$set": bson.M{"deleted_at": time.Now()}})
return err
}
func (ms *MongoStorage) cleanEmptyFilters(filters bson.M) {
for k, v := range filters {
switch value := v.(type) {
+ case *int64:
+ if value == nil {
+ delete(filters, k)
+ }
case *float64:
if value == nil {
delete(filters, k)
@@ -746,6 +746,10 @@ func (ms *MongoStorage) cleanEmptyFilters(filters bson.M) {
if value == nil {
delete(filters, k)
}
+ case *time.Duration:
+ if value == nil {
+ delete(filters, k)
+ }
case []string:
if len(value) == 0 {
delete(filters, k)
@@ -759,62 +763,89 @@ func (ms *MongoStorage) cleanEmptyFilters(filters bson.M) {
}
}
-func (ms *MongoStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr, int64, error) {
+func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter) ([]*CDR, int64, error) {
+ var minPDD, maxPDD, minUsage, maxUsage *time.Duration
+ if len(qryFltr.MinPDD) != 0 {
+ if parsed, err := utils.ParseDurationWithSecs(qryFltr.MinPDD); err != nil {
+ return nil, 0, err
+ } else {
+ minPDD = &parsed
+ }
+ }
+ if len(qryFltr.MaxPDD) != 0 {
+ if parsed, err := utils.ParseDurationWithSecs(qryFltr.MaxPDD); err != nil {
+ return nil, 0, err
+ } else {
+ maxPDD = &parsed
+ }
+ }
+ if len(qryFltr.MinUsage) != 0 {
+ if parsed, err := utils.ParseDurationWithSecs(qryFltr.MinUsage); err != nil {
+ return nil, 0, err
+ } else {
+ minUsage = &parsed
+ }
+ }
+ if len(qryFltr.MaxUsage) != 0 {
+ if parsed, err := utils.ParseDurationWithSecs(qryFltr.MaxUsage); err != nil {
+ return nil, 0, err
+ } else {
+ maxUsage = &parsed
+ }
+ }
filters := bson.M{
- "cgrid": bson.M{"$in": qryFltr.CgrIds, "$nin": qryFltr.NotCgrIds},
- "mediationrunid": bson.M{"$in": qryFltr.RunIds, "$nin": qryFltr.NotRunIds},
- "tor": bson.M{"$in": qryFltr.Tors, "$nin": qryFltr.NotTors},
- "cdrhost": bson.M{"$in": qryFltr.CdrHosts, "$nin": qryFltr.NotCdrHosts},
- "cdrsource": bson.M{"$in": qryFltr.CdrSources, "$nin": qryFltr.NotCdrSources},
- "reqtype": bson.M{"$in": qryFltr.ReqTypes, "$nin": qryFltr.NotReqTypes},
- "direction": bson.M{"$in": qryFltr.Directions, "$nin": qryFltr.NotDirections},
- "tenant": bson.M{"$in": qryFltr.Tenants, "$nin": qryFltr.NotTenants},
- "category": bson.M{"$in": qryFltr.Categories, "$nin": qryFltr.NotCategories},
- "account": bson.M{"$in": qryFltr.Accounts, "$nin": qryFltr.NotAccounts},
- "subject": bson.M{"$in": qryFltr.Subjects, "$nin": qryFltr.NotSubjects},
- "supplier": bson.M{"$in": qryFltr.Suppliers, "$nin": qryFltr.NotSuppliers},
- "disconnect_cause": bson.M{"$in": qryFltr.DisconnectCauses, "$nin": qryFltr.NotDisconnectCauses},
- "setuptime": bson.M{"$gte": qryFltr.SetupTimeStart, "$lt": qryFltr.SetupTimeEnd},
- "answertime": bson.M{"$gte": qryFltr.AnswerTimeStart, "$lt": qryFltr.AnswerTimeEnd},
- "created_at": bson.M{"$gte": qryFltr.CreatedAtStart, "$lt": qryFltr.CreatedAtEnd},
- "updated_at": bson.M{"$gte": qryFltr.UpdatedAtStart, "$lt": qryFltr.UpdatedAtEnd},
- "usage": bson.M{"$gte": qryFltr.MinUsage, "$lt": qryFltr.MaxUsage},
- "pdd": bson.M{"$gte": qryFltr.MinPdd, "$lt": qryFltr.MaxPdd},
- "costdetails.account": bson.M{"$in": qryFltr.RatedAccounts, "$nin": qryFltr.NotRatedAccounts},
- "costdetails.subject": bson.M{"$in": qryFltr.RatedSubjects, "$nin": qryFltr.NotRatedSubjects},
+ CGRIDLow: bson.M{"$in": qryFltr.CGRIDs, "$nin": qryFltr.NotCGRIDs},
+ RunIDLow: bson.M{"$in": qryFltr.RunIDs, "$nin": qryFltr.NotRunIDs},
+ OrderIDLow: bson.M{"$gte": qryFltr.OrderIDStart, "$lt": qryFltr.OrderIDEnd},
+ ToRLow: bson.M{"$in": qryFltr.ToRs, "$nin": qryFltr.NotToRs},
+ CDRHostLow: bson.M{"$in": qryFltr.OriginHosts, "$nin": qryFltr.NotOriginHosts},
+ CDRSourceLow: bson.M{"$in": qryFltr.Sources, "$nin": qryFltr.NotSources},
+ RequestTypeLow: bson.M{"$in": qryFltr.RequestTypes, "$nin": qryFltr.NotRequestTypes},
+ DirectionLow: bson.M{"$in": qryFltr.Directions, "$nin": qryFltr.NotDirections},
+ TenantLow: bson.M{"$in": qryFltr.Tenants, "$nin": qryFltr.NotTenants},
+ CategoryLow: bson.M{"$in": qryFltr.Categories, "$nin": qryFltr.NotCategories},
+ AccountLow: bson.M{"$in": qryFltr.Accounts, "$nin": qryFltr.NotAccounts},
+ SubjectLow: bson.M{"$in": qryFltr.Subjects, "$nin": qryFltr.NotSubjects},
+ SupplierLow: bson.M{"$in": qryFltr.Suppliers, "$nin": qryFltr.NotSuppliers},
+ DisconnectCauseLow: bson.M{"$in": qryFltr.DisconnectCauses, "$nin": qryFltr.NotDisconnectCauses},
+ SetupTimeLow: bson.M{"$gte": qryFltr.SetupTimeStart, "$lt": qryFltr.SetupTimeEnd},
+ AnswerTimeLow: bson.M{"$gte": qryFltr.AnswerTimeStart, "$lt": qryFltr.AnswerTimeEnd},
+ CreatedAtLow: bson.M{"$gte": qryFltr.CreatedAtStart, "$lt": qryFltr.CreatedAtEnd},
+ UpdatedAtLow: bson.M{"$gte": qryFltr.UpdatedAtStart, "$lt": qryFltr.UpdatedAtEnd},
+ UsageLow: bson.M{"$gte": minUsage, "$lt": maxUsage},
+ PDDLow: bson.M{"$gte": minPDD, "$lt": maxPDD},
+ //CostDetailsLow + "." + AccountLow: bson.M{"$in": qryFltr.RatedAccounts, "$nin": qryFltr.NotRatedAccounts},
+ //CostDetailsLow + "." + SubjectLow: bson.M{"$in": qryFltr.RatedSubjects, "$nin": qryFltr.NotRatedSubjects},
}
//file, _ := ioutil.TempFile(os.TempDir(), "debug")
//file.WriteString(fmt.Sprintf("FILTER: %v\n", utils.ToIJSON(qryFltr)))
//file.WriteString(fmt.Sprintf("BEFORE: %v\n", utils.ToIJSON(filters)))
ms.cleanEmptyFilters(filters)
-
- /*if qryFltr.OrderIdStart != 0 {
- filters["id"] = bson.M{"$gte": qryFltr.OrderIdStart}
+ if len(qryFltr.DestinationPrefixes) != 0 {
+ var regexpRule string
+ for _, prefix := range qryFltr.DestinationPrefixes {
+ if len(prefix) == 0 {
+ continue
+ }
+ if len(regexpRule) != 0 {
+ regexpRule += "|"
+ }
+ regexpRule += "^(" + prefix + ")"
+ }
+ if _, hasIt := filters["$and"]; !hasIt {
+ filters["$and"] = make([]bson.M, 0)
+ }
+ filters["$and"] = append(filters["$and"].([]bson.M), bson.M{DestinationLow: bson.RegEx{Pattern: regexpRule}}) // $and gathers all rules not fitting top level query
}
- if qryFltr.OrderIdEnd != 0 {
- if m, ok := filters["id"]; ok {
- m.(bson.M)["$gte"] = qryFltr.OrderIdStart
- } else {
- filters["id"] = bson.M{"$gte": qryFltr.OrderIdStart}
+ if len(qryFltr.NotDestinationPrefixes) != 0 {
+ if _, hasIt := filters["$and"]; !hasIt {
+ filters["$and"] = make([]bson.M, 0)
}
- }*/
-
- if len(qryFltr.DestPrefixes) != 0 {
- var regexes []bson.RegEx
- for _, prefix := range qryFltr.DestPrefixes {
- regexes = append(regexes, bson.RegEx{Pattern: regexp.QuoteMeta(prefix) + ".*"})
- }
- filters["destination"] = bson.M{"$in": regexes}
- }
- if len(qryFltr.NotDestPrefixes) != 0 {
- var notRegexes []bson.RegEx
- for _, prefix := range qryFltr.DestPrefixes {
- notRegexes = append(notRegexes, bson.RegEx{Pattern: regexp.QuoteMeta(prefix) + ".*"})
- }
- if m, ok := filters["destination"]; ok {
- m.(bson.M)["$nin"] = notRegexes
- } else {
- filters["destination"] = bson.M{"$nin": notRegexes}
+ for _, prefix := range qryFltr.NotDestinationPrefixes {
+ if len(prefix) == 0 {
+ continue
+ }
+ filters["$and"] = append(filters["$and"].([]bson.M), bson.M{DestinationLow: bson.RegEx{Pattern: "^(?!" + prefix + ")"}})
}
}
@@ -836,24 +867,24 @@ func (ms *MongoStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
if qryFltr.MinCost != nil {
if qryFltr.MaxCost == nil {
- filters["cost"] = bson.M{"$gte": *qryFltr.MinCost}
+ filters[CostLow] = bson.M{"$gte": *qryFltr.MinCost}
} else if *qryFltr.MinCost == 0.0 && *qryFltr.MaxCost == -1.0 { // Special case when we want to skip errors
filters["$or"] = []bson.M{
- bson.M{"cost": bson.M{"$gte": 0.0}},
+ bson.M{CostLow: bson.M{"$gte": 0.0}},
}
} else {
- filters["cost"] = bson.M{"$gte": *qryFltr.MinCost, "$lt": *qryFltr.MaxCost}
+ filters[CostLow] = bson.M{"$gte": *qryFltr.MinCost, "$lt": *qryFltr.MaxCost}
}
} else if qryFltr.MaxCost != nil {
if *qryFltr.MaxCost == -1.0 { // Non-rated CDRs
- filters["cost"] = 0.0 // Need to include it otherwise all CDRs will be returned
+ filters[CostLow] = 0.0 // Need to include it otherwise all CDRs will be returned
} else { // Above limited CDRs, since MinCost is empty, make sure we query also NULL cost
- filters["cost"] = bson.M{"$lt": *qryFltr.MaxCost}
+ filters[CostLow] = bson.M{"$lt": *qryFltr.MaxCost}
}
}
//file.WriteString(fmt.Sprintf("AFTER: %v\n", utils.ToIJSON(filters)))
//file.Close()
- q := ms.db.C(colCdrs).Find(filters)
+ q := ms.db.C(utils.TBL_CDRS).Find(filters)
if qryFltr.Paginator.Limit != nil {
q = q.Limit(*qryFltr.Paginator.Limit)
}
@@ -867,11 +898,10 @@ func (ms *MongoStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
}
return nil, int64(cnt), nil
}
-
// Execute query
iter := q.Iter()
- var cdrs []*StoredCdr
- cdr := StoredCdr{}
+ var cdrs []*CDR
+ cdr := CDR{}
for iter.Next(&cdr) {
clone := cdr
cdrs = append(cdrs, &clone)
diff --git a/engine/storage_mysql.go b/engine/storage_mysql.go
index 539a242e1..b59b1ce99 100644
--- a/engine/storage_mysql.go
+++ b/engine/storage_mysql.go
@@ -19,15 +19,16 @@ along with this program. If not, see
package engine
import (
- "encoding/json"
"fmt"
- "path"
- "time"
- "github.com/cgrates/cgrates/utils"
+ _ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
)
+type MySQLStorage struct {
+ *SQLStorage
+}
+
func NewMySQLStorage(host, port, name, user, password string, maxConn, maxIdleConn int) (*MySQLStorage, error) {
connectString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&loc=Local&parseTime=true", user, password, host, port, name)
db, err := gorm.Open("mysql", connectString)
@@ -43,81 +44,3 @@ func NewMySQLStorage(host, port, name, user, password string, maxConn, maxIdleCo
return &MySQLStorage{&SQLStorage{Db: db.DB(), db: db}}, nil
}
-
-type MySQLStorage struct {
- *SQLStorage
-}
-
-func (self *MySQLStorage) Flush(scriptsPath string) (err error) {
- for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} {
- if err := self.CreateTablesFromScript(path.Join(scriptsPath, scriptName)); err != nil {
- return err
- }
- }
- for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
- if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 FROM %s", tbl)); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (self *MySQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) (err error) {
- if cc == nil {
- return nil
- }
- tss, err := json.Marshal(cc.Timespans)
- if err != nil {
- utils.Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err))
- return err
- }
- _, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (cgrid,runid,tor,direction,tenant,category,account,subject,destination,cost,timespans,cost_source,created_at) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s',%f,'%s','%s','%s') ON DUPLICATE KEY UPDATE tor=values(tor),direction=values(direction),tenant=values(tenant),category=values(category),account=values(account),subject=values(subject),destination=values(destination),cost=values(cost),timespans=values(timespans),cost_source=values(cost_source),updated_at='%s'",
- utils.TBL_COST_DETAILS,
- cgrid,
- runid,
- cc.TOR,
- cc.Direction,
- cc.Tenant,
- cc.Category,
- cc.Account,
- cc.Subject,
- cc.Destination,
- cc.Cost,
- tss,
- source,
- time.Now().Format(time.RFC3339),
- time.Now().Format(time.RFC3339)))
- if err != nil {
- utils.Logger.Err(fmt.Sprintf("failed to execute insert statement: %v", err))
- return err
- }
- return nil
-}
-
-func (self *MySQLStorage) SetRatedCdr(storedCdr *StoredCdr) (err error) {
- _, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (cgrid,runid,reqtype,direction,tenant,category,account,subject,destination,setup_time,answer_time,`usage`,pdd,supplier,disconnect_cause,cost,extra_info,created_at) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',%v,%v,'%s','%s',%f,'%s','%s') ON DUPLICATE KEY UPDATE reqtype=values(reqtype),direction=values(direction),tenant=values(tenant),category=values(category),account=values(account),subject=values(subject),destination=values(destination),setup_time=values(setup_time),answer_time=values(answer_time),`usage`=values(`usage`),pdd=values(pdd),cost=values(cost),supplier=values(supplier),disconnect_cause=values(disconnect_cause),extra_info=values(extra_info), updated_at='%s'",
- utils.TBL_RATED_CDRS,
- storedCdr.CgrId,
- storedCdr.MediationRunId,
- storedCdr.ReqType,
- storedCdr.Direction,
- storedCdr.Tenant,
- storedCdr.Category,
- storedCdr.Account,
- storedCdr.Subject,
- storedCdr.Destination,
- storedCdr.SetupTime,
- storedCdr.AnswerTime,
- storedCdr.Usage.Seconds(),
- storedCdr.Pdd.Seconds(),
- storedCdr.Supplier,
- storedCdr.DisconnectCause,
- storedCdr.Cost,
- storedCdr.ExtraInfo,
- time.Now().Format(time.RFC3339),
- time.Now().Format(time.RFC3339)))
- if err != nil {
- utils.Logger.Err(fmt.Sprintf("failed to execute cdr insert statement: %s", err.Error()))
- }
- return
-}
diff --git a/engine/storage_mysql_local_test.go b/engine/storage_mysql_local_test.go
deleted file mode 100644
index 6f2be2799..000000000
--- a/engine/storage_mysql_local_test.go
+++ /dev/null
@@ -1,990 +0,0 @@
-/*
-Rating system designed to be used in VoIP Carriers World
-Copyright (C) 2012-2015 ITsysCOM
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see
-*/
-
-package engine
-
-import (
- "fmt"
- "path"
- "reflect"
- "testing"
- "time"
-
- "github.com/cgrates/cgrates/config"
- "github.com/cgrates/cgrates/utils"
-)
-
-var mysqlDb *MySQLStorage
-
-func TestMySQLCreateTables(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrConfig, _ := config.NewDefaultCGRConfig()
- var err error
- if mysqlDb, err = NewMySQLStorage(cgrConfig.StorDBHost, cgrConfig.StorDBPort, cgrConfig.StorDBName, cgrConfig.StorDBUser, cgrConfig.StorDBPass,
- cgrConfig.StorDBMaxOpenConns, cgrConfig.StorDBMaxIdleConns); err != nil {
- t.Error("Error on opening database connection: ", err)
- return
- }
- for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} {
- if err := mysqlDb.CreateTablesFromScript(path.Join(*dataDir, "storage", utils.MYSQL, scriptName)); err != nil {
- t.Error("Error on mysqlDb creation: ", err.Error())
- return // No point in going further
- }
- }
- for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
- if _, err := mysqlDb.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {
- t.Error(err.Error())
- }
- }
-}
-
-func TestMySQLSetGetTPTiming(t *testing.T) {
- if !*testLocal {
- return
- }
- tm := TpTiming{Tpid: utils.TEST_SQL, Tag: "ALWAYS", Time: "00:00:00"}
- if err := mysqlDb.SetTpTimings([]TpTiming{tm}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.Tag); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(tm, tmgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[0])
- }
- // Update
- tm.Time = "00:00:01"
- if err := mysqlDb.SetTpTimings([]TpTiming{tm}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.Tag); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(tm, tmgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[0])
- }
-}
-
-func TestMySQLSetGetTPDestination(t *testing.T) {
- if !*testLocal {
- return
- }
- dst := []TpDestination{
- TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49"},
- TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49151"},
- TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49176"},
- }
- if err := mysqlDb.SetTpDestinations(dst); err != nil {
- t.Error(err.Error())
- }
- storData, err := mysqlDb.GetTpDestinations(utils.TEST_SQL, utils.TEST_SQL)
- dsts, err := TpDestinations(storData).GetDestinations()
- expected := &Destination{Id: utils.TEST_SQL, Prefixes: []string{"+49", "+49151", "+49176"}}
- if err != nil {
- t.Error(err.Error())
- } else if !modelEqual(*expected, *dsts[utils.TEST_SQL]) {
- t.Errorf("Expecting: %+v, received: %+v", expected, dsts[utils.TEST_SQL])
- }
-}
-
-func TestMySQLSetGetTPRates(t *testing.T) {
- if !*testLocal {
- return
- }
- RT_ID := "RT_1"
- rtSlots := []*utils.RateSlot{
- &utils.RateSlot{ConnectFee: 0.02, Rate: 0.01, RateUnit: "60s", RateIncrement: "60s", GroupIntervalStart: "0s"},
- &utils.RateSlot{ConnectFee: 0.00, Rate: 0.005, RateUnit: "60s", RateIncrement: "1s", GroupIntervalStart: "60s"},
- }
- for _, rs := range rtSlots {
- rs.SetDurations()
- }
- rates := &utils.TPRate{
- TPid: utils.TEST_SQL,
- RateId: RT_ID,
- RateSlots: rtSlots,
- }
- mRates := APItoModelRate(rates)
- if err := mysqlDb.SetTpRates(mRates); err != nil {
- t.Error(err.Error())
- }
- if rts, err := mysqlDb.GetTpRates(utils.TEST_SQL, RT_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mRates[0], rts[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mRates, rts)
- }
-}
-
-func TestMySQLSetGetTPDestinationRates(t *testing.T) {
- if !*testLocal {
- return
- }
- DR_ID := "DR_1"
- dr := &utils.DestinationRate{DestinationId: "DST_1", RateId: "RT_1", RoundingMethod: "*up", RoundingDecimals: 4}
-
- eDrs := &utils.TPDestinationRate{TPid: utils.TEST_SQL, DestinationRateId: DR_ID, DestinationRates: []*utils.DestinationRate{dr}}
- mdrs := APItoModelDestinationRate(eDrs)
- if err := mysqlDb.SetTpDestinationRates(mdrs); err != nil {
- t.Error(err.Error())
- }
- if drs, err := mysqlDb.GetTpDestinationRates(utils.TEST_SQL, DR_ID, nil); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mdrs[0], drs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mdrs, drs)
- }
-}
-
-func TestMySQLSetGetTPRatingPlans(t *testing.T) {
- if !*testLocal {
- return
- }
- RP_ID := "RP_1"
- rbBinding := &utils.TPRatingPlanBinding{DestinationRatesId: "DR_1", TimingId: "TM_1", Weight: 10.0}
- rp := &utils.TPRatingPlan{
- TPid: utils.TEST_SQL,
- RatingPlanId: RP_ID,
- RatingPlanBindings: []*utils.TPRatingPlanBinding{rbBinding},
- }
- mrp := APItoModelRatingPlan(rp)
- if err := mysqlDb.SetTpRatingPlans(mrp); err != nil {
- t.Error(err.Error())
- }
- if drps, err := mysqlDb.GetTpRatingPlans(utils.TEST_SQL, RP_ID, nil); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mrp[0], drps[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mrp, drps)
- }
-}
-
-func TestMySQLSetGetTPRatingProfiles(t *testing.T) {
- if !*testLocal {
- return
- }
- ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RP_1"}}
- rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras}
- mrp := APItoModelRatingProfile(rp)
- if err := mysqlDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mrp[0], rps[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mrp, rps)
- }
-
-}
-
-func TestMySQLSetGetTPSharedGroups(t *testing.T) {
- if !*testLocal {
- return
- }
- SG_ID := "SG_1"
- tpSgs := &utils.TPSharedGroups{
- TPid: utils.TEST_SQL,
- SharedGroupsId: SG_ID,
- SharedGroups: []*utils.TPSharedGroup{
- &utils.TPSharedGroup{Account: "dan", Strategy: "*lowest_first", RatingSubject: "lowest_rates"},
- },
- }
- mSgs := APItoModelSharedGroup(tpSgs)
- if err := mysqlDb.SetTpSharedGroups(mSgs); err != nil {
- t.Error(err.Error())
- }
- if sgs, err := mysqlDb.GetTpSharedGroups(utils.TEST_SQL, SG_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mSgs[0], sgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mSgs, sgs)
- }
-}
-
-func TestMySQLSetGetTPCdrStats(t *testing.T) {
- if !*testLocal {
- return
- }
- CS_ID := "CDRSTATS_1"
- setCS := &utils.TPCdrStats{
- TPid: utils.TEST_SQL,
- CdrStatsId: CS_ID,
- CdrStats: []*utils.TPCdrStat{
- &utils.TPCdrStat{QueueLength: "10", TimeWindow: "10m", Metrics: "ASR", Tenants: "cgrates.org", Categories: "call"},
- },
- }
- mcs := APItoModelCdrStat(setCS)
- if err := mysqlDb.SetTpCdrStats(mcs); err != nil {
- t.Error(err.Error())
- }
- if cs, err := mysqlDb.GetTpCdrStats(utils.TEST_SQL, CS_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mcs[0], cs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mcs, cs)
- }
-}
-
-func TestMySQLSetGetTPDerivedChargers(t *testing.T) {
- if !*testLocal {
- return
- }
- dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^" + utils.META_PREPAID, AccountField: "^rif", SubjectField: "^rif",
- UsageField: "cgr_duration", SupplierField: "^supplier1"}
- dcs := &utils.TPDerivedChargers{TPid: utils.TEST_SQL, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: []*utils.TPDerivedCharger{dc}}
-
- mdcs := APItoModelDerivedCharger(dcs)
- if err := mysqlDb.SetTpDerivedChargers(mdcs); err != nil {
- t.Error(err.Error())
- }
- if rDCs, err := mysqlDb.GetTpDerivedChargers(&mdcs[0]); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mdcs[0], rDCs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mdcs, rDCs)
- }
-}
-
-func TestMySQLSetGetTPActions(t *testing.T) {
- if !*testLocal {
- return
- }
- ACTS_ID := "PREPAID_10"
- acts := []*utils.TPAction{
- &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited",
- DestinationIds: "*any", BalanceWeight: 10, Weight: 10}}
- tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts}
- mas := APItoModelAction(tpActions)
- if err := mysqlDb.SetTpActions(mas); err != nil {
- t.Error(err.Error())
- }
- if rTpActs, err := mysqlDb.GetTpActions(utils.TEST_SQL, ACTS_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mas[0], rTpActs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mas, rTpActs)
- }
-}
-
-func TestMySQLTPActionTimings(t *testing.T) {
- if !*testLocal {
- return
- }
- AP_ID := "AP_1"
- ap := &utils.TPActionPlan{
- TPid: utils.TEST_SQL,
- ActionPlanId: AP_ID,
- ActionPlan: []*utils.TPActionTiming{&utils.TPActionTiming{ActionsId: "ACTS_1", TimingId: "TM_1", Weight: 10.0}},
- }
- maps := APItoModelActionPlan(ap)
- if err := mysqlDb.SetTpActionPlans(maps); err != nil {
- t.Error(err.Error())
- }
- if rAP, err := mysqlDb.GetTpActionPlans(utils.TEST_SQL, AP_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(maps[0], rAP[0]) {
- t.Errorf("Expecting: %+v, received: %+v", maps, rAP)
- }
-}
-
-func TestMySQLSetGetTPActionTriggers(t *testing.T) {
- if !*testLocal {
- return
- }
- atrg := &utils.TPActionTrigger{
- Id: "MY_FIRST_ATGR",
- BalanceType: "*monetary",
- BalanceDirections: "*out",
- ThresholdType: "*min_balance",
- ThresholdValue: 2.0,
- Recurrent: true,
- BalanceDestinationIds: "*any",
- Weight: 10.0,
- ActionsId: "LOG_BALANCE",
- }
- atrgs := &utils.TPActionTriggers{
- TPid: utils.TEST_SQL,
- ActionTriggersId: "MY_FIRST_ATGR",
- ActionTriggers: []*utils.TPActionTrigger{atrg},
- }
- matrg := APItoModelActionTrigger(atrgs)
- if err := mysqlDb.SetTpActionTriggers(matrg); err != nil {
- t.Error("Unexpected error: ", err.Error())
- }
- if rcvMpAtrgs, err := mysqlDb.GetTpActionTriggers(utils.TEST_SQL, "MY_FIRST_ATGR"); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if !modelEqual(matrg[0], rcvMpAtrgs[0]) {
- t.Errorf("Expecting: %v, received: %v", matrg, rcvMpAtrgs)
- }
-}
-
-func TestMySQLSetGetTpAccountActions(t *testing.T) {
- if !*testLocal {
- return
- }
- aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
- maa := APItoModelAccountAction(aa)
- if err := mysqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(*maa, aas[0]) {
- t.Errorf("Expecting: %+v, received: %+v", maa, aas)
- }
-}
-
-func TestMySQLGetTPIds(t *testing.T) {
- if !*testLocal {
- return
- }
- eTPIds := []string{utils.TEST_SQL}
- if tpIds, err := mysqlDb.GetTpIds(); err != nil {
- t.Error(err.Error())
- } else if !reflect.DeepEqual(eTPIds, tpIds) {
- t.Errorf("Expecting: %+v, received: %+v", eTPIds, tpIds)
- }
-}
-
-func TestMySQLRemoveTPData(t *testing.T) {
- if !*testLocal {
- return
- }
- // Create Timings
- tm := &utils.ApierTPTiming{TPid: utils.TEST_SQL, TimingId: "ALWAYS", Time: "00:00:00"}
- tms := APItoModelTiming(tm)
- if err := mysqlDb.SetTpTimings([]TpTiming{*tms}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err.Error())
- } else if len(tmgs) == 0 {
- t.Error("Could not store TPTiming")
- }
- // Remove Timings
- if err := mysqlDb.RemTpData(utils.TBL_TP_TIMINGS, utils.TEST_SQL, map[string]string{"tag": tm.TimingId}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err)
- } else if len(tmgs) != 0 {
- t.Errorf("Timings should be empty, got instead: %+v", tmgs)
- }
- // Create RatingProfile
- ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1"}}
- rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras}
- mrp := APItoModelRatingProfile(rp)
- if err := mysqlDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if len(rps) == 0 {
- t.Error("Could not store TPRatingProfile")
- }
- // Remove RatingProfile
- if err := mysqlDb.RemTpData(utils.TBL_TP_RATE_PROFILES, rp.TPid, map[string]string{"loadid": rp.LoadId, "direction": rp.Direction, "tenant": rp.Tenant, "category": rp.Category, "subject": rp.Subject}); err != nil {
- t.Error(err.Error())
- }
- if rps, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err)
- } else if len(rps) != 0 {
- t.Errorf("RatingProfiles different than 0: %+v", rps)
- }
- // Create AccountActions
- aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
- maa := APItoModelAccountAction(aa)
- if err := mysqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if len(aas) == 0 {
- t.Error("Could not create TPAccountActions")
- }
- // Remove AccountActions
- if err := mysqlDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err)
- } else if len(aas) != 0 {
- t.Errorf("Non empty account actions: %+v", aas)
- }
- // Create again so we can test complete TP removal
- if err := mysqlDb.SetTpTimings([]TpTiming{*tms}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err.Error())
- } else if len(tmgs) == 0 {
- t.Error("Could not store TPTiming")
- }
- // Create RatingProfile
- if err := mysqlDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if len(rps) == 0 {
- t.Error("Could not store TPRatingProfile")
- }
- // Create AccountActions
- if err := mysqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if len(aas) == 0 {
- t.Error("Could not create TPAccountActions")
- }
- // Remove TariffPlan completely
- if err := mysqlDb.RemTpData("", utils.TEST_SQL, nil); err != nil {
- t.Error(err.Error())
- }
- // Make sure we have removed it
- if tms, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err)
- } else if len(tms) != 0 {
- t.Errorf("Non empty timings: %+v", tms)
- }
- if rpfs, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err)
- } else if len(rpfs) != 0 {
- t.Errorf("Non empty rpfs: %+v", rpfs)
- }
- if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err)
- } else if len(aas) != 0 {
- t.Errorf("Non empty account actions: %+v", aas)
- }
-}
-
-func TestMySQLSetCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrCdr1 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: utils.TEST_SQL}
-
- cgrCdr2 := &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", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr3 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr4 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr5 := &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", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- for _, cdr := range []*CgrCdr{cgrCdr1, cgrCdr2, cgrCdr3, cgrCdr4, cgrCdr5} {
- if err := mysqlDb.SetCdr(cdr.AsStoredCdr("")); err != nil {
- t.Error(err.Error())
- }
- }
- strCdr1 := &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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- 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 := &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, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL1",
- 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 := &StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: utils.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, Pdd: time.Duration(2) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201}
- strCdr3.CgrId = utils.Sha1(strCdr3.AccId, strCdr3.SetupTime.String())
-
- for _, cdr := range []*StoredCdr{strCdr1, strCdr2, strCdr3} {
- if err := mysqlDb.SetCdr(cdr); err != nil {
- t.Error(err.Error())
- }
- }
-}
-
-func TestMySQLSetRatedCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- strCdr1 := &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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- 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 := &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, Pdd: time.Duration(7) * time.Second, Supplier: "SUPPL1",
- 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 := &StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: utils.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, Pdd: time.Duration(2) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: "wholesale_run", Cost: 1.201}
- strCdr3.CgrId = utils.Sha1(strCdr3.AccId, strCdr3.SetupTime.String())
-
- for _, cdr := range []*StoredCdr{strCdr1, strCdr2, strCdr3} {
- if err := mysqlDb.SetRatedCdr(cdr); err != nil {
- t.Error(err.Error())
- }
- }
-}
-
-func TestMySQLCallCost(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrId := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- cc := &CallCost{
- Direction: "*out",
- Category: "call",
- Tenant: "cgrates.org",
- Subject: "91001",
- Account: "8001",
- Destination: "1002",
- TOR: utils.VOICE,
- Timespans: []*TimeSpan{
- &TimeSpan{
- TimeStart: time.Date(2013, 9, 10, 13, 40, 0, 0, time.UTC),
- TimeEnd: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC),
- },
- &TimeSpan{
- TimeStart: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC),
- TimeEnd: time.Date(2013, 9, 10, 13, 41, 30, 0, time.UTC),
- },
- },
- }
- if err := mysqlDb.LogCallCost(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil {
- t.Error(err.Error())
- }
- if ccRcv, err := mysqlDb.GetCallCostLog(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil {
- t.Error(err.Error())
- } else if !reflect.DeepEqual(cc, ccRcv) {
- t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv)
- }
- // UPDATE test here
- cc.Category = "premium_call"
- if err := mysqlDb.LogCallCost(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil {
- t.Error(err.Error())
- }
- if ccRcv, err := mysqlDb.GetCallCostLog(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil {
- t.Error(err.Error())
- } else if !reflect.DeepEqual(cc, ccRcv) {
- t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv)
- }
-}
-
-func TestMySQLGetStoredCdrs(t *testing.T) {
- if !*testLocal {
- return
- }
- var timeStart, timeEnd time.Time
- // All CDRs, no filter
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Count ALL
- if storedCdrs, count, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Count: true}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- } else if count != 8 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // Limit 5
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Offset 5
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Offset with limit 2
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on cgrids
- 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())}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Count on CGRIDS
- 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())}, Count: true}); err != nil {
- t.Error(err.Error())
- } else if count != 2 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // 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{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{utils.META_PREPAID}, Count: true}); err != nil {
- t.Error(err.Error())
- } else if count != 1 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // Filter on runId
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{RunIds: []string{utils.DEFAULT_RUNID}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on TOR
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Tors: []string{utils.SMS}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple TOR
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Tors: []string{utils.SMS, utils.VOICE}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on cdrHost
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrHosts: []string{"192.168.1.2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple cdrHost
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrHosts: []string{"192.168.1.1", "192.168.1.2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on cdrSource
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrSources: []string{"UNKNOWN"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple cdrSource
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrSources: []string{"UNKNOWN", "UNKNOWN2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on reqType
- 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{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)
- }
- // Filter on direction
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Directions: []string{"*out"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on tenant
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Tenants: []string{"itsyscom.com"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple tenants
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on category
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Categories: []string{"premium_call"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple categories
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Categories: []string{"premium_call", "call"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on account
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Accounts: []string{"1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple account
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Accounts: []string{"1001", "1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on subject
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Subjects: []string{"1000"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple subject
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{Subjects: []string{"1000", "1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on destPrefix
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{DestPrefixes: []string{"+498651"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple destPrefixes
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{DestPrefixes: []string{"1001", "+498651"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 4 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on ratedAccount
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{RatedAccounts: []string{"8001"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on ratedSubject
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{RatedSubjects: []string{"91001"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on ignoreRated
- var orderIdStart, orderIdEnd int64 // Capture also orderIds for the next test
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{MaxCost: utils.Float64Pointer(0.0)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- } else {
- for _, cdr := range storedCdrs {
- if cdr.OrderId < orderIdStart {
- orderIdStart = cdr.OrderId
- }
- if cdr.OrderId > orderIdEnd {
- orderIdEnd = cdr.OrderId
- }
- }
- }
- // Filter on orderIdStart
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on orderIdStart and orderIdEnd
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart, OrderIdEnd: orderIdEnd}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 4 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on timeStart
- timeStart = time.Date(2013, 11, 8, 8, 0, 0, 0, time.UTC)
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on timeStart and timeEnd
- timeEnd = time.Date(2013, 12, 1, 8, 0, 0, 0, time.UTC)
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on minPdd
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(3)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 7 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on maxPdd
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{MaxPdd: utils.Float64Pointer(3)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on minPdd, maxPdd
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(3), MaxPdd: utils.Float64Pointer(5)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Combined filter
- 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)
- }
- // Filter on ignoreDerived
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, FilterOnRated: true}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 { // ToDo: Recheck this value
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
-}
-
-func TestMySQLRemStoredCdrs(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrIdB1 := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- if err := mysqlDb.RemStoredCdrs([]string{cgrIdB1}); err != nil {
- t.Error(err.Error())
- }
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 7 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- tm, _ := utils.ParseTimeDetectLayout("2013-11-08T08:42:20Z", "")
- cgrIdA1 := utils.Sha1("aaa1", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-08T08:42:22Z", "")
- cgrIdA2 := utils.Sha1("aaa2", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:24Z", "")
- cgrIdA3 := utils.Sha1("aaa3", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:21Z", "")
- cgrIdA4 := utils.Sha1("aaa4", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:25Z", "")
- cgrIdA5 := utils.Sha1("aaa5", tm.String())
- cgrIdB2 := utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- cgrIdB3 := utils.Sha1("bbb3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- if err := mysqlDb.RemStoredCdrs([]string{cgrIdA1, cgrIdA2, cgrIdA3, cgrIdA4, cgrIdA5,
- cgrIdB2, cgrIdB3}); err != nil {
- t.Error(err.Error())
- }
- if storedCdrs, _, err := mysqlDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
-}
-
-// Make sure that what we get is what we set
-func TestMySQLStoreRestoreCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- strCdr := &StoredCdr{TOR: utils.VOICE, AccId: "ccc1", CdrHost: "192.168.1.1", CdrSource: "TEST_CDR", 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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201}
- strCdr.CgrId = utils.Sha1(strCdr.AccId, strCdr.SetupTime.String())
- if err := mysqlDb.SetCdr(strCdr); err != nil {
- t.Error(err.Error())
- }
- if err := mysqlDb.SetRatedCdr(strCdr); err != nil {
- t.Error(err.Error())
- }
- // Check RawCdr
- if rcvCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{strCdr.CgrId}}); err != nil {
- t.Error(err.Error())
- } else if len(rcvCdrs) != 1 {
- t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs)
- } else {
- rcvCdr := rcvCdrs[0]
- if strCdr.CgrId != rcvCdr.CgrId ||
- strCdr.TOR != rcvCdr.TOR ||
- strCdr.AccId != rcvCdr.AccId ||
- strCdr.CdrHost != rcvCdr.CdrHost ||
- strCdr.ReqType != rcvCdr.ReqType ||
- strCdr.Direction != rcvCdr.Direction ||
- strCdr.Tenant != rcvCdr.Tenant ||
- strCdr.Category != rcvCdr.Category ||
- strCdr.Account != rcvCdr.Account ||
- strCdr.Subject != rcvCdr.Subject ||
- strCdr.Destination != rcvCdr.Destination ||
- !strCdr.SetupTime.Equal(rcvCdr.SetupTime) ||
- !strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) ||
- strCdr.Usage != rcvCdr.Usage ||
- strCdr.Pdd != rcvCdr.Pdd ||
- strCdr.Supplier != rcvCdr.Supplier ||
- strCdr.DisconnectCause != rcvCdr.DisconnectCause ||
- !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) {
- t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0])
- }
- }
- // Check RatedCdr
- if rcvCdrs, _, err := mysqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{strCdr.CgrId}, FilterOnRated: true}); err != nil {
- t.Error(err.Error())
- } else if len(rcvCdrs) != 1 {
- t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs)
- } else {
- rcvCdr := rcvCdrs[0]
- if strCdr.CgrId != rcvCdr.CgrId ||
- strCdr.TOR != rcvCdr.TOR ||
- strCdr.AccId != rcvCdr.AccId ||
- strCdr.CdrHost != rcvCdr.CdrHost ||
- strCdr.ReqType != rcvCdr.ReqType ||
- strCdr.Direction != rcvCdr.Direction ||
- strCdr.Tenant != rcvCdr.Tenant ||
- strCdr.Category != rcvCdr.Category ||
- strCdr.Account != rcvCdr.Account ||
- strCdr.Subject != rcvCdr.Subject ||
- strCdr.Destination != rcvCdr.Destination ||
- //!strCdr.SetupTime.Equal(rcvCdr.SetupTime) || // FixMe
- //!strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || // FixMe
- strCdr.Usage != rcvCdr.Usage ||
- strCdr.Pdd != rcvCdr.Pdd ||
- strCdr.Supplier != rcvCdr.Supplier ||
- strCdr.DisconnectCause != rcvCdr.DisconnectCause ||
- strCdr.Cost != rcvCdr.Cost ||
- !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) {
- t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0])
- }
- }
-}
diff --git a/engine/storage_postgres.go b/engine/storage_postgres.go
index 8641e828b..00862cd39 100644
--- a/engine/storage_postgres.go
+++ b/engine/storage_postgres.go
@@ -19,12 +19,7 @@ along with this program. If not, see
package engine
import (
- "encoding/json"
"fmt"
- "path"
- "time"
-
- "github.com/cgrates/cgrates/utils"
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
@@ -50,97 +45,3 @@ func NewPostgresStorage(host, port, name, user, password string, maxConn, maxIdl
return &PostgresStorage{&SQLStorage{Db: db.DB(), db: db}}, nil
}
-
-func (self *PostgresStorage) Flush(scriptsPath string) (err error) {
- for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} {
- if err := self.CreateTablesFromScript(path.Join(scriptsPath, scriptName)); err != nil {
- return err
- }
- }
- for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
- if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 FROM %s", tbl)); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (self *PostgresStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) (err error) {
- if cc == nil {
- return nil
- }
- tss, err := json.Marshal(cc.Timespans)
- if err != nil {
- utils.Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err))
- return err
- }
- tx := self.db.Begin()
- cd := &TblCostDetail{
- Cgrid: cgrid,
- Runid: runid,
- Tor: cc.TOR,
- Direction: cc.Direction,
- Tenant: cc.Tenant,
- Category: cc.Category,
- Account: cc.Account,
- Subject: cc.Subject,
- Destination: cc.Destination,
- Cost: cc.Cost,
- Timespans: string(tss),
- CostSource: source,
- CreatedAt: time.Now(),
- }
-
- if tx.Save(cd).Error != nil { // Check further since error does not properly reflect duplicates here (sql: no rows in result set)
- tx.Rollback()
- tx = self.db.Begin()
- updated := tx.Model(TblCostDetail{}).Where(&TblCostDetail{Cgrid: cgrid, Runid: runid}).Updates(&TblCostDetail{Tor: cc.TOR, Direction: cc.Direction, Tenant: cc.Tenant, Category: cc.Category,
- Account: cc.Account, Subject: cc.Subject, Destination: cc.Destination, Cost: cc.Cost, Timespans: string(tss), CostSource: source, UpdatedAt: time.Now()})
- if updated.Error != nil {
- tx.Rollback()
- return updated.Error
- }
- }
- tx.Commit()
- return nil
-}
-
-func (self *PostgresStorage) SetRatedCdr(cdr *StoredCdr) (err error) {
- tx := self.db.Begin()
- saved := tx.Save(&TblRatedCdr{
- Cgrid: cdr.CgrId,
- Runid: cdr.MediationRunId,
- Reqtype: cdr.ReqType,
- Direction: cdr.Direction,
- Tenant: cdr.Tenant,
- Category: cdr.Category,
- Account: cdr.Account,
- Subject: cdr.Subject,
- Destination: cdr.Destination,
- SetupTime: cdr.SetupTime,
- AnswerTime: cdr.AnswerTime,
- Usage: cdr.Usage.Seconds(),
- Pdd: cdr.Pdd.Seconds(),
- Supplier: cdr.Supplier,
- DisconnectCause: cdr.DisconnectCause,
- Cost: cdr.Cost,
- ExtraInfo: cdr.ExtraInfo,
- CreatedAt: time.Now(),
- })
- if saved.Error != nil {
- tx.Rollback()
- tx = self.db.Begin()
- updated := tx.Model(TblRatedCdr{}).Where(&TblRatedCdr{Cgrid: cdr.CgrId, Runid: cdr.MediationRunId}).Updates(&TblRatedCdr{Reqtype: cdr.ReqType,
- Direction: cdr.Direction, Tenant: cdr.Tenant, Category: cdr.Category, Account: cdr.Account, Subject: cdr.Subject, Destination: cdr.Destination,
- SetupTime: cdr.SetupTime, AnswerTime: cdr.AnswerTime, Usage: cdr.Usage.Seconds(), Pdd: cdr.Pdd.Seconds(), Supplier: cdr.Supplier, DisconnectCause: cdr.DisconnectCause,
- Cost: cdr.Cost, ExtraInfo: cdr.ExtraInfo,
- UpdatedAt: time.Now()})
- if updated.Error != nil {
- tx.Rollback()
- return updated.Error
- }
- }
- tx.Commit()
- return nil
-
-}
diff --git a/engine/storage_psql_local_test.go b/engine/storage_psql_local_test.go
deleted file mode 100644
index d3245c93f..000000000
--- a/engine/storage_psql_local_test.go
+++ /dev/null
@@ -1,985 +0,0 @@
-/*
-Rating system designed to be used in VoIP Carriers World
-Copyright (C) 2012-2015 ITsysCOM
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see
-*/
-
-package engine
-
-import (
- "fmt"
- "path"
- "reflect"
- "testing"
- "time"
-
- "github.com/cgrates/cgrates/config"
- "github.com/cgrates/cgrates/utils"
-)
-
-var psqlDb *PostgresStorage
-
-func TestPSQLCreateTables(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrConfig, _ := config.NewDefaultCGRConfig()
- var err error
- if psqlDb, err = NewPostgresStorage("localhost", "5432", cgrConfig.StorDBName, cgrConfig.StorDBUser, cgrConfig.StorDBPass,
- cgrConfig.StorDBMaxOpenConns, cgrConfig.StorDBMaxIdleConns); err != nil {
- t.Error("Error on opening database connection: ", err)
- return
- }
- for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} {
- if err := psqlDb.CreateTablesFromScript(path.Join(*dataDir, "storage", utils.POSTGRES, scriptName)); err != nil {
- t.Error("Error on psqlDb creation: ", err.Error())
- return // No point in going further
- }
- }
- for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
- if _, err := psqlDb.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {
- t.Error(err.Error())
- }
- }
-}
-
-func TestPSQLSetGetTPTiming(t *testing.T) {
- if !*testLocal {
- return
- }
- tm := &utils.ApierTPTiming{TPid: utils.TEST_SQL, TimingId: "ALWAYS", Time: "00:00:00"}
- mtm := APItoModelTiming(tm)
- mtms := []TpTiming{*mtm}
- if err := psqlDb.SetTpTimings(mtms); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mtms[0], tmgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mtms, tmgs)
- }
- // Update
- tm.Time = "00:00:01"
- if err := psqlDb.SetTpTimings(mtms); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mtms[0], tmgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mtms, tmgs)
- }
-}
-
-func TestPSQLSetGetTPDestination(t *testing.T) {
- if !*testLocal {
- return
- }
- dst := &utils.TPDestination{TPid: utils.TEST_SQL, DestinationId: utils.TEST_SQL, Prefixes: []string{"+49", "+49151", "+49176"}}
- dests := APItoModelDestination(dst)
- if err := psqlDb.SetTpDestinations(dests); err != nil {
- t.Error(err.Error())
- }
- storData, err := psqlDb.GetTpDestinations(utils.TEST_SQL, utils.TEST_SQL)
- dsts, err := TpDestinations(storData).GetDestinations()
- if err != nil {
- t.Error(err.Error())
- } else if len(dst.Prefixes) != len(dsts[utils.TEST_SQL].Prefixes) {
- t.Errorf("Expecting: %+v, received: %+v", dst, dsts[utils.TEST_SQL])
- }
-}
-
-func TestPSQLSetGetTPRates(t *testing.T) {
- if !*testLocal {
- return
- }
- RT_ID := "RT_1"
- rtSlots := []*utils.RateSlot{
- &utils.RateSlot{ConnectFee: 0.02, Rate: 0.01, RateUnit: "60s", RateIncrement: "60s", GroupIntervalStart: "0s"},
- &utils.RateSlot{ConnectFee: 0.00, Rate: 0.005, RateUnit: "60s", RateIncrement: "1s", GroupIntervalStart: "60s"},
- }
- for _, rs := range rtSlots {
- rs.SetDurations()
- }
- expectedTPRate := &utils.TPRate{TPid: utils.TEST_SQL, RateId: RT_ID, RateSlots: rtSlots}
- mRates := APItoModelRate(expectedTPRate)
- if err := psqlDb.SetTpRates(mRates); err != nil {
- t.Error(err.Error())
- }
- rts, err := psqlDb.GetTpRates(utils.TEST_SQL, RT_ID)
- trts, err := TpRates(rts).GetRates()
- if err != nil {
- t.Error(err.Error())
- } else if len(expectedTPRate.RateSlots) != len(trts[RT_ID].RateSlots) {
- t.Errorf("Expecting: %+v, received: %+v", expectedTPRate, trts[RT_ID])
- }
-}
-
-func TestPSQLSetGetTPDestinationRates(t *testing.T) {
- if !*testLocal {
- return
- }
- DR_ID := "DR_1"
- dr := &utils.DestinationRate{DestinationId: "DST_1", RateId: "RT_1", RoundingMethod: "*up", RoundingDecimals: 4}
- eDrs := &utils.TPDestinationRate{TPid: utils.TEST_SQL, DestinationRateId: DR_ID, DestinationRates: []*utils.DestinationRate{dr}}
- mdrs := APItoModelDestinationRate(eDrs)
- if err := psqlDb.SetTpDestinationRates(mdrs); err != nil {
- t.Error(err.Error())
- }
- if drs, err := psqlDb.GetTpDestinationRates(utils.TEST_SQL, DR_ID, nil); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mdrs[0], drs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mdrs, drs)
- }
-}
-
-func TestPSQLSetGetTPRatingPlans(t *testing.T) {
- if !*testLocal {
- return
- }
- RP_ID := "RP_1"
- rbBinding := &utils.TPRatingPlanBinding{DestinationRatesId: "DR_1", TimingId: "TM_1", Weight: 10.0}
- rp := &utils.TPRatingPlan{
- TPid: utils.TEST_SQL,
- RatingPlanId: RP_ID,
- RatingPlanBindings: []*utils.TPRatingPlanBinding{rbBinding},
- }
- mrp := APItoModelRatingPlan(rp)
-
- if err := psqlDb.SetTpRatingPlans(mrp); err != nil {
- t.Error(err.Error())
- }
- if drps, err := psqlDb.GetTpRatingPlans(utils.TEST_SQL, RP_ID, nil); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mrp[0], drps[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mrp, drps)
- }
-}
-
-func TestPSQLSetGetTPRatingProfiles(t *testing.T) {
- if !*testLocal {
- return
- }
- ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RP_1"}}
- rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras}
-
- mrp := APItoModelRatingProfile(rp)
- if err := psqlDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mrp[0], rps[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mrp, rps)
- }
-}
-
-func TestPSQLSetGetTPSharedGroups(t *testing.T) {
- if !*testLocal {
- return
- }
- SG_ID := "SG_1"
- tpSgs := &utils.TPSharedGroups{
- TPid: utils.TEST_SQL,
- SharedGroupsId: SG_ID,
- SharedGroups: []*utils.TPSharedGroup{
- &utils.TPSharedGroup{Account: "dan", Strategy: "*lowest_first", RatingSubject: "lowest_rates"},
- },
- }
- mSgs := APItoModelSharedGroup(tpSgs)
- if err := psqlDb.SetTpSharedGroups(mSgs); err != nil {
- t.Error(err.Error())
- }
- if sgs, err := psqlDb.GetTpSharedGroups(utils.TEST_SQL, SG_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mSgs[0], sgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mSgs, sgs)
- }
-}
-
-func TestPSQLSetGetTPCdrStats(t *testing.T) {
- if !*testLocal {
- return
- }
- CS_ID := "CDRSTATS_1"
- setCS := &utils.TPCdrStats{
- TPid: utils.TEST_SQL,
- CdrStatsId: CS_ID,
- CdrStats: []*utils.TPCdrStat{
- &utils.TPCdrStat{QueueLength: "10", TimeWindow: "10m", Metrics: "ASR", Tenants: "cgrates.org", Categories: "call"},
- },
- }
- mcs := APItoModelCdrStat(setCS)
- if err := psqlDb.SetTpCdrStats(mcs); err != nil {
- t.Error(err.Error())
- }
- if cs, err := psqlDb.GetTpCdrStats(utils.TEST_SQL, CS_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mcs[0], cs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mcs, cs)
- }
-}
-
-func TestPSQLSetGetTPDerivedChargers(t *testing.T) {
- if !*testLocal {
- return
- }
- dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^" + utils.META_PREPAID, AccountField: "^rif", SubjectField: "^rif",
- UsageField: "cgr_duration", SupplierField: "^supplier1"}
- dcs := &utils.TPDerivedChargers{TPid: utils.TEST_SQL, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: []*utils.TPDerivedCharger{dc}}
- mdcs := APItoModelDerivedCharger(dcs)
- if err := psqlDb.SetTpDerivedChargers(mdcs); err != nil {
- t.Error(err.Error())
- }
- if rDCs, err := psqlDb.GetTpDerivedChargers(&mdcs[0]); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mdcs[0], rDCs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mdcs, rDCs)
- }
-}
-
-func TestPSQLSetGetTPActions(t *testing.T) {
- if !*testLocal {
- return
- }
- ACTS_ID := "PREPAID_10"
- acts := []*utils.TPAction{
- &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited",
- DestinationIds: "*any", BalanceWeight: 10, Weight: 10}}
- tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts}
- mas := APItoModelAction(tpActions)
- if err := psqlDb.SetTpActions(mas); err != nil {
- t.Error(err.Error())
- }
- if rTpActs, err := psqlDb.GetTpActions(utils.TEST_SQL, ACTS_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(mas[0], rTpActs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", mas, rTpActs)
- }
-}
-
-func TestPSQLTPActionTimings(t *testing.T) {
- if !*testLocal {
- return
- }
- AP_ID := "AP_1"
- ap := &utils.TPActionPlan{
- TPid: utils.TEST_SQL,
- ActionPlanId: AP_ID,
- ActionPlan: []*utils.TPActionTiming{&utils.TPActionTiming{ActionsId: "ACTS_1", TimingId: "TM_1", Weight: 10.0}},
- }
- maps := APItoModelActionPlan(ap)
- if err := psqlDb.SetTpActionPlans(maps); err != nil {
- t.Error(err.Error())
- }
- if rAP, err := psqlDb.GetTpActionPlans(utils.TEST_SQL, AP_ID); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(maps[0], rAP[0]) {
- t.Errorf("Expecting: %+v, received: %+v", maps, rAP)
- }
-}
-
-func TestPSQLSetGetTPActionTriggers(t *testing.T) {
- if !*testLocal {
- return
- }
- atrg := &utils.TPActionTrigger{
- Id: "MY_FIRST_ATGR",
- BalanceType: "*monetary",
- BalanceDirections: "*out",
- ThresholdType: "*min_balance",
- ThresholdValue: 2.0,
- Recurrent: true,
- BalanceDestinationIds: "*any",
- Weight: 10.0,
- ActionsId: "LOG_BALANCE",
- }
- atrgs := &utils.TPActionTriggers{
- TPid: utils.TEST_SQL,
- ActionTriggersId: "MY_FIRST_ATGR",
- ActionTriggers: []*utils.TPActionTrigger{atrg},
- }
- matrg := APItoModelActionTrigger(atrgs)
- if err := psqlDb.SetTpActionTriggers(matrg); err != nil {
- t.Error("Unexpected error: ", err.Error())
- }
- if rcvMpAtrgs, err := psqlDb.GetTpActionTriggers(utils.TEST_SQL, "MY_FIRST_ATGR"); err != nil {
- t.Error("Unexpected error: ", err.Error())
- } else if !modelEqual(matrg[0], rcvMpAtrgs[0]) {
- t.Errorf("Expecting: %+v, received: %+v", matrg, rcvMpAtrgs)
- }
-}
-
-func TestPSQLSetGetTpAccountActions(t *testing.T) {
- if !*testLocal {
- return
- }
- aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
- maa := APItoModelAccountAction(aa)
- if err := psqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := psqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if !modelEqual(*maa, aas[0]) {
- t.Errorf("Expecting: %+v, received: %+v", maa, aas)
- }
-}
-
-func TestPSQLGetTPIds(t *testing.T) {
- if !*testLocal {
- return
- }
- eTPIds := []string{utils.TEST_SQL}
- if tpIds, err := psqlDb.GetTpIds(); err != nil {
- t.Error(err.Error())
- } else if !reflect.DeepEqual(eTPIds, tpIds) {
- t.Errorf("Expecting: %+v, received: %+v", eTPIds, tpIds)
- }
-}
-
-func TestPSQLRemoveTPData(t *testing.T) {
- if !*testLocal {
- return
- }
- // Create Timings
- tm := &utils.ApierTPTiming{TPid: utils.TEST_SQL, TimingId: "ALWAYS", Time: "00:00:00"}
- tms := APItoModelTiming(tm)
- if err := psqlDb.SetTpTimings([]TpTiming{*tms}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err.Error())
- } else if len(tmgs) == 0 {
- t.Error("Could not store TPTiming")
- }
- // Remove Timings
- if err := psqlDb.RemTpData(utils.TBL_TP_TIMINGS, utils.TEST_SQL, map[string]string{"tag": tm.TimingId}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err)
- } else if len(tmgs) != 0 {
- t.Errorf("Timings should be empty, got instead: %+v", tmgs)
- }
- // Create RatingProfile
- ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1"}}
- rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras}
- mrp := APItoModelRatingProfile(rp)
- if err := psqlDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if len(rps) == 0 {
- t.Error("Could not store TPRatingProfile")
- }
- // Remove RatingProfile
- if err := psqlDb.RemTpData(utils.TBL_TP_RATE_PROFILES, rp.TPid, map[string]string{"loadid": rp.LoadId, "direction": rp.Direction, "tenant": rp.Tenant, "category": rp.Category, "subject": rp.Subject}); err != nil {
- t.Error(err.Error())
- }
- if rps, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err)
- } else if len(rps) != 0 {
- t.Errorf("RatingProfiles different than 0: %+v", rps)
- }
- // Create AccountActions
- aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
- maa := APItoModelAccountAction(aa)
- if err := psqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := psqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if len(aas) == 0 {
- t.Error("Could not create TPAccountActions")
- }
- // Remove AccountActions
- if err := psqlDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := psqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err)
- } else if len(aas) != 0 {
- t.Errorf("Non empty account actions: %+v", aas)
- }
- // Create again so we can test complete TP removal
- if err := psqlDb.SetTpTimings([]TpTiming{*tms}); err != nil {
- t.Error(err.Error())
- }
- if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err.Error())
- } else if len(tmgs) == 0 {
- t.Error("Could not store TPTiming")
- }
- // Create RatingProfile
- if err := psqlDb.SetTpRatingProfiles(mrp); err != nil {
- t.Error(err.Error())
- }
- if rps, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err.Error())
- } else if len(rps) == 0 {
- t.Error("Could not store TPRatingProfile")
- }
- // Create AccountActions
- if err := psqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
- t.Error(err.Error())
- }
- if aas, err := psqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err.Error())
- } else if len(aas) == 0 {
- t.Error("Could not create TPAccountActions")
- }
- // Remove TariffPlan completely
- if err := psqlDb.RemTpData("", utils.TEST_SQL, nil); err != nil {
- t.Error(err.Error())
- }
- // Make sure we have removed it
- if tms, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil {
- t.Error(err)
- } else if len(tms) != 0 {
- t.Errorf("Non empty timings: %+v", tms)
- }
- if rpfs, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil {
- t.Error(err)
- } else if len(rpfs) != 0 {
- t.Errorf("Non empty rpfs: %+v", rpfs)
- }
- if aas, err := psqlDb.GetTpAccountActions(maa); err != nil {
- t.Error(err)
- } else if len(aas) != 0 {
- t.Errorf("Non empty account actions: %+v", aas)
- }
-}
-
-func TestPSQLSetCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrCdr1 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: utils.TEST_SQL}
-
- cgrCdr2 := &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", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr3 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr4 := &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", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- cgrCdr5 := &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", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL}
-
- for _, cdr := range []*CgrCdr{cgrCdr1, cgrCdr2, cgrCdr3, cgrCdr4, cgrCdr5} {
- if err := psqlDb.SetCdr(cdr.AsStoredCdr("")); err != nil {
- t.Error(err.Error())
- }
- }
- strCdr1 := &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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- 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 := &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, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL1",
- 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 := &StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: utils.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, Pdd: time.Duration(2) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201}
- strCdr3.CgrId = utils.Sha1(strCdr3.AccId, strCdr3.SetupTime.String())
-
- for _, cdr := range []*StoredCdr{strCdr1, strCdr2, strCdr3} {
- if err := psqlDb.SetCdr(cdr); err != nil {
- t.Error(err.Error())
- }
- }
-}
-
-func TestPSQLCallCost(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrId := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- cc := &CallCost{
- Direction: "*out",
- Category: "call",
- Tenant: "cgrates.org",
- Subject: "91001",
- Account: "8001",
- Destination: "1002",
- TOR: utils.VOICE,
- Timespans: []*TimeSpan{
- &TimeSpan{
- TimeStart: time.Date(2013, 9, 10, 13, 40, 0, 0, time.UTC),
- TimeEnd: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC),
- },
- &TimeSpan{
- TimeStart: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC),
- TimeEnd: time.Date(2013, 9, 10, 13, 41, 30, 0, time.UTC),
- },
- },
- }
- if err := psqlDb.LogCallCost(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil {
- t.Error(err.Error())
- }
- if ccRcv, err := psqlDb.GetCallCostLog(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil {
- t.Error(err.Error())
- } else if !reflect.DeepEqual(cc, ccRcv) {
- t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv)
- }
- // UPDATE test here
- cc.Category = "premium_call"
- if err := psqlDb.LogCallCost(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil {
- t.Error(err.Error())
- }
- if ccRcv, err := psqlDb.GetCallCostLog(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil {
- t.Error(err.Error())
- } else if !reflect.DeepEqual(cc, ccRcv) {
- t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv)
- }
-}
-
-func TestPSQLSetRatedCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- strCdr1 := &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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- 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 := &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, Pdd: time.Duration(7) * time.Second, Supplier: "SUPPL1",
- 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 := &StoredCdr{TOR: utils.VOICE, AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: utils.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, Pdd: time.Duration(2) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: "wholesale_run", Cost: 1.201}
- strCdr3.CgrId = utils.Sha1(strCdr3.AccId, strCdr3.SetupTime.String())
-
- for _, cdr := range []*StoredCdr{strCdr1, strCdr2, strCdr3} {
- if err := psqlDb.SetRatedCdr(cdr); err != nil {
- t.Error(err.Error())
- }
- }
-}
-
-func TestPSQLGetStoredCdrs(t *testing.T) {
- if !*testLocal {
- return
- }
- var timeStart, timeEnd time.Time
- // All CDRs, no filter
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Count ALL
- if storedCdrs, count, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Count: true}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- } else if count != 8 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // Limit 5
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Offset 5
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Offset with limit 2
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
- }
- // Filter on cgrids
- 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())}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Count on CGRIDS
- 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())}, Count: true}); err != nil {
- t.Error(err.Error())
- } else if count != 2 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // 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{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{utils.META_PREPAID}, Count: true}); err != nil {
- t.Error(err.Error())
- } else if count != 1 {
- t.Error("Unexpected count of StoredCdrs returned: ", count)
- }
- // Filter on runId
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{RunIds: []string{utils.DEFAULT_RUNID}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on TOR
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Tors: []string{utils.SMS}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple TOR
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Tors: []string{utils.SMS, utils.VOICE}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on cdrHost
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrHosts: []string{"192.168.1.2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple cdrHost
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrHosts: []string{"192.168.1.1", "192.168.1.2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on cdrSource
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrSources: []string{"UNKNOWN"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple cdrSource
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrSources: []string{"UNKNOWN", "UNKNOWN2"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on reqType
- 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{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)
- }
- // Filter on direction
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Directions: []string{"*out"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on tenant
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Tenants: []string{"itsyscom.com"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple tenants
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on category
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Categories: []string{"premium_call"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple categories
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Categories: []string{"premium_call", "call"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on account
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Accounts: []string{"1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple account
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Accounts: []string{"1001", "1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on subject
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Subjects: []string{"1000"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple subject
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Subjects: []string{"1000", "1002"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on destPrefix
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{DestPrefixes: []string{"+498651"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 3 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on multiple destPrefixes
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{DestPrefixes: []string{"1001", "+498651"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 4 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on ratedAccount
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{RatedAccounts: []string{"8001"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on ratedSubject
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{RatedSubjects: []string{"91001"}}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on ignoreRated
- var orderIdStart, orderIdEnd int64 // Capture also orderIds for the next test
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{MaxCost: utils.Float64Pointer(0.0)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- } else {
- for _, cdr := range storedCdrs {
- if cdr.OrderId < orderIdStart {
- orderIdStart = cdr.OrderId
- }
- if cdr.OrderId > orderIdEnd {
- orderIdEnd = cdr.OrderId
- }
- }
- }
- // Filter on orderIdStart
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 8 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on orderIdStart and orderIdEnd
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart, OrderIdEnd: orderIdEnd}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 4 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on timeStart
- timeStart = time.Date(2013, 11, 8, 8, 0, 0, 0, time.UTC)
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on timeStart and timeEnd
- timeEnd = time.Date(2013, 12, 1, 8, 0, 0, 0, time.UTC)
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 2 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on minPdd
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(3)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 7 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on maxPdd
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{MaxPdd: utils.Float64Pointer(3)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 1 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Filter on minPdd, maxPdd
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(3), MaxPdd: utils.Float64Pointer(5)}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 5 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- // Combined filter
- 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)
- }
- // Filter on ignoreDerived
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, FilterOnRated: true}); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 { // ToDo: Recheck this value
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
-}
-
-func TestPSQLRemStoredCdrs(t *testing.T) {
- if !*testLocal {
- return
- }
- cgrIdB1 := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- if err := psqlDb.RemStoredCdrs([]string{cgrIdB1}); err != nil {
- t.Error(err.Error())
- }
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 7 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
- tm, _ := utils.ParseTimeDetectLayout("2013-11-08T08:42:20Z", "")
- cgrIdA1 := utils.Sha1("aaa1", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-08T08:42:22Z", "")
- cgrIdA2 := utils.Sha1("aaa2", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:24Z", "")
- cgrIdA3 := utils.Sha1("aaa3", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:21Z", "")
- cgrIdA4 := utils.Sha1("aaa4", tm.String())
- tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:25Z", "")
- cgrIdA5 := utils.Sha1("aaa5", tm.String())
- cgrIdB2 := utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- cgrIdB3 := utils.Sha1("bbb3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())
- if err := psqlDb.RemStoredCdrs([]string{cgrIdA1, cgrIdA2, cgrIdA3, cgrIdA4, cgrIdA5,
- cgrIdB2, cgrIdB3}); err != nil {
- t.Error(err.Error())
- }
- if storedCdrs, _, err := psqlDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
- t.Error(err.Error())
- } else if len(storedCdrs) != 0 {
- t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
- }
-}
-
-// Make sure that what we get is what we set
-func TestPSQLStoreRestoreCdr(t *testing.T) {
- if !*testLocal {
- return
- }
- strCdr := &StoredCdr{TOR: utils.VOICE, AccId: "ccc1", CdrHost: "192.168.1.1", CdrSource: "TEST_CDR", 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, Pdd: time.Duration(3) * time.Second, Supplier: "SUPPL1",
- ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
- MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201}
- strCdr.CgrId = utils.Sha1(strCdr.AccId, strCdr.SetupTime.String())
- if err := psqlDb.SetCdr(strCdr); err != nil {
- t.Error(err.Error())
- }
- if err := psqlDb.SetRatedCdr(strCdr); err != nil {
- t.Error(err.Error())
- }
- // Check RawCdr
- if rcvCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{strCdr.CgrId}}); err != nil {
- t.Error(err.Error())
- } else if len(rcvCdrs) != 1 {
- t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs)
- } else {
- rcvCdr := rcvCdrs[0]
- if strCdr.CgrId != rcvCdr.CgrId ||
- strCdr.TOR != rcvCdr.TOR ||
- strCdr.AccId != rcvCdr.AccId ||
- strCdr.CdrHost != rcvCdr.CdrHost ||
- strCdr.ReqType != rcvCdr.ReqType ||
- strCdr.Direction != rcvCdr.Direction ||
- strCdr.Tenant != rcvCdr.Tenant ||
- strCdr.Category != rcvCdr.Category ||
- strCdr.Account != rcvCdr.Account ||
- strCdr.Subject != rcvCdr.Subject ||
- strCdr.Destination != rcvCdr.Destination ||
- !strCdr.SetupTime.Equal(rcvCdr.SetupTime) ||
- !strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) ||
- strCdr.Usage != rcvCdr.Usage ||
- strCdr.Pdd != rcvCdr.Pdd ||
- strCdr.Supplier != rcvCdr.Supplier ||
- strCdr.DisconnectCause != rcvCdr.DisconnectCause ||
- !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) {
- t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0])
- }
- }
- // Check RatedCdr
- if rcvCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{strCdr.CgrId}, FilterOnRated: true}); err != nil {
- t.Error(err.Error())
- } else if len(rcvCdrs) != 1 {
- t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs)
- } else {
- rcvCdr := rcvCdrs[0]
- if strCdr.CgrId != rcvCdr.CgrId ||
- strCdr.TOR != rcvCdr.TOR ||
- strCdr.AccId != rcvCdr.AccId ||
- strCdr.CdrHost != rcvCdr.CdrHost ||
- strCdr.ReqType != rcvCdr.ReqType ||
- strCdr.Direction != rcvCdr.Direction ||
- strCdr.Tenant != rcvCdr.Tenant ||
- strCdr.Category != rcvCdr.Category ||
- strCdr.Account != rcvCdr.Account ||
- strCdr.Subject != rcvCdr.Subject ||
- strCdr.Destination != rcvCdr.Destination ||
- //!strCdr.SetupTime.Equal(rcvCdr.SetupTime) || // FixMe
- //!strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || // FixMe
- strCdr.Usage != rcvCdr.Usage ||
- strCdr.Pdd != rcvCdr.Pdd ||
- strCdr.Supplier != rcvCdr.Supplier ||
- strCdr.DisconnectCause != rcvCdr.DisconnectCause ||
- strCdr.Cost != rcvCdr.Cost ||
- !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) {
- t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0])
- }
- }
-}
diff --git a/engine/storage_redis_local_test.go b/engine/storage_redis_local_test.go
index b4c43b05e..d07d46b85 100644
--- a/engine/storage_redis_local_test.go
+++ b/engine/storage_redis_local_test.go
@@ -57,9 +57,9 @@ func TestSetGetDerivedCharges(t *testing.T) {
}
keyCharger1 := utils.ConcatenatedKey("*out", "cgrates.org", "call", "dan", "dan")
charger1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{
- &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra1", RequestTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
- &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
+ &utils.DerivedCharger{RunID: "extra2", RequestTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default",
AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"},
}}
if err := rds.SetDerivedChargers(keyCharger1, charger1); err != nil {
diff --git a/engine/storage_sql.go b/engine/storage_sql.go
index 2c0336e90..935a3eb8c 100644
--- a/engine/storage_sql.go
+++ b/engine/storage_sql.go
@@ -24,12 +24,12 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
+ "path"
"strconv"
"strings"
"time"
"github.com/cgrates/cgrates/utils"
- "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
)
@@ -43,8 +43,16 @@ func (self *SQLStorage) Close() {
self.db.Close()
}
-func (self *SQLStorage) Flush(placeholder string) (err error) {
- return utils.ErrNotImplemented
+func (self *SQLStorage) Flush(scriptsPath string) (err error) {
+ for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} {
+ if err := self.CreateTablesFromScript(path.Join(scriptsPath, scriptName)); err != nil {
+ return err
+ }
+ }
+ if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 FROM %s", utils.TBL_CDRS)); err != nil {
+ return err
+ }
+ return nil
}
func (self *SQLStorage) GetKeysForPrefix(prefix string) ([]string, error) {
@@ -561,32 +569,44 @@ func (self *SQLStorage) SetTpAccountActions(aas []TpAccountAction) error {
return nil
}
-
-func (self *SQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) error {
- return utils.ErrNotImplemented
+func (self *SQLStorage) LogCallCost(cgrid, runid, source string, cc *CallCost) error {
+ if cc == nil {
+ return nil
+ }
+ tss, err := json.Marshal(cc)
+ if err != nil {
+ utils.Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err))
+ return err
+ }
+ tx := self.db.Begin()
+ cd := &TBLSMCosts{
+ Cgrid: cgrid,
+ RunID: runid,
+ CostSource: source,
+ CostDetails: string(tss),
+ CreatedAt: time.Now(),
+ }
+ if tx.Save(cd).Error != nil { // Check further since error does not properly reflect duplicates here (sql: no rows in result set)
+ tx.Rollback()
+ return tx.Error
+ }
+ tx.Commit()
+ return nil
}
-func (self *SQLStorage) GetCallCostLog(cgrid, source, runid string) (*CallCost, error) {
- var tpCostDetail TblCostDetail
- if err := self.db.Where(&TblCostDetail{Cgrid: cgrid, Runid: runid, CostSource: source}).First(&tpCostDetail).Error; err != nil {
+func (self *SQLStorage) GetCallCostLog(cgrid, runid string) (*CallCost, error) {
+ var tpCostDetail TBLSMCosts
+ if err := self.db.Where(&TBLSMCosts{Cgrid: cgrid, RunID: runid}).First(&tpCostDetail).Error; err != nil {
return nil, err
}
- if len(tpCostDetail.Timespans) == 0 {
+ if len(tpCostDetail.CostDetails) == 0 {
return nil, nil // No costs returned
}
- cc := new(CallCost)
- cc.TOR = tpCostDetail.Tor
- cc.Direction = tpCostDetail.Direction
- cc.Category = tpCostDetail.Category
- cc.Tenant = tpCostDetail.Tenant
- cc.Account = tpCostDetail.Account
- cc.Subject = tpCostDetail.Subject
- cc.Destination = tpCostDetail.Destination
- cc.Cost = tpCostDetail.Cost
- if err := json.Unmarshal([]byte(tpCostDetail.Timespans), &cc.Timespans); err != nil {
+ var cc CallCost
+ if err := json.Unmarshal([]byte(tpCostDetail.CostDetails), &cc); err != nil {
return nil, err
}
- return cc, nil
+ return &cc, nil
}
func (self *SQLStorage) LogActionTrigger(ubId, source string, at *ActionTrigger, as Actions) (err error) {
@@ -596,19 +616,20 @@ func (self *SQLStorage) LogActionTiming(source string, at *ActionTiming, as Acti
return
}
-func (self *SQLStorage) SetCdr(cdr *StoredCdr) error {
+func (self *SQLStorage) SetCDR(cdr *CDR, allowUpdate bool) error {
extraFields, err := json.Marshal(cdr.ExtraFields)
if err != nil {
return err
}
tx := self.db.Begin()
- saved := tx.Save(&TblCdrsPrimary{
- Cgrid: cdr.CgrId,
- Tor: cdr.TOR,
- Accid: cdr.AccId,
- Cdrhost: cdr.CdrHost,
- Cdrsource: cdr.CdrSource,
- Reqtype: cdr.ReqType,
+ saved := tx.Save(&TBLCDRs{
+ Cgrid: cdr.CGRID,
+ RunID: cdr.RunID,
+ OriginHost: cdr.OriginHost,
+ Source: cdr.Source,
+ OriginID: cdr.OriginID,
+ Tor: cdr.ToR,
+ RequestType: cdr.RequestType,
Direction: cdr.Direction,
Tenant: cdr.Tenant,
Category: cdr.Category,
@@ -616,248 +637,176 @@ func (self *SQLStorage) SetCdr(cdr *StoredCdr) error {
Subject: cdr.Subject,
Destination: cdr.Destination,
SetupTime: cdr.SetupTime,
+ Pdd: cdr.PDD.Seconds(),
AnswerTime: cdr.AnswerTime,
Usage: cdr.Usage.Seconds(),
- Pdd: cdr.Pdd.Seconds(),
Supplier: cdr.Supplier,
DisconnectCause: cdr.DisconnectCause,
- CreatedAt: time.Now()})
+ ExtraFields: string(extraFields),
+ CostSource: cdr.CostSource,
+ Cost: cdr.Cost,
+ CostDetails: cdr.CostDetailsJson(),
+ ExtraInfo: cdr.ExtraInfo,
+ CreatedAt: time.Now(),
+ })
if saved.Error != nil {
tx.Rollback()
- return saved.Error
- }
- // Save extra fields
- if err := tx.Save(&TblCdrsExtra{Cgrid: cdr.CgrId, ExtraFields: string(extraFields), CreatedAt: time.Now()}).Error; err != nil {
- tx.Rollback()
- return err
+ if !allowUpdate {
+ return saved.Error
+ }
+ tx = self.db.Begin()
+ updated := tx.Model(TBLCDRs{}).Where(&TBLCDRs{Cgrid: cdr.CGRID, RunID: cdr.RunID}).Updates(
+ &TBLCDRs{
+ OriginHost: cdr.OriginHost,
+ Source: cdr.Source,
+ OriginID: cdr.OriginID,
+ Tor: cdr.ToR,
+ RequestType: cdr.RequestType,
+ Direction: cdr.Direction,
+ Tenant: cdr.Tenant,
+ Category: cdr.Category,
+ Account: cdr.Account,
+ Subject: cdr.Subject,
+ Destination: cdr.Destination,
+ SetupTime: cdr.SetupTime,
+ Pdd: cdr.PDD.Seconds(),
+ AnswerTime: cdr.AnswerTime,
+ Usage: cdr.Usage.Seconds(),
+ Supplier: cdr.Supplier,
+ DisconnectCause: cdr.DisconnectCause,
+ ExtraFields: string(extraFields),
+ CostSource: cdr.CostSource,
+ Cost: cdr.Cost,
+ CostDetails: cdr.CostDetailsJson(),
+ ExtraInfo: cdr.ExtraInfo,
+ UpdatedAt: time.Now(),
+ },
+ )
+ if updated.Error != nil {
+ tx.Rollback()
+ return updated.Error
+ }
}
tx.Commit()
return nil
}
-func (self *SQLStorage) SetRatedCdr(storedCdr *StoredCdr) error {
- return utils.ErrNotImplemented
-}
-func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr, int64, error) {
- var cdrs []*StoredCdr
- // Select string
- var selectStr string
- if qryFltr.FilterOnRated { // We use different tables to query account data in case of derived
- selectStr = fmt.Sprintf("%s.cgrid,%s.id,%s.tor,%s.accid,%s.cdrhost,%s.cdrsource,%s.reqtype,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.setup_time,%s.answer_time,%s.usage,%s.pdd,%s.supplier,%s.disconnect_cause,%s.extra_fields,%s.runid,%s.cost,%s.tor,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.cost,%s.timespans",
- utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS,
- utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS,
- utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS,
- utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS)
- } else {
- selectStr = fmt.Sprintf("%s.cgrid,%s.id,%s.tor,%s.accid,%s.cdrhost,%s.cdrsource,%s.reqtype,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.setup_time,%s.answer_time,%s.usage,%s.pdd,%s.supplier,%s.disconnect_cause,%s.extra_fields,%s.runid,%s.cost,%s.tor,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.cost,%s.timespans",
- utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY,
- utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY,
- utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS,
- utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS, utils.TBL_COST_DETAILS)
+func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter) ([]*CDR, int64, error) {
+ var cdrs []*CDR
- }
- // Join string
- joinStr := fmt.Sprintf("LEFT JOIN %s ON %s.cgrid=%s.cgrid LEFT JOIN %s ON %s.cgrid=%s.cgrid LEFT JOIN %s ON %s.cgrid=%s.cgrid AND %s.runid=%s.runid", utils.TBL_CDRS_EXTRA, utils.TBL_CDRS_PRIMARY,
- utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_CDRS_PRIMARY, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS, utils.TBL_COST_DETAILS)
- q := self.db.Table(utils.TBL_CDRS_PRIMARY).Select(selectStr).Joins(joinStr)
+ q := self.db.Table(utils.TBL_CDRS).Select("*")
if qryFltr.Unscoped {
q = q.Unscoped()
} else {
// Query filter
- for _, tblName := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS} {
- q = q.Where(fmt.Sprintf("(%s.deleted_at IS NULL OR %s.deleted_at <= '0001-01-02')", tblName, tblName)) // Soft deletes
- }
+ q = q.Where("(deleted_at IS NULL OR deleted_at <= '0001-01-02')") // Soft deletes
}
// Add filters, use in to replace the high number of ORs
- if len(qryFltr.CgrIds) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cgrid in (?)", qryFltr.CgrIds)
+ if len(qryFltr.CGRIDs) != 0 {
+ q = q.Where("cgrid in (?)", qryFltr.CGRIDs)
}
- if len(qryFltr.NotCgrIds) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cgrid not in (?)", qryFltr.NotCgrIds)
+ if len(qryFltr.NotCGRIDs) != 0 {
+ q = q.Where("cgrid not in (?)", qryFltr.NotCGRIDs)
}
- if len(qryFltr.RunIds) != 0 {
- q = q.Where(utils.TBL_RATED_CDRS+".runid in (?)", qryFltr.RunIds)
+ if len(qryFltr.RunIDs) != 0 {
+ q = q.Where("run_id in (?)", qryFltr.RunIDs)
}
- if len(qryFltr.NotRunIds) != 0 {
- q = q.Where(utils.TBL_RATED_CDRS+".runid not in (?)", qryFltr.NotRunIds)
+ if len(qryFltr.NotRunIDs) != 0 {
+ q = q.Where("run_id not in (?)", qryFltr.NotRunIDs)
}
- if len(qryFltr.Tors) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".tor in (?)", qryFltr.Tors)
+ if len(qryFltr.ToRs) != 0 {
+ q = q.Where("tor in (?)", qryFltr.ToRs)
}
- if len(qryFltr.NotTors) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".tor not in (?)", qryFltr.NotTors)
+ if len(qryFltr.NotToRs) != 0 {
+ q = q.Where("tor not in (?)", qryFltr.NotToRs)
}
- if len(qryFltr.CdrHosts) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrhost in (?)", qryFltr.CdrHosts)
+ if len(qryFltr.OriginHosts) != 0 {
+ q = q.Where("origin_host in (?)", qryFltr.OriginHosts)
}
- if len(qryFltr.NotCdrHosts) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrhost not in (?)", qryFltr.NotCdrHosts)
+ if len(qryFltr.NotOriginHosts) != 0 {
+ q = q.Where("origin_host not in (?)", qryFltr.NotOriginHosts)
}
- if len(qryFltr.CdrSources) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrsource in (?)", qryFltr.CdrSources)
+ if len(qryFltr.Sources) != 0 {
+ q = q.Where("source in (?)", qryFltr.Sources)
}
- if len(qryFltr.NotCdrSources) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrsource not in (?)", qryFltr.NotCdrSources)
+ if len(qryFltr.NotSources) != 0 {
+ q = q.Where("source not in (?)", qryFltr.NotSources)
}
- if len(qryFltr.ReqTypes) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".reqtype in (?)", qryFltr.ReqTypes)
+ if len(qryFltr.RequestTypes) != 0 {
+ q = q.Where("request_type in (?)", qryFltr.RequestTypes)
}
- if len(qryFltr.NotReqTypes) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".reqtype not in (?)", qryFltr.NotReqTypes)
+ if len(qryFltr.NotRequestTypes) != 0 {
+ q = q.Where("request_type not in (?)", qryFltr.NotRequestTypes)
}
if len(qryFltr.Directions) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".direction in (?)", qryFltr.Directions)
+ q = q.Where("direction in (?)", qryFltr.Directions)
}
if len(qryFltr.NotDirections) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".direction not in (?)", qryFltr.NotDirections)
+ q = q.Where("direction not in (?)", qryFltr.NotDirections)
}
if len(qryFltr.Tenants) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".tenant in (?)", qryFltr.Tenants)
+ q = q.Where("tenant in (?)", qryFltr.Tenants)
}
if len(qryFltr.NotTenants) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".tenant not in (?)", qryFltr.NotTenants)
+ q = q.Where("tenant not in (?)", qryFltr.NotTenants)
}
if len(qryFltr.Categories) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".category in (?)", qryFltr.Categories)
+ q = q.Where("category in (?)", qryFltr.Categories)
}
if len(qryFltr.NotCategories) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".category not in (?)", qryFltr.NotCategories)
+ q = q.Where("category not in (?)", qryFltr.NotCategories)
}
if len(qryFltr.Accounts) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".account in (?)", qryFltr.Accounts)
+ q = q.Where("account in (?)", qryFltr.Accounts)
}
if len(qryFltr.NotAccounts) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".account not in (?)", qryFltr.NotAccounts)
+ q = q.Where("account not in (?)", qryFltr.NotAccounts)
}
if len(qryFltr.Subjects) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".subject in (?)", qryFltr.Subjects)
+ q = q.Where("subject in (?)", qryFltr.Subjects)
}
if len(qryFltr.NotSubjects) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".subject not in (?)", qryFltr.NotSubjects)
+ q = q.Where("subject not in (?)", qryFltr.NotSubjects)
}
- if len(qryFltr.DestPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
+ if len(qryFltr.DestinationPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
qIds := bytes.NewBufferString("(")
- for idx, destPrefix := range qryFltr.DestPrefixes {
+ for idx, destPrefix := range qryFltr.DestinationPrefixes {
if idx != 0 {
qIds.WriteString(" OR")
}
- qIds.WriteString(fmt.Sprintf(" %s.destination LIKE '%s%%'", tblName, destPrefix))
+ qIds.WriteString(fmt.Sprintf(" destination LIKE '%s%%'", destPrefix))
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
- if len(qryFltr.NotDestPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
+ if len(qryFltr.NotDestinationPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
qIds := bytes.NewBufferString("(")
- for idx, destPrefix := range qryFltr.NotDestPrefixes {
+ for idx, destPrefix := range qryFltr.NotDestinationPrefixes {
if idx != 0 {
qIds.WriteString(" AND")
}
- qIds.WriteString(fmt.Sprintf(" %s.destination not LIKE '%%%s%%'", tblName, destPrefix))
+ qIds.WriteString(fmt.Sprintf(" destination not LIKE '%s%%'", destPrefix))
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
if len(qryFltr.Suppliers) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".supplier in (?)", qryFltr.Subjects)
+ q = q.Where("supplier in (?)", qryFltr.Subjects)
}
if len(qryFltr.NotSuppliers) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".supplier not in (?)", qryFltr.NotSubjects)
+ q = q.Where("supplier not in (?)", qryFltr.NotSubjects)
}
if len(qryFltr.DisconnectCauses) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".disconnect_cause in (?)", qryFltr.DisconnectCauses)
+ q = q.Where("disconnect_cause in (?)", qryFltr.DisconnectCauses)
}
if len(qryFltr.NotDisconnectCauses) != 0 {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".disconnect_cause not in (?)", qryFltr.NotDisconnectCauses)
- }
- if len(qryFltr.RatedAccounts) != 0 {
- q = q.Where(utils.TBL_COST_DETAILS+".account in (?)", qryFltr.RatedAccounts)
- }
- if len(qryFltr.NotRatedAccounts) != 0 {
- q = q.Where(utils.TBL_COST_DETAILS+".account not in (?)", qryFltr.NotRatedAccounts)
- }
- if len(qryFltr.RatedSubjects) != 0 {
- q = q.Where(utils.TBL_COST_DETAILS+".subject in (?)", qryFltr.RatedSubjects)
- }
- if len(qryFltr.NotRatedSubjects) != 0 {
- q = q.Where(utils.TBL_COST_DETAILS+".subject not in (?)", qryFltr.NotRatedSubjects)
+ q = q.Where("disconnect_cause not in (?)", qryFltr.NotDisconnectCauses)
}
if len(qryFltr.Costs) != 0 {
- q = q.Where(utils.TBL_RATED_CDRS+".cost in (?)", qryFltr.Costs)
+ q = q.Where(utils.TBL_CDRS+".cost in (?)", qryFltr.Costs)
}
if len(qryFltr.NotCosts) != 0 {
- q = q.Where(utils.TBL_RATED_CDRS+".cost not in (?)", qryFltr.NotCosts)
+ q = q.Where(utils.TBL_CDRS+".cost not in (?)", qryFltr.NotCosts)
}
if len(qryFltr.ExtraFields) != 0 { // Extra fields searches, implemented as contains in extra field
qIds := bytes.NewBufferString("(")
@@ -866,7 +815,7 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
if needOr {
qIds.WriteString(" OR")
}
- qIds.WriteString(fmt.Sprintf(` %s.extra_fields LIKE '%%"%s":"%s"%%'`, utils.TBL_CDRS_EXTRA, field, value))
+ qIds.WriteString(fmt.Sprintf(` extra_fields LIKE '%%"%s":"%s"%%'`, field, value))
needOr = true
}
qIds.WriteString(" )")
@@ -879,117 +828,87 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
if needAnd {
qIds.WriteString(" OR")
}
- qIds.WriteString(fmt.Sprintf(` %s.extra_fields LIKE '%%"%s":"%s"%%'`, utils.TBL_CDRS_EXTRA, field, value))
+ qIds.WriteString(fmt.Sprintf(` extra_fields LIKE '%%"%s":"%s"%%'`, field, value))
needAnd = true
}
qIds.WriteString(" )")
q = q.Where(qIds.String())
}
- if qryFltr.OrderIdStart != 0 { // Keep backwards compatible by testing 0 value
- q = q.Where(utils.TBL_CDRS_PRIMARY+".id >= ?", qryFltr.OrderIdStart)
+ if qryFltr.OrderIDStart != nil { // Keep backwards compatible by testing 0 value
+ q = q.Where(utils.TBL_CDRS+".id >= ?", *qryFltr.OrderIDStart)
}
- if qryFltr.OrderIdEnd != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".id < ?", qryFltr.OrderIdEnd)
+ if qryFltr.OrderIDEnd != nil {
+ q = q.Where(utils.TBL_CDRS+".id < ?", *qryFltr.OrderIDEnd)
}
if qryFltr.SetupTimeStart != nil {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".setup_time >= ?", qryFltr.SetupTimeStart)
+ q = q.Where("setup_time >= ?", qryFltr.SetupTimeStart)
}
if qryFltr.SetupTimeEnd != nil {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".setup_time < ?", qryFltr.SetupTimeEnd)
+ q = q.Where("setup_time < ?", qryFltr.SetupTimeEnd)
}
if qryFltr.AnswerTimeStart != nil && !qryFltr.AnswerTimeStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".answer_time >= ?", qryFltr.AnswerTimeStart)
+ q = q.Where("answer_time >= ?", qryFltr.AnswerTimeStart)
}
if qryFltr.AnswerTimeEnd != nil && !qryFltr.AnswerTimeEnd.IsZero() {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".answer_time < ?", qryFltr.AnswerTimeEnd)
+ q = q.Where("answer_time < ?", qryFltr.AnswerTimeEnd)
}
if qryFltr.CreatedAtStart != nil && !qryFltr.CreatedAtStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".created_at >= ?", qryFltr.CreatedAtStart)
+ q = q.Where("created_at >= ?", qryFltr.CreatedAtStart)
}
if qryFltr.CreatedAtEnd != nil && !qryFltr.CreatedAtEnd.IsZero() {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".created_at < ?", qryFltr.CreatedAtEnd)
+ q = q.Where("created_at < ?", qryFltr.CreatedAtEnd)
}
if qryFltr.UpdatedAtStart != nil && !qryFltr.UpdatedAtStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".updated_at >= ?", qryFltr.UpdatedAtStart)
+ q = q.Where("updated_at >= ?", qryFltr.UpdatedAtStart)
}
if qryFltr.UpdatedAtEnd != nil && !qryFltr.UpdatedAtEnd.IsZero() {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- q = q.Where(tblName+".updated_at < ?", qryFltr.UpdatedAtEnd)
+ q = q.Where("updated_at < ?", qryFltr.UpdatedAtEnd)
}
- if qryFltr.MinUsage != nil {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
+ if len(qryFltr.MinUsage) != 0 {
+ if minUsage, err := utils.ParseDurationWithSecs(qryFltr.MinUsage); err != nil {
+ return nil, 0, err
+ } else {
+ q = q.Where("usage >= ?", minUsage.Seconds())
}
- q = q.Where(tblName+".usage >= ?", qryFltr.MinUsage)
}
- if qryFltr.MaxUsage != nil {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
+ if len(qryFltr.MaxUsage) != 0 {
+ if maxUsage, err := utils.ParseDurationWithSecs(qryFltr.MaxUsage); err != nil {
+ return nil, 0, err
+ } else {
+ q = q.Where("usage < ?", maxUsage.Seconds())
}
- q = q.Where(tblName+".usage < ?", qryFltr.MaxUsage)
+
}
- if qryFltr.MinPdd != nil {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
+ if len(qryFltr.MinPDD) != 0 {
+ if minPDD, err := utils.ParseDurationWithSecs(qryFltr.MinPDD); err != nil {
+ return nil, 0, err
+ } else {
+ q = q.Where("pdd >= ?", minPDD.Seconds())
}
- q = q.Where(tblName+".pdd >= ?", qryFltr.MinPdd)
+
}
- if qryFltr.MaxPdd != nil {
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
+ if len(qryFltr.MaxPDD) != 0 {
+ if maxPDD, err := utils.ParseDurationWithSecs(qryFltr.MaxPDD); err != nil {
+ return nil, 0, err
+ } else {
+ q = q.Where("pdd < ?", maxPDD.Seconds())
}
- q = q.Where(tblName+".pdd < ?", qryFltr.MaxPdd)
}
if qryFltr.MinCost != nil {
if qryFltr.MaxCost == nil {
- q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.MinCost)
+ q = q.Where("cost >= ?", *qryFltr.MinCost)
} else if *qryFltr.MinCost == 0.0 && *qryFltr.MaxCost == -1.0 { // Special case when we want to skip errors
- q = q.Where(fmt.Sprintf("( %s.cost IS NULL OR %s.cost >= 0.0 )", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS))
+ q = q.Where("( cost IS NULL OR cost >= 0.0 )")
} else {
- q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.MinCost)
- q = q.Where(utils.TBL_RATED_CDRS+".cost < ?", *qryFltr.MaxCost)
+ q = q.Where("cost >= ?", *qryFltr.MinCost)
+ q = q.Where("cost < ?", *qryFltr.MaxCost)
}
} else if qryFltr.MaxCost != nil {
if *qryFltr.MaxCost == -1.0 { // Non-rated CDRs
- q = q.Where(utils.TBL_RATED_CDRS + ".cost IS NULL") // Need to include it otherwise all CDRs will be returned
+ q = q.Where("cost IS NULL") // Need to include it otherwise all CDRs will be returned
} else { // Above limited CDRs, since MinCost is empty, make sure we query also NULL cost
- q = q.Where(fmt.Sprintf("( %s.cost IS NULL OR %s.cost < %f )", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, *qryFltr.MaxCost))
+ q = q.Where(fmt.Sprintf("( cost IS NULL OR cost < %f )", *qryFltr.MaxCost))
}
}
if qryFltr.Paginator.Limit != nil {
@@ -1008,402 +927,73 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
}
// Execute query
- rows, err := q.Rows()
- if err != nil {
- return nil, 0, err
- }
- for rows.Next() {
- var cgrid, tor, accid, cdrhost, cdrsrc, reqtype, direction, tenant, category, account, subject, destination, runid, ccTor,
- ccDirection, ccTenant, ccCategory, ccAccount, ccSubject, ccDestination, ccSupplier, ccDisconnectCause sql.NullString
- var extraFields, ccTimespansBytes []byte
- var setupTime, answerTime mysql.NullTime
- var orderid int64
- var usage, pdd, cost, ccCost sql.NullFloat64
+ results := make([]*TBLCDRs, 0)
+ q.Find(&results)
+
+ for _, result := range results {
var extraFieldsMp map[string]string
- var ccTimespans TimeSpans
- if err := rows.Scan(&cgrid, &orderid, &tor, &accid, &cdrhost, &cdrsrc, &reqtype, &direction, &tenant, &category, &account, &subject, &destination,
- &setupTime, &answerTime, &usage, &pdd, &ccSupplier, &ccDisconnectCause,
- &extraFields, &runid, &cost, &ccTor, &ccDirection, &ccTenant, &ccCategory, &ccAccount, &ccSubject, &ccDestination, &ccCost, &ccTimespansBytes); err != nil {
- return nil, 0, err
+ if err := json.Unmarshal([]byte(result.ExtraFields), &extraFieldsMp); err != nil {
+ return nil, 0, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %v, error: %s", result.Cgrid, result.RunID, err.Error())
}
- if len(extraFields) != 0 {
- if err := json.Unmarshal(extraFields, &extraFieldsMp); err != nil {
- return nil, 0, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %v, error: %s", cgrid.String, runid.String, err.Error())
+ var callCost CallCost
+ if len(result.CostDetails) != 0 {
+ if err := json.Unmarshal([]byte(result.CostDetails), &callCost); err != nil {
+ return nil, 0, fmt.Errorf("JSON unmarshal callcost error for cgrid: %s, runid: %v, error: %s", result.Cgrid, result.RunID, err.Error())
}
}
- if len(ccTimespansBytes) != 0 {
- if err := json.Unmarshal(ccTimespansBytes, &ccTimespans); err != nil {
- return nil, 0, fmt.Errorf("JSON unmarshal callcost error for cgrid: %s, runid: %v, error: %s", cgrid.String, runid.String, err.Error())
- }
- }
- usageDur, _ := time.ParseDuration(strconv.FormatFloat(usage.Float64, 'f', -1, 64) + "s")
- pddDur, _ := time.ParseDuration(strconv.FormatFloat(pdd.Float64, 'f', -1, 64) + "s")
- storCdr := &StoredCdr{
- CgrId: cgrid.String, OrderId: orderid, TOR: tor.String, AccId: accid.String, CdrHost: cdrhost.String, CdrSource: cdrsrc.String, ReqType: reqtype.String,
- Direction: direction.String, Tenant: tenant.String,
- Category: category.String, Account: account.String, Subject: subject.String, Destination: destination.String,
- SetupTime: setupTime.Time, AnswerTime: answerTime.Time, Usage: usageDur, Pdd: pddDur, Supplier: ccSupplier.String, DisconnectCause: ccDisconnectCause.String,
- ExtraFields: extraFieldsMp, MediationRunId: runid.String, RatedAccount: ccAccount.String, RatedSubject: ccSubject.String, Cost: cost.Float64,
- }
- if ccTimespans != nil {
- storCdr.CostDetails = &CallCost{Direction: ccDirection.String, Category: ccCategory.String, Tenant: ccTenant.String, Subject: ccSubject.String, Account: ccAccount.String, Destination: ccDestination.String, TOR: ccTor.String,
- Cost: ccCost.Float64, Timespans: ccTimespans}
- }
- if !cost.Valid { //There was no cost provided, will fakely insert 0 if we do not handle it and reflect on re-rating
- storCdr.Cost = -1
+ usageDur, _ := time.ParseDuration(strconv.FormatFloat(result.Usage, 'f', -1, 64) + "s")
+ pddDur, _ := time.ParseDuration(strconv.FormatFloat(result.Pdd, 'f', -1, 64) + "s")
+ storCdr := &CDR{
+ CGRID: result.Cgrid,
+ RunID: result.RunID,
+ OrderID: result.ID,
+ OriginHost: result.OriginHost,
+ Source: result.Source,
+ OriginID: result.OriginID,
+ ToR: result.Tor,
+ RequestType: result.RequestType,
+ Direction: result.Direction,
+ Tenant: result.Tenant,
+ Category: result.Category,
+ Account: result.Account,
+ Subject: result.Subject,
+ Destination: result.Destination,
+ SetupTime: result.SetupTime,
+ PDD: pddDur,
+ AnswerTime: result.AnswerTime,
+ Usage: usageDur,
+ Supplier: result.Supplier,
+ DisconnectCause: result.DisconnectCause,
+ ExtraFields: extraFieldsMp,
+ CostSource: result.CostSource,
+ Cost: result.Cost,
+ CostDetails: &callCost,
+ ExtraInfo: result.ExtraInfo,
}
cdrs = append(cdrs, storCdr)
}
return cdrs, 0, nil
}
-/*func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr, int64, error) {
- var cdrs []*StoredCdr
- // Select string
- var selectStr string
- if qryFltr.FilterOnRated { // We use different tables to query account data in case of derived
- selectTmpl := template.Must(template.New("select").Parse("{{.Pr}}.cgrid,{{.Pr}}.id,{{.Pr}}.tor,{{.Pr}}.accid,{{.Pr}}.cdrhost,{{.Pr}}.cdrsource,{{.Rc}}.reqtype,{{.Rc}}.direction,{{.Rc}}.tenant,{{.Rc}}.category,{{.Rc}}.account,{{.Rc}}.subject,{{.Rc}}.destination,{{.Rc}}.setup_time,{{.Rc}}.answer_time,{{.Rc}}.usage,{{.Rc}}.pdd,{{.Rc}}.supplier,{{.Rc}}.disconnect_cause,{{.Ex}}.extra_fields,{{.Rc}}.runid,{{.Rc}}.cost,{{.Cd}}.tor,{{.Cd}}.direction,{{.Cd}}.tenant,{{.Cd}}.category,{{.Cd}}.account,{{.Cd}}.subject,{{.Cd}}.destination,{{.Cd}}.cost,{{.Cd}}.timespans"))
- var selectBuf bytes.Buffer
- selectTmpl.Execute(&selectBuf, &struct {
- Pr string
- Ex string
- Rc string
- Cd string
- }{utils.TBL_CDRS_PRIMARY,
- utils.TBL_CDRS_EXTRA,
- utils.TBL_RATED_CDRS,
- utils.TBL_COST_DETAILS})
- selectStr = selectBuf.String()
- } else {
- selectTmpl := template.Must(template.New("select").Parse("{{.Pr}}.cgrid,{{.Pr}}.id,{{.Pr}}.tor,{{.Pr}}.accid,{{.Pr}}.cdrhost,{{.Pr}}.cdrsource,{{.Pr}}.reqtype,{{.Pr}}.direction,{{.Pr}}.tenant,{{.Pr}}.category,{{.Pr}}.account,{{.Pr}}.subject,{{.Pr}}.destination,{{.Pr}}.setup_time,{{.Pr}}.answer_time,{{.Pr}}.usage,{{.Pr}}.pdd,{{.Pr}}.supplier,{{.Pr}}.disconnect_cause,{{.Ex}}.extra_fields,{{.Rc}}.runid,{{.Rc}}.cost,{{.Cd}}.tor,{{.Cd}}.direction,{{.Cd}}.tenant,{{.Cd}}.category,{{.Cd}}.account,{{.Cd}}.subject,{{.Cd}}.destination,{{.Cd}}.cost,{{.Cd}}.timespans"))
- var selectBuf bytes.Buffer
- selectTmpl.Execute(&selectBuf, &struct {
- Pr string
- Ex string
- Rc string
- Cd string
- }{utils.TBL_CDRS_PRIMARY,
- utils.TBL_CDRS_EXTRA,
- utils.TBL_RATED_CDRS,
- utils.TBL_COST_DETAILS})
- selectStr = selectBuf.String()
- }
- // Join string
- selectTmpl := template.Must(template.New("join").Parse("LEFT JOIN {{.Ex}} ON {{.Pr}}.cgrid={{.Ex}}.cgrid LEFT JOIN {{.Rc}} ON {{.Pr}}.cgrid={{.Rc}}.cgrid LEFT JOIN {{.Cd}} ON {{.Rc}}.cgrid={{.Cd}}.cgrid AND {{.Rc}}.runid={{.Cd}}.runid"))
- var joinBuf bytes.Buffer
- selectTmpl.Execute(&joinBuf, &struct {
- Pr string
- Ex string
- Rc string
- Cd string
- }{utils.TBL_CDRS_PRIMARY,
- utils.TBL_CDRS_EXTRA,
- utils.TBL_RATED_CDRS,
- utils.TBL_COST_DETAILS})
- joinStr := joinBuf.String()
- q := self.db.Table(utils.TBL_CDRS_PRIMARY).Select(selectStr).Joins(joinStr)
- if qryFltr.Unscoped {
- q = q.Unscoped()
- } else {
- // Query filter
- for _, tblName := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS} {
- q = q.Where(fmt.Sprintf("(%s.deleted_at IS NULL OR %s.deleted_at <= '0001-01-02')", tblName, tblName)) // Soft deletes
- }
- }
- tblName := utils.TBL_CDRS_PRIMARY
- if qryFltr.FilterOnRated {
- tblName = utils.TBL_RATED_CDRS
- }
- // Add filters, use in to replace the high number of ORs
- if len(qryFltr.CgrIds) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cgrid in (?)", qryFltr.CgrIds)
- }
- if len(qryFltr.NotCgrIds) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cgrid not in (?)", qryFltr.NotCgrIds)
- }
- if len(qryFltr.RunIds) != 0 {
- q = q.Where(utils.TBL_RATED_CDRS+".runid in (?)", qryFltr.RunIds)
- }
- if len(qryFltr.NotRunIds) != 0 {
- q = q.Where(utils.TBL_RATED_CDRS+".runid not in (?)", qryFltr.NotRunIds)
- }
- if len(qryFltr.Tors) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".tor in (?)", qryFltr.Tors)
- }
- if len(qryFltr.NotTors) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".tor not in (?)", qryFltr.NotTors)
- }
- if len(qryFltr.CdrHosts) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrhost in (?)", qryFltr.CdrHosts)
- }
- if len(qryFltr.NotCdrHosts) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrhost not in (?)", qryFltr.NotCdrHosts)
- }
- if len(qryFltr.CdrSources) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrsource in (?)", qryFltr.CdrSources)
- }
- if len(qryFltr.NotCdrSources) != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".cdrsource not in (?)", qryFltr.NotCdrSources)
- }
- if len(qryFltr.ReqTypes) != 0 {
- q = q.Where(tblName+".reqtype in (?)", qryFltr.ReqTypes)
- }
- if len(qryFltr.NotReqTypes) != 0 {
- q = q.Where(tblName+".reqtype not in (?)", qryFltr.NotReqTypes)
- }
- if len(qryFltr.Directions) != 0 {
- q = q.Where(tblName+".direction in (?)", qryFltr.Directions)
- }
- if len(qryFltr.NotDirections) != 0 {
- q = q.Where(tblName+".direction not in (?)", qryFltr.NotDirections)
- }
- if len(qryFltr.Tenants) != 0 {
- q = q.Where(tblName+".tenant in (?)", qryFltr.Tenants)
- }
- if len(qryFltr.NotTenants) != 0 {
- q = q.Where(tblName+".tenant not in (?)", qryFltr.NotTenants)
- }
- if len(qryFltr.Categories) != 0 {
- q = q.Where(tblName+".category in (?)", qryFltr.Categories)
- }
- if len(qryFltr.NotCategories) != 0 {
- q = q.Where(tblName+".category not in (?)", qryFltr.NotCategories)
- }
- if len(qryFltr.Accounts) != 0 {
- q = q.Where(tblName+".account in (?)", qryFltr.Accounts)
- }
- if len(qryFltr.NotAccounts) != 0 {
- q = q.Where(tblName+".account not in (?)", qryFltr.NotAccounts)
- }
- if len(qryFltr.Subjects) != 0 {
- q = q.Where(tblName+".subject in (?)", qryFltr.Subjects)
- }
- if len(qryFltr.NotSubjects) != 0 {
- q = q.Where(tblName+".subject not in (?)", qryFltr.NotSubjects)
- }
- if len(qryFltr.DestPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
- qIds := bytes.NewBufferString("(")
- for idx, destPrefix := range qryFltr.DestPrefixes {
- if idx != 0 {
- qIds.WriteString(" OR")
- }
- qIds.WriteString(fmt.Sprintf(" %s.destination LIKE '%s%%'", tblName, destPrefix))
- }
- qIds.WriteString(" )")
- q = q.Where(qIds.String())
- }
- if len(qryFltr.NotDestPrefixes) != 0 { // A bit ugly but still more readable than scopes provided by gorm
- qIds := bytes.NewBufferString("(")
- for idx, destPrefix := range qryFltr.NotDestPrefixes {
- if idx != 0 {
- qIds.WriteString(" AND")
- }
- qIds.WriteString(fmt.Sprintf(" %s.destination not LIKE '%%%s%%'", tblName, destPrefix))
- }
- qIds.WriteString(" )")
- q = q.Where(qIds.String())
- }
- if len(qryFltr.Suppliers) != 0 {
- q = q.Where(tblName+".supplier in (?)", qryFltr.Subjects)
- }
- if len(qryFltr.NotSuppliers) != 0 {
- q = q.Where(tblName+".supplier not in (?)", qryFltr.NotSubjects)
- }
- if len(qryFltr.DisconnectCauses) != 0 {
- q = q.Where(tblName+".disconnect_cause in (?)", qryFltr.DisconnectCauses)
- }
- if len(qryFltr.NotDisconnectCauses) != 0 {
- q = q.Where(tblName+".disconnect_cause not in (?)", qryFltr.NotDisconnectCauses)
- }
- if len(qryFltr.RatedAccounts) != 0 {
- q = q.Where(utils.TBL_COST_DETAILS+".account in (?)", qryFltr.RatedAccounts)
- }
- if len(qryFltr.NotRatedAccounts) != 0 {
- q = q.Where(utils.TBL_COST_DETAILS+".account not in (?)", qryFltr.NotRatedAccounts)
- }
- if len(qryFltr.RatedSubjects) != 0 {
- q = q.Where(utils.TBL_COST_DETAILS+".subject in (?)", qryFltr.RatedSubjects)
- }
- if len(qryFltr.NotRatedSubjects) != 0 {
- q = q.Where(utils.TBL_COST_DETAILS+".subject not in (?)", qryFltr.NotRatedSubjects)
- }
- if len(qryFltr.Costs) != 0 {
- q = q.Where(utils.TBL_RATED_CDRS+".cost in (?)", qryFltr.Costs)
- }
- if len(qryFltr.NotCosts) != 0 {
- q = q.Where(utils.TBL_RATED_CDRS+".cost not in (?)", qryFltr.NotCosts)
- }
- if len(qryFltr.ExtraFields) != 0 { // Extra fields searches, implemented as contains in extra field
- qIds := bytes.NewBufferString("(")
- needOr := false
- for field, value := range qryFltr.ExtraFields {
- if needOr {
- qIds.WriteString(" OR")
- }
- qIds.WriteString(fmt.Sprintf(` %s.extra_fields LIKE '%%"%s":"%s"%%'`, utils.TBL_CDRS_EXTRA, field, value))
- needOr = true
- }
- qIds.WriteString(" )")
- q = q.Where(qIds.String())
- }
- if len(qryFltr.NotExtraFields) != 0 { // Extra fields searches, implemented as contains in extra field
- qIds := bytes.NewBufferString("(")
- needAnd := false
- for field, value := range qryFltr.NotExtraFields {
- if needAnd {
- qIds.WriteString(" OR")
- }
- qIds.WriteString(fmt.Sprintf(` %s.extra_fields LIKE '%%"%s":"%s"%%'`, utils.TBL_CDRS_EXTRA, field, value))
- needAnd = true
- }
- qIds.WriteString(" )")
- q = q.Where(qIds.String())
- }
- if qryFltr.OrderIdStart != 0 { // Keep backwards compatible by testing 0 value
- q = q.Where(utils.TBL_CDRS_PRIMARY+".id >= ?", qryFltr.OrderIdStart)
- }
- if qryFltr.OrderIdEnd != 0 {
- q = q.Where(utils.TBL_CDRS_PRIMARY+".id < ?", qryFltr.OrderIdEnd)
- }
- if qryFltr.SetupTimeStart != nil {
- q = q.Where(tblName+".setup_time >= ?", qryFltr.SetupTimeStart)
- }
- if qryFltr.SetupTimeEnd != nil {
- q = q.Where(tblName+".setup_time < ?", qryFltr.SetupTimeEnd)
- }
- if qryFltr.AnswerTimeStart != nil && !qryFltr.AnswerTimeStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
- q = q.Where(tblName+".answer_time >= ?", qryFltr.AnswerTimeStart)
- }
- if qryFltr.AnswerTimeEnd != nil && !qryFltr.AnswerTimeEnd.IsZero() {
- q = q.Where(tblName+".answer_time < ?", qryFltr.AnswerTimeEnd)
- }
- if qryFltr.CreatedAtStart != nil && !qryFltr.CreatedAtStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
- q = q.Where(tblName+".created_at >= ?", qryFltr.CreatedAtStart)
- }
- if qryFltr.CreatedAtEnd != nil && !qryFltr.CreatedAtEnd.IsZero() {
- q = q.Where(tblName+".created_at < ?", qryFltr.CreatedAtEnd)
- }
- if qryFltr.UpdatedAtStart != nil && !qryFltr.UpdatedAtStart.IsZero() { // With IsZero we keep backwards compatible with ApierV1
- q = q.Where(tblName+".updated_at >= ?", qryFltr.UpdatedAtStart)
- }
- if qryFltr.UpdatedAtEnd != nil && !qryFltr.UpdatedAtEnd.IsZero() {
- q = q.Where(tblName+".updated_at < ?", qryFltr.UpdatedAtEnd)
- }
- if qryFltr.MinUsage != nil {
- q = q.Where(tblName+".usage >= ?", qryFltr.MinUsage)
- }
- if qryFltr.MaxUsage != nil {
- q = q.Where(tblName+".usage < ?", qryFltr.MaxUsage)
- }
- if qryFltr.MinPdd != nil {
- q = q.Where(tblName+".pdd >= ?", qryFltr.MinPdd)
- }
- if qryFltr.MaxPdd != nil {
- q = q.Where(tblName+".pdd < ?", qryFltr.MaxPdd)
- }
-
- if qryFltr.MinCost != nil {
- if qryFltr.MaxCost == nil {
- q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.MinCost)
- } else if *qryFltr.MinCost == 0.0 && *qryFltr.MaxCost == -1.0 { // Special case when we want to skip errors
- q = q.Where(fmt.Sprintf("( %s.cost IS NULL OR %s.cost >= 0.0 )", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS))
- } else {
- q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.MinCost)
- q = q.Where(utils.TBL_RATED_CDRS+".cost < ?", *qryFltr.MaxCost)
- }
- } else if qryFltr.MaxCost != nil {
- if *qryFltr.MaxCost == -1.0 { // Non-rated CDRs
- q = q.Where(utils.TBL_RATED_CDRS + ".cost IS NULL") // Need to include it otherwise all CDRs will be returned
- } else { // Above limited CDRs, since MinCost is empty, make sure we query also NULL cost
- q = q.Where(fmt.Sprintf("( %s.cost IS NULL OR %s.cost < %f )", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS, *qryFltr.MaxCost))
- }
- }
- if qryFltr.Paginator.Limit != nil {
- q = q.Limit(*qryFltr.Paginator.Limit)
- }
- if qryFltr.Paginator.Offset != nil {
- q = q.Offset(*qryFltr.Paginator.Offset)
- }
- if qryFltr.Count {
- var cnt int64
- if err := q.Count(&cnt).Error; err != nil {
- //if err := q.Debug().Count(&cnt).Error; err != nil {
- return nil, 0, err
- }
- return nil, cnt, nil
- }
-
- // Execute query
- rows, err := q.Rows()
- if err != nil {
- return nil, 0, err
- }
- for rows.Next() {
- var cgrid, tor, accid, cdrhost, cdrsrc, reqtype, direction, tenant, category, account, subject, destination, runid, ccTor,
- ccDirection, ccTenant, ccCategory, ccAccount, ccSubject, ccDestination, ccSupplier, ccDisconnectCause sql.NullString
- var extraFields, ccTimespansBytes []byte
- var setupTime, answerTime mysql.NullTime
- var orderid int64
- var usage, pdd, cost, ccCost sql.NullFloat64
- var extraFieldsMp map[string]string
- var ccTimespans TimeSpans
- if err := rows.Scan(&cgrid, &orderid, &tor, &accid, &cdrhost, &cdrsrc, &reqtype, &direction, &tenant, &category, &account, &subject, &destination,
- &setupTime, &answerTime, &usage, &pdd, &ccSupplier, &ccDisconnectCause,
- &extraFields, &runid, &cost, &ccTor, &ccDirection, &ccTenant, &ccCategory, &ccAccount, &ccSubject, &ccDestination, &ccCost, &ccTimespansBytes); err != nil {
- return nil, 0, err
- }
- if len(extraFields) != 0 {
- if err := json.Unmarshal(extraFields, &extraFieldsMp); err != nil {
- return nil, 0, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %v, error: %s", cgrid.String, runid.String, err.Error())
- }
- }
- if len(ccTimespansBytes) != 0 {
- if err := json.Unmarshal(ccTimespansBytes, &ccTimespans); err != nil {
- return nil, 0, fmt.Errorf("JSON unmarshal callcost error for cgrid: %s, runid: %v, error: %s", cgrid.String, runid.String, err.Error())
- }
- }
- usageDur, _ := time.ParseDuration(strconv.FormatFloat(usage.Float64, 'f', -1, 64) + "s")
- pddDur, _ := time.ParseDuration(strconv.FormatFloat(pdd.Float64, 'f', -1, 64) + "s")
- storCdr := &StoredCdr{
- CgrId: cgrid.String, OrderId: orderid, TOR: tor.String, AccId: accid.String, CdrHost: cdrhost.String, CdrSource: cdrsrc.String, ReqType: reqtype.String,
- Direction: direction.String, Tenant: tenant.String,
- Category: category.String, Account: account.String, Subject: subject.String, Destination: destination.String,
- SetupTime: setupTime.Time, AnswerTime: answerTime.Time, Usage: usageDur, Pdd: pddDur, Supplier: ccSupplier.String, DisconnectCause: ccDisconnectCause.String,
- ExtraFields: extraFieldsMp, MediationRunId: runid.String, RatedAccount: ccAccount.String, RatedSubject: ccSubject.String, Cost: cost.Float64,
- }
- if ccTimespans != nil {
- storCdr.CostDetails = &CallCost{Direction: ccDirection.String, Category: ccCategory.String, Tenant: ccTenant.String, Subject: ccSubject.String, Account: ccAccount.String, Destination: ccDestination.String, TOR: ccTor.String,
- Cost: ccCost.Float64, Timespans: ccTimespans}
- }
- if !cost.Valid { //There was no cost provided, will fakely insert 0 if we do not handle it and reflect on re-rating
- storCdr.Cost = -1
- }
- cdrs = append(cdrs, storCdr)
- }
- return cdrs, 0, nil
-}
-*/
-
// Remove CDR data out of all CDR tables based on their cgrid
-func (self *SQLStorage) RemStoredCdrs(cgrIds []string) error {
+func (self *SQLStorage) RemCDRs(cgrIds []string) error {
if len(cgrIds) == 0 {
return nil
}
tx := self.db.Begin()
- for _, tblName := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_COST_DETAILS, utils.TBL_RATED_CDRS} {
- txI := tx.Table(tblName)
- for idx, cgrId := range cgrIds {
- if idx == 0 {
- txI = txI.Where("cgrid = ?", cgrId)
- } else {
- txI = txI.Or("cgrid = ?", cgrId)
- }
- }
- if err := txI.Update("deleted_at", time.Now()).Error; err != nil {
- tx.Rollback()
- return err
+
+ txI := tx.Table(utils.TBL_CDRS)
+ for idx, cgrId := range cgrIds {
+ if idx == 0 {
+ txI = txI.Where("cgrid = ?", cgrId)
+ } else {
+ txI = txI.Or("cgrid = ?", cgrId)
}
}
+ if err := txI.Update("deleted_at", time.Now()).Error; err != nil {
+ tx.Rollback()
+ return err
+ }
tx.Commit()
return nil
}
diff --git a/engine/storage_utils.go b/engine/storage_utils.go
index 934e99378..5d550cee9 100644
--- a/engine/storage_utils.go
+++ b/engine/storage_utils.go
@@ -145,3 +145,11 @@ func ConfigureCdrStorage(db_type, host, port, name, user, pass string, maxConn,
}
return d, nil
}
+
+// Stores one Cost coming from SM
+type SMCost struct {
+ CGRID string
+ RunID string
+ CostSource string
+ CostDetails *CallCost
+}
diff --git a/engine/suretax.go b/engine/suretax.go
index cbf7d3666..b112b3fac 100644
--- a/engine/suretax.go
+++ b/engine/suretax.go
@@ -36,7 +36,7 @@ import (
var sureTaxClient *http.Client // Cache the client here if in use
// Init a new request to be sent out to SureTax
-func NewSureTaxRequest(cdr *StoredCdr, stCfg *config.SureTaxCfg) (*SureTaxRequest, error) {
+func NewSureTaxRequest(cdr *CDR, stCfg *config.SureTaxCfg) (*SureTaxRequest, error) {
if stCfg == nil {
return nil, errors.New("Invalid SureTax config.")
}
@@ -176,7 +176,7 @@ type STTaxItem struct {
TaxAmount string // Tax Amount
}
-func SureTaxProcessCdr(cdr *StoredCdr) error {
+func SureTaxProcessCdr(cdr *CDR) error {
stCfg := config.CgrConfig().SureTaxCfg()
if stCfg == nil {
return errors.New("Invalid SureTax configuration")
diff --git a/engine/suretax_test.go b/engine/suretax_test.go
index c6f897814..8e9fce485 100644
--- a/engine/suretax_test.go
+++ b/engine/suretax_test.go
@@ -29,12 +29,13 @@ import (
)
func TestNewSureTaxRequest(t *testing.T) {
- cgrId := utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String())
- cdr := &StoredCdr{CgrId: cgrId, OrderId: 123, TOR: utils.VOICE,
- AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
+ CGRID := utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String())
+ cdr := &CDR{CGRID: CGRID, OrderID: 123, ToR: utils.VOICE,
+ OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: "*out",
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Supplier: "SUPPL1",
- SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
- Usage: time.Duration(12) * time.Second, Pdd: time.Duration(7) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, RatedAccount: "dan", RatedSubject: "dans", Rated: true,
+ SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.DEFAULT_RUNID,
+ Usage: time.Duration(12) * time.Second, PDD: time.Duration(7) * time.Second,
+ ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, Rated: true,
}
cfg, _ := config.NewDefaultCGRConfig()
stCfg := cfg.SureTaxCfg()
@@ -48,7 +49,7 @@ func TestNewSureTaxRequest(t *testing.T) {
DataMonth: "11",
TotalRevenue: 1.01,
ReturnFileCode: "0",
- ClientTracking: cgrId,
+ ClientTracking: CGRID,
ResponseGroup: "03",
ResponseType: "D4",
ItemList: []*STRequestItem{
diff --git a/engine/tp_reader.go b/engine/tp_reader.go
index 8c1467e0c..5f22f0a2a 100644
--- a/engine/tp_reader.go
+++ b/engine/tp_reader.go
@@ -922,7 +922,7 @@ func (tpr *TpReader) LoadDerivedChargersFiltered(filter *TpDerivedCharger, save
tag := tpDcs.GetDerivedChargersKey()
if _, hasIt := tpr.derivedChargers[tag]; !hasIt {
tpr.derivedChargers[tag] = &utils.DerivedChargers{
- DestinationIds: make(utils.StringMap),
+ DestinationIDs: make(utils.StringMap),
Chargers: make([]*utils.DerivedCharger, 0),
} // Load object map since we use this method also from LoadDerivedChargers
}
@@ -933,7 +933,7 @@ func (tpr *TpReader) LoadDerivedChargersFiltered(filter *TpDerivedCharger, save
if err != nil {
return err
}
- tpr.derivedChargers[tag].DestinationIds.Copy(utils.ParseStringMap(tpDcs.DestinationIds))
+ tpr.derivedChargers[tag].DestinationIDs.Copy(utils.ParseStringMap(tpDcs.DestinationIds))
tpr.derivedChargers[tag].Chargers = append(tpr.derivedChargers[tag].Chargers, dc)
}
}
diff --git a/engine/units_counter_test.go b/engine/units_counter_test.go
index ef8a52d3a..be8b3a49c 100644
--- a/engine/units_counter_test.go
+++ b/engine/units_counter_test.go
@@ -245,3 +245,87 @@ func TestUnitCountersCountAllVoiceDestinationEvent(t *testing.T) {
t.Errorf("Error adding unit counters: %v", len(a.UnitCounters))
}
}
+
+/*
+func TestUnitCountersResetCounterById(t *testing.T) {
+ a := &Account{
+ ActionTriggers: ActionTriggers{
+ &ActionTrigger{
+ ID: "TestTR1",
+ ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ ID: "TestTR11",
+ ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ ID: "TestTR2",
+ ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ ID: "TestTR3",
+ ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ ID: "TestTR4",
+ ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ ID: "TestTR5",
+ ThresholdType: utils.TRIGGER_MAX_BALANCE,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ },
+ }
+ a.InitCounters()
+ a.UnitCounters.addUnits(10, utils.MONETARY, &CallCost{}, nil)
+
+ if len(a.UnitCounters) != 4 ||
+ len(a.UnitCounters[0].Balances) != 2 ||
+ a.UnitCounters[0].Balances[0].Value != 10 ||
+ a.UnitCounters[0].Balances[1].Value != 10 {
+ for _, uc := range a.UnitCounters {
+ t.Logf("UC: %+v", uc)
+ for _, b := range uc.Balances {
+ t.Logf("B: %+v", b)
+ }
+ }
+ t.Errorf("Error Initializing adding unit counters: %v", len(a.UnitCounters))
+ }
+ a.UnitCounters.resetCounters(&Action{
+ BalanceType: utils.MONETARY,
+ Balance: &Balance{
+ Id: "TestTR11",
+ },
+ })
+ if len(a.UnitCounters) != 4 ||
+ len(a.UnitCounters[0].Balances) != 2 ||
+ a.UnitCounters[0].Balances[0].Value != 10 ||
+ a.UnitCounters[0].Balances[1].Value != 0 {
+ for _, uc := range a.UnitCounters {
+ t.Logf("UC: %+v", uc)
+ for _, b := range uc.Balances {
+ t.Logf("B: %+v", b)
+ }
+ }
+ t.Errorf("Error Initializing adding unit counters: %v", len(a.UnitCounters))
+ }
+}
+*/
diff --git a/engine/users_test.go b/engine/users_test.go
index a9e640351..a22401014 100644
--- a/engine/users_test.go
+++ b/engine/users_test.go
@@ -582,17 +582,17 @@ func TestUsersAddUpdateRemoveIndexes(t *testing.T) {
func TestUsersUsageRecordGetLoadUserProfile(t *testing.T) {
userService = &UserMap{
table: map[string]map[string]string{
- "test:user": map[string]string{"TOR": "01", "ReqType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"},
- ":user": map[string]string{"TOR": "02", "ReqType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"},
- "test:": map[string]string{"TOR": "03", "ReqType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"},
- "test1:user1": map[string]string{"TOR": "04", "ReqType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13"},
+ "test:user": map[string]string{utils.TOR: "01", "RequestType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"},
+ ":user": map[string]string{utils.TOR: "02", "RequestType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"},
+ "test:": map[string]string{utils.TOR: "03", "RequestType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"},
+ "test1:user1": map[string]string{utils.TOR: "04", "RequestType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13"},
},
index: make(map[string]map[string]bool),
}
ur := &UsageRecord{
- TOR: utils.USERS,
- ReqType: utils.USERS,
+ ToR: utils.USERS,
+ RequestType: utils.USERS,
Direction: "*out",
Tenant: "",
Category: "call",
@@ -609,8 +609,8 @@ func TestUsersUsageRecordGetLoadUserProfile(t *testing.T) {
t.Error("Error loading user profile: ", err)
}
expected := &UsageRecord{
- TOR: "04",
- ReqType: "4",
+ ToR: "04",
+ RequestType: "4",
Direction: "*out",
Tenant: "",
Category: "call",
@@ -626,20 +626,20 @@ func TestUsersUsageRecordGetLoadUserProfile(t *testing.T) {
}
}
-func TestUsersExternalCdrGetLoadUserProfileExtraFields(t *testing.T) {
+func TestUsersExternalCDRGetLoadUserProfileExtraFields(t *testing.T) {
userService = &UserMap{
table: map[string]map[string]string{
- "test:user": map[string]string{"TOR": "01", "ReqType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"},
- ":user": map[string]string{"TOR": "02", "ReqType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"},
- "test:": map[string]string{"TOR": "03", "ReqType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"},
- "test1:user1": map[string]string{"TOR": "04", "ReqType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13", "Test": "1"},
+ "test:user": map[string]string{utils.TOR: "01", "RequestType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"},
+ ":user": map[string]string{utils.TOR: "02", "RequestType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"},
+ "test:": map[string]string{utils.TOR: "03", "RequestType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"},
+ "test1:user1": map[string]string{utils.TOR: "04", "RequestType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13", "Test": "1"},
},
index: make(map[string]map[string]bool),
}
- ur := &ExternalCdr{
- TOR: utils.USERS,
- ReqType: utils.USERS,
+ ur := &ExternalCDR{
+ ToR: utils.USERS,
+ RequestType: utils.USERS,
Direction: "*out",
Tenant: "",
Category: "call",
@@ -658,9 +658,9 @@ func TestUsersExternalCdrGetLoadUserProfileExtraFields(t *testing.T) {
if err != nil {
t.Error("Error loading user profile: ", err)
}
- expected := &ExternalCdr{
- TOR: "04",
- ReqType: "4",
+ expected := &ExternalCDR{
+ ToR: "04",
+ RequestType: "4",
Direction: "*out",
Tenant: "",
Category: "call",
@@ -679,20 +679,20 @@ func TestUsersExternalCdrGetLoadUserProfileExtraFields(t *testing.T) {
}
}
-func TestUsersExternalCdrGetLoadUserProfileExtraFieldsNotFound(t *testing.T) {
+func TestUsersExternalCDRGetLoadUserProfileExtraFieldsNotFound(t *testing.T) {
userService = &UserMap{
table: map[string]map[string]string{
- "test:user": map[string]string{"TOR": "01", "ReqType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"},
- ":user": map[string]string{"TOR": "02", "ReqType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"},
- "test:": map[string]string{"TOR": "03", "ReqType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"},
- "test1:user1": map[string]string{"TOR": "04", "ReqType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13", "Test": "2"},
+ "test:user": map[string]string{utils.TOR: "01", "RequestType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"},
+ ":user": map[string]string{utils.TOR: "02", "RequestType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"},
+ "test:": map[string]string{utils.TOR: "03", "RequestType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"},
+ "test1:user1": map[string]string{utils.TOR: "04", "RequestType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13", "Test": "2"},
},
index: make(map[string]map[string]bool),
}
- ur := &ExternalCdr{
- TOR: utils.USERS,
- ReqType: utils.USERS,
+ ur := &ExternalCDR{
+ ToR: utils.USERS,
+ RequestType: utils.USERS,
Direction: "*out",
Tenant: "",
Category: "call",
@@ -713,20 +713,20 @@ func TestUsersExternalCdrGetLoadUserProfileExtraFieldsNotFound(t *testing.T) {
}
}
-func TestUsersExternalCdrGetLoadUserProfileExtraFieldsSet(t *testing.T) {
+func TestUsersExternalCDRGetLoadUserProfileExtraFieldsSet(t *testing.T) {
userService = &UserMap{
table: map[string]map[string]string{
- "test:user": map[string]string{"TOR": "01", "ReqType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"},
- ":user": map[string]string{"TOR": "02", "ReqType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"},
- "test:": map[string]string{"TOR": "03", "ReqType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"},
- "test1:user1": map[string]string{"TOR": "04", "ReqType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13", "Test": "1", "Best": "BestValue"},
+ "test:user": map[string]string{utils.TOR: "01", "RequestType": "1", "Direction": "*out", "Category": "c1", "Account": "dan", "Subject": "0723", "Destination": "+401", "SetupTime": "s1", "AnswerTime": "t1", "Usage": "10"},
+ ":user": map[string]string{utils.TOR: "02", "RequestType": "2", "Direction": "*out", "Category": "c2", "Account": "ivo", "Subject": "0724", "Destination": "+402", "SetupTime": "s2", "AnswerTime": "t2", "Usage": "11"},
+ "test:": map[string]string{utils.TOR: "03", "RequestType": "3", "Direction": "*out", "Category": "c3", "Account": "elloy", "Subject": "0725", "Destination": "+403", "SetupTime": "s3", "AnswerTime": "t3", "Usage": "12"},
+ "test1:user1": map[string]string{utils.TOR: "04", "RequestType": "4", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726", "Destination": "+404", "SetupTime": "s4", "AnswerTime": "t4", "Usage": "13", "Test": "1", "Best": "BestValue"},
},
index: make(map[string]map[string]bool),
}
- ur := &ExternalCdr{
- TOR: utils.USERS,
- ReqType: utils.USERS,
+ ur := &ExternalCDR{
+ ToR: utils.USERS,
+ RequestType: utils.USERS,
Direction: "*out",
Tenant: "",
Category: "call",
@@ -746,9 +746,9 @@ func TestUsersExternalCdrGetLoadUserProfileExtraFieldsSet(t *testing.T) {
if err != nil {
t.Error("Error loading user profile: ", err)
}
- expected := &ExternalCdr{
- TOR: "04",
- ReqType: "4",
+ expected := &ExternalCDR{
+ ToR: "04",
+ RequestType: "4",
Direction: "*out",
Tenant: "",
Category: "call",
@@ -771,9 +771,9 @@ func TestUsersExternalCdrGetLoadUserProfileExtraFieldsSet(t *testing.T) {
func TestUsersCallDescLoadUserProfile(t *testing.T) {
userService = &UserMap{
table: map[string]map[string]string{
- "cgrates.org:dan": map[string]string{"ReqType": "*prepaid", "Category": "call1", "Account": "dan", "Subject": "dan", "Cli": "+4986517174963"},
- "cgrates.org:danvoice": map[string]string{"TOR": "*voice", "ReqType": "*prepaid", "Category": "call1", "Account": "dan", "Subject": "0723"},
- "cgrates:rif": map[string]string{"ReqType": "*postpaid", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726"},
+ "cgrates.org:dan": map[string]string{"RequestType": "*prepaid", "Category": "call1", "Account": "dan", "Subject": "dan", "Cli": "+4986517174963"},
+ "cgrates.org:danvoice": map[string]string{utils.TOR: "*voice", "RequestType": "*prepaid", "Category": "call1", "Account": "dan", "Subject": "0723"},
+ "cgrates:rif": map[string]string{"RequestType": "*postpaid", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726"},
},
index: make(map[string]map[string]bool),
}
@@ -809,19 +809,19 @@ func TestUsersCallDescLoadUserProfile(t *testing.T) {
}
}
-func TestUsersStoredCdrLoadUserProfile(t *testing.T) {
+func TestUsersCDRLoadUserProfile(t *testing.T) {
userService = &UserMap{
table: map[string]map[string]string{
- "cgrates.org:dan": map[string]string{"ReqType": "*prepaid", "Category": "call1", "Account": "dan", "Subject": "dan", "Cli": "+4986517174963"},
- "cgrates.org:danvoice": map[string]string{"TOR": "*voice", "ReqType": "*prepaid", "Category": "call1", "Account": "dan", "Subject": "0723"},
- "cgrates:rif": map[string]string{"ReqType": "*postpaid", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726"},
+ "cgrates.org:dan": map[string]string{"RequestType": "*prepaid", "Category": "call1", "Account": "dan", "Subject": "dan", "Cli": "+4986517174963"},
+ "cgrates.org:danvoice": map[string]string{utils.TOR: "*voice", "RequestType": "*prepaid", "Category": "call1", "Account": "dan", "Subject": "0723"},
+ "cgrates:rif": map[string]string{"RequestType": "*postpaid", "Direction": "*out", "Category": "call", "Account": "rif", "Subject": "0726"},
},
index: make(map[string]map[string]bool),
}
startTime := time.Now()
- cdr := &StoredCdr{
- TOR: "*sms",
- ReqType: utils.USERS,
+ cdr := &CDR{
+ ToR: "*sms",
+ RequestType: utils.USERS,
Tenant: utils.USERS,
Category: utils.USERS,
Account: utils.USERS,
@@ -832,9 +832,9 @@ func TestUsersStoredCdrLoadUserProfile(t *testing.T) {
Usage: time.Duration(1) * time.Minute,
ExtraFields: map[string]string{"Cli": "+4986517174963"},
}
- expected := &StoredCdr{
- TOR: "*sms",
- ReqType: "*prepaid",
+ expected := &CDR{
+ ToR: "*sms",
+ RequestType: "*prepaid",
Tenant: "cgrates.org",
Category: "call1",
Account: "dan",
diff --git a/general_tests/auth_test.go b/general_tests/auth_test.go
index d976c5c8e..b9069716e 100644
--- a/general_tests/auth_test.go
+++ b/general_tests/auth_test.go
@@ -93,7 +93,7 @@ RP_ANY,DR_ANY_1CNT,*any,10`
}
func TestAuthPostpaidNoAcnt(t *testing.T) {
- cdr := &engine.StoredCdr{TOR: utils.VOICE, ReqType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
+ cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "nonexistent", Subject: "testauthpostpaid1",
Destination: "4986517174963", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)}
var maxSessionTime float64
@@ -104,7 +104,7 @@ func TestAuthPostpaidNoAcnt(t *testing.T) {
func TestAuthPostpaidNoDestination(t *testing.T) {
// Test subject which does not have destination attached
- cdr := &engine.StoredCdr{TOR: utils.VOICE, ReqType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
+ cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid1",
Destination: "441231234", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)}
var maxSessionTime float64
@@ -115,7 +115,7 @@ func TestAuthPostpaidNoDestination(t *testing.T) {
func TestAuthPostpaidFallbackDest(t *testing.T) {
// Test subject which has fallback for destination
- cdr := &engine.StoredCdr{TOR: utils.VOICE, ReqType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
+ cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid2",
Destination: "441231234", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)}
var maxSessionTime float64
@@ -128,7 +128,7 @@ func TestAuthPostpaidFallbackDest(t *testing.T) {
func TestAuthPostpaidWithDestination(t *testing.T) {
// Test subject which does not have destination attached
- cdr := &engine.StoredCdr{TOR: utils.VOICE, ReqType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
+ cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: "*out", Tenant: "cgrates.org",
Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid1",
Destination: "4986517174963", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)}
var maxSessionTime float64
diff --git a/engine/cdrs_local_test.go b/general_tests/cdrs_replication_it_test.go
similarity index 72%
rename from engine/cdrs_local_test.go
rename to general_tests/cdrs_replication_it_test.go
index 7c1e631dd..66a682f7a 100644
--- a/engine/cdrs_local_test.go
+++ b/general_tests/cdrs_replication_it_test.go
@@ -16,14 +16,16 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see
*/
-package engine
+package general_tests
import (
+ "flag"
"path"
"testing"
"time"
"github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/utils"
"github.com/cgrates/rpcclient"
)
@@ -31,12 +33,10 @@ import (
var cdrsMasterCfgPath, cdrsSlaveCfgPath string
var cdrsMasterCfg, cdrsSlaveCfg *config.CGRConfig
-//var cdrsHttpJsonRpc *rpcclient.RpcClient
-
-var waitRater = 500
+var testIntegration = flag.Bool("integration", false, "Perform the tests in integration mode, not by default.") // This flag will be passed here via "go test -local" args
func TestCdrsInitConfig(t *testing.T) {
- if !*testLocal {
+ if !*testIntegration {
return
}
var err error
@@ -52,64 +52,64 @@ func TestCdrsInitConfig(t *testing.T) {
// InitDb so we can rely on count
func TestCdrsInitCdrDb(t *testing.T) {
- if !*testLocal {
+ if !*testIntegration {
return
}
- if err := InitStorDb(cdrsMasterCfg); err != nil {
+ if err := engine.InitStorDb(cdrsMasterCfg); err != nil {
t.Fatal(err)
}
- if err := InitStorDb(cdrsSlaveCfg); err != nil {
+ if err := engine.InitStorDb(cdrsSlaveCfg); err != nil {
t.Fatal(err)
}
}
func TestCdrsStartMasterEngine(t *testing.T) {
- if !*testLocal {
+ if !*testIntegration {
return
}
- if _, err := StopStartEngine(cdrsMasterCfgPath, waitRater); err != nil {
+ if _, err := engine.StopStartEngine(cdrsMasterCfgPath, *waitRater); err != nil {
t.Fatal(err)
}
}
func TestCdrsStartSlaveEngine(t *testing.T) {
- if !*testLocal {
+ if !*testIntegration {
return
}
- if _, err := StartEngine(cdrsSlaveCfgPath, waitRater); err != nil {
+ if _, err := engine.StartEngine(cdrsSlaveCfgPath, *waitRater); err != nil {
t.Fatal(err)
}
}
// Connect rpc client to rater
func TestCdrsHttpCdrReplication(t *testing.T) {
- if !*testLocal {
+ if !*testIntegration {
return
}
cdrsMasterRpc, err := rpcclient.NewRpcClient("tcp", cdrsMasterCfg.RPCJSONListen, 1, 1, "json", nil)
if err != nil {
t.Fatal("Could not connect to rater: ", err.Error())
}
- testCdr1 := &StoredCdr{CgrId: utils.Sha1("httpjsonrpc1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
- TOR: utils.VOICE, AccId: "httpjsonrpc1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: utils.META_PSEUDOPREPAID,
+ testCdr1 := &engine.CDR{CGRID: utils.Sha1("httpjsonrpc1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
+ ToR: utils.VOICE, OriginID: "httpjsonrpc1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_PSEUDOPREPAID,
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, Rated: true}
+ RunID: utils.DEFAULT_RUNID, Cost: 1.201, Rated: true}
var reply string
if err := cdrsMasterRpc.Call("CdrsV2.ProcessCdr", testCdr1, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
t.Error("Unexpected reply received: ", reply)
}
- time.Sleep(time.Duration(waitRater) * time.Millisecond)
+ time.Sleep(time.Duration(*waitRater) * time.Millisecond)
cdrsSlaveRpc, err := rpcclient.NewRpcClient("tcp", "127.0.0.1:12012", 1, 1, "json", nil)
if err != nil {
t.Fatal("Could not connect to rater: ", err.Error())
}
// ToDo: Fix cdr_http to be compatible with rest of processCdr methods
- var rcvedCdrs []*ExternalCdr
- if err := cdrsSlaveRpc.Call("ApierV2.GetCdrs", utils.RpcCdrsFilter{CgrIds: []string{testCdr1.CgrId}, RunIds: []string{utils.META_DEFAULT}}, &rcvedCdrs); err != nil {
+ var rcvedCdrs []*engine.ExternalCDR
+ if err := cdrsSlaveRpc.Call("ApierV2.GetCdrs", utils.RPCCDRsFilter{CGRIDs: []string{testCdr1.CGRID}, RunIDs: []string{utils.META_DEFAULT}}, &rcvedCdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(rcvedCdrs) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(rcvedCdrs))
@@ -117,11 +117,11 @@ func TestCdrsHttpCdrReplication(t *testing.T) {
rcvSetupTime, _ := utils.ParseTimeDetectLayout(rcvedCdrs[0].SetupTime, "")
rcvAnswerTime, _ := utils.ParseTimeDetectLayout(rcvedCdrs[0].AnswerTime, "")
//rcvUsage, _ := utils.ParseDurationWithSecs(rcvedCdrs[0].Usage)
- if rcvedCdrs[0].CgrId != testCdr1.CgrId ||
- rcvedCdrs[0].TOR != testCdr1.TOR ||
- rcvedCdrs[0].CdrHost != testCdr1.CdrHost ||
- rcvedCdrs[0].CdrSource != testCdr1.CdrSource ||
- rcvedCdrs[0].ReqType != testCdr1.ReqType ||
+ if rcvedCdrs[0].CGRID != testCdr1.CGRID ||
+ rcvedCdrs[0].ToR != testCdr1.ToR ||
+ rcvedCdrs[0].OriginHost != testCdr1.OriginHost ||
+ rcvedCdrs[0].Source != testCdr1.Source ||
+ rcvedCdrs[0].RequestType != testCdr1.RequestType ||
rcvedCdrs[0].Direction != testCdr1.Direction ||
rcvedCdrs[0].Tenant != testCdr1.Tenant ||
rcvedCdrs[0].Category != testCdr1.Category ||
@@ -131,7 +131,7 @@ func TestCdrsHttpCdrReplication(t *testing.T) {
!rcvSetupTime.Equal(testCdr1.SetupTime) ||
!rcvAnswerTime.Equal(testCdr1.AnswerTime) ||
//rcvUsage != 10 ||
- rcvedCdrs[0].MediationRunId != testCdr1.MediationRunId {
+ rcvedCdrs[0].RunID != testCdr1.RunID {
//rcvedCdrs[0].Cost != testCdr1.Cost ||
//!reflect.DeepEqual(rcvedCdrs[0].ExtraFields, testCdr1.ExtraFields) {
t.Errorf("Expected: %+v, received: %+v", testCdr1, rcvedCdrs[0])
diff --git a/general_tests/fsevcorelate_test.go b/general_tests/fsevcorelate_test.go
index 0928ebc93..898be1012 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_RequestType: *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_RequestType":"*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) {
answerEv := new(sessionmanager.FSEvent).AsEvent(answerEvent)
@@ -222,11 +222,11 @@ func TestEvCorelate(t *testing.T) {
cdrEv, err := engine.NewFSCdr(jsonCdr, cfg)
if err != nil {
t.Errorf("Error loading cdr: %v", err.Error())
- } else if cdrEv.AsStoredCdr("").AccId != "86cfd6e2-dbda-45a3-b59d-f683ec368e8b" {
- t.Error("Unexpected acntId received", cdrEv.AsStoredCdr("").AccId)
+ } else if cdrEv.AsStoredCdr("").OriginID != "86cfd6e2-dbda-45a3-b59d-f683ec368e8b" {
+ t.Error("Unexpected acntId received", cdrEv.AsStoredCdr("").OriginID)
}
- if answerEv.GetCgrId("") != cdrEv.AsStoredCdr("").CgrId {
- t.Error("CgrIds do not match", answerEv.GetCgrId(""), cdrEv.AsStoredCdr("").CgrId)
+ if answerEv.GetCgrId("") != cdrEv.AsStoredCdr("").CGRID {
+ t.Error("CGRIDs do not match", answerEv.GetCgrId(""), cdrEv.AsStoredCdr("").CGRID)
}
}
@@ -372,7 +372,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_RequestType: *prepaid
variable_cgr_supplier: supplier1
variable_user_name: 1001
variable_domain_name: cgrates.org
@@ -540,7 +540,7 @@ variable_rtp_audio_out_cng_packet_count: 0
variable_rtp_audio_rtcp_packet_count: 1450
variable_rtp_audio_rtcp_octet_count: 45940`
-var jsonCdr2 = []byte(`{"core-uuid":"651a8db2-4f67-4cf8-b622-169e8a482e50","switchname":"CgrDev1","channel_data":{"state":"CS_REPORTING","direction":"inbound","state_number":"11","flags":"0=1;1=1;37=1;38=1;40=1;43=1;48=1;53=1;105=1;111=1;112=1;116=1;118=1","caps":"1=1;2=1;3=1;4=1;5=1;6=1"},"variables":{"direction":"inbound","uuid":"e3133bf7-dcde-4daf-9663-9a79ffcef5ad","session_id":"4","sip_from_user":"1001","sip_from_uri":"1001@127.0.0.1","sip_from_host":"127.0.0.1","channel_name":"sofia/cgrtest/1001@127.0.0.1","ep_codec_string":"speex@16000h@20i,speex@8000h@20i,speex@32000h@20i,GSM@8000h@20i@13200b,PCMU@8000h@20i@64000b,PCMA@8000h@20i@64000b,G722@8000h@20i@64000b","sip_local_network_addr":"127.0.0.1","sip_network_ip":"127.0.0.1","sip_network_port":"46615","sip_received_ip":"127.0.0.1","sip_received_port":"46615","sip_via_protocol":"tcp","sip_authorized":"true","Event-Name":"REQUEST_PARAMS","Core-UUID":"651a8db2-4f67-4cf8-b622-169e8a482e50","FreeSWITCH-Hostname":"CgrDev1","FreeSWITCH-Switchname":"CgrDev1","FreeSWITCH-IPv4":"10.0.3.15","FreeSWITCH-IPv6":"::1","Event-Date-Local":"2015-07-07 16:52:08","Event-Date-GMT":"Tue, 07 Jul 2015 14:52:08 GMT","Event-Date-Timestamp":"1436280728471153","Event-Calling-File":"sofia.c","Event-Calling-Function":"sofia_handle_sip_i_invite","Event-Calling-Line-Number":"9056","Event-Sequence":"515","sip_number_alias":"1001","sip_auth_username":"1001","sip_auth_realm":"127.0.0.1","number_alias":"1001","requested_domain_name":"cgrates.org","record_stereo":"true","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","cgr_reqtype":"*prepaid","cgr_supplier":"supplier1","user_name":"1001","domain_name":"cgrates.org","sip_from_user_stripped":"1001","sofia_profile_name":"cgrtest","recovery_profile_name":"cgrtest","sip_full_route":"","sip_recover_via":"SIP/2.0/TCP 127.0.0.1:46615;rport=46615;branch=z9hG4bKPjGj7AlihmVwAVz9McwVeI64NeBHlPmXAN;alias","sip_req_user":"1003","sip_req_uri":"1003@127.0.0.1","sip_req_host":"127.0.0.1","sip_to_user":"1003","sip_to_uri":"1003@127.0.0.1","sip_to_host":"127.0.0.1","sip_contact_params":"ob","sip_contact_user":"1001","sip_contact_port":"5072","sip_contact_uri":"1001@127.0.0.1:5072","sip_contact_host":"127.0.0.1","sip_via_host":"127.0.0.1","sip_via_port":"46615","sip_via_rport":"46615","switch_r_sdp":"v=0\r\no=- 3645269528 3645269528 IN IP4 10.0.3.15\r\ns=pjmedia\r\nb=AS:84\r\nt=0 0\r\na=X-nat:0\r\nm=audio 4006 RTP/AVP 98 97 99 104 3 0 8 9 96\r\nc=IN IP4 10.0.3.15\r\nb=AS:64000\r\na=rtpmap:98 speex/16000\r\na=rtpmap:97 speex/8000\r\na=rtpmap:99 speex/32000\r\na=rtpmap:104 iLBC/8000\r\na=fmtp:104 mode=30\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:96 telephone-event/8000\r\na=fmtp:96 0-16\r\na=rtcp:4007 IN IP4 10.0.3.15\r\n","rtp_remote_audio_rtcp_port":"4007 IN IP4 10.0.3.15","rtp_audio_recv_pt":"99","rtp_use_codec_name":"SPEEX","rtp_use_codec_rate":"32000","rtp_use_codec_ptime":"20","rtp_use_codec_channels":"1","rtp_last_audio_codec_string":"SPEEX@32000h@20i@1c","read_codec":"SPEEX","original_read_codec":"SPEEX","read_rate":"32000","original_read_rate":"32000","write_codec":"SPEEX","write_rate":"32000","dtmf_type":"rfc2833","execute_on_answer":"sched_hangup +3120 alloted_timeout","cgr_notify":"+AUTH_OK","max_forwards":"69","transfer_history":"1436280728:e7c250e8-6ad7-4bd4-8962-318e0b0da728:bl_xfer:1003/default/XML","transfer_source":"1436280728:e7c250e8-6ad7-4bd4-8962-318e0b0da728:bl_xfer:1003/default/XML","DP_MATCH":"ARRAY::1003|:1003","call_uuid":"e3133bf7-dcde-4daf-9663-9a79ffcef5ad","ringback":"%(2000,4000,440,480)","call_timeout":"30","dialed_user":"1003","dialed_domain":"cgrates.org","originated_legs":"ARRAY::0a30dd7c-c222-482f-a322-b1218a15f8cd;Outbound Call;1003|:0a30dd7c-c222-482f-a322-b1218a15f8cd;Outbound Call;1003","switch_m_sdp":"v=0\r\no=- 3645269528 3645269529 IN IP4 10.0.3.15\r\ns=pjmedia\r\nb=AS:84\r\nt=0 0\r\na=X-nat:0\r\nm=audio 4018 RTP/AVP 99 101\r\nc=IN IP4 10.0.3.15\r\nb=AS:64000\r\na=rtpmap:99 speex/32000\r\na=rtpmap:101 telephone-event/8000\r\na=fmtp:101 0-16\r\na=rtcp:4019 IN IP4 10.0.3.15\r\n","rtp_local_sdp_str":"v=0\no=FreeSWITCH 1436250882 1436250883 IN IP4 10.0.3.15\ns=FreeSWITCH\nc=IN IP4 10.0.3.15\nt=0 0\nm=audio 29846 RTP/AVP 99 96\na=rtpmap:99 speex/32000\na=rtpmap:96 telephone-event/8000\na=fmtp:96 0-16\na=ptime:20\na=sendrecv\na=rtcp:29847 IN IP4 10.0.3.15\n","local_media_ip":"10.0.3.15","local_media_port":"29846","advertised_media_ip":"10.0.3.15","rtp_use_pt":"99","rtp_use_ssrc":"1470667272","rtp_2833_send_payload":"96","rtp_2833_recv_payload":"96","remote_media_ip":"10.0.3.15","remote_media_port":"4006","endpoint_disposition":"ANSWER","current_application_data":"+3120 alloted_timeout","current_application":"sched_hangup","originate_causes":"ARRAY::0a30dd7c-c222-482f-a322-b1218a15f8cd;NONE|:0a30dd7c-c222-482f-a322-b1218a15f8cd;NONE","originate_disposition":"SUCCESS","DIALSTATUS":"SUCCESS","last_bridge_to":"0a30dd7c-c222-482f-a322-b1218a15f8cd","bridge_channel":"sofia/cgrtest/1003@127.0.0.1:5070","bridge_uuid":"0a30dd7c-c222-482f-a322-b1218a15f8cd","signal_bond":"0a30dd7c-c222-482f-a322-b1218a15f8cd","sip_to_tag":"5Qt4ecvreSHZN","sip_from_tag":"YwuG8U3rRbqIn.xYTnU8NrI3giyxDBHJ","sip_cseq":"4178","sip_call_id":"r3xaJ8CLpyTAIHWUZG7gtZQYgAPEGf9S","sip_full_via":"SIP/2.0/UDP 10.0.3.15:5072;rport=5072;branch=z9hG4bKPjPqma7vnLxDkBqcCH3eXLmLYZoPS.6MDc;received=127.0.0.1","sip_full_from":"sip:1001@127.0.0.1;tag=YwuG8U3rRbqIn.xYTnU8NrI3giyxDBHJ","sip_full_to":"sip:1003@127.0.0.1;tag=5Qt4ecvreSHZN","last_sent_callee_id_name":"Outbound Call","last_sent_callee_id_number":"1003","sip_term_status":"200","proto_specific_hangup_cause":"sip:200","sip_term_cause":"16","last_bridge_role":"originator","sip_user_agent":"PJSUA v2.3 Linux-3.2.0.4/x86_64/glibc-2.13","sip_hangup_disposition":"recv_bye","bridge_hangup_cause":"NORMAL_CLEARING","hangup_cause":"NORMAL_CLEARING","hangup_cause_q850":"16","digits_dialed":"none","start_stamp":"2015-07-07 16:52:08","profile_start_stamp":"2015-07-07 16:52:08","answer_stamp":"2015-07-07 16:52:08","bridge_stamp":"2015-07-07 16:52:08","end_stamp":"2015-07-07 16:53:14","start_epoch":"1436280728","start_uepoch":"1436280728471153","profile_start_epoch":"1436280728","profile_start_uepoch":"1436280728930693","answer_epoch":"1436280728","answer_uepoch":"1436280728971147","bridge_epoch":"1436280728","bridge_uepoch":"1436280728971147","last_hold_epoch":"0","last_hold_uepoch":"0","hold_accum_seconds":"0","hold_accum_usec":"0","hold_accum_ms":"0","resurrect_epoch":"0","resurrect_uepoch":"0","progress_epoch":"0","progress_uepoch":"0","progress_media_epoch":"0","progress_media_uepoch":"0","end_epoch":"1436280794","end_uepoch":"1436280794010851","last_app":"sched_hangup","last_arg":"+3120 alloted_timeout","caller_id":"\"1001\" <1001>","duration":"66","billsec":"66","progresssec":"0","answersec":"0","waitsec":"0","progress_mediasec":"0","flow_billsec":"66","mduration":"65539","billmsec":"65039","progressmsec":"28","answermsec":"500","waitmsec":"500","progress_mediamsec":"28","flow_billmsec":"65539","uduration":"65539698","billusec":"65039704","progressusec":"0","answerusec":"499994","waitusec":"499994","progress_mediausec":"0","flow_billusec":"65539698","rtp_audio_in_raw_bytes":"6770","rtp_audio_in_media_bytes":"6762","rtp_audio_in_packet_count":"192","rtp_audio_in_media_packet_count":"190","rtp_audio_in_skip_packet_count":"6","rtp_audio_in_jitter_packet_count":"0","rtp_audio_in_dtmf_packet_count":"0","rtp_audio_in_cng_packet_count":"0","rtp_audio_in_flush_packet_count":"2","rtp_audio_in_largest_jb_size":"0","rtp_audio_in_jitter_min_variance":"26.73","rtp_audio_in_jitter_max_variance":"6716.71","rtp_audio_in_jitter_loss_rate":"0.00","rtp_audio_in_jitter_burst_rate":"0.00","rtp_audio_in_mean_interval":"36.67","rtp_audio_in_flaw_total":"0","rtp_audio_in_quality_percentage":"100.00","rtp_audio_in_mos":"4.50","rtp_audio_out_raw_bytes":"4686","rtp_audio_out_media_bytes":"4686","rtp_audio_out_packet_count":"108","rtp_audio_out_media_packet_count":"108","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":"1450","rtp_audio_rtcp_octet_count":"45940"},"app_log":{"applications":[{"app_name":"info","app_data":""},{"app_name":"park","app_data":""},{"app_name":"info","app_data":""},{"app_name":"set","app_data":"ringback=%(2000,4000,440,480)"},{"app_name":"set","app_data":"call_timeout=30"},{"app_name":"bridge","app_data":"user/1003@cgrates.org"},{"app_name":"sched_hangup","app_data":"+3120 alloted_timeout"}]},"callflow":{"dialplan":"XML","profile_index":"2","extension":{"name":"call_debug","number":"1003","applications":[{"app_name":"info","app_data":""},{"app_name":"set","app_data":"ringback=${us-ring}"},{"app_name":"set","app_data":"call_timeout=30"},{"app_name":"bridge","app_data":"user/${destination_number}@${domain_name}"}]},"caller_profile":{"username":"1001","dialplan":"XML","caller_id_name":"1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"127.0.0.1","rdnis":"1003","destination_number":"1003","uuid":"e3133bf7-dcde-4daf-9663-9a79ffcef5ad","source":"mod_sofia","context":"default","chan_name":"sofia/cgrtest/1001@127.0.0.1","originatee":{"originatee_caller_profiles":[{"username":"1001","dialplan":"XML","caller_id_name":"Extension 1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"127.0.0.1","rdnis":"1003","destination_number":"1003","uuid":"0a30dd7c-c222-482f-a322-b1218a15f8cd","source":"mod_sofia","context":"default","chan_name":"sofia/cgrtest/1003@127.0.0.1:5070"},{"username":"1001","dialplan":"XML","caller_id_name":"Extension 1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"127.0.0.1","rdnis":"1003","destination_number":"1003","uuid":"0a30dd7c-c222-482f-a322-b1218a15f8cd","source":"mod_sofia","context":"default","chan_name":"sofia/cgrtest/1003@127.0.0.1:5070"}]}},"times":{"created_time":"1436280728471153","profile_created_time":"1436280728930693","progress_time":"0","progress_media_time":"0","answered_time":"1436280728971147","bridged_time":"1436280728971147","last_hold_time":"0","hold_accum_time":"0","hangup_time":"1436280794010851","resurrect_time":"0","transfer_time":"0"}},"callflow":{"dialplan":"XML","profile_index":"1","extension":{"name":"call_debug","number":"1003","applications":[{"app_name":"info","app_data":""},{"app_name":"park","app_data":""}]},"caller_profile":{"username":"1001","dialplan":"XML","caller_id_name":"1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"127.0.0.1","rdnis":"","destination_number":"1003","uuid":"e3133bf7-dcde-4daf-9663-9a79ffcef5ad","source":"mod_sofia","context":"default","chan_name":"sofia/cgrtest/1001@127.0.0.1"},"times":{"created_time":"1436280728471153","profile_created_time":"1436280728471153","progress_time":"0","progress_media_time":"0","answered_time":"0","bridged_time":"0","last_hold_time":"0","hold_accum_time":"0","hangup_time":"0","resurrect_time":"0","transfer_time":"1436280728930693"}}}`)
+var jsonCdr2 = []byte(`{"core-uuid":"651a8db2-4f67-4cf8-b622-169e8a482e50","switchname":"CgrDev1","channel_data":{"state":"CS_REPORTING","direction":"inbound","state_number":"11","flags":"0=1;1=1;37=1;38=1;40=1;43=1;48=1;53=1;105=1;111=1;112=1;116=1;118=1","caps":"1=1;2=1;3=1;4=1;5=1;6=1"},"variables":{"direction":"inbound","uuid":"e3133bf7-dcde-4daf-9663-9a79ffcef5ad","session_id":"4","sip_from_user":"1001","sip_from_uri":"1001@127.0.0.1","sip_from_host":"127.0.0.1","channel_name":"sofia/cgrtest/1001@127.0.0.1","ep_codec_string":"speex@16000h@20i,speex@8000h@20i,speex@32000h@20i,GSM@8000h@20i@13200b,PCMU@8000h@20i@64000b,PCMA@8000h@20i@64000b,G722@8000h@20i@64000b","sip_local_network_addr":"127.0.0.1","sip_network_ip":"127.0.0.1","sip_network_port":"46615","sip_received_ip":"127.0.0.1","sip_received_port":"46615","sip_via_protocol":"tcp","sip_authorized":"true","Event-Name":"REQUEST_PARAMS","Core-UUID":"651a8db2-4f67-4cf8-b622-169e8a482e50","FreeSWITCH-Hostname":"CgrDev1","FreeSWITCH-Switchname":"CgrDev1","FreeSWITCH-IPv4":"10.0.3.15","FreeSWITCH-IPv6":"::1","Event-Date-Local":"2015-07-07 16:52:08","Event-Date-GMT":"Tue, 07 Jul 2015 14:52:08 GMT","Event-Date-Timestamp":"1436280728471153","Event-Calling-File":"sofia.c","Event-Calling-Function":"sofia_handle_sip_i_invite","Event-Calling-Line-Number":"9056","Event-Sequence":"515","sip_number_alias":"1001","sip_auth_username":"1001","sip_auth_realm":"127.0.0.1","number_alias":"1001","requested_domain_name":"cgrates.org","record_stereo":"true","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","cgr_RequestType":"*prepaid","cgr_supplier":"supplier1","user_name":"1001","domain_name":"cgrates.org","sip_from_user_stripped":"1001","sofia_profile_name":"cgrtest","recovery_profile_name":"cgrtest","sip_full_route":"","sip_recover_via":"SIP/2.0/TCP 127.0.0.1:46615;rport=46615;branch=z9hG4bKPjGj7AlihmVwAVz9McwVeI64NeBHlPmXAN;alias","sip_req_user":"1003","sip_req_uri":"1003@127.0.0.1","sip_req_host":"127.0.0.1","sip_to_user":"1003","sip_to_uri":"1003@127.0.0.1","sip_to_host":"127.0.0.1","sip_contact_params":"ob","sip_contact_user":"1001","sip_contact_port":"5072","sip_contact_uri":"1001@127.0.0.1:5072","sip_contact_host":"127.0.0.1","sip_via_host":"127.0.0.1","sip_via_port":"46615","sip_via_rport":"46615","switch_r_sdp":"v=0\r\no=- 3645269528 3645269528 IN IP4 10.0.3.15\r\ns=pjmedia\r\nb=AS:84\r\nt=0 0\r\na=X-nat:0\r\nm=audio 4006 RTP/AVP 98 97 99 104 3 0 8 9 96\r\nc=IN IP4 10.0.3.15\r\nb=AS:64000\r\na=rtpmap:98 speex/16000\r\na=rtpmap:97 speex/8000\r\na=rtpmap:99 speex/32000\r\na=rtpmap:104 iLBC/8000\r\na=fmtp:104 mode=30\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:96 telephone-event/8000\r\na=fmtp:96 0-16\r\na=rtcp:4007 IN IP4 10.0.3.15\r\n","rtp_remote_audio_rtcp_port":"4007 IN IP4 10.0.3.15","rtp_audio_recv_pt":"99","rtp_use_codec_name":"SPEEX","rtp_use_codec_rate":"32000","rtp_use_codec_ptime":"20","rtp_use_codec_channels":"1","rtp_last_audio_codec_string":"SPEEX@32000h@20i@1c","read_codec":"SPEEX","original_read_codec":"SPEEX","read_rate":"32000","original_read_rate":"32000","write_codec":"SPEEX","write_rate":"32000","dtmf_type":"rfc2833","execute_on_answer":"sched_hangup +3120 alloted_timeout","cgr_notify":"+AUTH_OK","max_forwards":"69","transfer_history":"1436280728:e7c250e8-6ad7-4bd4-8962-318e0b0da728:bl_xfer:1003/default/XML","transfer_source":"1436280728:e7c250e8-6ad7-4bd4-8962-318e0b0da728:bl_xfer:1003/default/XML","DP_MATCH":"ARRAY::1003|:1003","call_uuid":"e3133bf7-dcde-4daf-9663-9a79ffcef5ad","ringback":"%(2000,4000,440,480)","call_timeout":"30","dialed_user":"1003","dialed_domain":"cgrates.org","originated_legs":"ARRAY::0a30dd7c-c222-482f-a322-b1218a15f8cd;Outbound Call;1003|:0a30dd7c-c222-482f-a322-b1218a15f8cd;Outbound Call;1003","switch_m_sdp":"v=0\r\no=- 3645269528 3645269529 IN IP4 10.0.3.15\r\ns=pjmedia\r\nb=AS:84\r\nt=0 0\r\na=X-nat:0\r\nm=audio 4018 RTP/AVP 99 101\r\nc=IN IP4 10.0.3.15\r\nb=AS:64000\r\na=rtpmap:99 speex/32000\r\na=rtpmap:101 telephone-event/8000\r\na=fmtp:101 0-16\r\na=rtcp:4019 IN IP4 10.0.3.15\r\n","rtp_local_sdp_str":"v=0\no=FreeSWITCH 1436250882 1436250883 IN IP4 10.0.3.15\ns=FreeSWITCH\nc=IN IP4 10.0.3.15\nt=0 0\nm=audio 29846 RTP/AVP 99 96\na=rtpmap:99 speex/32000\na=rtpmap:96 telephone-event/8000\na=fmtp:96 0-16\na=ptime:20\na=sendrecv\na=rtcp:29847 IN IP4 10.0.3.15\n","local_media_ip":"10.0.3.15","local_media_port":"29846","advertised_media_ip":"10.0.3.15","rtp_use_pt":"99","rtp_use_ssrc":"1470667272","rtp_2833_send_payload":"96","rtp_2833_recv_payload":"96","remote_media_ip":"10.0.3.15","remote_media_port":"4006","endpoint_disposition":"ANSWER","current_application_data":"+3120 alloted_timeout","current_application":"sched_hangup","originate_causes":"ARRAY::0a30dd7c-c222-482f-a322-b1218a15f8cd;NONE|:0a30dd7c-c222-482f-a322-b1218a15f8cd;NONE","originate_disposition":"SUCCESS","DIALSTATUS":"SUCCESS","last_bridge_to":"0a30dd7c-c222-482f-a322-b1218a15f8cd","bridge_channel":"sofia/cgrtest/1003@127.0.0.1:5070","bridge_uuid":"0a30dd7c-c222-482f-a322-b1218a15f8cd","signal_bond":"0a30dd7c-c222-482f-a322-b1218a15f8cd","sip_to_tag":"5Qt4ecvreSHZN","sip_from_tag":"YwuG8U3rRbqIn.xYTnU8NrI3giyxDBHJ","sip_cseq":"4178","sip_call_id":"r3xaJ8CLpyTAIHWUZG7gtZQYgAPEGf9S","sip_full_via":"SIP/2.0/UDP 10.0.3.15:5072;rport=5072;branch=z9hG4bKPjPqma7vnLxDkBqcCH3eXLmLYZoPS.6MDc;received=127.0.0.1","sip_full_from":"sip:1001@127.0.0.1;tag=YwuG8U3rRbqIn.xYTnU8NrI3giyxDBHJ","sip_full_to":"sip:1003@127.0.0.1;tag=5Qt4ecvreSHZN","last_sent_callee_id_name":"Outbound Call","last_sent_callee_id_number":"1003","sip_term_status":"200","proto_specific_hangup_cause":"sip:200","sip_term_cause":"16","last_bridge_role":"originator","sip_user_agent":"PJSUA v2.3 Linux-3.2.0.4/x86_64/glibc-2.13","sip_hangup_disposition":"recv_bye","bridge_hangup_cause":"NORMAL_CLEARING","hangup_cause":"NORMAL_CLEARING","hangup_cause_q850":"16","digits_dialed":"none","start_stamp":"2015-07-07 16:52:08","profile_start_stamp":"2015-07-07 16:52:08","answer_stamp":"2015-07-07 16:52:08","bridge_stamp":"2015-07-07 16:52:08","end_stamp":"2015-07-07 16:53:14","start_epoch":"1436280728","start_uepoch":"1436280728471153","profile_start_epoch":"1436280728","profile_start_uepoch":"1436280728930693","answer_epoch":"1436280728","answer_uepoch":"1436280728971147","bridge_epoch":"1436280728","bridge_uepoch":"1436280728971147","last_hold_epoch":"0","last_hold_uepoch":"0","hold_accum_seconds":"0","hold_accum_usec":"0","hold_accum_ms":"0","resurrect_epoch":"0","resurrect_uepoch":"0","progress_epoch":"0","progress_uepoch":"0","progress_media_epoch":"0","progress_media_uepoch":"0","end_epoch":"1436280794","end_uepoch":"1436280794010851","last_app":"sched_hangup","last_arg":"+3120 alloted_timeout","caller_id":"\"1001\" <1001>","duration":"66","billsec":"66","progresssec":"0","answersec":"0","waitsec":"0","progress_mediasec":"0","flow_billsec":"66","mduration":"65539","billmsec":"65039","progressmsec":"28","answermsec":"500","waitmsec":"500","progress_mediamsec":"28","flow_billmsec":"65539","uduration":"65539698","billusec":"65039704","progressusec":"0","answerusec":"499994","waitusec":"499994","progress_mediausec":"0","flow_billusec":"65539698","rtp_audio_in_raw_bytes":"6770","rtp_audio_in_media_bytes":"6762","rtp_audio_in_packet_count":"192","rtp_audio_in_media_packet_count":"190","rtp_audio_in_skip_packet_count":"6","rtp_audio_in_jitter_packet_count":"0","rtp_audio_in_dtmf_packet_count":"0","rtp_audio_in_cng_packet_count":"0","rtp_audio_in_flush_packet_count":"2","rtp_audio_in_largest_jb_size":"0","rtp_audio_in_jitter_min_variance":"26.73","rtp_audio_in_jitter_max_variance":"6716.71","rtp_audio_in_jitter_loss_rate":"0.00","rtp_audio_in_jitter_burst_rate":"0.00","rtp_audio_in_mean_interval":"36.67","rtp_audio_in_flaw_total":"0","rtp_audio_in_quality_percentage":"100.00","rtp_audio_in_mos":"4.50","rtp_audio_out_raw_bytes":"4686","rtp_audio_out_media_bytes":"4686","rtp_audio_out_packet_count":"108","rtp_audio_out_media_packet_count":"108","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":"1450","rtp_audio_rtcp_octet_count":"45940"},"app_log":{"applications":[{"app_name":"info","app_data":""},{"app_name":"park","app_data":""},{"app_name":"info","app_data":""},{"app_name":"set","app_data":"ringback=%(2000,4000,440,480)"},{"app_name":"set","app_data":"call_timeout=30"},{"app_name":"bridge","app_data":"user/1003@cgrates.org"},{"app_name":"sched_hangup","app_data":"+3120 alloted_timeout"}]},"callflow":{"dialplan":"XML","profile_index":"2","extension":{"name":"call_debug","number":"1003","applications":[{"app_name":"info","app_data":""},{"app_name":"set","app_data":"ringback=${us-ring}"},{"app_name":"set","app_data":"call_timeout=30"},{"app_name":"bridge","app_data":"user/${destination_number}@${domain_name}"}]},"caller_profile":{"username":"1001","dialplan":"XML","caller_id_name":"1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"127.0.0.1","rdnis":"1003","destination_number":"1003","uuid":"e3133bf7-dcde-4daf-9663-9a79ffcef5ad","source":"mod_sofia","context":"default","chan_name":"sofia/cgrtest/1001@127.0.0.1","originatee":{"originatee_caller_profiles":[{"username":"1001","dialplan":"XML","caller_id_name":"Extension 1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"127.0.0.1","rdnis":"1003","destination_number":"1003","uuid":"0a30dd7c-c222-482f-a322-b1218a15f8cd","source":"mod_sofia","context":"default","chan_name":"sofia/cgrtest/1003@127.0.0.1:5070"},{"username":"1001","dialplan":"XML","caller_id_name":"Extension 1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"127.0.0.1","rdnis":"1003","destination_number":"1003","uuid":"0a30dd7c-c222-482f-a322-b1218a15f8cd","source":"mod_sofia","context":"default","chan_name":"sofia/cgrtest/1003@127.0.0.1:5070"}]}},"times":{"created_time":"1436280728471153","profile_created_time":"1436280728930693","progress_time":"0","progress_media_time":"0","answered_time":"1436280728971147","bridged_time":"1436280728971147","last_hold_time":"0","hold_accum_time":"0","hangup_time":"1436280794010851","resurrect_time":"0","transfer_time":"0"}},"callflow":{"dialplan":"XML","profile_index":"1","extension":{"name":"call_debug","number":"1003","applications":[{"app_name":"info","app_data":""},{"app_name":"park","app_data":""}]},"caller_profile":{"username":"1001","dialplan":"XML","caller_id_name":"1001","ani":"1001","aniii":"","caller_id_number":"1001","network_addr":"127.0.0.1","rdnis":"","destination_number":"1003","uuid":"e3133bf7-dcde-4daf-9663-9a79ffcef5ad","source":"mod_sofia","context":"default","chan_name":"sofia/cgrtest/1001@127.0.0.1"},"times":{"created_time":"1436280728471153","profile_created_time":"1436280728471153","progress_time":"0","progress_media_time":"0","answered_time":"0","bridged_time":"0","last_hold_time":"0","hold_accum_time":"0","hangup_time":"0","resurrect_time":"0","transfer_time":"1436280728930693"}}}`)
// Make sure that both hangup and json cdr produce the same CGR primary fields
func TestEvCdrCorelate(t *testing.T) {
@@ -554,21 +554,21 @@ func TestEvCdrCorelate(t *testing.T) {
cdrEv, err := engine.NewFSCdr(jsonCdr2, cfg)
if err != nil {
t.Errorf("Error loading cdr: %v", err.Error())
- } else if cdrEv.AsStoredCdr("").AccId != "e3133bf7-dcde-4daf-9663-9a79ffcef5ad" {
- t.Error("Unexpected acntId received", cdrEv.AsStoredCdr("").AccId)
+ } else if cdrEv.AsStoredCdr("").OriginID != "e3133bf7-dcde-4daf-9663-9a79ffcef5ad" {
+ t.Error("Unexpected acntId received", cdrEv.AsStoredCdr("").OriginID)
}
jsnStoredCdr := cdrEv.AsStoredCdr("")
- if evStoredCdr.CgrId != jsnStoredCdr.CgrId {
- t.Errorf("evStoredCdr.CgrId: %s, jsnStoredCdr.CgrId: %s", evStoredCdr.CgrId, jsnStoredCdr.CgrId)
+ if evStoredCdr.CGRID != jsnStoredCdr.CGRID {
+ t.Errorf("evStoredCdr.CGRID: %s, jsnStoredCdr.CGRID: %s", evStoredCdr.CGRID, jsnStoredCdr.CGRID)
}
- if evStoredCdr.TOR != jsnStoredCdr.TOR {
- t.Errorf("evStoredCdr.TOR: %s, jsnStoredCdr.TOR: %s", evStoredCdr.TOR, jsnStoredCdr.TOR)
+ if evStoredCdr.ToR != jsnStoredCdr.ToR {
+ t.Errorf("evStoredCdr.ToR: %s, jsnStoredCdr.ToR: %s", evStoredCdr.ToR, jsnStoredCdr.ToR)
}
- if evStoredCdr.AccId != jsnStoredCdr.AccId {
- t.Errorf("evStoredCdr.AccId: %s, jsnStoredCdr.AccId: %s", evStoredCdr.AccId, jsnStoredCdr.AccId)
+ if evStoredCdr.OriginID != jsnStoredCdr.OriginID {
+ t.Errorf("evStoredCdr.OriginID: %s, jsnStoredCdr.OriginID: %s", evStoredCdr.OriginID, jsnStoredCdr.OriginID)
}
- if evStoredCdr.ReqType != jsnStoredCdr.ReqType {
- t.Errorf("evStoredCdr.ReqType: %s, jsnStoredCdr.ReqType: %s", evStoredCdr.ReqType, jsnStoredCdr.ReqType)
+ if evStoredCdr.RequestType != jsnStoredCdr.RequestType {
+ t.Errorf("evStoredCdr.RequestType: %s, jsnStoredCdr.RequestType: %s", evStoredCdr.RequestType, jsnStoredCdr.RequestType)
}
if evStoredCdr.Direction != jsnStoredCdr.Direction {
t.Errorf("evStoredCdr.Direction: %s, jsnStoredCdr.Direction: %s", evStoredCdr.Direction, jsnStoredCdr.Direction)
@@ -591,8 +591,8 @@ func TestEvCdrCorelate(t *testing.T) {
if evStoredCdr.SetupTime != jsnStoredCdr.SetupTime {
t.Errorf("evStoredCdr.SetupTime: %v, jsnStoredCdr.SetupTime: %v", evStoredCdr.SetupTime, jsnStoredCdr.SetupTime)
}
- if evStoredCdr.Pdd != jsnStoredCdr.Pdd {
- t.Errorf("evStoredCdr.Pdd: %v, jsnStoredCdr.Pdd: %v", evStoredCdr.Pdd, jsnStoredCdr.Pdd)
+ if evStoredCdr.PDD != jsnStoredCdr.PDD {
+ t.Errorf("evStoredCdr.PDD: %v, jsnStoredCdr.PDD: %v", evStoredCdr.PDD, jsnStoredCdr.PDD)
}
if evStoredCdr.AnswerTime != jsnStoredCdr.AnswerTime {
t.Errorf("evStoredCdr.AnswerTime: %v, jsnStoredCdr.AnswerTime: %v", evStoredCdr.AnswerTime, jsnStoredCdr.AnswerTime)
diff --git a/general_tests/multiplecdrc_local_test.go b/general_tests/multiplecdrc_local_test.go
index d0d704754..0d393554e 100644
--- a/general_tests/multiplecdrc_local_test.go
+++ b/general_tests/multiplecdrc_local_test.go
@@ -92,10 +92,8 @@ func TestMCDRCEmptyTables(t *testing.T) {
t.Fatal("Error on mysql creation: ", err.Error())
return // No point in going further
}
- for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} {
- if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {
- t.Fatal(err.Error())
- }
+ if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", utils.TBL_CDRS)); err != nil {
+ t.Fatal(err.Error())
}
}
diff --git a/general_tests/suretax_it_test.go b/general_tests/suretax_it_test.go
index b5eacd153..43d9575c9 100644
--- a/general_tests/suretax_it_test.go
+++ b/general_tests/suretax_it_test.go
@@ -133,11 +133,11 @@ func TestSTIProcessExternalCdr(t *testing.T) {
if !*testSureTax {
return
}
- cdr := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "teststicdr1", CdrHost: "192.168.1.1", CdrSource: "STI_TEST", ReqType: utils.META_RATED, Direction: utils.OUT,
+ cdr := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "teststicdr1", OriginHost: "192.168.1.1", Source: "STI_TEST", RequestType: utils.META_RATED, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "+14082342500", Destination: "+16268412300", Supplier: "SUPPL1",
SetupTime: "2015-10-18T13:00:00Z", AnswerTime: "2015-10-18T13:00:00Z",
- Usage: "15s", Pdd: "7.0", ExtraFields: map[string]string{"CustomerNumber": "000000534", "ZipCode": ""},
+ Usage: "15s", PDD: "7.0", ExtraFields: map[string]string{"CustomerNumber": "000000534", "ZipCode": ""},
}
var reply string
if err := stiRpc.Call("CdrsV2.ProcessExternalCdr", cdr, &reply); err != nil {
@@ -152,8 +152,8 @@ func TestSTIGetCdrs(t *testing.T) {
if !*testSureTax {
return
}
- var cdrs []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}}
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}}
if err := stiRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
@@ -163,7 +163,7 @@ func TestSTIGetCdrs(t *testing.T) {
t.Errorf("Unexpected Cost for CDR: %+v", cdrs[0])
}
}
- req = utils.RpcCdrsFilter{RunIds: []string{utils.META_SURETAX}, Accounts: []string{"1001"}}
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_SURETAX}, Accounts: []string{"1001"}}
if err := stiRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
diff --git a/general_tests/tutorial_fs_calls_test.go b/general_tests/tutorial_fs_calls_test.go
index 7d9494e5e..ae097294f 100644
--- a/general_tests/tutorial_fs_calls_test.go
+++ b/general_tests/tutorial_fs_calls_test.go
@@ -330,21 +330,21 @@ func TestTutFsCalls1001Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- var cgrId string // Share with getCostDetails
+ var reply []*engine.ExternalCDR
+ var CGRID string // Share with getCostDetails
var cCost engine.CallCost
- req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1002"}}
+ req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1002"}}
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- cgrId = reply[0].CgrId
- if reply[0].CdrSource != "freeswitch_json" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ CGRID = reply[0].CGRID
+ if reply[0].Source != "freeswitch_json" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Usage != "67" { // Usage as seconds
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
@@ -357,21 +357,21 @@ func TestTutFsCalls1001Cdrs(t *testing.T) {
//}
}
// Make sure call cost contains the matched information
- if err := tutFsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil {
+ if err := tutFsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: CGRID}, &cCost); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") {
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
}
- req = utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1003"}}
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1003"}}
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- cgrId = reply[0].CgrId
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ CGRID = reply[0].CGRID
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
@@ -381,19 +381,19 @@ func TestTutFsCalls1001Cdrs(t *testing.T) {
}
}
// Make sure call cost contains the matched information
- if err := tutFsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil {
+ if err := tutFsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: CGRID}, &cCost); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") {
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
}
- req = utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{"derived_run1"}, FilterOnRated: true}
+ req = utils.RPCCDRsFilter{Accounts: []string{"1001"}, RunIDs: []string{"derived_run1"}}
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].ReqType != utils.META_RATED {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_RATED {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Subject != "1002" {
t.Errorf("Unexpected Subject for CDR: %+v", reply[0])
@@ -407,18 +407,18 @@ func TestTutFsCalls1002Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1002"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 { // Should be counted here also call originated form 1006 which is aliased to 1002
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "freeswitch_json" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "freeswitch_json" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_POSTPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_POSTPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -434,18 +434,18 @@ func TestTutFsCalls1003Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1003"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "freeswitch_json" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "freeswitch_json" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PSEUDOPREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PSEUDOPREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -462,18 +462,18 @@ func TestTutFsCalls1004Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1004"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "freeswitch_json" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "freeswitch_json" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_RATED {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_RATED {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -490,8 +490,8 @@ func TestTutFsCalls1006Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1006"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 0 {
@@ -504,18 +504,18 @@ func TestTutFsCalls1007Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1007"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "freeswitch_json" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "freeswitch_json" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1002" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
diff --git a/general_tests/tutorial_kam_calls_test.go b/general_tests/tutorial_kam_calls_test.go
index c9f90885d..a724d6122 100644
--- a/general_tests/tutorial_kam_calls_test.go
+++ b/general_tests/tutorial_kam_calls_test.go
@@ -330,21 +330,21 @@ func TestTutKamCalls1001Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
+ var reply []*engine.ExternalCDR
var cgrId string // Share with getCostDetails
var cCost engine.CallCost
- req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1002"}}
+ req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1002"}}
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- cgrId = reply[0].CgrId
- if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ cgrId = reply[0].CGRID
+ if reply[0].Source != "KAMAILIO_CGR_CALL_END" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Usage != "67" { // Usage as seconds
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
@@ -363,15 +363,15 @@ func TestTutKamCalls1001Cdrs(t *testing.T) {
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
}
- req = utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1003"}}
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1003"}}
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- cgrId = reply[0].CgrId
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ cgrId = reply[0].CGRID
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
@@ -386,14 +386,14 @@ func TestTutKamCalls1001Cdrs(t *testing.T) {
} else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") {
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
}
- req = utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{"derived_run1"}, FilterOnRated: true}
+ req = utils.RPCCDRsFilter{Accounts: []string{"1001"}, RunIDs: []string{"derived_run1"}}
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].ReqType != utils.META_RATED {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_RATED {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Subject != "1002" {
t.Errorf("Unexpected Subject for CDR: %+v", reply[0])
@@ -407,18 +407,18 @@ func TestTutKamCalls1002Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1002"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "KAMAILIO_CGR_CALL_END" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_POSTPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_POSTPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -434,18 +434,18 @@ func TestTutKamCalls1003Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1003"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "KAMAILIO_CGR_CALL_END" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PSEUDOPREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PSEUDOPREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -462,18 +462,18 @@ func TestTutKamCalls1004Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1004"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "KAMAILIO_CGR_CALL_END" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_RATED {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_RATED {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -490,8 +490,8 @@ func TestTutKamCalls1006Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1006"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 0 {
@@ -504,18 +504,18 @@ func TestTutKamCalls1007Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1007"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "KAMAILIO_CGR_CALL_END" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1002" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
diff --git a/general_tests/tutorial_local_test.go b/general_tests/tutorial_local_test.go
index db6e1d1c7..4bd82c70b 100644
--- a/general_tests/tutorial_local_test.go
+++ b/general_tests/tutorial_local_test.go
@@ -418,12 +418,12 @@ func TestTutLocalDerivedMaxSessionTime(t *testing.T) {
return
}
tStart := time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC)
- ev := engine.StoredCdr{
- CgrId: utils.Sha1("testevent1", tStart.String()),
- TOR: utils.VOICE,
- AccId: "testevent1",
- CdrHost: "127.0.0.1",
- ReqType: utils.META_PREPAID,
+ ev := engine.CDR{
+ CGRID: utils.Sha1("testevent1", tStart.String()),
+ ToR: utils.VOICE,
+ OriginID: "testevent1",
+ OriginHost: "127.0.0.1",
+ RequestType: utils.META_PREPAID,
Direction: utils.OUT,
Tenant: "cgrates.org",
Category: "call",
@@ -449,7 +449,7 @@ func TestTutLocalMaxUsage(t *testing.T) {
if !*testLocal {
return
}
- setupReq := &engine.UsageRecord{TOR: utils.VOICE, ReqType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call",
+ setupReq := &engine.UsageRecord{ToR: utils.VOICE, RequestType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call",
Account: "1003", Subject: "1003", Destination: "1001",
SetupTime: "2014-08-04T13:00:00Z", Usage: "1",
}
@@ -459,7 +459,7 @@ func TestTutLocalMaxUsage(t *testing.T) {
} else if maxTime != 1 {
t.Errorf("Calling ApierV2.MaxUsage got maxTime: %f", maxTime)
}
- setupReq = &engine.UsageRecord{TOR: utils.VOICE, ReqType: utils.META_RATED, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call",
+ setupReq = &engine.UsageRecord{ToR: utils.VOICE, RequestType: utils.META_RATED, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call",
Account: "test_max_usage", Destination: "1001",
SetupTime: "2014-08-04T13:00:00Z",
}
@@ -475,7 +475,7 @@ func TestTutLocalDebitUsage(t *testing.T) {
if !*testLocal {
return
}
- setupReq := &engine.UsageRecord{TOR: utils.VOICE, ReqType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call",
+ setupReq := &engine.UsageRecord{ToR: utils.VOICE, RequestType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call",
Account: "1003", Subject: "1003", Destination: "1001",
AnswerTime: "2014-08-04T13:00:00Z", Usage: "1",
}
@@ -492,11 +492,11 @@ func TestTutLocalProcessExternalCdr(t *testing.T) {
if !*testLocal {
return
}
- cdr := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "testextcdr1", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: utils.OUT,
+ cdr := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "testextcdr1", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1001", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "1", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Usage: "1", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
var reply string
if err := tutLocalRpc.Call("CdrsV2.ProcessExternalCdr", cdr, &reply); err != nil {
@@ -511,11 +511,11 @@ func TestTutLocalProcessExternalCdrUP(t *testing.T) {
if !*testLocal {
return
}
- cdr := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "testextcdr2", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, Direction: utils.OUT,
- ReqType: utils.USERS, Tenant: utils.USERS, Account: utils.USERS, Destination: "1001", Supplier: "SUPPL1",
+ cdr := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "testextcdr2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, Direction: utils.OUT,
+ RequestType: utils.USERS, Tenant: utils.USERS, Account: utils.USERS, Destination: "1001", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "2", Pdd: "0.2", DisconnectCause: "NORMAL_DISCONNECT",
+ Usage: "2", PDD: "0.2", DisconnectCause: "NORMAL_DISCONNECT",
ExtraFields: map[string]string{"Cli": "+4986517174964", "fieldextr2": "valextr2", "SysUserName": utils.USERS},
}
var reply string
@@ -524,32 +524,33 @@ func TestTutLocalProcessExternalCdrUP(t *testing.T) {
} else if reply != utils.OK {
t.Error("Unexpected reply received: ", reply)
}
- eCdr := &engine.ExternalCdr{CgrId: "63a8d2bfeca2cfb790826c3ec461696d6574cfde", OrderId: 2,
- TOR: utils.VOICE,
- AccId: "testextcdr2", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: utils.OUT,
+ time.Sleep(time.Duration(*waitRater) * time.Millisecond)
+ eCdr := &engine.ExternalCDR{CGRID: "63a8d2bfeca2cfb790826c3ec461696d6574cfde", OrderID: 2,
+ ToR: utils.VOICE,
+ OriginID: "testextcdr2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "call", Account: "1004", Subject: "1004", Destination: "1001", Supplier: "SUPPL1",
SetupTime: time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC).Local().Format(time.RFC3339), AnswerTime: time.Date(2014, 8, 4, 13, 0, 7, 0, time.UTC).Local().Format(time.RFC3339),
- Usage: "2", Pdd: "0.2", DisconnectCause: "NORMAL_DISCONNECT",
- ExtraFields: map[string]string{"Cli": "+4986517174964", "fieldextr2": "valextr2", "SysUserName": "danb4"},
- MediationRunId: utils.DEFAULT_RUNID, Cost: 1}
- var cdrs []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1004"}, DestPrefixes: []string{"1001"}}
+ Usage: "2", PDD: "0.2", DisconnectCause: "NORMAL_DISCONNECT",
+ ExtraFields: map[string]string{"Cli": "+4986517174964", "fieldextr2": "valextr2", "SysUserName": "danb4"},
+ RunID: utils.DEFAULT_RUNID, Cost: 1}
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1004"}, DestinationPrefixes: []string{"1001"}}
if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
} else {
- if cdrs[0].CgrId != eCdr.CgrId {
- t.Errorf("Unexpected CgrId for CDR: %+v", cdrs[0])
+ if cdrs[0].CGRID != eCdr.CGRID {
+ t.Errorf("Unexpected CGRID for CDR: %+v", cdrs[0])
}
- if cdrs[0].TOR != eCdr.TOR {
+ if cdrs[0].ToR != eCdr.ToR {
t.Errorf("Unexpected TOR for CDR: %+v", cdrs[0])
}
- if cdrs[0].CdrSource != eCdr.CdrSource {
- t.Errorf("Unexpected CdrSource for CDR: %+v", cdrs[0])
+ if cdrs[0].Source != eCdr.Source {
+ t.Errorf("Unexpected Source for CDR: %+v", cdrs[0])
}
- if cdrs[0].ReqType != eCdr.ReqType {
- t.Errorf("Unexpected ReqType for CDR: %+v", cdrs[0])
+ if cdrs[0].RequestType != eCdr.RequestType {
+ t.Errorf("Unexpected RequestType for CDR: %+v", cdrs[0])
}
if cdrs[0].Tenant != eCdr.Tenant {
t.Errorf("Unexpected Tenant for CDR: %+v", cdrs[0])
@@ -572,8 +573,8 @@ func TestTutLocalProcessExternalCdrUP(t *testing.T) {
if cdrs[0].SetupTime != eCdr.SetupTime {
t.Errorf("Unexpected SetupTime for CDR: %+v", cdrs[0])
}
- if cdrs[0].Pdd != eCdr.Pdd {
- t.Errorf("Unexpected Pdd for CDR: %+v", cdrs[0])
+ if cdrs[0].PDD != eCdr.PDD {
+ t.Errorf("Unexpected PDD for CDR: %+v", cdrs[0])
}
if cdrs[0].AnswerTime != eCdr.AnswerTime {
t.Errorf("Unexpected AnswerTime for CDR: %+v", cdrs[0])
@@ -591,11 +592,11 @@ func TestTutLocalCostErrors(t *testing.T) {
if !*testLocal {
return
}
- cdr := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "testtutlocal_1", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: utils.OUT,
+ cdr := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "testtutlocal_1", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "fake", Account: "2001", Subject: "2001", Destination: "1001", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "1", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Usage: "1", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
var reply string
if err := tutLocalRpc.Call("CdrsV2.ProcessExternalCdr", cdr, &reply); err != nil {
@@ -604,25 +605,25 @@ func TestTutLocalCostErrors(t *testing.T) {
t.Error("Unexpected reply received: ", reply)
}
time.Sleep(time.Duration(*waitRater) * time.Millisecond)
- var cdrs []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{cdr.Account}, DestPrefixes: []string{cdr.Destination}}
+ var cdrs []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr.Account}, DestinationPrefixes: []string{cdr.Destination}}
if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
} else {
- if cdrs[0].AccId != cdr.AccId {
- t.Errorf("Unexpected AccId for Cdr received: %+v", cdrs[0])
+ if cdrs[0].OriginID != cdr.OriginID {
+ t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0])
}
if cdrs[0].Cost != -1 {
t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0])
}
}
- cdr2 := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "testtutlocal_2", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_POSTPAID, Direction: utils.OUT,
+ cdr2 := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "testtutlocal_2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "fake", Account: "2002", Subject: "2002", Destination: "1001", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "1", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Usage: "1", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
if err := tutLocalRpc.Call("CdrsV2.ProcessExternalCdr", cdr2, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
@@ -630,24 +631,24 @@ func TestTutLocalCostErrors(t *testing.T) {
t.Error("Unexpected reply received: ", reply)
}
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for CDR to be processed
- req = utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{cdr2.Account}, DestPrefixes: []string{cdr2.Destination}}
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr2.Account}, DestinationPrefixes: []string{cdr2.Destination}}
if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
} else {
- if cdrs[0].AccId != cdr2.AccId {
- t.Errorf("Unexpected AccId for Cdr received: %+v", cdrs[0])
+ if cdrs[0].OriginID != cdr2.OriginID {
+ t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0])
}
if cdrs[0].Cost != -1 {
t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0])
}
}
- cdr3 := &engine.ExternalCdr{TOR: utils.VOICE,
- AccId: "testtutlocal_3", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_POSTPAID, Direction: utils.OUT,
+ cdr3 := &engine.ExternalCDR{ToR: utils.VOICE,
+ OriginID: "testtutlocal_3", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, Direction: utils.OUT,
Tenant: "cgrates.org", Category: "fake", Account: "1001", Subject: "1001", Destination: "2002", Supplier: "SUPPL1",
SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z",
- Usage: "1", Pdd: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
+ Usage: "1", PDD: "7.0", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
}
if err := tutLocalRpc.Call("CdrsV2.ProcessExternalCdr", cdr3, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
@@ -655,14 +656,14 @@ func TestTutLocalCostErrors(t *testing.T) {
t.Error("Unexpected reply received: ", reply)
}
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for CDR to be processed
- req = utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{cdr3.Account}, DestPrefixes: []string{cdr3.Destination}}
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr3.Account}, DestinationPrefixes: []string{cdr3.Destination}}
if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(cdrs) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
} else {
- if cdrs[0].AccId != cdr3.AccId {
- t.Errorf("Unexpected AccId for Cdr received: %+v", cdrs[0])
+ if cdrs[0].OriginID != cdr3.OriginID {
+ t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0])
}
if cdrs[0].Cost != -1 {
t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0])
@@ -822,20 +823,20 @@ func TestTutLocalLcrQos(t *testing.T) {
t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0])
}
// Post some CDRs to influence stats
- testCdr1 := &engine.StoredCdr{CgrId: utils.Sha1("testcdr1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
- TOR: utils.VOICE, AccId: "testcdr1", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED,
+ testCdr1 := &engine.CDR{CGRID: utils.Sha1("testcdr1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
+ ToR: utils.VOICE, OriginID: "testcdr1", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC),
Usage: time.Duration(2) * time.Minute, Supplier: "suppl1",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}}
- testCdr2 := &engine.StoredCdr{CgrId: utils.Sha1("testcdr2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
- TOR: utils.VOICE, AccId: "testcdr2", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED,
+ testCdr2 := &engine.CDR{CGRID: utils.Sha1("testcdr2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
+ ToR: utils.VOICE, OriginID: "testcdr2", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", Destination: "1003",
SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC),
Usage: time.Duration(90) * time.Second, Supplier: "suppl2",
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}}
var reply string
- for _, cdr := range []*engine.StoredCdr{testCdr1, testCdr2} {
+ for _, cdr := range []*engine.CDR{testCdr1, testCdr2} {
if err := tutLocalRpc.Call("CdrsV2.ProcessCdr", cdr, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if reply != utils.OK {
@@ -860,8 +861,8 @@ func TestTutLocalLcrQos(t *testing.T) {
//} else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) {
// t.Errorf("Expecting: %+v, %+v, received: %+v, %+v", eStLcr.SupplierCosts[0], eStLcr.SupplierCosts[1], lcr.SupplierCosts[0], lcr.SupplierCosts[1])
}
- testCdr3 := &engine.StoredCdr{CgrId: utils.Sha1("testcdr3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
- TOR: utils.VOICE, AccId: "testcdr3", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED,
+ testCdr3 := &engine.CDR{CGRID: utils.Sha1("testcdr3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
+ ToR: utils.VOICE, OriginID: "testcdr3", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004",
SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC),
Usage: time.Duration(180) * time.Second, Supplier: "suppl2"}
@@ -924,8 +925,8 @@ func TestTutLocalLcrQosThreshold(t *testing.T) {
//} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) {
// t.Errorf("Expecting: %+v, %+v received: %+v, %+v", eLcr.SupplierCosts[0], eLcr.SupplierCosts[1], lcr.SupplierCosts[0], lcr.SupplierCosts[1])
}
- testCdr4 := &engine.StoredCdr{CgrId: utils.Sha1("testcdr4", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
- TOR: utils.VOICE, AccId: "testcdr4", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED,
+ testCdr4 := &engine.CDR{CGRID: utils.Sha1("testcdr4", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
+ ToR: utils.VOICE, OriginID: "testcdr4", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004",
SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC),
Usage: time.Duration(60) * time.Second, Supplier: "suppl2"}
@@ -987,8 +988,8 @@ func TestTutLocalLcrQosThreshold(t *testing.T) {
//} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eLcr2.SupplierCosts, lcr.SupplierCosts) {
// t.Errorf("Expecting: %+v, received: %+v", eLcr.SupplierCosts[1], lcr.SupplierCosts[1])
}
- testCdr5 := &engine.StoredCdr{CgrId: utils.Sha1("testcdr5", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
- TOR: utils.VOICE, AccId: "testcdr5", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED,
+ testCdr5 := &engine.CDR{CGRID: utils.Sha1("testcdr5", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
+ ToR: utils.VOICE, OriginID: "testcdr5", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED,
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004",
SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC),
Usage: time.Duration(1) * time.Second, Supplier: "suppl2"}
diff --git a/general_tests/tutorial_osips_calls_test.go b/general_tests/tutorial_osips_calls_test.go
index 2ee358950..30cb0590b 100644
--- a/general_tests/tutorial_osips_calls_test.go
+++ b/general_tests/tutorial_osips_calls_test.go
@@ -330,21 +330,21 @@ func TestTutOsipsCalls1001Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
+ var reply []*engine.ExternalCDR
var cgrId string // Share with getCostDetails
var cCost engine.CallCost
- req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1002"}}
+ req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1002"}}
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- cgrId = reply[0].CgrId
- if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ cgrId = reply[0].CGRID
+ if reply[0].Source != "OSIPS_E_ACC_EVENT" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Usage != "67" { // Usage as seconds
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
@@ -363,15 +363,15 @@ func TestTutOsipsCalls1001Cdrs(t *testing.T) {
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
}
- req = utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1003"}}
+ req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1003"}}
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- cgrId = reply[0].CgrId
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ cgrId = reply[0].CGRID
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
@@ -386,14 +386,14 @@ func TestTutOsipsCalls1001Cdrs(t *testing.T) {
} else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") {
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
}
- req = utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{"derived_run1"}, FilterOnRated: true}
+ req = utils.RPCCDRsFilter{Accounts: []string{"1001"}, RunIDs: []string{"derived_run1"}}
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].ReqType != utils.META_RATED {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_RATED {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Subject != "1002" {
t.Errorf("Unexpected Subject for CDR: %+v", reply[0])
@@ -407,18 +407,18 @@ func TestTutOsipsCalls1002Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1002"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 2 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "OSIPS_E_ACC_EVENT" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_POSTPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_POSTPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -434,18 +434,18 @@ func TestTutOsipsCalls1003Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1003"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "OSIPS_E_ACC_EVENT" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PSEUDOPREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PSEUDOPREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -462,18 +462,18 @@ func TestTutOsipsCalls1004Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1004"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "OSIPS_E_ACC_EVENT" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_RATED {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_RATED {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1001" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
@@ -490,8 +490,8 @@ func TestTutOsipsCalls1006Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1006"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 0 {
@@ -504,18 +504,18 @@ func TestTutOsipsCalls1007Cdrs(t *testing.T) {
if !*testCalls {
return
}
- var reply []*engine.ExternalCdr
- req := utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
+ var reply []*engine.ExternalCDR
+ req := utils.RPCCDRsFilter{Accounts: []string{"1007"}, RunIDs: []string{utils.META_DEFAULT}}
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if len(reply) != 1 {
t.Error("Unexpected number of CDRs returned: ", len(reply))
} else {
- if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" {
- t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
+ if reply[0].Source != "OSIPS_E_ACC_EVENT" {
+ t.Errorf("Unexpected Source for CDR: %+v", reply[0])
}
- if reply[0].ReqType != utils.META_PREPAID {
- t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
+ if reply[0].RequestType != utils.META_PREPAID {
+ t.Errorf("Unexpected RequestType for CDR: %+v", reply[0])
}
if reply[0].Destination != "1002" {
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
diff --git a/local_test.sh b/local_test.sh
index b2089608c..b35a4e809 100755
--- a/local_test.sh
+++ b/local_test.sh
@@ -8,8 +8,8 @@ ap1=$?
echo 'go test github.com/cgrates/cgrates/apier/v2 -local'
go test github.com/cgrates/cgrates/apier/v2 -local
ap2=$?
-echo 'go test github.com/cgrates/cgrates/engine -local'
-go test github.com/cgrates/cgrates/engine -local
+echo 'go test github.com/cgrates/cgrates/engine -local -integration'
+go test github.com/cgrates/cgrates/engine -local -integration
en=$?
echo 'go test github.com/cgrates/cgrates/cdrc -local'
go test github.com/cgrates/cgrates/cdrc -local
@@ -18,8 +18,10 @@ echo 'go test github.com/cgrates/cgrates/config -local'
go test github.com/cgrates/cgrates/config -local
cfg=$?
echo 'go test github.com/cgrates/cgrates/utils -local'
-echo 'go test github.com/cgrates/cgrates/general_tests -local'
-go test github.com/cgrates/cgrates/general_tests -local
+go test github.com/cgrates/cgrates/utils -local
+utl=$?
+echo 'go test github.com/cgrates/cgrates/general_tests -local -integration'
+go test github.com/cgrates/cgrates/general_tests -local -integration
gnr=$?
echo 'go test github.com/cgrates/cgrates/agents -integration'
go test github.com/cgrates/cgrates/agents -integration
@@ -29,4 +31,4 @@ agts=$?
-exit $gen && $ap1 && $ap2 && $en && $cdrc && $cfg && $gnr && $agts
+exit $gen && $ap1 && $ap2 && $en && $cdrc && $cfg && $utl && $gnr && $agts
diff --git a/sessionmanager/fsevent.go b/sessionmanager/fsevent.go
index 905239d70..4ba9bdd4c 100644
--- a/sessionmanager/fsevent.go
+++ b/sessionmanager/fsevent.go
@@ -182,7 +182,7 @@ func (fsev FSEvent) MissingParameter(timezone string) bool {
func (fsev FSEvent) GetSetupTime(fieldName, timezone string) (t time.Time, err error) {
fsSTimeStr, hasKey := fsev[SETUP_TIME]
if hasKey && fsSTimeStr != "0" {
- // Discard the nanoseconds information since MySQL cannot store them in early versions and csv uses default seconds so cgrid will not corelate
+ // Discard the nanoseconds information since MySQL cannot store them in early versions and csv uses default seconds so CGRID will not corelate
fsSTimeStr = fsSTimeStr[:len(fsSTimeStr)-6]
}
sTimeStr := utils.FirstNonEmpty(fsev[fieldName], fsSTimeStr)
@@ -194,7 +194,7 @@ func (fsev FSEvent) GetSetupTime(fieldName, timezone string) (t time.Time, err e
func (fsev FSEvent) GetAnswerTime(fieldName, timezone string) (t time.Time, err error) {
fsATimeStr, hasKey := fsev[ANSWER_TIME]
if hasKey && fsATimeStr != "0" {
- // Discard the nanoseconds information since MySQL cannot store them in early versions and csv uses default seconds so cgrid will not corelate
+ // Discard the nanoseconds information since MySQL cannot store them in early versions and csv uses default seconds so CGRID will not corelate
fsATimeStr = fsATimeStr[:len(fsATimeStr)-6]
}
aTimeStr := utils.FirstNonEmpty(fsev[fieldName], fsATimeStr)
@@ -217,18 +217,18 @@ func (fsev FSEvent) GetDuration(fieldName string) (time.Duration, error) {
}
func (fsev FSEvent) GetPdd(fieldName string) (time.Duration, error) {
- var pddStr string
+ var PDDStr string
if utils.IsSliceMember([]string{utils.PDD, utils.META_DEFAULT}, fieldName) {
- pddStr = utils.FirstNonEmpty(fsev[PDD_MEDIA_MS], fsev[PDD_NOMEDIA_MS])
- if len(pddStr) != 0 {
- pddStr = pddStr + "ms" // PDD is in milliseconds and CGR expects it in seconds
+ PDDStr = utils.FirstNonEmpty(fsev[PDD_MEDIA_MS], fsev[PDD_NOMEDIA_MS])
+ if len(PDDStr) != 0 {
+ PDDStr = PDDStr + "ms" // PDD is in milliseconds and CGR expects it in seconds
}
} else if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
- pddStr = fieldName[len(utils.STATIC_VALUE_PREFIX):]
+ PDDStr = fieldName[len(utils.STATIC_VALUE_PREFIX):]
} else {
- pddStr = fsev[fieldName]
+ PDDStr = fsev[fieldName]
}
- return utils.ParseDurationWithSecs(pddStr)
+ return utils.ParseDurationWithSecs(PDDStr)
}
func (fsev FSEvent) GetSupplier(fieldName string) string {
@@ -297,8 +297,8 @@ func (fsev FSEvent) ParseEventValue(rsrFld *utils.RSRField, timezone string) str
dur, _ := fsev.GetDuration("")
return rsrFld.ParseValue(strconv.FormatInt(dur.Nanoseconds(), 10))
case utils.PDD:
- pdd, _ := fsev.GetPdd(utils.META_DEFAULT)
- return rsrFld.ParseValue(strconv.FormatFloat(pdd.Seconds(), 'f', -1, 64))
+ PDD, _ := fsev.GetPdd(utils.META_DEFAULT)
+ return rsrFld.ParseValue(strconv.FormatFloat(PDD.Seconds(), 'f', -1, 64))
case utils.SUPPLIER:
return rsrFld.ParseValue(fsev.GetSupplier(""))
case utils.DISCONNECT_CAUSE:
@@ -337,14 +337,14 @@ func (fsev FSEvent) PassesFieldFilter(fieldFilter *utils.RSRField) (bool, string
return false, ""
}
-func (fsev FSEvent) AsStoredCdr(timezone string) *engine.StoredCdr {
- storCdr := new(engine.StoredCdr)
- storCdr.CgrId = fsev.GetCgrId(timezone)
- storCdr.TOR = utils.VOICE
- storCdr.AccId = fsev.GetUUID()
- storCdr.CdrHost = fsev.GetOriginatorIP(utils.META_DEFAULT)
- storCdr.CdrSource = "FS_" + fsev.GetName()
- storCdr.ReqType = fsev.GetReqType(utils.META_DEFAULT)
+func (fsev FSEvent) AsStoredCdr(timezone string) *engine.CDR {
+ storCdr := new(engine.CDR)
+ storCdr.CGRID = fsev.GetCgrId(timezone)
+ storCdr.ToR = utils.VOICE
+ storCdr.OriginID = fsev.GetUUID()
+ storCdr.OriginHost = fsev.GetOriginatorIP(utils.META_DEFAULT)
+ storCdr.Source = "FS_" + fsev.GetName()
+ storCdr.RequestType = fsev.GetReqType(utils.META_DEFAULT)
storCdr.Direction = fsev.GetDirection(utils.META_DEFAULT)
storCdr.Tenant = fsev.GetTenant(utils.META_DEFAULT)
storCdr.Category = fsev.GetCategory(utils.META_DEFAULT)
@@ -354,7 +354,7 @@ func (fsev FSEvent) AsStoredCdr(timezone string) *engine.StoredCdr {
storCdr.SetupTime, _ = fsev.GetSetupTime(utils.META_DEFAULT, timezone)
storCdr.AnswerTime, _ = fsev.GetAnswerTime(utils.META_DEFAULT, timezone)
storCdr.Usage, _ = fsev.GetDuration(utils.META_DEFAULT)
- storCdr.Pdd, _ = fsev.GetPdd(utils.META_DEFAULT)
+ storCdr.PDD, _ = fsev.GetPdd(utils.META_DEFAULT)
storCdr.ExtraFields = fsev.GetExtraFields()
storCdr.Cost = -1
storCdr.Supplier = fsev.GetSupplier(utils.META_DEFAULT)
diff --git a/sessionmanager/fsevent_test.go b/sessionmanager/fsevent_test.go
index 30647505c..3dbb6c7e7 100644
--- a/sessionmanager/fsevent_test.go
+++ b/sessionmanager/fsevent_test.go
@@ -633,11 +633,12 @@ func TestFsEvAsStoredCdr(t *testing.T) {
ev := new(FSEvent).AsEvent(hangupEv)
setupTime, _ := utils.ParseTimeDetectLayout("1436280728", "")
aTime, _ := utils.ParseTimeDetectLayout("1436280728", "")
- eStoredCdr := &engine.StoredCdr{CgrId: "164b0422fdc6a5117031b427439482c6a4f90e41",
- TOR: utils.VOICE, AccId: "e3133bf7-dcde-4daf-9663-9a79ffcef5ad", CdrHost: "10.0.3.15", CdrSource: "FS_CHANNEL_HANGUP_COMPLETE", ReqType: utils.META_PREPAID,
+ eStoredCdr := &engine.CDR{CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41",
+ ToR: utils.VOICE, OriginID: "e3133bf7-dcde-4daf-9663-9a79ffcef5ad", OriginHost: "10.0.3.15", Source: "FS_CHANNEL_HANGUP_COMPLETE", RequestType: utils.META_PREPAID,
Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001",
Destination: "1003", SetupTime: setupTime, AnswerTime: aTime,
- Usage: time.Duration(66) * time.Second, Pdd: time.Duration(28) * time.Millisecond, Supplier: "supplier1", DisconnectCause: "NORMAL_CLEARING", ExtraFields: make(map[string]string), Cost: -1}
+ Usage: time.Duration(66) * time.Second, PDD: time.Duration(28) * time.Millisecond, Supplier: "supplier1",
+ DisconnectCause: "NORMAL_CLEARING", ExtraFields: make(map[string]string), Cost: -1}
if storedCdr := ev.AsStoredCdr(""); !reflect.DeepEqual(eStoredCdr, storedCdr) {
t.Errorf("Expecting: %+v, received: %+v", eStoredCdr, storedCdr)
}
diff --git a/sessionmanager/fssessionmanager.go b/sessionmanager/fssessionmanager.go
index bc7d7982c..3bd1bc215 100644
--- a/sessionmanager/fssessionmanager.go
+++ b/sessionmanager/fssessionmanager.go
@@ -296,10 +296,10 @@ func (sm *FSSessionManager) DisconnectSession(ev engine.Event, connId, notify st
return nil
}
-func (sm *FSSessionManager) ProcessCdr(storedCdr *engine.StoredCdr) error {
+func (sm *FSSessionManager) ProcessCdr(storedCdr *engine.CDR) error {
var reply string
if err := sm.cdrsrv.Call("CdrServer.ProcessCdr", storedCdr, &reply); err != nil {
- utils.Logger.Err(fmt.Sprintf(" Failed processing CDR, cgrid: %s, accid: %s, error: <%s>", storedCdr.CgrId, storedCdr.AccId, err.Error()))
+ utils.Logger.Err(fmt.Sprintf(" Failed processing CDR, cgrid: %s, accid: %s, error: <%s>", storedCdr.CGRID, storedCdr.OriginID, err.Error()))
}
return nil
}
diff --git a/sessionmanager/kamailiosm.go b/sessionmanager/kamailiosm.go
index 50034d7df..7d6dc3a15 100644
--- a/sessionmanager/kamailiosm.go
+++ b/sessionmanager/kamailiosm.go
@@ -205,13 +205,13 @@ func (self *KamailioSessionManager) Rater() rpcclient.RpcClientConnection {
return self.rater
}
-func (self *KamailioSessionManager) ProcessCdr(cdr *engine.StoredCdr) error {
+func (self *KamailioSessionManager) ProcessCdr(cdr *engine.CDR) error {
if !self.cfg.CreateCdr {
return nil
}
var reply string
if err := self.cdrsrv.Call("CdrServer.ProcessCdr", cdr, &reply); err != nil {
- utils.Logger.Err(fmt.Sprintf(" Failed processing CDR, cgrid: %s, accid: %s, error: <%s>", cdr.CgrId, cdr.AccId, err.Error()))
+ utils.Logger.Err(fmt.Sprintf(" Failed processing CDR, cgrid: %s, accid: %s, error: <%s>", cdr.CGRID, cdr.OriginID, err.Error()))
}
return nil
}
diff --git a/sessionmanager/kamevent.go b/sessionmanager/kamevent.go
index 4c9fe9fde..422498c0f 100644
--- a/sessionmanager/kamevent.go
+++ b/sessionmanager/kamevent.go
@@ -316,14 +316,14 @@ func (kev KamEvent) PassesFieldFilter(*utils.RSRField) (bool, string) {
return false, ""
}
-func (kev KamEvent) AsStoredCdr(timezone string) *engine.StoredCdr {
- storCdr := new(engine.StoredCdr)
- storCdr.CgrId = kev.GetCgrId(timezone)
- storCdr.TOR = utils.VOICE
- storCdr.AccId = kev.GetUUID()
- storCdr.CdrHost = kev.GetOriginatorIP(utils.META_DEFAULT)
- storCdr.CdrSource = kev.GetCdrSource()
- storCdr.ReqType = kev.GetReqType(utils.META_DEFAULT)
+func (kev KamEvent) AsStoredCdr(timezone string) *engine.CDR {
+ storCdr := new(engine.CDR)
+ storCdr.CGRID = kev.GetCgrId(timezone)
+ storCdr.ToR = utils.VOICE
+ storCdr.OriginID = kev.GetUUID()
+ storCdr.OriginHost = kev.GetOriginatorIP(utils.META_DEFAULT)
+ storCdr.Source = kev.GetCdrSource()
+ storCdr.RequestType = kev.GetReqType(utils.META_DEFAULT)
storCdr.Direction = kev.GetDirection(utils.META_DEFAULT)
storCdr.Tenant = kev.GetTenant(utils.META_DEFAULT)
storCdr.Category = kev.GetCategory(utils.META_DEFAULT)
@@ -333,7 +333,7 @@ func (kev KamEvent) AsStoredCdr(timezone string) *engine.StoredCdr {
storCdr.SetupTime, _ = kev.GetSetupTime(utils.META_DEFAULT, timezone)
storCdr.AnswerTime, _ = kev.GetAnswerTime(utils.META_DEFAULT, timezone)
storCdr.Usage, _ = kev.GetDuration(utils.META_DEFAULT)
- storCdr.Pdd, _ = kev.GetPdd(utils.META_DEFAULT)
+ storCdr.PDD, _ = kev.GetPdd(utils.META_DEFAULT)
storCdr.Supplier = kev.GetSupplier(utils.META_DEFAULT)
storCdr.DisconnectCause = kev.GetDisconnectCause(utils.META_DEFAULT)
storCdr.ExtraFields = kev.GetExtraFields()
diff --git a/sessionmanager/osipsevent.go b/sessionmanager/osipsevent.go
index 42332eba0..cbb5052f9 100644
--- a/sessionmanager/osipsevent.go
+++ b/sessionmanager/osipsevent.go
@@ -264,14 +264,14 @@ func (osipsev *OsipsEvent) DialogId() string {
return osipsev.osipsEvent.AttrValues[OSIPS_DIALOG_ID]
}
-func (osipsEv *OsipsEvent) AsStoredCdr(timezone string) *engine.StoredCdr {
- storCdr := new(engine.StoredCdr)
- storCdr.CgrId = osipsEv.GetCgrId(timezone)
- storCdr.TOR = utils.VOICE
- storCdr.AccId = osipsEv.GetUUID()
- storCdr.CdrHost = osipsEv.GetOriginatorIP(utils.META_DEFAULT)
- storCdr.CdrSource = "OSIPS_" + osipsEv.GetName()
- storCdr.ReqType = osipsEv.GetReqType(utils.META_DEFAULT)
+func (osipsEv *OsipsEvent) AsStoredCdr(timezone string) *engine.CDR {
+ storCdr := new(engine.CDR)
+ storCdr.CGRID = osipsEv.GetCgrId(timezone)
+ storCdr.ToR = utils.VOICE
+ storCdr.OriginID = osipsEv.GetUUID()
+ storCdr.OriginHost = osipsEv.GetOriginatorIP(utils.META_DEFAULT)
+ storCdr.Source = "OSIPS_" + osipsEv.GetName()
+ storCdr.RequestType = osipsEv.GetReqType(utils.META_DEFAULT)
storCdr.Direction = osipsEv.GetDirection(utils.META_DEFAULT)
storCdr.Tenant = osipsEv.GetTenant(utils.META_DEFAULT)
storCdr.Category = osipsEv.GetCategory(utils.META_DEFAULT)
@@ -281,7 +281,7 @@ func (osipsEv *OsipsEvent) AsStoredCdr(timezone string) *engine.StoredCdr {
storCdr.SetupTime, _ = osipsEv.GetSetupTime(utils.META_DEFAULT, timezone)
storCdr.AnswerTime, _ = osipsEv.GetAnswerTime(utils.META_DEFAULT, timezone)
storCdr.Usage, _ = osipsEv.GetDuration(utils.META_DEFAULT)
- storCdr.Pdd, _ = osipsEv.GetPdd(utils.META_DEFAULT)
+ storCdr.PDD, _ = osipsEv.GetPdd(utils.META_DEFAULT)
storCdr.Supplier = osipsEv.GetSupplier(utils.META_DEFAULT)
storCdr.DisconnectCause = osipsEv.GetDisconnectCause(utils.META_DEFAULT)
storCdr.ExtraFields = osipsEv.GetExtraFields()
diff --git a/sessionmanager/osipsevent_test.go b/sessionmanager/osipsevent_test.go
index 59b24c0e3..ac8c2b665 100644
--- a/sessionmanager/osipsevent_test.go
+++ b/sessionmanager/osipsevent_test.go
@@ -44,7 +44,7 @@ func TestOsipsEventParseStatic(t *testing.T) {
setupTime, _ := osipsEv.GetSetupTime("^2013-12-07 08:42:24", "")
answerTime, _ := osipsEv.GetAnswerTime("^2013-12-07 08:42:24", "")
dur, _ := osipsEv.GetDuration("^60s")
- pdd, _ := osipsEv.GetPdd("^10s")
+ PDD, _ := osipsEv.GetPdd("^10s")
if osipsEv.GetReqType("^test") != "test" ||
osipsEv.GetDirection("^test") != "test" ||
osipsEv.GetTenant("^test") != "test" ||
@@ -55,7 +55,7 @@ func TestOsipsEventParseStatic(t *testing.T) {
setupTime != time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC) ||
answerTime != time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC) ||
dur != time.Duration(60)*time.Second ||
- pdd != time.Duration(10)*time.Second ||
+ PDD != time.Duration(10)*time.Second ||
osipsEv.GetSupplier("^test") != "test" ||
osipsEv.GetDisconnectCause("^test") != "test" {
t.Error("Values out of static not matching",
@@ -69,7 +69,7 @@ func TestOsipsEventParseStatic(t *testing.T) {
setupTime != time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC),
answerTime != time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC),
dur != time.Duration(60)*time.Second,
- pdd != time.Duration(10)*time.Second,
+ PDD != time.Duration(10)*time.Second,
osipsEv.GetSupplier("^test") != "test",
osipsEv.GetDisconnectCause("^test") != "test")
}
@@ -83,7 +83,7 @@ func TestOsipsEventGetValues(t *testing.T) {
answerTime, _ := osipsEv.GetAnswerTime(utils.META_DEFAULT, "")
eAnswerTime, _ := utils.ParseTimeDetectLayout("1406370499", "")
dur, _ := osipsEv.GetDuration(utils.META_DEFAULT)
- pdd, _ := osipsEv.GetPdd(utils.META_DEFAULT)
+ PDD, _ := osipsEv.GetPdd(utils.META_DEFAULT)
endTime, _ := osipsEv.GetEndTime(utils.META_DEFAULT, "")
if osipsEv.GetName() != "E_ACC_CDR" ||
osipsEv.GetCgrId("") != utils.Sha1("ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", setupTime.UTC().String()) ||
@@ -100,7 +100,7 @@ func TestOsipsEventGetValues(t *testing.T) {
!answerTime.Equal(eAnswerTime) ||
!endTime.Equal(eAnswerTime.Add(dur)) ||
dur != time.Duration(20*time.Second) ||
- pdd != time.Duration(3)*time.Second ||
+ PDD != time.Duration(3)*time.Second ||
osipsEv.GetSupplier(utils.META_DEFAULT) != "supplier3" ||
osipsEv.GetDisconnectCause(utils.META_DEFAULT) != "200" ||
osipsEv.GetOriginatorIP(utils.META_DEFAULT) != "172.16.254.77" {
@@ -119,7 +119,7 @@ func TestOsipsEventGetValues(t *testing.T) {
!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)),
dur != time.Duration(20*time.Second),
- pdd != time.Duration(3)*time.Second,
+ PDD != time.Duration(3)*time.Second,
osipsEv.GetSupplier(utils.META_DEFAULT) != "supplier3",
osipsEv.GetDisconnectCause(utils.META_DEFAULT) != "200",
osipsEv.GetOriginatorIP(utils.META_DEFAULT) != "172.16.254.77",
@@ -143,12 +143,12 @@ func TestOsipsEventMissingParameter(t *testing.T) {
func TestOsipsEventAsStoredCdr(t *testing.T) {
setupTime, _ := utils.ParseTimeDetectLayout("1406370492", "")
answerTime, _ := utils.ParseTimeDetectLayout("1406370499", "")
- eStoredCdr := &engine.StoredCdr{CgrId: utils.Sha1("ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", setupTime.UTC().String()),
- TOR: utils.VOICE, AccId: "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", 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",
+ eStoredCdr := &engine.CDR{CGRID: utils.Sha1("ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", setupTime.UTC().String()),
+ ToR: utils.VOICE, OriginID: "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", OriginHost: "172.16.254.77", Source: "OSIPS_E_ACC_CDR",
+ RequestType: utils.META_PREPAID,
+ Direction: utils.OUT, Tenant: "itsyscom.com", Category: "call", Account: "dan", Subject: "dan",
Destination: "+4986517174963", SetupTime: setupTime, AnswerTime: answerTime,
- Usage: time.Duration(20) * time.Second, Pdd: time.Duration(3) * time.Second, Supplier: "supplier3", DisconnectCause: "200", ExtraFields: map[string]string{"extra1": "val1", "extra2": "val2"}, Cost: -1}
+ Usage: time.Duration(20) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "supplier3", DisconnectCause: "200", ExtraFields: map[string]string{"extra1": "val1", "extra2": "val2"}, Cost: -1}
if storedCdr := osipsEv.AsStoredCdr(""); !reflect.DeepEqual(eStoredCdr, storedCdr) {
t.Errorf("Expecting: %+v, received: %+v", eStoredCdr, storedCdr)
}
@@ -162,9 +162,9 @@ func TestOsipsAccMissedToStoredCdr(t *testing.T) {
"cgr_account": "1001", "cgr_destination": "1002", utils.CGR_SUPPLIER: "supplier1",
"duration": "", "dialog_id": "3547:277000822", "extra1": "val1", "extra2": "val2"}, OriginatorAddress: addr,
}}
- eStoredCdr := &engine.StoredCdr{CgrId: utils.Sha1("27b1e6679ad0109b5d756e42bb4c9c28@0:0:0:0:0:0:0:0", setupTime.UTC().String()),
- TOR: utils.VOICE, AccId: "27b1e6679ad0109b5d756e42bb4c9c28@0:0:0:0:0:0:0:0", CdrHost: "172.16.254.77", CdrSource: "OSIPS_E_ACC_MISSED_EVENT",
- ReqType: utils.META_PSEUDOPREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Supplier: "supplier1",
+ eStoredCdr := &engine.CDR{CGRID: utils.Sha1("27b1e6679ad0109b5d756e42bb4c9c28@0:0:0:0:0:0:0:0", setupTime.UTC().String()),
+ ToR: utils.VOICE, OriginID: "27b1e6679ad0109b5d756e42bb4c9c28@0:0:0:0:0:0:0:0", OriginHost: "172.16.254.77", Source: "OSIPS_E_ACC_MISSED_EVENT",
+ RequestType: utils.META_PSEUDOPREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Supplier: "supplier1",
DisconnectCause: "404", Destination: "1002", SetupTime: setupTime, AnswerTime: setupTime,
Usage: time.Duration(0), ExtraFields: map[string]string{"extra1": "val1", "extra2": "val2"}, Cost: -1}
if storedCdr := osipsEv.AsStoredCdr(""); !reflect.DeepEqual(eStoredCdr, storedCdr) {
diff --git a/sessionmanager/osipssm.go b/sessionmanager/osipssm.go
index 86ffe40f7..de785188f 100644
--- a/sessionmanager/osipssm.go
+++ b/sessionmanager/osipssm.go
@@ -151,7 +151,7 @@ func (osm *OsipsSessionManager) Shutdown() error {
}
// Process the CDR with CDRS component
-func (osm *OsipsSessionManager) ProcessCdr(storedCdr *engine.StoredCdr) error {
+func (osm *OsipsSessionManager) ProcessCdr(storedCdr *engine.CDR) error {
var reply string
return osm.cdrsrv.Call("CdrServer.ProcessCdr", storedCdr, &reply)
}
diff --git a/sessionmanager/session.go b/sessionmanager/session.go
index 9320bd66e..30f36905c 100644
--- a/sessionmanager/session.go
+++ b/sessionmanager/session.go
@@ -40,7 +40,7 @@ type Session struct {
func (s *Session) GetSessionRun(runid string) *engine.SessionRun {
for _, sr := range s.sessionRuns {
- if sr.DerivedCharger.RunId == runid {
+ if sr.DerivedCharger.RunID == runid {
return sr
}
}
@@ -237,7 +237,7 @@ func (s *Session) SaveOperations() {
err := s.sessionManager.CdrSrv().Call("CdrServer.LogCallCost", &engine.CallCostLog{
CgrId: s.eventStart.GetCgrId(s.sessionManager.Timezone()),
Source: utils.SESSION_MANAGER_SOURCE,
- RunId: sr.DerivedCharger.RunId,
+ RunId: sr.DerivedCharger.RunID,
CallCost: firstCC,
CheckDuplicate: true,
}, &reply)
@@ -283,7 +283,7 @@ func (s *Session) AsActiveSessions() []*ActiveSession {
SMId: "UNKNOWN",
}
if sessionRun.DerivedCharger != nil {
- aSession.RunId = sessionRun.DerivedCharger.RunId
+ aSession.RunId = sessionRun.DerivedCharger.RunID
}
if sessionRun.CallDescriptor != nil {
aSession.LoopIndex = sessionRun.CallDescriptor.LoopIndex
diff --git a/sessionmanager/smg_event.go b/sessionmanager/smg_event.go
index 861b33768..c775c45a1 100644
--- a/sessionmanager/smg_event.go
+++ b/sessionmanager/smg_event.go
@@ -299,14 +299,14 @@ func (self SMGenericEvent) PassesFieldFilter(*utils.RSRField) (bool, string) {
return true, ""
}
-func (self SMGenericEvent) AsStoredCdr(cfg *config.CGRConfig, timezone string) *engine.StoredCdr {
- storCdr := engine.NewStoredCdrWithDefaults(cfg)
- storCdr.CgrId = self.GetCgrId(timezone)
- storCdr.TOR = utils.FirstNonEmpty(self.GetTOR(utils.META_DEFAULT), storCdr.TOR) // Keep default if none in the event
- storCdr.AccId = self.GetUUID()
- storCdr.CdrHost = self.GetOriginatorIP(utils.META_DEFAULT)
- storCdr.CdrSource = self.GetCdrSource()
- storCdr.ReqType = utils.FirstNonEmpty(self.GetReqType(utils.META_DEFAULT), storCdr.ReqType)
+func (self SMGenericEvent) AsStoredCdr(cfg *config.CGRConfig, timezone string) *engine.CDR {
+ storCdr := engine.NewCDRWithDefaults(cfg)
+ storCdr.CGRID = self.GetCgrId(timezone)
+ storCdr.ToR = utils.FirstNonEmpty(self.GetTOR(utils.META_DEFAULT), storCdr.ToR) // Keep default if none in the event
+ storCdr.OriginID = self.GetUUID()
+ storCdr.OriginHost = self.GetOriginatorIP(utils.META_DEFAULT)
+ storCdr.Source = self.GetCdrSource()
+ storCdr.RequestType = utils.FirstNonEmpty(self.GetReqType(utils.META_DEFAULT), storCdr.RequestType)
storCdr.Direction = utils.FirstNonEmpty(self.GetDirection(utils.META_DEFAULT), storCdr.Direction)
storCdr.Tenant = utils.FirstNonEmpty(self.GetTenant(utils.META_DEFAULT), storCdr.Tenant)
storCdr.Category = utils.FirstNonEmpty(self.GetCategory(utils.META_DEFAULT), storCdr.Category)
@@ -316,7 +316,7 @@ func (self SMGenericEvent) AsStoredCdr(cfg *config.CGRConfig, timezone string) *
storCdr.SetupTime, _ = self.GetSetupTime(utils.META_DEFAULT, timezone)
storCdr.AnswerTime, _ = self.GetAnswerTime(utils.META_DEFAULT, timezone)
storCdr.Usage, _ = self.GetUsage(utils.META_DEFAULT)
- storCdr.Pdd, _ = self.GetPdd(utils.META_DEFAULT)
+ storCdr.PDD, _ = self.GetPdd(utils.META_DEFAULT)
storCdr.Supplier = self.GetSupplier(utils.META_DEFAULT)
storCdr.DisconnectCause = self.GetDisconnectCause(utils.META_DEFAULT)
storCdr.ExtraFields = self.GetExtraFields()
diff --git a/sessionmanager/smg_event_test.go b/sessionmanager/smg_event_test.go
index 055d3821a..a52503560 100644
--- a/sessionmanager/smg_event_test.go
+++ b/sessionmanager/smg_event_test.go
@@ -147,11 +147,11 @@ func TestSMGenericEventAsStoredCdr(t *testing.T) {
smGev[utils.CDRHOST] = "10.0.3.15"
smGev["Extra1"] = "Value1"
smGev["Extra2"] = 5
- eStoredCdr := &engine.StoredCdr{CgrId: "0711eaa78e53937f1593dabc08c83ea04a915f2e",
- TOR: utils.VOICE, AccId: "12345", CdrHost: "10.0.3.15", CdrSource: "SMG_TEST_EVENT", ReqType: utils.META_PREPAID,
+ eStoredCdr := &engine.CDR{CGRID: "0711eaa78e53937f1593dabc08c83ea04a915f2e",
+ ToR: utils.VOICE, OriginID: "12345", OriginHost: "10.0.3.15", Source: "SMG_TEST_EVENT", RequestType: utils.META_PREPAID,
Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "account1", Subject: "subject1",
Destination: "+4986517174963", SetupTime: time.Date(2015, 11, 9, 14, 21, 24, 0, time.UTC), AnswerTime: time.Date(2015, 11, 9, 14, 22, 2, 0, time.UTC),
- Usage: time.Duration(83) * time.Second, Pdd: time.Duration(300) * time.Millisecond, Supplier: "supplier1", DisconnectCause: "NORMAL_DISCONNECT",
+ Usage: time.Duration(83) * time.Second, PDD: time.Duration(300) * time.Millisecond, Supplier: "supplier1", DisconnectCause: "NORMAL_DISCONNECT",
ExtraFields: map[string]string{"Extra1": "Value1", "Extra2": "5"}, Cost: -1}
if storedCdr := smGev.AsStoredCdr(cfg, "UTC"); !reflect.DeepEqual(eStoredCdr, storedCdr) {
t.Errorf("Expecting: %+v, received: %+v", eStoredCdr, storedCdr)
diff --git a/sessionmanager/smgeneric.go b/sessionmanager/smgeneric.go
index b12cb7e9f..ede6f4b3f 100644
--- a/sessionmanager/smgeneric.go
+++ b/sessionmanager/smgeneric.go
@@ -91,7 +91,7 @@ func (self *SMGeneric) sessionStart(evStart SMGenericEvent, connId string) error
}
stopDebitChan := make(chan struct{})
for _, sessionRun := range sessionRuns {
- s := &SMGSession{eventStart: evStart, connId: connId, runId: sessionRun.DerivedCharger.RunId, timezone: self.timezone,
+ s := &SMGSession{eventStart: evStart, connId: connId, runId: sessionRun.DerivedCharger.RunID, timezone: self.timezone,
rater: self.rater, cdrsrv: self.cdrsrv, cd: sessionRun.CallDescriptor}
self.indexSession(sessionId, s)
if self.cgrCfg.SmGenericConfig.DebitInterval != 0 {
diff --git a/utils/apitpdata.go b/utils/apitpdata.go
index 65892955f..f4246bd3a 100644
--- a/utils/apitpdata.go
+++ b/utils/apitpdata.go
@@ -612,10 +612,8 @@ type AttrExpFileCdrs struct {
Accounts []string // If provided, it will filter account
Subjects []string // If provided, it will filter the rating subject
DestinationPrefixes []string // If provided, it will filter on destination prefix
- RatedAccounts []string // If provided, it will filter ratedaccount
- RatedSubjects []string // If provided, it will filter the ratedsubject
- OrderIdStart int64 // Export from this order identifier
- OrderIdEnd int64 // Export smaller than this order identifier
+ OrderIdStart *int64 // Export from this order identifier
+ OrderIdEnd *int64 // Export smaller than this order identifier
TimeStart string // If provided, it will represent the starting of the CDRs interval (>=)
TimeEnd string // If provided, it will represent the end of the CDRs interval (<)
SkipErrors bool // Do not export errored CDRs
@@ -624,25 +622,23 @@ type AttrExpFileCdrs struct {
Paginator
}
-func (self *AttrExpFileCdrs) AsCdrsFilter(timezone string) (*CdrsFilter, error) {
- cdrFltr := &CdrsFilter{
- CgrIds: self.CgrIds,
- RunIds: self.MediationRunIds,
- Tors: self.TORs,
- CdrHosts: self.CdrHosts,
- CdrSources: self.CdrSources,
- ReqTypes: self.ReqTypes,
- Directions: self.Directions,
- Tenants: self.Tenants,
- Categories: self.Categories,
- Accounts: self.Accounts,
- Subjects: self.Subjects,
- DestPrefixes: self.DestinationPrefixes,
- RatedAccounts: self.RatedAccounts,
- RatedSubjects: self.RatedSubjects,
- OrderIdStart: self.OrderIdStart,
- OrderIdEnd: self.OrderIdEnd,
- Paginator: self.Paginator,
+func (self *AttrExpFileCdrs) AsCDRsFilter(timezone string) (*CDRsFilter, error) {
+ cdrFltr := &CDRsFilter{
+ CGRIDs: self.CgrIds,
+ RunIDs: self.MediationRunIds,
+ ToRs: self.TORs,
+ OriginHosts: self.CdrHosts,
+ Sources: self.CdrSources,
+ RequestTypes: self.ReqTypes,
+ Directions: self.Directions,
+ Tenants: self.Tenants,
+ Categories: self.Categories,
+ Accounts: self.Accounts,
+ Subjects: self.Subjects,
+ DestinationPrefixes: self.DestinationPrefixes,
+ OrderIDStart: self.OrderIdStart,
+ OrderIDEnd: self.OrderIdEnd,
+ Paginator: self.Paginator,
}
if len(self.TimeStart) != 0 {
if answerTimeStart, err := ParseTimeDetectLayout(self.TimeStart, timezone); err != nil {
@@ -691,8 +687,8 @@ type AttrGetCdrs struct {
DestinationPrefixes []string // If provided, it will filter on destination prefix
RatedAccounts []string // If provided, it will filter ratedaccount
RatedSubjects []string // If provided, it will filter the ratedsubject
- OrderIdStart int64 // Export from this order identifier
- OrderIdEnd int64 // Export smaller than this order identifier
+ OrderIdStart *int64 // Export from this order identifier
+ OrderIdEnd *int64 // Export smaller than this order identifier
TimeStart string // If provided, it will represent the starting of the CDRs interval (>=)
TimeEnd string // If provided, it will represent the end of the CDRs interval (<)
SkipErrors bool // Do not export errored CDRs
@@ -700,25 +696,23 @@ type AttrGetCdrs struct {
Paginator
}
-func (self *AttrGetCdrs) AsCdrsFilter(timezone string) (*CdrsFilter, error) {
- cdrFltr := &CdrsFilter{
- CgrIds: self.CgrIds,
- RunIds: self.MediationRunIds,
- Tors: self.TORs,
- CdrHosts: self.CdrHosts,
- CdrSources: self.CdrSources,
- ReqTypes: self.ReqTypes,
- Directions: self.Directions,
- Tenants: self.Tenants,
- Categories: self.Categories,
- Accounts: self.Accounts,
- Subjects: self.Subjects,
- DestPrefixes: self.DestinationPrefixes,
- RatedAccounts: self.RatedAccounts,
- RatedSubjects: self.RatedSubjects,
- OrderIdStart: self.OrderIdStart,
- OrderIdEnd: self.OrderIdEnd,
- Paginator: self.Paginator,
+func (self *AttrGetCdrs) AsCDRsFilter(timezone string) (*CDRsFilter, error) {
+ cdrFltr := &CDRsFilter{
+ CGRIDs: self.CgrIds,
+ RunIDs: self.MediationRunIds,
+ ToRs: self.TORs,
+ OriginHosts: self.CdrHosts,
+ Sources: self.CdrSources,
+ RequestTypes: self.ReqTypes,
+ Directions: self.Directions,
+ Tenants: self.Tenants,
+ Categories: self.Categories,
+ Accounts: self.Accounts,
+ Subjects: self.Subjects,
+ DestinationPrefixes: self.DestinationPrefixes,
+ OrderIDStart: self.OrderIdStart,
+ OrderIDEnd: self.OrderIdEnd,
+ Paginator: self.Paginator,
}
if len(self.TimeStart) != 0 {
if answerTimeStart, err := ParseTimeDetectLayout(self.TimeStart, timezone); err != nil {
@@ -760,10 +754,8 @@ type AttrRateCdrs struct {
Accounts []string // If provided, it will filter account
Subjects []string // If provided, it will filter the rating subject
DestinationPrefixes []string // If provided, it will filter on destination prefix
- RatedAccounts []string // If provided, it will filter ratedaccount
- RatedSubjects []string // If provided, it will filter the ratedsubject
- OrderIdStart int64 // Export from this order identifier
- OrderIdEnd int64 // Export smaller than this order identifier
+ OrderIdStart *int64 // Export from this order identifier
+ OrderIdEnd *int64 // Export smaller than this order identifier
TimeStart string // If provided, it will represent the starting of the CDRs interval (>=)
TimeEnd string // If provided, it will represent the end of the CDRs interval (<)
RerateErrors bool // Rerate previous CDRs with errors (makes sense for reqtype rated and pseudoprepaid
@@ -771,6 +763,44 @@ type AttrRateCdrs struct {
SendToStats bool // Set to true if the CDRs should be sent to stats server
}
+func (attrRateCDRs *AttrRateCdrs) AsCDRsFilter(timezone string) (*CDRsFilter, error) {
+ cdrFltr := &CDRsFilter{
+ CGRIDs: attrRateCDRs.CgrIds,
+ RunIDs: attrRateCDRs.MediationRunIds,
+ OriginHosts: attrRateCDRs.CdrHosts,
+ Sources: attrRateCDRs.CdrSources,
+ ToRs: attrRateCDRs.TORs,
+ RequestTypes: attrRateCDRs.ReqTypes,
+ Directions: attrRateCDRs.Directions,
+ Tenants: attrRateCDRs.Tenants,
+ Categories: attrRateCDRs.Categories,
+ Accounts: attrRateCDRs.Accounts,
+ Subjects: attrRateCDRs.Subjects,
+ DestinationPrefixes: attrRateCDRs.DestinationPrefixes,
+ OrderIDStart: attrRateCDRs.OrderIdStart,
+ OrderIDEnd: attrRateCDRs.OrderIdEnd,
+ }
+ if aTime, err := ParseTimeDetectLayout(attrRateCDRs.TimeStart, timezone); err != nil {
+ return nil, err
+ } else if !aTime.IsZero() {
+ cdrFltr.AnswerTimeStart = &aTime
+ }
+ if aTimeEnd, err := ParseTimeDetectLayout(attrRateCDRs.TimeEnd, timezone); err != nil {
+ return nil, err
+ } else if !aTimeEnd.IsZero() {
+ cdrFltr.AnswerTimeEnd = &aTimeEnd
+ }
+ if attrRateCDRs.RerateErrors {
+ cdrFltr.MinCost = Float64Pointer(-1.0)
+ if !attrRateCDRs.RerateRated {
+ cdrFltr.MaxCost = Float64Pointer(0.0)
+ }
+ } else if attrRateCDRs.RerateRated {
+ cdrFltr.MinCost = Float64Pointer(0.0)
+ }
+ return cdrFltr, nil
+}
+
type AttrLoadTpFromFolder struct {
FolderPath string // Take files from folder absolute path
DryRun bool // Do not write to database but parse only
@@ -835,172 +865,158 @@ type ExportedTPStats struct {
Compressed bool
}
-// Filter used in engine.GetStoredCdrs
-type CdrsFilter struct {
- CgrIds []string // If provided, it will filter based on the cgrids present in list
- NotCgrIds []string // Filter specific CgrIds out
- RunIds []string // If provided, it will filter on mediation runid
- NotRunIds []string // Filter specific runIds out
- Tors []string // If provided, filter on TypeOfRecord
- NotTors []string // Filter specific TORs out
- CdrHosts []string // If provided, it will filter cdrhost
- NotCdrHosts []string // Filter out specific cdr hosts
- CdrSources []string // If provided, it will filter cdrsource
- NotCdrSources []string // Filter out specific CDR sources
- ReqTypes []string // If provided, it will fiter reqtype
- NotReqTypes []string // Filter out specific request types
- Directions []string // If provided, it will fiter direction
- NotDirections []string // Filter out specific directions
- Tenants []string // If provided, it will filter tenant
- NotTenants []string // If provided, it will filter tenant
- Categories []string // If provided, it will filter çategory
- NotCategories []string // Filter out specific categories
- Accounts []string // If provided, it will filter account
- NotAccounts []string // Filter out specific Accounts
- Subjects []string // If provided, it will filter the rating subject
- NotSubjects []string // Filter out specific subjects
- DestPrefixes []string // If provided, it will filter on destination prefix
- NotDestPrefixes []string // Filter out specific destination prefixes
- Suppliers []string // If provided, it will filter the supplier
- NotSuppliers []string // Filter out specific suppliers
- DisconnectCauses []string // Filter for disconnect Cause
- NotDisconnectCauses []string // Filter out specific disconnect causes
- RatedAccounts []string // If provided, it will filter ratedaccount
- NotRatedAccounts []string // Filter out specific RatedAccounts
- RatedSubjects []string // If provided, it will filter the ratedsubject
- NotRatedSubjects []string // Filter out specific RatedSubjects
- Costs []float64 // Query based on costs specified
- NotCosts []float64 // Filter out specific costs out from result
- ExtraFields map[string]string // Query based on extra fields content
- NotExtraFields map[string]string // Filter out based on extra fields content
- OrderIdStart int64 // Export from this order identifier
- OrderIdEnd int64 // Export smaller than this order identifier
- SetupTimeStart *time.Time // Start of interval, bigger or equal than configured
- SetupTimeEnd *time.Time // End interval, smaller than setupTime
- AnswerTimeStart *time.Time // Start of interval, bigger or equal than configured
- AnswerTimeEnd *time.Time // End interval, smaller than answerTime
- CreatedAtStart *time.Time // Start of interval, bigger or equal than configured
- CreatedAtEnd *time.Time // End interval, smaller than
- UpdatedAtStart *time.Time // Start of interval, bigger or equal than configured
- UpdatedAtEnd *time.Time // End interval, smaller than
- MinUsage *float64 // Start of the usage interval (>=)
- MaxUsage *float64 // End of the usage interval (<)
- MinPdd *float64 // Start of the pdd interval (>=)
- MaxPdd *float64 // End of the pdd interval (<)
- MinCost *float64 // Start of the cost interval (>=)
- MaxCost *float64 // End of the usage interval (<)
- FilterOnRated bool // Do not consider rated CDRs but raw one
- Unscoped bool // Include soft-deleted records in results
- Count bool // If true count the items instead of returning data
+// CDRsFilter is a filter used to get records out of storDB
+type CDRsFilter struct {
+ CGRIDs []string // If provided, it will filter based on the cgrids present in list
+ NotCGRIDs []string // Filter specific CgrIds out
+ RunIDs []string // If provided, it will filter on mediation runid
+ NotRunIDs []string // Filter specific runIds out
+ OriginHosts []string // If provided, it will filter cdrhost
+ NotOriginHosts []string // Filter out specific cdr hosts
+ Sources []string // If provided, it will filter cdrsource
+ NotSources []string // Filter out specific CDR sources
+ ToRs []string // If provided, filter on TypeOfRecord
+ NotToRs []string // Filter specific TORs out
+ RequestTypes []string // If provided, it will fiter reqtype
+ NotRequestTypes []string // Filter out specific request types
+ Directions []string // If provided, it will fiter direction
+ NotDirections []string // Filter out specific directions
+ Tenants []string // If provided, it will filter tenant
+ NotTenants []string // If provided, it will filter tenant
+ Categories []string // If provided, it will filter çategory
+ NotCategories []string // Filter out specific categories
+ Accounts []string // If provided, it will filter account
+ NotAccounts []string // Filter out specific Accounts
+ Subjects []string // If provided, it will filter the rating subject
+ NotSubjects []string // Filter out specific subjects
+ DestinationPrefixes []string // If provided, it will filter on destination prefix
+ NotDestinationPrefixes []string // Filter out specific destination prefixes
+ Suppliers []string // If provided, it will filter the supplier
+ NotSuppliers []string // Filter out specific suppliers
+ DisconnectCauses []string // Filter for disconnect Cause
+ NotDisconnectCauses []string // Filter out specific disconnect causes
+ Costs []float64 // Query based on costs specified
+ NotCosts []float64 // Filter out specific costs out from result
+ ExtraFields map[string]string // Query based on extra fields content
+ NotExtraFields map[string]string // Filter out based on extra fields content
+ OrderIDStart *int64 // Export from this order identifier
+ OrderIDEnd *int64 // Export smaller than this order identifier
+ SetupTimeStart *time.Time // Start of interval, bigger or equal than configured
+ SetupTimeEnd *time.Time // End interval, smaller than setupTime
+ AnswerTimeStart *time.Time // Start of interval, bigger or equal than configured
+ AnswerTimeEnd *time.Time // End interval, smaller than answerTime
+ CreatedAtStart *time.Time // Start of interval, bigger or equal than configured
+ CreatedAtEnd *time.Time // End interval, smaller than
+ UpdatedAtStart *time.Time // Start of interval, bigger or equal than configured
+ UpdatedAtEnd *time.Time // End interval, smaller than
+ MinUsage string // Start of the usage interval (>=)
+ MaxUsage string // End of the usage interval (<)
+ MinPDD string // Start of the pdd interval (>=)
+ MaxPDD string // End of the pdd interval (<)
+ MinCost *float64 // Start of the cost interval (>=)
+ MaxCost *float64 // End of the usage interval (<)
+ Unscoped bool // Include soft-deleted records in results
+ Count bool // If true count the items instead of returning data
Paginator
}
-// Used in Rpc calls, slightly different than CdrsFilter by using string instead of Time filters
-type RpcCdrsFilter struct {
- CgrIds []string // If provided, it will filter based on the cgrids present in list
- NotCgrIds []string // Filter specific CgrIds out
- RunIds []string // If provided, it will filter on mediation runid
- NotRunIds []string // Filter specific runIds out
- Tors []string // If provided, filter on TypeOfRecord
- NotTors []string // Filter specific TORs out
- CdrHosts []string // If provided, it will filter cdrhost
- NotCdrHosts []string // Filter out specific cdr hosts
- CdrSources []string // If provided, it will filter cdrsource
- NotCdrSources []string // Filter out specific CDR sources
- ReqTypes []string // If provided, it will fiter reqtype
- NotReqTypes []string // Filter out specific request types
- Directions []string // If provided, it will fiter direction
- NotDirections []string // Filter out specific directions
- Tenants []string // If provided, it will filter tenant
- NotTenants []string // If provided, it will filter tenant
- Categories []string // If provided, it will filter çategory
- NotCategories []string // Filter out specific categories
- Accounts []string // If provided, it will filter account
- NotAccounts []string // Filter out specific Accounts
- Subjects []string // If provided, it will filter the rating subject
- NotSubjects []string // Filter out specific subjects
- DestPrefixes []string // If provided, it will filter on destination prefix
- NotDestPrefixes []string // Filter out specific destination prefixes
- Suppliers []string // If provided, it will filter the supplier
- NotSuppliers []string // Filter out specific suppliers
- DisconnectCauses []string // Filter for disconnect Cause
- NotDisconnectCauses []string // Filter out specific disconnect causes
- RatedAccounts []string // If provided, it will filter ratedaccount
- NotRatedAccounts []string // Filter out specific RatedAccounts
- RatedSubjects []string // If provided, it will filter the ratedsubject
- NotRatedSubjects []string // Filter out specific RatedSubjects
- Costs []float64 // Query based on costs specified
- NotCosts []float64 // Filter out specific costs out from result
- ExtraFields map[string]string // Query based on extra fields content
- NotExtraFields map[string]string // Filter out based on extra fields content
- OrderIdStart int64 // Export from this order identifier
- OrderIdEnd int64 // Export smaller than this order identifier
- SetupTimeStart string // Start of interval, bigger or equal than configured
- SetupTimeEnd string // End interval, smaller than setupTime
- AnswerTimeStart string // Start of interval, bigger or equal than configured
- AnswerTimeEnd string // End interval, smaller than answerTime
- CreatedAtStart string // Start of interval, bigger or equal than configured
- CreatedAtEnd string // End interval, smaller than
- UpdatedAtStart string // Start of interval, bigger or equal than configured
- UpdatedAtEnd string // End interval, smaller than
- MinUsage *float64 // Start of the usage interval (>=)
- MaxUsage *float64 // End of the usage interval (<)
- MinPdd *float64 // Start of the pdd interval (>=)
- MaxPdd *float64 // End of the pdd interval (<)
- MinCost *float64 // Start of the cost interval (>=)
- MaxCost *float64 // End of the usage interval (<)
- FilterOnRated bool // Do not consider derived CDRs but original one
- Paginator // Add pagination
+// RPCCDRsFilter is a filter used in Rpc calls
+// RPCCDRsFilter is slightly different than CDRsFilter by using string instead of Time filters
+type RPCCDRsFilter struct {
+ CGRIDs []string // If provided, it will filter based on the cgrids present in list
+ NotCGRIDs []string // Filter specific CgrIds out
+ RunIDs []string // If provided, it will filter on mediation runid
+ NotRunIDs []string // Filter specific runIds out
+ OriginHosts []string // If provided, it will filter cdrhost
+ NotOriginHosts []string // Filter out specific cdr hosts
+ Sources []string // If provided, it will filter cdrsource
+ NotSources []string // Filter out specific CDR sources
+ ToRs []string // If provided, filter on TypeOfRecord
+ NotToRs []string // Filter specific TORs out
+ RequestTypes []string // If provided, it will fiter reqtype
+ NotRequestTypes []string // Filter out specific request types
+ Directions []string // If provided, it will fiter direction
+ NotDirections []string // Filter out specific directions
+ Tenants []string // If provided, it will filter tenant
+ NotTenants []string // If provided, it will filter tenant
+ Categories []string // If provided, it will filter çategory
+ NotCategories []string // Filter out specific categories
+ Accounts []string // If provided, it will filter account
+ NotAccounts []string // Filter out specific Accounts
+ Subjects []string // If provided, it will filter the rating subject
+ NotSubjects []string // Filter out specific subjects
+ DestinationPrefixes []string // If provided, it will filter on destination prefix
+ NotDestinationPrefixes []string // Filter out specific destination prefixes
+ Suppliers []string // If provided, it will filter the supplier
+ NotSuppliers []string // Filter out specific suppliers
+ DisconnectCauses []string // Filter for disconnect Cause
+ NotDisconnectCauses []string // Filter out specific disconnect causes
+ Costs []float64 // Query based on costs specified
+ NotCosts []float64 // Filter out specific costs out from result
+ ExtraFields map[string]string // Query based on extra fields content
+ NotExtraFields map[string]string // Filter out based on extra fields content
+ OrderIDStart *int64 // Export from this order identifier
+ OrderIDEnd *int64 // Export smaller than this order identifier
+ SetupTimeStart string // Start of interval, bigger or equal than configured
+ SetupTimeEnd string // End interval, smaller than setupTime
+ AnswerTimeStart string // Start of interval, bigger or equal than configured
+ AnswerTimeEnd string // End interval, smaller than answerTime
+ CreatedAtStart string // Start of interval, bigger or equal than configured
+ CreatedAtEnd string // End interval, smaller than
+ UpdatedAtStart string // Start of interval, bigger or equal than configured
+ UpdatedAtEnd string // End interval, smaller than
+ MinUsage string // Start of the usage interval (>=)
+ MaxUsage string // End of the usage interval (<)
+ MinPDD string // Start of the pdd interval (>=)
+ MaxPDD string // End of the pdd interval (<)
+ MinCost *float64 // Start of the cost interval (>=)
+ MaxCost *float64 // End of the usage interval (<)
+ Paginator // Add pagination
}
-func (self *RpcCdrsFilter) AsCdrsFilter(timezone string) (*CdrsFilter, error) {
- cdrFltr := &CdrsFilter{
- CgrIds: self.CgrIds,
- NotCgrIds: self.NotCgrIds,
- RunIds: self.RunIds,
- NotRunIds: self.NotRunIds,
- Tors: self.Tors,
- NotTors: self.NotTors,
- CdrHosts: self.CdrHosts,
- NotCdrHosts: self.NotCdrHosts,
- CdrSources: self.CdrSources,
- NotCdrSources: self.NotCdrSources,
- ReqTypes: self.ReqTypes,
- NotReqTypes: self.NotReqTypes,
- Directions: self.Directions,
- NotDirections: self.NotDirections,
- Tenants: self.Tenants,
- NotTenants: self.NotTenants,
- Categories: self.Categories,
- NotCategories: self.NotCategories,
- Accounts: self.Accounts,
- NotAccounts: self.NotAccounts,
- Subjects: self.Subjects,
- NotSubjects: self.NotSubjects,
- DestPrefixes: self.DestPrefixes,
- NotDestPrefixes: self.NotDestPrefixes,
- Suppliers: self.Suppliers,
- NotSuppliers: self.NotSuppliers,
- DisconnectCauses: self.DisconnectCauses,
- NotDisconnectCauses: self.NotDisconnectCauses,
- RatedAccounts: self.RatedAccounts,
- NotRatedAccounts: self.NotRatedAccounts,
- RatedSubjects: self.RatedSubjects,
- NotRatedSubjects: self.NotRatedSubjects,
- Costs: self.Costs,
- NotCosts: self.NotCosts,
- ExtraFields: self.ExtraFields,
- NotExtraFields: self.NotExtraFields,
- OrderIdStart: self.OrderIdStart,
- OrderIdEnd: self.OrderIdEnd,
- MinUsage: self.MinUsage,
- MaxUsage: self.MaxUsage,
- MinPdd: self.MinPdd,
- MaxPdd: self.MaxPdd,
- MinCost: self.MinCost,
- MaxCost: self.MaxCost,
- FilterOnRated: self.FilterOnRated,
- Paginator: self.Paginator,
+func (self *RPCCDRsFilter) AsCDRsFilter(timezone string) (*CDRsFilter, error) {
+ cdrFltr := &CDRsFilter{
+ CGRIDs: self.CGRIDs,
+ NotCGRIDs: self.NotCGRIDs,
+ RunIDs: self.RunIDs,
+ NotRunIDs: self.NotRunIDs,
+ ToRs: self.ToRs,
+ NotToRs: self.NotToRs,
+ OriginHosts: self.OriginHosts,
+ NotOriginHosts: self.NotOriginHosts,
+ Sources: self.Sources,
+ NotSources: self.NotSources,
+ RequestTypes: self.RequestTypes,
+ NotRequestTypes: self.NotRequestTypes,
+ Directions: self.Directions,
+ NotDirections: self.NotDirections,
+ Tenants: self.Tenants,
+ NotTenants: self.NotTenants,
+ Categories: self.Categories,
+ NotCategories: self.NotCategories,
+ Accounts: self.Accounts,
+ NotAccounts: self.NotAccounts,
+ Subjects: self.Subjects,
+ NotSubjects: self.NotSubjects,
+ DestinationPrefixes: self.DestinationPrefixes,
+ NotDestinationPrefixes: self.NotDestinationPrefixes,
+ Suppliers: self.Suppliers,
+ NotSuppliers: self.NotSuppliers,
+ DisconnectCauses: self.DisconnectCauses,
+ NotDisconnectCauses: self.NotDisconnectCauses,
+ Costs: self.Costs,
+ NotCosts: self.NotCosts,
+ ExtraFields: self.ExtraFields,
+ NotExtraFields: self.NotExtraFields,
+ OrderIDStart: self.OrderIDStart,
+ OrderIDEnd: self.OrderIDEnd,
+ MinUsage: self.MinUsage,
+ MaxUsage: self.MaxUsage,
+ MinPDD: self.MinPDD,
+ MaxPDD: self.MaxPDD,
+ MinCost: self.MinCost,
+ MaxCost: self.MaxCost,
+ Paginator: self.Paginator,
}
if len(self.SetupTimeStart) != 0 {
if sTimeStart, err := ParseTimeDetectLayout(self.SetupTimeStart, timezone); err != nil {
@@ -1064,20 +1080,20 @@ func (self *RpcCdrsFilter) AsCdrsFilter(timezone string) (*CdrsFilter, error) {
type AttrExportCdrsToFile struct {
CdrFormat *string // Cdr output file format
FieldSeparator *string // Separator used between fields
- ExportId *string // Optional exportid
- ExportDir *string // If provided it overwrites the configured export directory
+ ExportID *string // Optional exportid
+ ExportFolder *string // If provided it overwrites the configured export directory
ExportFileName *string // If provided the output filename will be set to this
ExportTemplate *string // Exported fields template <""|fld1,fld2|*xml:instance_name>
DataUsageMultiplyFactor *float64 // Multiply data usage before export (eg: convert from KBytes to Bytes)
- SmsUsageMultiplyFactor *float64 // Multiply sms usage before export (eg: convert from SMS unit to call duration for some billing systems)
+ SMSUsageMultiplyFactor *float64 // Multiply sms usage before export (eg: convert from SMS unit to call duration for some billing systems)
GenericUsageMultiplyFactor *float64 // Multiply generic usage before export (eg: convert from GENERIC unit to call duration for some billing systems)
CostMultiplyFactor *float64 // Multiply the cost before export, eg: apply VAT
CostShiftDigits *int // If defined it will shift cost digits before applying rouding (eg: convert from Eur->cents), -1 to use general config ones
RoundDecimals *int // Overwrite configured roundDecimals with this dynamically, -1 to use general config ones
- MaskDestinationId *string // Overwrite configured MaskDestId
+ MaskDestinationID *string // Overwrite configured MaskDestId
MaskLength *int // Overwrite configured MaskLength, -1 to use general config ones
- SuppressCgrIds bool // Disable CgrIds reporting in reply/ExportedCgrIds and reply/UnexportedCgrIds
- RpcCdrsFilter // Inherit the CDR filter attributes
+ Verbose bool // Disable CgrIds reporting in reply/ExportedCgrIds and reply/UnexportedCgrIds
+ RPCCDRsFilter // Inherit the CDR filter attributes
}
type AttrSetActions struct {
diff --git a/utils/consts.go b/utils/consts.go
index caff839a2..a78f97e88 100644
--- a/utils/consts.go
+++ b/utils/consts.go
@@ -66,10 +66,8 @@ const (
TBL_TP_DERIVED_CHARGERS = "tp_derived_chargers"
TBL_TP_USERS = "tp_users"
TBL_TP_ALIASES = "tp_aliases"
- TBL_CDRS_PRIMARY = "cdrs_primary"
- TBL_CDRS_EXTRA = "cdrs_extra"
- TBL_COST_DETAILS = "cost_details"
- TBL_RATED_CDRS = "rated_cdrs"
+ TBLSMCosts = "sm_costs"
+ TBL_CDRS = "cdrs"
TIMINGS_CSV = "Timings.csv"
DESTINATIONS_CSV = "Destinations.csv"
RATES_CSV = "Rates.csv"
@@ -105,13 +103,13 @@ const (
GOB = "gob"
MSGPACK = "msgpack"
CSV_LOAD = "CSVLOAD"
- CGRID = "CgrId"
- TOR = "TOR"
- ORDERID = "OrderId"
- ACCID = "AccId"
- CDRHOST = "CdrHost"
- CDRSOURCE = "CdrSource"
- REQTYPE = "ReqType"
+ CGRID = "CGRID"
+ TOR = "ToR"
+ ORDERID = "OrderID"
+ ACCID = "OriginID"
+ CDRSOURCE = "Source"
+ CDRHOST = "OriginHost"
+ REQTYPE = "RequestType"
DIRECTION = "Direction"
TENANT = "Tenant"
CATEGORY = "Category"
@@ -121,11 +119,9 @@ const (
SETUP_TIME = "SetupTime"
ANSWER_TIME = "AnswerTime"
USAGE = "Usage"
- PDD = "Pdd"
+ PDD = "PDD"
SUPPLIER = "Supplier"
- MEDI_RUNID = "MediationRunId"
- RATED_ACCOUNT = "RatedAccount"
- RATED_SUBJECT = "RatedSubject"
+ MEDI_RUNID = "RunID"
COST = "Cost"
COST_DETAILS = "CostDetails"
RATED = "rated"
@@ -260,10 +256,13 @@ const (
MatchEndPrefix = "$"
SMG = "SMG"
MetaGrouped = "*grouped"
+ MetaRaw = "*raw"
+ CreatedAt = "CreatedAt"
+ UpdatedAt = "UpdatedAt"
)
var (
CdreCdrFormats = []string{CSV, DRYRUN, CDRE_FIXED_WIDTH}
- PrimaryCdrFields = []string{CGRID, TOR, ACCID, CDRHOST, CDRSOURCE, REQTYPE, DIRECTION, TENANT, CATEGORY, ACCOUNT, SUBJECT, DESTINATION, SETUP_TIME, PDD, ANSWER_TIME, USAGE,
+ PrimaryCdrFields = []string{CGRID, CDRSOURCE, CDRHOST, ACCID, TOR, REQTYPE, DIRECTION, TENANT, CATEGORY, ACCOUNT, SUBJECT, DESTINATION, SETUP_TIME, PDD, ANSWER_TIME, USAGE,
SUPPLIER, DISCONNECT_CAUSE, COST, RATED}
)
diff --git a/utils/derivedchargers.go b/utils/derivedchargers.go
index 5d9d8def8..8496947f3 100644
--- a/utils/derivedchargers.go
+++ b/utils/derivedchargers.go
@@ -29,16 +29,16 @@ func NewDerivedCharger(runId, runFilters, reqTypeFld, dirFld, tenantFld, catFld,
if len(runId) == 0 {
return nil, errors.New("Empty run id field")
}
- dc = &DerivedCharger{RunId: runId}
+ dc = &DerivedCharger{RunID: runId}
dc.RunFilters = runFilters
if strings.HasPrefix(dc.RunFilters, REGEXP_PREFIX) || strings.HasPrefix(dc.RunFilters, STATIC_VALUE_PREFIX) {
if dc.rsrRunFilters, err = ParseRSRFields(dc.RunFilters, INFIELD_SEP); err != nil {
return nil, err
}
}
- dc.ReqTypeField = reqTypeFld
- if strings.HasPrefix(dc.ReqTypeField, REGEXP_PREFIX) || strings.HasPrefix(dc.ReqTypeField, STATIC_VALUE_PREFIX) {
- if dc.rsrReqTypeField, err = NewRSRField(dc.ReqTypeField); err != nil {
+ dc.RequestTypeField = reqTypeFld
+ if strings.HasPrefix(dc.RequestTypeField, REGEXP_PREFIX) || strings.HasPrefix(dc.RequestTypeField, STATIC_VALUE_PREFIX) {
+ if dc.rsrRequestTypeField, err = NewRSRField(dc.RequestTypeField); err != nil {
return nil, err
}
}
@@ -84,9 +84,9 @@ func NewDerivedCharger(runId, runFilters, reqTypeFld, dirFld, tenantFld, catFld,
return nil, err
}
}
- dc.PddField = pddFld
- if strings.HasPrefix(dc.PddField, REGEXP_PREFIX) || strings.HasPrefix(dc.PddField, STATIC_VALUE_PREFIX) {
- if dc.rsrPddField, err = NewRSRField(dc.PddField); err != nil {
+ dc.PDDField = pddFld
+ if strings.HasPrefix(dc.PDDField, REGEXP_PREFIX) || strings.HasPrefix(dc.PDDField, STATIC_VALUE_PREFIX) {
+ if dc.rsrPddField, err = NewRSRField(dc.PDDField); err != nil {
return nil, err
}
}
@@ -130,9 +130,9 @@ func NewDerivedCharger(runId, runFilters, reqTypeFld, dirFld, tenantFld, catFld,
}
type DerivedCharger struct {
- RunId string // Unique runId in the chain
+ RunID string // Unique runId in the chain
RunFilters string // Only run the charger if all the filters match
- ReqTypeField string // Field containing request type info, number in case of csv source, '^' as prefix in case of static values
+ RequestTypeField string // Field containing request type info, number in case of csv source, '^' as prefix in case of static values
DirectionField string // Field containing direction info
TenantField string // Field containing tenant info
CategoryField string // Field containing tor info
@@ -140,7 +140,7 @@ type DerivedCharger struct {
SubjectField string // Field containing subject information
DestinationField string // Field containing destination information
SetupTimeField string // Field containing setup time information
- PddField string // Field containing setup time information
+ PDDField string // Field containing setup time information
AnswerTimeField string // Field containing answer time information
UsageField string // Field containing usage information
SupplierField string // Field containing supplier information
@@ -148,7 +148,7 @@ type DerivedCharger struct {
CostField string // Field containing cost information
RatedField string // Field marking rated request in CDR
rsrRunFilters []*RSRField // Storage for compiled Regexp in case of RSRFields
- rsrReqTypeField *RSRField
+ rsrRequestTypeField *RSRField
rsrDirectionField *RSRField
rsrTenantField *RSRField
rsrCategoryField *RSRField
@@ -166,9 +166,9 @@ type DerivedCharger struct {
}
func (dc *DerivedCharger) Equal(other *DerivedCharger) bool {
- return dc.RunId == other.RunId &&
+ return dc.RunID == other.RunID &&
dc.RunFilters == other.RunFilters &&
- dc.ReqTypeField == other.ReqTypeField &&
+ dc.RequestTypeField == other.RequestTypeField &&
dc.DirectionField == other.DirectionField &&
dc.TenantField == other.TenantField &&
dc.CategoryField == other.CategoryField &&
@@ -176,7 +176,7 @@ func (dc *DerivedCharger) Equal(other *DerivedCharger) bool {
dc.SubjectField == other.SubjectField &&
dc.DestinationField == other.DestinationField &&
dc.SetupTimeField == other.SetupTimeField &&
- dc.PddField == other.PddField &&
+ dc.PDDField == other.PDDField &&
dc.AnswerTimeField == other.AnswerTimeField &&
dc.UsageField == other.UsageField &&
dc.SupplierField == other.SupplierField &&
@@ -190,17 +190,17 @@ func DerivedChargersKey(direction, tenant, category, account, subject string) st
}
type DerivedChargers struct {
- DestinationIds StringMap
+ DestinationIDs StringMap
Chargers []*DerivedCharger
}
// Precheck that RunId is unique
func (dcs *DerivedChargers) Append(dc *DerivedCharger) (*DerivedChargers, error) {
- if dc.RunId == DEFAULT_RUNID {
+ if dc.RunID == DEFAULT_RUNID {
return nil, errors.New("Reserved RunId")
}
for _, dcLocal := range dcs.Chargers {
- if dcLocal.RunId == dc.RunId {
+ if dcLocal.RunID == dc.RunID {
return nil, errors.New("Duplicated RunId")
}
}
@@ -216,7 +216,7 @@ func (dcs *DerivedChargers) AppendDefaultRun() (*DerivedChargers, error) {
}
func (dcs *DerivedChargers) Equal(other *DerivedChargers) bool {
- dcs.DestinationIds.Equal(other.DestinationIds)
+ dcs.DestinationIDs.Equal(other.DestinationIDs)
for i, dc := range dcs.Chargers {
if !dc.Equal(other.Chargers[i]) {
return false
diff --git a/utils/derivedchargers_test.go b/utils/derivedchargers_test.go
index 4a2fffe31..7de46b728 100644
--- a/utils/derivedchargers_test.go
+++ b/utils/derivedchargers_test.go
@@ -27,29 +27,29 @@ func TestAppendDerivedChargers(t *testing.T) {
var err error
dcs := &DerivedChargers{Chargers: make([]*DerivedCharger, 0)}
- if _, err := dcs.Append(&DerivedCharger{RunId: DEFAULT_RUNID}); err == nil {
- t.Error("Failed to detect using of the default runid")
+ if _, err := dcs.Append(&DerivedCharger{RunID: DEFAULT_RUNID}); err == nil {
+ t.Error("Failed to detect using of the default RunID")
}
- if dcs, err = dcs.Append(&DerivedCharger{RunId: "FIRST_RUNID"}); err != nil {
- t.Error("Failed to add runid")
+ if dcs, err = dcs.Append(&DerivedCharger{RunID: "FIRST_RunID"}); err != nil {
+ t.Error("Failed to add RunID")
} else if len(dcs.Chargers) != 1 {
t.Error("Unexpected number of items inside DerivedChargers configuration", len(dcs.Chargers))
}
- if dcs, err = dcs.Append(&DerivedCharger{RunId: "SECOND_RUNID"}); err != nil {
- t.Error("Failed to add runid")
+ if dcs, err = dcs.Append(&DerivedCharger{RunID: "SECOND_RunID"}); err != nil {
+ t.Error("Failed to add RunID")
} else if len(dcs.Chargers) != 2 {
t.Error("Unexpected number of items inside DerivedChargers configuration", len(dcs.Chargers))
}
- if _, err := dcs.Append(&DerivedCharger{RunId: "SECOND_RUNID"}); err == nil {
- t.Error("Failed to detect duplicate runid")
+ if _, err := dcs.Append(&DerivedCharger{RunID: "SECOND_RunID"}); err == nil {
+ t.Error("Failed to detect duplicate RunID")
}
}
func TestNewDerivedCharger(t *testing.T) {
edc1 := &DerivedCharger{
- RunId: "test1",
+ RunID: "test1",
RunFilters: "",
- ReqTypeField: "reqtype1",
+ RequestTypeField: "reqtype1",
DirectionField: "direction1",
TenantField: "tenant1",
CategoryField: "tor1",
@@ -57,7 +57,7 @@ func TestNewDerivedCharger(t *testing.T) {
SubjectField: "subject1",
DestinationField: "destination1",
SetupTimeField: "setuptime1",
- PddField: "pdd1",
+ PDDField: "pdd1",
AnswerTimeField: "answertime1",
UsageField: "duration1",
SupplierField: "supplier1",
@@ -72,9 +72,9 @@ func TestNewDerivedCharger(t *testing.T) {
t.Errorf("Expecting: %v, received: %v", edc1, dc1)
}
edc2 := &DerivedCharger{
- RunId: "test2",
+ RunID: "test2",
RunFilters: "^cdr_source/tdm_cdrs/",
- ReqTypeField: "~reqtype2:s/sip:(.+)/$1/",
+ RequestTypeField: "~reqtype2:s/sip:(.+)/$1/",
DirectionField: "~direction2:s/sip:(.+)/$1/",
TenantField: "~tenant2:s/sip:(.+)/$1/",
CategoryField: "~tor2:s/sip:(.+)/$1/",
@@ -82,7 +82,7 @@ func TestNewDerivedCharger(t *testing.T) {
SubjectField: "~subject2:s/sip:(.+)/$1/",
DestinationField: "~destination2:s/sip:(.+)/$1/",
SetupTimeField: "~setuptime2:s/sip:(.+)/$1/",
- PddField: "~pdd:s/sip:(.+)/$1/",
+ PDDField: "~pdd:s/sip:(.+)/$1/",
AnswerTimeField: "~answertime2:s/sip:(.+)/$1/",
UsageField: "~duration2:s/sip:(.+)/$1/",
SupplierField: "~supplier2:s/(.+)/$1/",
@@ -91,7 +91,7 @@ func TestNewDerivedCharger(t *testing.T) {
RatedField: "~cgr_rated:s/(.+)/$1/",
}
edc2.rsrRunFilters, _ = ParseRSRFields("^cdr_source/tdm_cdrs/", INFIELD_SEP)
- edc2.rsrReqTypeField, _ = NewRSRField("~reqtype2:s/sip:(.+)/$1/")
+ edc2.rsrRequestTypeField, _ = NewRSRField("~reqtype2:s/sip:(.+)/$1/")
edc2.rsrDirectionField, _ = NewRSRField("~direction2:s/sip:(.+)/$1/")
edc2.rsrTenantField, _ = NewRSRField("~tenant2:s/sip:(.+)/$1/")
edc2.rsrCategoryField, _ = NewRSRField("~tor2:s/sip:(.+)/$1/")
@@ -137,20 +137,20 @@ func TestDerivedChargersKey(t *testing.T) {
func TestAppendDefaultRun(t *testing.T) {
dc1 := &DerivedChargers{}
- dcDf := &DerivedCharger{RunId: DEFAULT_RUNID, RunFilters: "", ReqTypeField: META_DEFAULT, DirectionField: META_DEFAULT,
+ dcDf := &DerivedCharger{RunID: DEFAULT_RUNID, RunFilters: "", RequestTypeField: META_DEFAULT, DirectionField: META_DEFAULT,
TenantField: META_DEFAULT, CategoryField: META_DEFAULT, AccountField: META_DEFAULT, SubjectField: META_DEFAULT,
- DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PddField: META_DEFAULT, AnswerTimeField: META_DEFAULT, UsageField: META_DEFAULT, SupplierField: META_DEFAULT,
+ DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PDDField: META_DEFAULT, AnswerTimeField: META_DEFAULT, UsageField: META_DEFAULT, SupplierField: META_DEFAULT,
DisconnectCauseField: META_DEFAULT, CostField: META_DEFAULT, RatedField: META_DEFAULT}
eDc1 := &DerivedChargers{Chargers: []*DerivedCharger{dcDf}}
if dc1, _ = dc1.AppendDefaultRun(); !reflect.DeepEqual(dc1, eDc1) {
t.Errorf("Expecting: %+v, received: %+v", eDc1.Chargers[0], dc1.Chargers[0])
}
dc2 := &DerivedChargers{Chargers: []*DerivedCharger{
- &DerivedCharger{RunId: "extra1", RunFilters: "", ReqTypeField: "reqtype2", DirectionField: META_DEFAULT, TenantField: META_DEFAULT, CategoryField: META_DEFAULT,
- AccountField: "rif", SubjectField: "rif", DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PddField: META_DEFAULT, AnswerTimeField: META_DEFAULT, UsageField: META_DEFAULT,
+ &DerivedCharger{RunID: "extra1", RunFilters: "", RequestTypeField: "reqtype2", DirectionField: META_DEFAULT, TenantField: META_DEFAULT, CategoryField: META_DEFAULT,
+ AccountField: "rif", SubjectField: "rif", DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PDDField: META_DEFAULT, AnswerTimeField: META_DEFAULT, UsageField: META_DEFAULT,
DisconnectCauseField: META_DEFAULT},
- &DerivedCharger{RunId: "extra2", ReqTypeField: META_DEFAULT, DirectionField: META_DEFAULT, TenantField: META_DEFAULT, CategoryField: META_DEFAULT,
- AccountField: "ivo", SubjectField: "ivo", DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PddField: META_DEFAULT, AnswerTimeField: META_DEFAULT,
+ &DerivedCharger{RunID: "extra2", RequestTypeField: META_DEFAULT, DirectionField: META_DEFAULT, TenantField: META_DEFAULT, CategoryField: META_DEFAULT,
+ AccountField: "ivo", SubjectField: "ivo", DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PDDField: META_DEFAULT, AnswerTimeField: META_DEFAULT,
UsageField: META_DEFAULT, SupplierField: META_DEFAULT, DisconnectCauseField: META_DEFAULT}},
}
eDc2 := &DerivedChargers{}