diff --git a/apier/cdre.go b/apier/cdre.go index 5f04edbb1..a0bb03191 100644 --- a/apier/cdre.go +++ b/apier/cdre.go @@ -70,7 +70,7 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E if attr.MaskLength != -1 { maskLen = attr.MaskLength } - cdrs, err := self.CdrDb.GetStoredCdrs(attr.CgrIds, attr.MediationRunId, attr.CdrHost, attr.CdrSource, attr.ReqType, attr.Direction, + cdrs, err := self.CdrDb.GetStoredCdrs(attr.CgrIds, attr.MediationRunId, attr.TOR, attr.CdrHost, attr.CdrSource, attr.ReqType, attr.Direction, attr.Tenant, attr.Tor, attr.Account, attr.Subject, attr.DestinationPrefix, attr.OrderIdStart, attr.OrderIdEnd, tStart, tEnd, attr.SkipErrors, attr.SkipRated) if err != nil { return err diff --git a/engine/storage_interface.go b/engine/storage_interface.go index 194b8ed01..bbdb7294b 100644 --- a/engine/storage_interface.go +++ b/engine/storage_interface.go @@ -110,7 +110,7 @@ type CdrStorage interface { Storage SetCdr(*utils.StoredCdr) error SetRatedCdr(*utils.StoredCdr, string) error - GetStoredCdrs([]string, []string, []string, []string, []string, []string, []string, []string, []string, []string, []string, + GetStoredCdrs([]string, []string, []string, []string, []string, []string, []string, []string, []string, []string, []string, []string, int64, int64, time.Time, time.Time, bool, bool) ([]*utils.StoredCdr, error) RemStoredCdrs([]string) error } diff --git a/engine/storage_sql.go b/engine/storage_sql.go index a55c4032e..cd47fe3c7 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -606,10 +606,11 @@ func (self *SQLStorage) SetRatedCdr(storedCdr *utils.StoredCdr, extraInfo string // Return a slice of CDRs from storDb using optional filters.a // ignoreErr - do not consider cdrs with rating errors // ignoreRated - do not consider cdrs which were already rated, including here the ones with errors -func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqTypes, directions, tenants, categories, accounts, subjects, destPrefixes []string, orderIdStart, orderIdEnd int64, +func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, tors, cdrHosts, cdrSources, reqTypes, directions, tenants, categories, accounts, subjects, destPrefixes []string, orderIdStart, orderIdEnd int64, timeStart, timeEnd time.Time, ignoreErr, ignoreRated bool) ([]*utils.StoredCdr, error) { var cdrs []*utils.StoredCdr - q := bytes.NewBufferString(fmt.Sprintf("SELECT %s.cgrid,%s.tbid,%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.extra_fields,%s.runid,%s.cost FROM %s LEFT JOIN %s ON %s.cgrid=%s.cgrid LEFT JOIN %s ON %s.cgrid=%s.cgrid", + q := bytes.NewBufferString(fmt.Sprintf("SELECT %s.cgrid,%s.tbid,%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.extra_fields,%s.runid,%s.cost FROM %s LEFT JOIN %s ON %s.cgrid=%s.cgrid LEFT JOIN %s ON %s.cgrid=%s.cgrid", + utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, @@ -664,6 +665,20 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT } fltr.Write(qIds.Bytes()) } + if len(tors) != 0 { + qIds := bytes.NewBufferString(" (") + for idx, host := range tors { + if idx != 0 { + qIds.WriteString(" OR") + } + qIds.WriteString(fmt.Sprintf(" %s.tor='%s'", utils.TBL_CDRS_PRIMARY, host)) + } + qIds.WriteString(" )") + if fltr.Len() != 0 { + fltr.WriteString(" AND") + } + fltr.Write(qIds.Bytes()) + } if len(cdrHosts) != 0 { qIds := bytes.NewBufferString(" (") for idx, host := range cdrHosts { @@ -838,14 +853,14 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT } defer rows.Close() for rows.Next() { - var cgrid, accid, cdrhost, cdrsrc, reqtype, direction, tenant, category, account, subject, destination string + var cgrid, tor, accid, cdrhost, cdrsrc, reqtype, direction, tenant, category, account, subject, destination string var extraFields []byte var setupTime, answerTime time.Time var runid sql.NullString // So we can export unmediated CDRs var orderid, usage int64 var cost sql.NullFloat64 // So we can export unmediated CDRs var extraFieldsMp map[string]string - if err := rows.Scan(&cgrid, &orderid, &accid, &cdrhost, &cdrsrc, &reqtype, &direction, &tenant, &category, &account, &subject, &destination, &setupTime, &answerTime, &usage, + if err := rows.Scan(&cgrid, &orderid, &tor, &accid, &cdrhost, &cdrsrc, &reqtype, &direction, &tenant, &category, &account, &subject, &destination, &setupTime, &answerTime, &usage, &extraFields, &runid, &cost); err != nil { return nil, err } @@ -853,7 +868,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT return nil, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %v, error: %s", cgrid, runid, err.Error()) } storCdr := &utils.StoredCdr{ - CgrId: cgrid, OrderId: orderid, AccId: accid, CdrHost: cdrhost, CdrSource: cdrsrc, ReqType: reqtype, Direction: direction, Tenant: tenant, + CgrId: cgrid, OrderId: orderid, TOR: tor, AccId: accid, CdrHost: cdrhost, CdrSource: cdrsrc, ReqType: reqtype, Direction: direction, Tenant: tenant, Category: category, Account: account, Subject: subject, Destination: destination, SetupTime: setupTime, AnswerTime: answerTime, Duration: time.Duration(usage), ExtraFields: extraFieldsMp, MediationRunId: runid.String, Cost: cost.Float64, } diff --git a/engine/storage_sql_local_test.go b/engine/storage_sql_local_test.go index 8f3c99360..1512eef4b 100644 --- a/engine/storage_sql_local_test.go +++ b/engine/storage_sql_local_test.go @@ -137,22 +137,22 @@ func TestSetCdr(t *testing.T) { if !*testLocal { return } - cgrCdr1 := &utils.CgrCdr{utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr1 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "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.DURATION: "10s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: TEST_SQL} - cgrCdr2 := &utils.CgrCdr{utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "prepaid", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr2 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "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.DURATION: "20", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr3 := &utils.CgrCdr{utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", + cgrCdr3 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "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.DURATION: "60s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr4 := &utils.CgrCdr{utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: "pseudoprepaid", utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", + cgrCdr4 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: "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.DURATION: "1m2s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} - cgrCdr5 := &utils.CgrCdr{utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: "postpaid", utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", + cgrCdr5 := &utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: "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.DURATION: "15s", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": TEST_SQL} @@ -223,7 +223,7 @@ func TestGetStoredCdrs(t *testing.T) { } var timeStart, timeEnd time.Time // All CDRs, no filter - if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) @@ -231,7 +231,7 @@ func TestGetStoredCdrs(t *testing.T) { // Filter on cgrids if storedCdrs, err := mysql.GetStoredCdrs([]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())}, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) @@ -239,131 +239,143 @@ func TestGetStoredCdrs(t *testing.T) { // Filter on cgrids plus reqType if storedCdrs, err := mysql.GetStoredCdrs([]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())}, - nil, nil, nil, []string{"prepaid"}, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + nil, nil, nil, nil, []string{"prepaid"}, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on runId - if storedCdrs, err := mysql.GetStoredCdrs(nil, []string{utils.DEFAULT_RUNID}, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, []string{utils.DEFAULT_RUNID}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, []string{utils.SMS}, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, []string{utils.SMS, utils.VOICE}, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, []string{"192.168.1.2"}, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, []string{"192.168.1.2"}, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, []string{"192.168.1.1", "192.168.1.2"}, nil, nil, nil, nil, nil, nil, nil, nil, + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, []string{"192.168.1.1", "192.168.1.2"}, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, []string{"UNKNOWN"}, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, []string{"UNKNOWN"}, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, []string{"UNKNOWN", "UNKNOWN2"}, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, []string{"UNKNOWN", "UNKNOWN2"}, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, []string{"prepaid"}, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, []string{"prepaid"}, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, []string{"prepaid", "pseudoprepaid"}, nil, nil, nil, nil, nil, nil, + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, []string{"prepaid", "pseudoprepaid"}, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, []string{"*out"}, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, []string{"*out"}, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, []string{"itsyscom.com"}, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, []string{"itsyscom.com"}, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, []string{"itsyscom.com", "cgrates.org"}, nil, nil, nil, nil, + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, []string{"itsyscom.com", "cgrates.org"}, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on tor - if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, []string{"premium_call"}, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, []string{"premium_call"}, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple tor - if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, []string{"premium_call", "call"}, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, []string{"premium_call", "call"}, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, []string{"1002"}, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1002"}, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, []string{"1001", "1002"}, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1001", "1002"}, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1000"}, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1000"}, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1000", "1002"}, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1000", "1002"}, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"+498651"}, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"+498651"}, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1001", "+498651"}, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1001", "+498651"}, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 4 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on ignoreErr - if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, true, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, true, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, true); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, true); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 5 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) @@ -378,33 +390,33 @@ func TestGetStoredCdrs(t *testing.T) { } } // Filter on orderIdStart - if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, orderIdStart, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, orderIdStart, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, orderIdStart, orderIdEnd+1, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, orderIdStart, orderIdEnd+1, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 5 { 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); 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 := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Combined filter - if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, []string{"rated"}, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, []string{"rated"}, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) @@ -447,7 +459,7 @@ func TestRemStoredCdrs(t *testing.T) { if err := mysql.RemStoredCdrs([]string{cgrIdB1}); err != nil { t.Error(err.Error()) } - if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 7 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) @@ -468,7 +480,7 @@ func TestRemStoredCdrs(t *testing.T) { cgrIdB2, cgrIdB3}); err != nil { t.Error(err.Error()) } - if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { + if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, false, false); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 0 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) diff --git a/mediator/mediator.go b/mediator/mediator.go index 53773cc93..4ce3ac6b2 100644 --- a/mediator/mediator.go +++ b/mediator/mediator.go @@ -45,11 +45,11 @@ type Mediator struct { cgrCfg *config.CGRConfig } -// Retrive the cost from logging database +// Retrive the cost from logging database, nil in case of no log func (self *Mediator) getCostsFromDB(cgrid, runId string) (cc *engine.CallCost, err error) { for i := 0; i < 3; i++ { // Mechanism to avoid concurrency between SessionManager writing the costs and mediator picking them up - cc, err = self.logDb.GetCallCostLog(cgrid, engine.SESSION_MANAGER_SOURCE, runId) //ToDo: What are we getting when there is no log? - if cc != nil { // There were no errors, chances are that we got what we are looking for + cc, err = self.logDb.GetCallCostLog(cgrid, engine.SESSION_MANAGER_SOURCE, runId) + if cc != nil { break } time.Sleep(time.Duration(i) * time.Second) @@ -58,7 +58,7 @@ func (self *Mediator) getCostsFromDB(cgrid, runId string) (cc *engine.CallCost, } // Retrive the cost from engine -func (self *Mediator) getCostsFromRater(storedCdr *utils.StoredCdr) (*engine.CallCost, error) { +func (self *Mediator) getCostsVoiceFromRater(storedCdr *utils.StoredCdr) (*engine.CallCost, error) { cc := &engine.CallCost{} var err error if storedCdr.Duration == time.Duration(0) { // failed call, returning empty callcost, no error @@ -96,8 +96,10 @@ func (self *Mediator) rateCDR(storedCdr *utils.StoredCdr) error { if storedCdr.ReqType == utils.PREPAID || storedCdr.ReqType == utils.POSTPAID { // Should be previously calculated and stored in DB qryCC, errCost = self.getCostsFromDB(storedCdr.CgrId, storedCdr.MediationRunId) + } else if storedCdr.TOR == utils.VOICE { + qryCC, errCost = self.getCostsVoiceFromRater(storedCdr) } else { - qryCC, errCost = self.getCostsFromRater(storedCdr) + return fmt.Errorf("Unsupported TOR: %s", storedCdr.TOR) } if errCost != nil { return errCost @@ -109,6 +111,7 @@ func (self *Mediator) rateCDR(storedCdr *utils.StoredCdr) error { } func (self *Mediator) RateCdr(storedCdr *utils.StoredCdr) error { + engine.Logger.Debug(fmt.Sprintf("Rating CDR: %v", storedCdr)) storedCdr.MediationRunId = utils.DEFAULT_RUNID cdrRuns := []*utils.StoredCdr{storedCdr} // Start with initial storCdr, will add here all to be mediated attrsDC := utils.AttrDerivedChargers{Tenant: storedCdr.Tenant, Category: storedCdr.Category, Direction: storedCdr.Direction, @@ -153,7 +156,7 @@ func (self *Mediator) RateCdr(storedCdr *utils.StoredCdr) error { } func (self *Mediator) RateCdrs(timeStart, timeEnd time.Time, rerateErrors, rerateRated bool) error { - cdrs, err := self.cdrDb.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, !rerateErrors, !rerateRated) + cdrs, err := self.cdrDb.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, timeStart, timeEnd, !rerateErrors, !rerateRated) if err != nil { return err } diff --git a/mediator/mediator_local_test.go b/mediator/mediator_local_test.go index 1725639b5..52deb09ad 100644 --- a/mediator/mediator_local_test.go +++ b/mediator/mediator_local_test.go @@ -136,11 +136,11 @@ func TestPostCdrs(t *testing.T) { return } httpClient := new(http.Client) - cdrForm1 := url.Values{utils.ACCID: []string{"dsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{"rated"}, utils.DIRECTION: []string{"*out"}, + cdrForm1 := url.Values{utils.TOR: []string{utils.VOICE}, utils.ACCID: []string{"dsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{"rated"}, utils.DIRECTION: []string{"*out"}, utils.TENANT: []string{"cgrates.org"}, utils.CATEGORY: []string{"call"}, utils.ACCOUNT: []string{"1001"}, utils.SUBJECT: []string{"1001"}, utils.DESTINATION: []string{"+4986517174963"}, utils.ANSWER_TIME: []string{"2013-11-07T08:42:26Z"}, utils.DURATION: []string{"10"}, "field_extr1": []string{"val_extr1"}, "fieldextr2": []string{"valextr2"}} - cdrForm2 := url.Values{utils.ACCID: []string{"adsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{"rated"}, utils.DIRECTION: []string{"*out"}, + cdrForm2 := url.Values{utils.TOR: []string{utils.VOICE}, utils.ACCID: []string{"adsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{"rated"}, utils.DIRECTION: []string{"*out"}, utils.TENANT: []string{"itsyscom.com"}, utils.CATEGORY: []string{"call"}, utils.ACCOUNT: []string{"1003"}, utils.SUBJECT: []string{"1003"}, utils.DESTINATION: []string{"+4986517174964"}, utils.ANSWER_TIME: []string{"2013-11-07T08:42:26Z"}, utils.DURATION: []string{"10"}, "field_extr1": []string{"val_extr1"}, "fieldextr2": []string{"valextr2"}} for _, cdrForm := range []url.Values{cdrForm1, cdrForm2} { @@ -150,12 +150,12 @@ func TestPostCdrs(t *testing.T) { } } time.Sleep(100 * time.Millisecond) // Give time for CDRs to reach database - if storedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, false, false); err != nil { + if storedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, false, false); err != nil { t.Error(err) } else if len(storedCdrs) != 4 { // Make sure CDRs made it into StorDb t.Error(fmt.Sprintf("Unexpected number of CDRs stored: %d", len(storedCdrs))) } - if nonErrorCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, true, false); err != nil { + if nonErrorCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, true, false); err != nil { t.Error(err) } else if len(nonErrorCdrs) != 0 { // Just two of them should be without errors t.Error(fmt.Sprintf("Unexpected number of CDRs stored: %d", len(nonErrorCdrs))) @@ -167,10 +167,10 @@ func TestInjectCdrs(t *testing.T) { if !*testLocal { return } - cgrCdr1 := utils.CgrCdr{utils.ACCID: "aaaaadsafdsaf", "cdrsource": engine.TEST_SQL, utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", + cgrCdr1 := utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaaaadsafdsaf", "cdrsource": engine.TEST_SQL, utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "call", utils.ACCOUNT: "dan", utils.SUBJECT: "dan", utils.DESTINATION: "+4986517174963", utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.DURATION: "10"} - cgrCdr2 := utils.CgrCdr{utils.ACCID: "baaaadsafdsaf", "cdrsource": engine.TEST_SQL, utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", + cgrCdr2 := utils.CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "baaaadsafdsaf", "cdrsource": engine.TEST_SQL, utils.CDRHOST: "192.168.1.1", utils.REQTYPE: "rated", utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", utils.CATEGORY: "call", utils.ACCOUNT: "dan", utils.SUBJECT: "dan", utils.DESTINATION: "+4986517173964", utils.ANSWER_TIME: "2013-11-07T09:42:26Z", utils.DURATION: "20"} for _, cdr := range []utils.CgrCdr{cgrCdr1, cgrCdr2} { @@ -178,12 +178,12 @@ func TestInjectCdrs(t *testing.T) { t.Error(err) } } - if storedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, false, false); err != nil { + if storedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, false, false); err != nil { t.Error(err) } else if len(storedCdrs) != 6 { // Make sure CDRs made it into StorDb t.Error(fmt.Sprintf("Unexpected number of CDRs stored: %d", len(storedCdrs))) } - if nonRatedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, true, true); err != nil { + if nonRatedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, true, true); err != nil { t.Error(err) } else if len(nonRatedCdrs) != 2 { // Just two of them should be non-rated t.Error(fmt.Sprintf("Unexpected number of CDRs non-rated: %d", len(nonRatedCdrs))) @@ -215,12 +215,12 @@ func TestRateCdrs(t *testing.T) { } else if reply != utils.OK { t.Errorf("Unexpected reply: %s", reply) } - if nonRatedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, true, true); err != nil { + if nonRatedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, true, true); err != nil { t.Error(err) } else if len(nonRatedCdrs) != 0 { // Just two of them should be non-rated t.Error(fmt.Sprintf("Unexpected number of CDRs non-rated: %d", len(nonRatedCdrs))) } - if errRatedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, false, true); err != nil { + if errRatedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, false, true); err != nil { t.Error(err) } else if len(errRatedCdrs) != 4 { // The first 2 with errors should be still there before rerating t.Error(fmt.Sprintf("Unexpected number of CDRs with errors: %d", len(errRatedCdrs))) @@ -230,7 +230,7 @@ func TestRateCdrs(t *testing.T) { } else if reply != utils.OK { t.Errorf("Unexpected reply: %s", reply) } - if errRatedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, false, true); err != nil { + if errRatedCdrs, err := cdrStor.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 0, time.Time{}, time.Time{}, false, true); err != nil { t.Error(err) } else if len(errRatedCdrs) != 2 { t.Error(fmt.Sprintf("Unexpected number of CDRs with errors: %d", len(errRatedCdrs))) diff --git a/utils/apitpdata.go b/utils/apitpdata.go index eb8d11ac2..e5fb815e6 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -332,6 +332,7 @@ type AttrExpFileCdrs struct { MaskLength int // Overwrite configured MaskLength, -1 to use general config ones CgrIds []string // If provided, it will filter based on the cgrids present in list MediationRunId []string // If provided, it will filter on mediation runid + TOR []string // If provided, filter on TypeOfRecord CdrHost []string // If provided, it will filter cdrhost CdrSource []string // If provided, it will filter cdrsource ReqType []string // If provided, it will fiter reqtype