mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-16 13:49:53 +05:00
Default RunId changed to *default for consistency, StoredCdr.Rated property so we can import already calculated CDRs, fixes for SkipErrors and SkipRated API filters for CDRs, created_time fix on MySQL, fix injected Cost when importing from external file and .Rated is false
This commit is contained in:
@@ -41,7 +41,7 @@ var cdrsRpc *rpc.Client
|
||||
|
||||
var cmdEngineCdrsMysql *exec.Cmd
|
||||
|
||||
func TestInitConfig(t *testing.T) {
|
||||
func TestV2CdrsMysqlInitConfig(t *testing.T) {
|
||||
if !*testLocal {
|
||||
return
|
||||
}
|
||||
@@ -71,6 +71,29 @@ func TestV2CdrsMysqlInitCdrDb(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestV2CdrsMysqlInjectUnratedCdr(t *testing.T) {
|
||||
if !*testLocal {
|
||||
return
|
||||
}
|
||||
var mysqlDb *engine.MySQLStorage
|
||||
if d, err := engine.NewMySQLStorage(cdrsCfg.StorDBHost, cdrsCfg.StorDBPort, cdrsCfg.StorDBName, cdrsCfg.StorDBUser, cdrsCfg.StorDBPass,
|
||||
cdrsCfg.StorDBMaxOpenConns, cdrsCfg.StorDBMaxIdleConns); err != nil {
|
||||
t.Error("Error on opening database connection: ", err)
|
||||
return
|
||||
} else {
|
||||
mysqlDb = d.(*engine.MySQLStorage)
|
||||
}
|
||||
strCdr1 := &utils.StoredCdr{CgrId: utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
|
||||
TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: "rated",
|
||||
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}
|
||||
if err := mysqlDb.SetCdr(strCdr1); err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestV2CdrsMysqlStartEngine(t *testing.T) {
|
||||
if !*testLocal {
|
||||
return
|
||||
@@ -103,17 +126,20 @@ func TestV2CdrsMysqlProcessCdr(t *testing.T) {
|
||||
&utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
|
||||
CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
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",
|
||||
Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
RatedAccount: "dan", RatedSubject: "dans", Rated: true,
|
||||
},
|
||||
&utils.StoredCdr{CgrId: utils.Sha1("abcdeftg", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
|
||||
CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", Destination: "1002",
|
||||
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",
|
||||
Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
RatedAccount: "dan", RatedSubject: "dans",
|
||||
},
|
||||
&utils.StoredCdr{CgrId: utils.Sha1("aererfddf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
|
||||
CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1002",
|
||||
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",
|
||||
Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
RatedAccount: "dan", RatedSubject: "dans",
|
||||
},
|
||||
}
|
||||
for _, cdr := range cdrs {
|
||||
@@ -130,15 +156,42 @@ func TestV2CdrsMysqlGetCdrs(t *testing.T) {
|
||||
return
|
||||
}
|
||||
var reply []*utils.StoredCdr
|
||||
req := utils.AttrGetCdrs{}
|
||||
req := utils.RpcCdrsFilter{}
|
||||
if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 4 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
}
|
||||
// CDRs with errors
|
||||
req = utils.RpcCdrsFilter{CostStart: utils.Float64Pointer(-1.0), CostEnd: 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{CostStart: 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: ", len(reply))
|
||||
t.Error("Unexpected number of CDRs returned: ", reply)
|
||||
}
|
||||
// CDRs non rated OR SkipRated
|
||||
req = utils.RpcCdrsFilter{CostEnd: 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)
|
||||
}
|
||||
// Skip Errors
|
||||
req = utils.RpcCdrsFilter{CostStart: utils.Float64Pointer(0.0), CostEnd: utils.Float64Pointer(-1.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)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func TestV2CdrsMysqlCountCdrs(t *testing.T) {
|
||||
if !*testLocal {
|
||||
return
|
||||
@@ -147,11 +200,10 @@ func TestV2CdrsMysqlCountCdrs(t *testing.T) {
|
||||
req := utils.AttrGetCdrs{}
|
||||
if err := cdrsRpc.Call("ApierV2.CountCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if reply != 3 {
|
||||
} else if reply != 4 {
|
||||
t.Error("Unexpected number of CDRs returned: ", reply)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func TestV2CdrsMysqlKillEngine(t *testing.T) {
|
||||
if !*testLocal {
|
||||
|
||||
@@ -65,6 +65,29 @@ func TestV2CdrsPsqlInitCdrDb(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestV2CdrsPsqlInjectUnratedCdr(t *testing.T) {
|
||||
if !*testLocal {
|
||||
return
|
||||
}
|
||||
var psqlDb *engine.PostgresStorage
|
||||
if d, err := engine.NewPostgresStorage(cdrsPsqlCfg.StorDBHost, cdrsPsqlCfg.StorDBPort, cdrsPsqlCfg.StorDBName, cdrsPsqlCfg.StorDBUser, cdrsPsqlCfg.StorDBPass,
|
||||
cdrsPsqlCfg.StorDBMaxOpenConns, cdrsPsqlCfg.StorDBMaxIdleConns); err != nil {
|
||||
t.Error("Error on opening database connection: ", err)
|
||||
return
|
||||
} else {
|
||||
psqlDb = d.(*engine.PostgresStorage)
|
||||
}
|
||||
strCdr1 := &utils.StoredCdr{CgrId: utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()),
|
||||
TOR: utils.VOICE, AccId: "bbb1", CdrHost: "192.168.1.1", CdrSource: "UNKNOWN", ReqType: "rated",
|
||||
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}
|
||||
if err := psqlDb.SetCdr(strCdr1); err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestV2CdrsPsqlStartEngine(t *testing.T) {
|
||||
if !*testLocal {
|
||||
return
|
||||
@@ -97,17 +120,20 @@ func TestV2CdrsPsqlProcessCdr(t *testing.T) {
|
||||
&utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
|
||||
CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
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",
|
||||
Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
RatedAccount: "dan", RatedSubject: "dans", Rated: true,
|
||||
},
|
||||
&utils.StoredCdr{CgrId: utils.Sha1("abcdeftg", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
|
||||
CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", Destination: "1002",
|
||||
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",
|
||||
Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
RatedAccount: "dan", RatedSubject: "dans",
|
||||
},
|
||||
&utils.StoredCdr{CgrId: utils.Sha1("aererfddf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
|
||||
CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1002",
|
||||
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",
|
||||
Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
RatedAccount: "dan", RatedSubject: "dans",
|
||||
},
|
||||
}
|
||||
for _, cdr := range cdrs {
|
||||
@@ -124,15 +150,42 @@ func TestV2CdrsPsqlGetCdrs(t *testing.T) {
|
||||
return
|
||||
}
|
||||
var reply []*utils.StoredCdr
|
||||
req := utils.AttrGetCdrs{}
|
||||
req := utils.RpcCdrsFilter{}
|
||||
if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 4 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
}
|
||||
// CDRs with errors
|
||||
req = utils.RpcCdrsFilter{CostStart: utils.Float64Pointer(-1.0), CostEnd: 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{CostStart: 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: ", len(reply))
|
||||
t.Error("Unexpected number of CDRs returned: ", reply)
|
||||
}
|
||||
// CDRs non rated OR SkipRated
|
||||
req = utils.RpcCdrsFilter{CostEnd: 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)
|
||||
}
|
||||
// Skip Errors
|
||||
req = utils.RpcCdrsFilter{CostStart: utils.Float64Pointer(0.0), CostEnd: utils.Float64Pointer(-1.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)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func TestV2CdrsPsqlCountCdrs(t *testing.T) {
|
||||
if !*testLocal {
|
||||
return
|
||||
@@ -141,11 +194,10 @@ func TestV2CdrsPsqlCountCdrs(t *testing.T) {
|
||||
req := utils.AttrGetCdrs{}
|
||||
if err := cdrsPsqlRpc.Call("ApierV2.CountCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if reply != 3 {
|
||||
} else if reply != 4 {
|
||||
t.Error("Unexpected number of CDRs returned: ", reply)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func TestV2CdrsPsqlKillEngine(t *testing.T) {
|
||||
if !*testLocal {
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestCsvCdrWriter(t *testing.T) {
|
||||
if err := cdre.writeCsv(csvWriter); err != nil {
|
||||
t.Error("Unexpected error: ", err)
|
||||
}
|
||||
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6,default,*voice,dsafdsaf,rated,*out,cgrates.org,call,1001,1001,1002,2013-11-07T08:42:25Z,2013-11-07T08:42:26Z,10,1.0100`
|
||||
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6,*default,*voice,dsafdsaf,rated,*out,cgrates.org,call,1001,1001,1002,2013-11-07T08:42:25Z,2013-11-07T08:42:26Z,10,1.0100`
|
||||
result := strings.TrimSpace(writer.String())
|
||||
if result != expected {
|
||||
t.Errorf("Expected: \n%s received: \n%s.", expected, result)
|
||||
@@ -76,7 +76,7 @@ func TestAlternativeFieldSeparator(t *testing.T) {
|
||||
if err := cdre.writeCsv(csvWriter); err != nil {
|
||||
t.Error("Unexpected error: ", err)
|
||||
}
|
||||
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6|default|*voice|dsafdsaf|rated|*out|cgrates.org|call|1001|1001|1002|2013-11-07T08:42:25Z|2013-11-07T08:42:26Z|10|1.0100`
|
||||
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6|*default|*voice|dsafdsaf|rated|*out|cgrates.org|call|1001|1001|1002|2013-11-07T08:42:25Z|2013-11-07T08:42:26Z|10|1.0100`
|
||||
result := strings.TrimSpace(writer.String())
|
||||
if result != expected {
|
||||
t.Errorf("Expected: \n%s received: \n%s.", expected, result)
|
||||
|
||||
@@ -19,7 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"os/exec"
|
||||
"path"
|
||||
"time"
|
||||
@@ -40,6 +42,8 @@ func InitDataDb(cfg *config.CGRConfig) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ratingDb.CacheRating(nil, nil, nil, nil, nil)
|
||||
accountDb.CacheAccounting(nil, nil, nil, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -77,3 +81,28 @@ func KillEngine(waitEngine int) error {
|
||||
time.Sleep(time.Duration(waitEngine) * time.Millisecond)
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadTariffPlanFromFolder(tpPath string, ratingDb RatingStorage, accountingDb AccountingStorage) error {
|
||||
loader := NewFileCSVReader(ratingDb, accountingDb, utils.CSV_SEP,
|
||||
path.Join(tpPath, utils.DESTINATIONS_CSV),
|
||||
path.Join(tpPath, utils.TIMINGS_CSV),
|
||||
path.Join(tpPath, utils.RATES_CSV),
|
||||
path.Join(tpPath, utils.DESTINATION_RATES_CSV),
|
||||
path.Join(tpPath, utils.RATING_PLANS_CSV),
|
||||
path.Join(tpPath, utils.RATING_PROFILES_CSV),
|
||||
path.Join(tpPath, utils.SHARED_GROUPS_CSV),
|
||||
path.Join(tpPath, utils.LCRS_CSV),
|
||||
path.Join(tpPath, utils.ACTIONS_CSV),
|
||||
path.Join(tpPath, utils.ACTION_PLANS_CSV),
|
||||
path.Join(tpPath, utils.ACTION_TRIGGERS_CSV),
|
||||
path.Join(tpPath, utils.ACCOUNT_ACTIONS_CSV),
|
||||
path.Join(tpPath, utils.DERIVED_CHARGERS_CSV),
|
||||
path.Join(tpPath, utils.CDR_STATS_CSV))
|
||||
if err := loader.LoadAll(); err != nil {
|
||||
return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
|
||||
}
|
||||
if err := loader.WriteToDatabase(false, false); err != nil {
|
||||
return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -165,8 +165,11 @@ func (self *Mediator) RateCdr(storedCdr *utils.StoredCdr, sendToStats bool) erro
|
||||
}
|
||||
for _, cdr := range cdrRuns {
|
||||
extraInfo := ""
|
||||
if err := self.rateCDR(cdr); err != nil {
|
||||
extraInfo = err.Error()
|
||||
if cdr.MediationRunId != utils.DEFAULT_RUNID || !cdr.Rated { // Do not rate calls which are out of default run and marked as rated already, eg premium SMSes
|
||||
if err := self.rateCDR(cdr); err != nil {
|
||||
cdr.Cost = -1.0 // If there was an error, mark the CDR as it is
|
||||
extraInfo = err.Error()
|
||||
}
|
||||
}
|
||||
if !self.cgrCfg.MediatorStoreDisable {
|
||||
if err := self.cdrDb.SetRatedCdr(cdr, extraInfo); err != nil {
|
||||
|
||||
@@ -104,7 +104,7 @@ func (self *MySQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost)
|
||||
}
|
||||
|
||||
func (self *MySQLStorage) SetRatedCdr(storedCdr *utils.StoredCdr, extraInfo string) (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`,cost,extra_info,created_at) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',%v,%f,'%s',%d) 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`),cost=values(cost),extra_info=values(extra_info), updated_at=%d",
|
||||
_, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (cgrid,runid,reqtype,direction,tenant,category,account,subject,destination,setup_time,answer_time,`usage`,cost,extra_info,created_at) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',%v,%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`),cost=values(cost),extra_info=values(extra_info), updated_at='%s'",
|
||||
utils.TBL_RATED_CDRS,
|
||||
storedCdr.CgrId,
|
||||
storedCdr.MediationRunId,
|
||||
@@ -120,8 +120,8 @@ func (self *MySQLStorage) SetRatedCdr(storedCdr *utils.StoredCdr, extraInfo stri
|
||||
storedCdr.Usage.Seconds(),
|
||||
storedCdr.Cost,
|
||||
extraInfo,
|
||||
time.Now().Unix(),
|
||||
time.Now().Unix()))
|
||||
time.Now().Format(time.RFC3339),
|
||||
time.Now().Format(time.RFC3339)))
|
||||
if err != nil {
|
||||
Logger.Err(fmt.Sprintf("failed to execute cdr insert statement: %s", err.Error()))
|
||||
}
|
||||
|
||||
@@ -873,10 +873,10 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*utils.Store
|
||||
q = q.Where(utils.TBL_COST_DETAILS+".subject not in (?)", qryFltr.NotRatedSubjects)
|
||||
}
|
||||
if len(qryFltr.Costs) != 0 {
|
||||
q = q.Where(utils.TBL_COST_DETAILS+".cost in (?)", qryFltr.Costs)
|
||||
q = q.Where(utils.TBL_RATED_CDRS+".cost in (?)", qryFltr.Costs)
|
||||
}
|
||||
if len(qryFltr.NotCosts) != 0 {
|
||||
q = q.Where(utils.TBL_COST_DETAILS+".cost not in (?)", qryFltr.NotCosts)
|
||||
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("(")
|
||||
@@ -935,11 +935,15 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*utils.Store
|
||||
q = q.Where(utils.TBL_RATED_CDRS+".usage < ?", qryFltr.RatedUsageEnd)
|
||||
}
|
||||
if qryFltr.CostStart != nil {
|
||||
q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.CostStart)
|
||||
if qryFltr.CostEnd != nil {
|
||||
if qryFltr.CostEnd == nil {
|
||||
q = q.Where(utils.TBL_RATED_CDRS+".cost >= ?", *qryFltr.CostStart)
|
||||
} else if *qryFltr.CostStart == 0.0 && *qryFltr.CostEnd == -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.CostStart)
|
||||
q = q.Where(utils.TBL_RATED_CDRS+".cost < ?", *qryFltr.CostEnd)
|
||||
}
|
||||
} else if qryFltr.CostEnd != nil { // In case of both nil, we do not need to add any filter
|
||||
} else if qryFltr.CostEnd != nil {
|
||||
if *qryFltr.CostEnd == -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 costStart is empty, make sure we query also NULL cost
|
||||
|
||||
@@ -725,8 +725,9 @@ func (self *AttrExpFileCdrs) AsCdrsFilter() (*CdrsFilter, error) {
|
||||
}
|
||||
}
|
||||
if self.SkipRated {
|
||||
cdrFltr.CostEnd = Float64Pointer(0.0)
|
||||
} else if self.SkipErrors {
|
||||
cdrFltr.CostEnd = Float64Pointer(-1.0)
|
||||
} else if self.SkipRated {
|
||||
cdrFltr.CostStart = Float64Pointer(0.0)
|
||||
cdrFltr.CostEnd = Float64Pointer(-1.0)
|
||||
}
|
||||
return cdrFltr, nil
|
||||
@@ -799,8 +800,9 @@ func (self *AttrGetCdrs) AsCdrsFilter() (*CdrsFilter, error) {
|
||||
}
|
||||
}
|
||||
if self.SkipRated {
|
||||
cdrFltr.CostEnd = Float64Pointer(0.0)
|
||||
} else if self.SkipErrors {
|
||||
cdrFltr.CostEnd = Float64Pointer(-1.0)
|
||||
} else if self.SkipRated {
|
||||
cdrFltr.CostStart = Float64Pointer(0.0)
|
||||
cdrFltr.CostEnd = Float64Pointer(-1.0)
|
||||
}
|
||||
return cdrFltr, nil
|
||||
|
||||
@@ -101,7 +101,7 @@ const (
|
||||
RATED_ACCOUNT = "rated_account"
|
||||
RATED_SUBJECT = "rated_subject"
|
||||
COST = "cost"
|
||||
DEFAULT_RUNID = "default"
|
||||
DEFAULT_RUNID = "*default"
|
||||
META_DEFAULT = "*default"
|
||||
STATIC_VALUE_PREFIX = "^"
|
||||
CSV = "csv"
|
||||
|
||||
@@ -52,6 +52,7 @@ type StoredCdr struct {
|
||||
RatedAccount string // Populated out of rating data
|
||||
RatedSubject string
|
||||
Cost float64
|
||||
Rated bool // Mark the CDR as rated so we do not process it during mediation
|
||||
}
|
||||
|
||||
// Used to multiply usage on export
|
||||
|
||||
Reference in New Issue
Block a user