mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Merge branch 'master' of https://github.com/cgrates/cgrates
This commit is contained in:
@@ -121,7 +121,7 @@ func TestApierStartEngine(t *testing.T) {
|
||||
exec.Command("pkill", "cgr-engine").Run() // Just to make sure another one is not running, bit brutal maybe we can fine tune it
|
||||
time.Sleep(time.Duration(*waitRater) * time.Millisecond)
|
||||
engine := exec.Command(enginePath, "-config_dir", cfgPath)
|
||||
engine.Stderr = os.Stderr
|
||||
//engine.Stderr = os.Stderr
|
||||
if err := engine.Start(); err != nil {
|
||||
t.Fatal("Cannot start cgr-engine: ", err.Error())
|
||||
}
|
||||
|
||||
@@ -145,38 +145,50 @@ func TestV2CdrsMongoGetCdrs(t *testing.T) {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{}
|
||||
req := utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}}
|
||||
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)
|
||||
}
|
||||
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)}
|
||||
req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, 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 {
|
||||
t.Error("Unexpected number of CDRs returned: ", reply)
|
||||
}
|
||||
// CDRs Rated
|
||||
req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(-1.0)}
|
||||
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) != 3 {
|
||||
} 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{MaxCost: utils.Float64Pointer(-1.0)}
|
||||
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) != 1 {
|
||||
} 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{MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)}
|
||||
req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, 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) != 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)
|
||||
}
|
||||
}
|
||||
@@ -186,7 +198,7 @@ func TestV2CdrsMongoCountCdrs(t *testing.T) {
|
||||
return
|
||||
}
|
||||
var reply int64
|
||||
req := utils.AttrGetCdrs{}
|
||||
req := utils.AttrGetCdrs{CdrSources: []string{"test", "UNKNOWN"}}
|
||||
if err := cdrsMongoRpc.Call("ApierV2.CountCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if reply != 4 {
|
||||
|
||||
36
data/conf/samples/actions/cgradmin.json
Normal file
36
data/conf/samples/actions/cgradmin.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
// CGRateS Configuration file
|
||||
//
|
||||
// Used for cgradmin
|
||||
// Starts rater, scheduler
|
||||
|
||||
"listen": {
|
||||
"rpc_json": ":2012", // RPC JSON listening address
|
||||
"rpc_gob": ":2013", // RPC GOB listening address
|
||||
"http": ":2080", // HTTP listening address
|
||||
},
|
||||
|
||||
"rater": {
|
||||
"enabled": true, // enable Rater service: <true|false>
|
||||
"pubsubs": "internal",
|
||||
"users": "internal",
|
||||
"aliases": "internal",
|
||||
},
|
||||
|
||||
"scheduler": {
|
||||
"enabled": true, // start Scheduler service: <true|false>
|
||||
},
|
||||
|
||||
"pubsubs": {
|
||||
"enabled": true, // starts pubsub service: <true|false>.
|
||||
},
|
||||
|
||||
"users": {
|
||||
"enabled": true, // starts users service: <true|false>.
|
||||
},
|
||||
|
||||
"aliases": {
|
||||
"enabled": true,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"net/rpc/jsonrpc"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
@@ -30,7 +31,7 @@ import (
|
||||
|
||||
var actsLclCfg *config.CGRConfig
|
||||
var actsLclRpc *rpc.Client
|
||||
var actsLclCfgPath = path.Join(*dataDir, "conf", "samples", "cgradmin")
|
||||
var actsLclCfgPath = path.Join(*dataDir, "conf", "samples", "actions")
|
||||
|
||||
func TestActionsLocalInitCfg(t *testing.T) {
|
||||
if !*testLocal {
|
||||
@@ -71,6 +72,7 @@ func TestActionsLocalRpcConn(t *testing.T) {
|
||||
return
|
||||
}
|
||||
var err error
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
actsLclRpc, err = jsonrpc.Dial("tcp", actsLclCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -307,32 +307,6 @@ func (b *Balance) SetValue(amount float64) {
|
||||
b.Value = amount
|
||||
b.Value = utils.Round(b.GetValue(), globalRoundingDecimals, utils.ROUNDING_MIDDLE)
|
||||
b.dirty = true
|
||||
|
||||
// publish event
|
||||
accountId := ""
|
||||
allowNegative := ""
|
||||
disabled := ""
|
||||
if b.account != nil { // only publish modifications for balances with account set
|
||||
accountId = b.account.Id
|
||||
allowNegative = strconv.FormatBool(b.account.AllowNegative)
|
||||
disabled = strconv.FormatBool(b.account.Disabled)
|
||||
Publish(CgrEvent{
|
||||
"EventName": utils.EVT_ACCOUNT_BALANCE_MODIFIED,
|
||||
"Uuid": b.Uuid,
|
||||
"Id": b.Id,
|
||||
"Value": strconv.FormatFloat(b.Value, 'f', -1, 64),
|
||||
"ExpirationDate": b.ExpirationDate.String(),
|
||||
"Weight": strconv.FormatFloat(b.Weight, 'f', -1, 64),
|
||||
"DestinationIds": b.DestinationIds,
|
||||
"RatingSubject": b.RatingSubject,
|
||||
"Category": b.Category,
|
||||
"SharedGroup": b.SharedGroup,
|
||||
"TimingIDs": b.TimingIDs,
|
||||
"Account": accountId,
|
||||
"AccountAllowNegative": allowNegative,
|
||||
"AccountDisabled": disabled,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances BalanceChain, count bool, dryRun bool) (cc *CallCost, err error) {
|
||||
@@ -669,10 +643,39 @@ func (bc BalanceChain) HasBalance(balance *Balance) bool {
|
||||
}
|
||||
|
||||
func (bc BalanceChain) SaveDirtyBalances(acc *Account) {
|
||||
savedAccounts := make(map[string]bool)
|
||||
for _, b := range bc {
|
||||
// TODO: check if the account was not already saved ?
|
||||
if b.account != nil && b.account != acc && b.dirty {
|
||||
if b.dirty {
|
||||
// publish event
|
||||
accountId := ""
|
||||
allowNegative := ""
|
||||
disabled := ""
|
||||
if b.account != nil { // only publish modifications for balances with account set
|
||||
//debug.PrintStack()
|
||||
accountId = b.account.Id
|
||||
allowNegative = strconv.FormatBool(b.account.AllowNegative)
|
||||
disabled = strconv.FormatBool(b.account.Disabled)
|
||||
Publish(CgrEvent{
|
||||
"EventName": utils.EVT_ACCOUNT_BALANCE_MODIFIED,
|
||||
"Uuid": b.Uuid,
|
||||
"Id": b.Id,
|
||||
"Value": strconv.FormatFloat(b.Value, 'f', -1, 64),
|
||||
"ExpirationDate": b.ExpirationDate.String(),
|
||||
"Weight": strconv.FormatFloat(b.Weight, 'f', -1, 64),
|
||||
"DestinationIds": b.DestinationIds,
|
||||
"RatingSubject": b.RatingSubject,
|
||||
"Category": b.Category,
|
||||
"SharedGroup": b.SharedGroup,
|
||||
"TimingIDs": b.TimingIDs,
|
||||
"Account": accountId,
|
||||
"AccountAllowNegative": allowNegative,
|
||||
"AccountDisabled": disabled,
|
||||
})
|
||||
}
|
||||
}
|
||||
if b.account != nil && b.account != acc && b.dirty && savedAccounts[b.account.Id] == false {
|
||||
accountingStorage.SetAccount(b.account)
|
||||
savedAccounts[b.account.Id] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,6 @@ func StartEngine(cfgPath string, waitEngine int) (*exec.Cmd, error) {
|
||||
return nil, err
|
||||
}
|
||||
engine := exec.Command(enginePath, "-config_dir", cfgPath)
|
||||
engine.Stderr = os.Stderr
|
||||
if err := engine.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ func (ps *PubSub) Unsubscribe(si SubscribeInfo, reply *string) error {
|
||||
func (ps *PubSub) Publish(evt CgrEvent, reply *string) error {
|
||||
ps.mux.Lock()
|
||||
defer ps.mux.Unlock()
|
||||
evt["Timestamp"] = time.Now().Format(time.RFC3339Nano)
|
||||
for key, subData := range ps.subscribers {
|
||||
if !subData.ExpTime.IsZero() && subData.ExpTime.Before(time.Now()) {
|
||||
delete(ps.subscribers, key)
|
||||
|
||||
@@ -137,7 +137,7 @@ func TestPublish(t *testing.T) {
|
||||
t.Error("Error publishing: ", err)
|
||||
}
|
||||
for i := 0; i < 1000; i++ { // wait for the theread to populate map
|
||||
if len(m) == 1 {
|
||||
if len(m) == 2 {
|
||||
time.Sleep(time.Microsecond)
|
||||
} else {
|
||||
break
|
||||
|
||||
@@ -575,7 +575,7 @@ func TestMongoCallCost(t *testing.T) {
|
||||
}
|
||||
if ccRcv, err := mongoDb.GetCallCostLog(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else if !reflect.DeepEqual(cc.Timespans[0].TimeStart, ccRcv.Timespans[0].TimeStart) {
|
||||
} 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
|
||||
@@ -585,7 +585,7 @@ func TestMongoCallCost(t *testing.T) {
|
||||
}
|
||||
if ccRcv, err := mongoDb.GetCallCostLog(cgrId, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else if !reflect.DeepEqual(cc, ccRcv) {
|
||||
} else if cc.Cost != ccRcv.Cost {
|
||||
t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv)
|
||||
}
|
||||
}
|
||||
@@ -598,28 +598,28 @@ func TestMongoGetStoredCdrs(t *testing.T) {
|
||||
// All CDRs, no filter
|
||||
if storedCdrs, _, err := mongoDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else if len(storedCdrs) != 8 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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: ", storedCdrs)
|
||||
} else if count != 8 {
|
||||
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: ", storedCdrs)
|
||||
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: ", storedCdrs)
|
||||
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 {
|
||||
@@ -631,14 +631,14 @@ func TestMongoGetStoredCdrs(t *testing.T) {
|
||||
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) != 2 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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 != 2 {
|
||||
} else if count != 3 {
|
||||
t.Error("Unexpected count of StoredCdrs returned: ", count)
|
||||
}
|
||||
// Filter on cgrids plus reqType
|
||||
@@ -646,7 +646,7 @@ func TestMongoGetStoredCdrs(t *testing.T) {
|
||||
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)
|
||||
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()),
|
||||
@@ -658,141 +658,141 @@ func TestMongoGetStoredCdrs(t *testing.T) {
|
||||
// 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) != 2 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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: ", storedCdrs)
|
||||
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) != 8 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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: ", storedCdrs)
|
||||
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) != 8 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 1 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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: ", storedCdrs)
|
||||
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) != 2 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 3 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 8 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 3 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 8 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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: ", storedCdrs)
|
||||
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) != 8 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 3 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 8 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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: ", storedCdrs)
|
||||
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) != 3 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 3 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 4 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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: ", storedCdrs)
|
||||
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: ", storedCdrs)
|
||||
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) != 5 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} else if len(storedCdrs) != 7 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
|
||||
} else {
|
||||
for _, cdr := range storedCdrs {
|
||||
if cdr.OrderId < orderIdStart {
|
||||
@@ -806,58 +806,58 @@ func TestMongoGetStoredCdrs(t *testing.T) {
|
||||
// Filter on orderIdStart
|
||||
if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart}); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else if len(storedCdrs) != 8 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 4 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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) != 5 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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: ", storedCdrs)
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
|
||||
}
|
||||
// Filter on minPdd
|
||||
if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(3)}); err != nil {
|
||||
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(3)}); err != nil {
|
||||
if storedCdrs, _, err := mongoDb.GetStoredCdrs(&utils.CdrsFilter{MaxPdd: utils.Float64Pointer(float64(3 * time.Second))}); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else if len(storedCdrs) != 1 {
|
||||
} 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(3), MaxPdd: utils.Float64Pointer(5)}); err != nil {
|
||||
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) != 5 {
|
||||
} 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: ", storedCdrs)
|
||||
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) != 0 { // ToDo: Recheck this value
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} else if len(storedCdrs) != 2 { // ToDo: Recheck this value
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -871,8 +871,8 @@ func TestMongoRemStoredCdrs(t *testing.T) {
|
||||
}
|
||||
if storedCdrs, _, err := mongoDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else if len(storedCdrs) != 7 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} 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())
|
||||
@@ -892,8 +892,8 @@ func TestMongoRemStoredCdrs(t *testing.T) {
|
||||
}
|
||||
if storedCdrs, _, err := mongoDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else if len(storedCdrs) != 0 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
|
||||
} else if len(storedCdrs) != 20 {
|
||||
t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -48,7 +49,7 @@ func (ms *MongoStorage) GetTpTableIds(tpid, table string, distinct utils.TPDisti
|
||||
var searchItems []bson.M
|
||||
for _, d := range distinct {
|
||||
searchItems = append(searchItems, bson.M{d: bson.RegEx{
|
||||
Pattern: ".*" + pag.SearchTerm + ".*",
|
||||
Pattern: ".*" + regexp.QuoteMeta(pag.SearchTerm) + ".*",
|
||||
Options: ""}})
|
||||
}
|
||||
findMap["$and"] = []bson.M{bson.M{"$or": searchItems}}
|
||||
@@ -720,12 +721,12 @@ func (ms *MongoStorage) GetCallCostLog(cgrid, source, runid string) (cc *CallCos
|
||||
}
|
||||
|
||||
func (ms *MongoStorage) SetCdr(cdr *StoredCdr) error {
|
||||
_, err := ms.db.C(colCdrs).Upsert(bson.M{"cgrid": cdr.CgrId}, cdr)
|
||||
_, 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}, storedCdr)
|
||||
_, err := ms.db.C(colCdrs).Upsert(bson.M{"cgrid": storedCdr.CgrId, "mediationrunid": storedCdr.MediationRunId}, storedCdr)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -734,7 +735,8 @@ func (ms *MongoStorage) RemStoredCdrs(cgrIds []string) error {
|
||||
if len(cgrIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
return ms.db.C(colCdrs).Update(bson.M{"cgrid": bson.M{"$in": cgrIds}}, map[string]interface{}{"deleted_at": time.Now()})
|
||||
_, err := ms.db.C(colCdrs).UpdateAll(bson.M{"cgrid": bson.M{"$in": cgrIds}}, bson.M{"$set": bson.M{"deleted_at": time.Now()}})
|
||||
return err
|
||||
}
|
||||
|
||||
func (ms *MongoStorage) cleanEmptyFilters(filters bson.M) {
|
||||
@@ -764,7 +766,7 @@ func (ms *MongoStorage) cleanEmptyFilters(filters bson.M) {
|
||||
func (ms *MongoStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr, int64, error) {
|
||||
filters := bson.M{
|
||||
"cgrid": bson.M{"$in": qryFltr.CgrIds, "$nin": qryFltr.NotCgrIds},
|
||||
"runid": bson.M{"$in": qryFltr.RunIds, "$nin": qryFltr.NotRunIds},
|
||||
"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},
|
||||
@@ -785,47 +787,40 @@ func (ms *MongoStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
|
||||
"costdetails.account": bson.M{"$in": qryFltr.RatedAccounts, "$nin": qryFltr.NotRatedAccounts},
|
||||
"costdetails.subject": 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 {
|
||||
/*if qryFltr.OrderIdStart != 0 {
|
||||
filters["id"] = bson.M{"$gte": qryFltr.OrderIdStart}
|
||||
}
|
||||
if qryFltr.OrderIdEnd != 0 {
|
||||
if m, ok := filters["id"]; ok {
|
||||
m.(bson.M)["id"] = bson.M{"$gte": qryFltr.OrderIdStart}
|
||||
m.(bson.M)["$gte"] = qryFltr.OrderIdStart
|
||||
} else {
|
||||
filters["id"] = bson.M{"$gte": qryFltr.OrderIdStart}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
var regexes []bson.RegEx
|
||||
if len(qryFltr.DestPrefixes) != 0 {
|
||||
var regexes []bson.RegEx
|
||||
for _, prefix := range qryFltr.DestPrefixes {
|
||||
regexes = append(regexes, bson.RegEx{Pattern: prefix + ".*"})
|
||||
regexes = append(regexes, bson.RegEx{Pattern: regexp.QuoteMeta(prefix) + ".*"})
|
||||
}
|
||||
filters["destination"] = bson.M{"$in": regexes}
|
||||
}
|
||||
var notRegexes []bson.RegEx
|
||||
if len(qryFltr.NotDestPrefixes) != 0 {
|
||||
var notRegexes []bson.RegEx
|
||||
for _, prefix := range qryFltr.DestPrefixes {
|
||||
notRegexes = append(notRegexes, bson.RegEx{Pattern: prefix + ".*"})
|
||||
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}
|
||||
}
|
||||
}
|
||||
filters["destination"] = bson.M{"$in": regexes, "$nin": notRegexes}
|
||||
|
||||
regexes = make([]bson.RegEx, 0)
|
||||
if len(qryFltr.DestPrefixes) != 0 {
|
||||
for _, prefix := range qryFltr.DestPrefixes {
|
||||
regexes = append(regexes, bson.RegEx{Pattern: prefix + ".*"})
|
||||
}
|
||||
}
|
||||
notRegexes = make([]bson.RegEx, 0)
|
||||
if len(qryFltr.NotDestPrefixes) != 0 {
|
||||
for _, prefix := range qryFltr.DestPrefixes {
|
||||
notRegexes = append(notRegexes, bson.RegEx{Pattern: prefix + ".*"})
|
||||
}
|
||||
}
|
||||
filters["destination"] = bson.M{"$in": regexes, "$nin": notRegexes}
|
||||
|
||||
if len(qryFltr.ExtraFields) != 0 {
|
||||
var extrafields []bson.M
|
||||
@@ -847,17 +842,21 @@ func (ms *MongoStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
|
||||
if qryFltr.MaxCost == nil {
|
||||
filters["cost"] = bson.M{"$gte": *qryFltr.MinCost}
|
||||
} else if *qryFltr.MinCost == 0.0 && *qryFltr.MaxCost == -1.0 { // Special case when we want to skip errors
|
||||
filters["cost"] = bson.M{"$or": []bson.M{bson.M{"$eq": nil}, bson.M{"$gte": 0.0}}}
|
||||
filters["$or"] = []bson.M{
|
||||
bson.M{"cost": bson.M{"$gte": 0.0}},
|
||||
}
|
||||
} else {
|
||||
filters["cost"] = bson.M{"$gte": *qryFltr.MinCost, "$lt": *qryFltr.MaxCost}
|
||||
}
|
||||
} else if qryFltr.MaxCost != nil {
|
||||
if *qryFltr.MaxCost == -1.0 { // Non-rated CDRs
|
||||
filters["cost"] = bson.M{"$eq": nil} // Need to include it otherwise all CDRs will be returned
|
||||
filters["cost"] = 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}
|
||||
}
|
||||
}
|
||||
//file.WriteString(fmt.Sprintf("AFTER: %v\n", utils.ToIJSON(filters)))
|
||||
//file.Close()
|
||||
q := ms.db.C(colCdrs).Find(filters)
|
||||
if qryFltr.Paginator.Limit != nil {
|
||||
q = q.Limit(*qryFltr.Paginator.Limit)
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
@@ -639,8 +638,426 @@ func (self *SQLStorage) SetCdr(cdr *StoredCdr) error {
|
||||
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)
|
||||
|
||||
}
|
||||
// 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)
|
||||
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
|
||||
}
|
||||
}
|
||||
// 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 {
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
q = q.Where(tblName+".reqtype in (?)", qryFltr.ReqTypes)
|
||||
}
|
||||
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.Directions) != 0 {
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
q = q.Where(tblName+".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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
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 {
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
q = q.Where(tblName+".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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
q = q.Where(tblName+".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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
if qryFltr.MinUsage != nil {
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
q = q.Where(tblName+".usage >= ?", qryFltr.MinUsage)
|
||||
}
|
||||
if qryFltr.MaxUsage != nil {
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
q = q.Where(tblName+".usage < ?", qryFltr.MaxUsage)
|
||||
}
|
||||
if qryFltr.MinPdd != nil {
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
q = q.Where(tblName+".pdd >= ?", qryFltr.MinPdd)
|
||||
}
|
||||
if qryFltr.MaxPdd != nil {
|
||||
tblName := utils.TBL_CDRS_PRIMARY
|
||||
if qryFltr.FilterOnRated {
|
||||
tblName = utils.TBL_RATED_CDRS
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
/*func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr, int64, error) {
|
||||
var cdrs []*StoredCdr
|
||||
// Select string
|
||||
var selectStr string
|
||||
@@ -965,6 +1382,7 @@ func (self *SQLStorage) GetStoredCdrs(qryFltr *utils.CdrsFilter) ([]*StoredCdr,
|
||||
}
|
||||
return cdrs, 0, nil
|
||||
}
|
||||
*/
|
||||
|
||||
// Remove CDR data out of all CDR tables based on their cgrid
|
||||
func (self *SQLStorage) RemStoredCdrs(cgrIds []string) error {
|
||||
|
||||
Reference in New Issue
Block a user