Merge branch 'master' into lcr

This commit is contained in:
Radu Ioan Fericean
2014-04-01 20:50:05 +03:00
33 changed files with 456 additions and 417 deletions

View File

@@ -34,11 +34,11 @@ const (
INBOUND = "*in"
OUTBOUND = "*out"
// Balance types
CREDIT = "*monetary"
SMS = "*sms"
TRAFFIC = "*internet"
TRAFFIC_TIME = "*internet_time"
MINUTES = "*minutes"
CREDIT = "*monetary"
SMS = "*sms"
DATA = "*data"
DATA_TIME = "*data_time"
MINUTES = "*minutes"
// action price type
PRICE_PERCENT = "*percent"
PRICE_ABSOLUTE = "*absolute"
@@ -306,15 +306,6 @@ func (ub *Account) refundIncrement(increment *Increment, direction string, count
}
}
// Debits some amount of user's specified balance. Returns the remaining credit in user's balance.
func (ub *Account) debitGenericBalance(balanceId string, direction string, amount float64, count bool) float64 {
if count {
ub.countUnits(&Action{BalanceType: balanceId, Direction: direction, Balance: &Balance{Value: amount}})
}
ub.BalanceMap[balanceId+direction].Debit(amount)
return ub.BalanceMap[balanceId+direction].GetTotalValue()
}
// Scans the action trigers and execute the actions for which trigger is met
func (ub *Account) executeActionTriggers(a *Action) {
ub.ActionTriggers.Sort()

View File

@@ -157,47 +157,6 @@ func TestAccountStorageStore(t *testing.T) {
}
}
func TestDebitMoneyBalance(t *testing.T) {
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
result := rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, 6, false)
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 15 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
t.Errorf("Expected %v was %v", 15, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
}
}
func TestDebitAllMoneyBalance(t *testing.T) {
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, 21, false)
result := rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, 0, false)
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 0 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
t.Errorf("Expected %v was %v", 0, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
}
}
func TestDebitMoreMoneyBalance(t *testing.T) {
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
result := rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, 22, false)
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != -1 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
t.Errorf("Expected %v was %v", -1, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
}
}
func TestDebitNegativeMoneyBalance(t *testing.T) {
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
result := rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, -15, false)
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 36 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
t.Errorf("Expected %v was %v", 36, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
}
}
func TestDebitCreditZeroSecond(t *testing.T) {
b1 := &Balance{Uuid: "testb", Value: 10, Weight: 10, DestinationId: "NAT", RateSubject: "*zero1s"}
cc := &CallCost{
@@ -791,51 +750,11 @@ func TestDebitCreditSubjectMixedPartPay(t *testing.T) {
}
}
func TestDebitSMSBalance(t *testing.T) {
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
result := rifsBalance.debitGenericBalance(SMS, OUTBOUND, 12, false)
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 88 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
t.Errorf("Expected %v was %v", 88, rifsBalance.BalanceMap[SMS+OUTBOUND])
}
}
func TestDebitAllSMSBalance(t *testing.T) {
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
result := rifsBalance.debitGenericBalance(SMS, OUTBOUND, 100, false)
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 0 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
t.Errorf("Expected %v was %v", 0, rifsBalance.BalanceMap[SMS+OUTBOUND])
}
}
func TestDebitMoreSMSBalance(t *testing.T) {
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
result := rifsBalance.debitGenericBalance(SMS, OUTBOUND, 110, false)
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != -10 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
t.Errorf("Expected %v was %v", -10, rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value)
}
}
func TestDebitNegativeSMSBalance(t *testing.T) {
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
result := rifsBalance.debitGenericBalance(SMS, OUTBOUND, -15, false)
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 115 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
t.Errorf("Expected %v was %v", 115, rifsBalance.BalanceMap[SMS+OUTBOUND])
}
}
func TestAccountdebitBalance(t *testing.T) {
ub := &Account{
Id: "rif",
AllowNegative: true,
BalanceMap: map[string]BalanceChain{SMS: BalanceChain{&Balance{Value: 14}}, TRAFFIC: BalanceChain{&Balance{Value: 1204}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
BalanceMap: map[string]BalanceChain{SMS: BalanceChain{&Balance{Value: 14}}, DATA: BalanceChain{&Balance{Value: 1204}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
}
newMb := &Balance{Weight: 20, DestinationId: "NEW"}
a := &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: newMb}
@@ -850,7 +769,7 @@ func TestAccountdebitBalanceExists(t *testing.T) {
ub := &Account{
Id: "rif",
AllowNegative: true,
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 15, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, DATA + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 15, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
}
newMb := &Balance{Value: -10, Weight: 20, DestinationId: "NAT"}
a := &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: newMb}
@@ -864,7 +783,7 @@ func TestAccountAddMinuteNil(t *testing.T) {
ub := &Account{
Id: "rif",
AllowNegative: true,
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, DATA + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
}
ub.debitBalanceAction(nil)
if len(ub.BalanceMap[MINUTES+OUTBOUND]) != 2 {

View File

@@ -32,13 +32,12 @@ type Balance struct {
Value float64
ExpirationDate time.Time
Weight float64
//GroupIds []string
DestinationId string
RateSubject string
SharedGroup string
precision int
account *Account // used to store ub reference for shared balances
dirty bool
DestinationId string
RateSubject string
SharedGroup string
precision int
account *Account // used to store ub reference for shared balances
dirty bool
}
func (b *Balance) Equal(o *Balance) bool {

View File

@@ -113,11 +113,11 @@ type CallDescriptor struct {
TimeStart, TimeEnd time.Time
LoopIndex float64 // indicates the position of this segment in a cost request loop
CallDuration time.Duration // the call duration so far (till TimeEnd)
Amount float64
FallbackSubject string // the subject to check for destination if not found on primary subject
RatingInfos RatingInfos
Increments Increments
account *Account
//Amount float64
FallbackSubject string // the subject to check for destination if not found on primary subject
RatingInfos RatingInfos
Increments Increments
account *Account
}
func (cd *CallDescriptor) ValidateCallData() error {
@@ -620,60 +620,6 @@ func (cd *CallDescriptor) RefundIncrements() (left float64, err error) {
return 0.0, err
}
/*
Interface method used to add/substract an amount of cents from user's money balance.
The amount filed has to be filled in call descriptor.
*/
func (cd *CallDescriptor) DebitCents() (left float64, err error) {
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
defer accountingStorage.SetAccount(userBalance)
return userBalance.debitGenericBalance(CREDIT, cd.Direction, cd.Amount, true), nil
}
return 0.0, err
}
/*
Interface method used to add/substract an amount of units from user's sms balance.
The amount filed has to be filled in call descriptor.
*/
func (cd *CallDescriptor) DebitSMS() (left float64, err error) {
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
defer accountingStorage.SetAccount(userBalance)
return userBalance.debitGenericBalance(SMS, cd.Direction, cd.Amount, true), nil
}
return 0, err
}
/*
Interface method used to add/substract an amount of seconds from user's minutes balance.
The amount filed has to be filled in call descriptor.
*/
func (cd *CallDescriptor) DebitSeconds() (err error) {
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
defer accountingStorage.SetAccount(userBalance)
return userBalance.debitCreditBalance(cd.CreateCallCost(), true)
}
return err
}
/*
Adds the specified amount of seconds to the received call seconds. When the threshold specified
in the user's tariff plan is reached then the received call balance is reseted and the bonus
specified in the tariff plan is applied.
The amount filed has to be filled in call descriptor.
*/
func (cd *CallDescriptor) AddRecievedCallSeconds() (err error) {
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
a := &Action{
Direction: INBOUND,
Balance: &Balance{Value: cd.Amount, DestinationId: cd.Destination},
}
userBalance.countUnits(a)
return nil
}
return err
}
func (cd *CallDescriptor) FlushCache() (err error) {
cache2go.XFlush()
cache2go.Flush()
@@ -697,17 +643,17 @@ func (cd *CallDescriptor) CreateCallCost() *CallCost {
func (cd *CallDescriptor) Clone() *CallDescriptor {
return &CallDescriptor{
Direction: cd.Direction,
TOR: cd.TOR,
Tenant: cd.Tenant,
Subject: cd.Subject,
Account: cd.Account,
Destination: cd.Destination,
TimeStart: cd.TimeStart,
TimeEnd: cd.TimeEnd,
LoopIndex: cd.LoopIndex,
CallDuration: cd.CallDuration,
Amount: cd.Amount,
Direction: cd.Direction,
TOR: cd.TOR,
Tenant: cd.Tenant,
Subject: cd.Subject,
Account: cd.Account,
Destination: cd.Destination,
TimeStart: cd.TimeStart,
TimeEnd: cd.TimeEnd,
LoopIndex: cd.LoopIndex,
CallDuration: cd.CallDuration,
// Amount: cd.Amount,
FallbackSubject: cd.FallbackSubject,
//RatingInfos: cd.RatingInfos,
//Increments: cd.Increments,

View File

@@ -425,7 +425,7 @@ func TestMaxSessionTimeWithAccountAccount(t *testing.T) {
Subject: "minu_from_tm",
Account: "minu",
Destination: "0723",
Amount: 1000}
}
result, err := cd.GetMaxSessionDuration()
expected := time.Minute
if result != expected || err != nil {
@@ -442,7 +442,7 @@ func TestMaxSessionTimeNoCredit(t *testing.T) {
Tenant: "vdf",
Subject: "broker",
Destination: "0723",
Amount: 5400}
}
result, err := cd.GetMaxSessionDuration()
if result != time.Minute || err != nil {
t.Errorf("Expected %v was %v", time.Minute, result)
@@ -462,7 +462,7 @@ func TestMaxSessionModifiesCallDesc(t *testing.T) {
Account: "minu",
Destination: "0723",
CallDuration: t2.Sub(t1),
Amount: 5400}
}
initial := cd.Clone()
cd.GetMaxSessionDuration()
cd.account = nil // it's OK to cache the account
@@ -481,7 +481,7 @@ func TestMaxDebitDurationNoGreatherThanInitialDuration(t *testing.T) {
Subject: "minu_from_tm",
Account: "minu",
Destination: "0723",
Amount: 1000}
}
initialDuration := cd.TimeEnd.Sub(cd.TimeStart)
result, _ := cd.GetMaxSessionDuration()
if result > initialDuration {
@@ -671,7 +671,7 @@ func BenchmarkSplitting(b *testing.B) {
func BenchmarkStorageSingleGetSessionTime(b *testing.B) {
b.StopTimer()
cd := &CallDescriptor{Tenant: "vdf", Subject: "minutosu", Destination: "0723", Amount: 100}
cd := &CallDescriptor{Tenant: "vdf", Subject: "minutosu", Destination: "0723"}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionDuration()
@@ -680,7 +680,7 @@ func BenchmarkStorageSingleGetSessionTime(b *testing.B) {
func BenchmarkStorageMultipleGetSessionTime(b *testing.B) {
b.StopTimer()
cd := &CallDescriptor{Direction: "*out", TOR: "0", Tenant: "vdf", Subject: "minutosu", Destination: "0723", Amount: 5400}
cd := &CallDescriptor{Direction: "*out", TOR: "0", Tenant: "vdf", Subject: "minutosu", Destination: "0723"}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionDuration()

View File

@@ -20,9 +20,11 @@ package engine
import (
"encoding/json"
"github.com/cgrates/cgrates/cache2go"
"strings"
"github.com/cgrates/cgrates/cache2go"
"github.com/cgrates/cgrates/utils"
"github.com/cgrates/cgrates/history"
)
@@ -81,3 +83,26 @@ func CachedDestHasPrefix(destId, prefix string) bool {
}
return false
}
func CleanStalePrefixes(destIds []string) {
prefixMap := cache2go.GetAllEntries(DESTINATION_PREFIX)
for prefix, idIDs := range prefixMap {
dIDs := idIDs.([]string)
changed := false
for _, searchedDID := range destIds {
if found, i := utils.GetSliceMemberIndex(dIDs, searchedDID); found {
if len(dIDs) == 1 {
// remove de prefix from cache
cache2go.RemKey(prefix)
} else {
// delte the testination from list and put the new list in chache
dIDs[i], dIDs = dIDs[len(dIDs)-1], dIDs[:len(dIDs)-1]
changed = true
}
}
}
if changed {
cache2go.Cache(prefix, dIDs)
}
}
}

View File

@@ -125,6 +125,22 @@ func TestNonCachedDestWrongPrefix(t *testing.T) {
}
}
func TestCleanStalePrefixes(t *testing.T) {
cache2go.Cache(DESTINATION_PREFIX+"1", []string{"D1", "D2"})
cache2go.Cache(DESTINATION_PREFIX+"2", []string{"D1"})
cache2go.Cache(DESTINATION_PREFIX+"3", []string{"D2"})
CleanStalePrefixes([]string{"D1"})
if r, err := cache2go.GetCached(DESTINATION_PREFIX + "1"); err != nil || len(r.([]string)) != 1 {
t.Error("Error cleaning stale destination ids", r)
}
if r, err := cache2go.GetCached(DESTINATION_PREFIX + "2"); err == nil {
t.Error("Error removing stale prefix: ", r)
}
if r, err := cache2go.GetCached(DESTINATION_PREFIX + "3"); err != nil || len(r.([]string)) != 1 {
t.Error("Error performing stale cleaning: ", r)
}
}
/********************************* Benchmarks **********************************/
func BenchmarkDestinationStorageStoreRestore(b *testing.B) {

View File

@@ -495,7 +495,6 @@ func TestLoadDestinationRateTimings(t *testing.T) {
},
Ratings: map[string]*RIRate{
"d54545c1": &RIRate{
Id: "R1",
ConnectFee: 0,
Rates: []*Rate{
&Rate{
@@ -509,7 +508,6 @@ func TestLoadDestinationRateTimings(t *testing.T) {
RoundingDecimals: 2,
},
"4bb00b9c": &RIRate{
Id: "R2",
ConnectFee: 0,
Rates: []*Rate{
&Rate{
@@ -523,7 +521,6 @@ func TestLoadDestinationRateTimings(t *testing.T) {
RoundingDecimals: 2,
},
"e06c337f": &RIRate{
Id: "R3",
ConnectFee: 0,
Rates: []*Rate{
&Rate{

View File

@@ -126,7 +126,6 @@ func GetRateInterval(rpl *utils.TPRatingPlanBinding, dr *utils.DestinationRate)
},
Weight: rpl.Weight,
Rating: &RIRate{
Id: dr.Rate.RateId,
ConnectFee: dr.Rate.RateSlots[0].ConnectFee,
RoundingMethod: dr.Rate.RateSlots[0].RoundingMethod,
RoundingDecimals: dr.Rate.RateSlots[0].RoundingDecimals,

View File

@@ -53,7 +53,6 @@ func (rit *RITiming) Stringify() string {
// Separate structure used for rating plan size optimization
type RIRate struct {
Id string // informational role only
ConnectFee float64
Rates RateGroups // GroupRateInterval (start time): Rate
RoundingMethod string //ROUNDING_UP, ROUNDING_DOWN, ROUNDING_MIDDLE

View File

@@ -89,42 +89,6 @@ func (rs *Responder) RefundIncrements(arg CallDescriptor, reply *float64) (err e
return
}
func (rs *Responder) DebitCents(arg CallDescriptor, reply *float64) (err error) {
if rs.Bal != nil {
*reply, err = rs.callMethod(&arg, "Responder.DebitCents")
} else {
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
return arg.DebitCents()
})
*reply, err = r, e
}
return
}
func (rs *Responder) DebitSMS(arg CallDescriptor, reply *float64) (err error) {
if rs.Bal != nil {
*reply, err = rs.callMethod(&arg, "Responder.DebitSMS")
} else {
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
return arg.DebitSMS()
})
*reply, err = r, e
}
return
}
func (rs *Responder) DebitSeconds(arg CallDescriptor, reply *float64) (err error) {
if rs.Bal != nil {
*reply, err = rs.callMethod(&arg, "Responder.DebitSeconds")
} else {
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
return 0, arg.DebitSeconds()
})
*reply, err = r, e
}
return
}
func (rs *Responder) GetMaxSessionTime(arg CallDescriptor, reply *float64) (err error) {
if rs.Bal != nil {
*reply, err = rs.callMethod(&arg, "Responder.GetMaxSessionTime")
@@ -138,19 +102,6 @@ func (rs *Responder) GetMaxSessionTime(arg CallDescriptor, reply *float64) (err
return
}
func (rs *Responder) AddRecievedCallSeconds(arg CallDescriptor, reply *float64) (err error) {
if rs.Bal != nil {
*reply, err = rs.callMethod(&arg, "Responder.AddRecievedCallSeconds")
} else {
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
return 0, arg.AddRecievedCallSeconds()
})
*reply, err = r, e
}
return
}
func (rs *Responder) FlushCache(arg CallDescriptor, reply *float64) (err error) {
if rs.Bal != nil {
*reply, err = rs.callMethod(&arg, "Responder.FlushCache")
@@ -200,12 +151,12 @@ func (rs *Responder) GetSMS(arg CallDescriptor, reply *CallCost) (err error) {
}
func (rs *Responder) GetInternet(arg CallDescriptor, reply *CallCost) (err error) {
err = rs.getBalance(&arg, TRAFFIC, reply)
err = rs.getBalance(&arg, DATA, reply)
return err
}
func (rs *Responder) GetInternetTime(arg CallDescriptor, reply *CallCost) (err error) {
err = rs.getBalance(&arg, TRAFFIC_TIME, reply)
err = rs.getBalance(&arg, DATA_TIME, reply)
return err
}
@@ -355,8 +306,6 @@ type Connector interface {
Debit(CallDescriptor, *CallCost) error
MaxDebit(CallDescriptor, *CallCost) error
RefundIncrements(CallDescriptor, *float64) error
DebitCents(CallDescriptor, *float64) error
DebitSeconds(CallDescriptor, *float64) error
GetMaxSessionTime(CallDescriptor, *float64) error
}
@@ -375,15 +324,11 @@ func (rcc *RPCClientConnector) Debit(cd CallDescriptor, cc *CallCost) error {
func (rcc *RPCClientConnector) MaxDebit(cd CallDescriptor, cc *CallCost) error {
return rcc.Client.Call("Responder.MaxDebit", cd, cc)
}
func (rcc *RPCClientConnector) RefundIncrements(cd CallDescriptor, resp *float64) error {
return rcc.Client.Call("Responder.RefundIncrements", cd, resp)
}
func (rcc *RPCClientConnector) DebitCents(cd CallDescriptor, resp *float64) error {
return rcc.Client.Call("Responder.DebitCents", cd, resp)
}
func (rcc *RPCClientConnector) DebitSeconds(cd CallDescriptor, resp *float64) error {
return rcc.Client.Call("Responder.DebitSeconds", cd, resp)
}
func (rcc *RPCClientConnector) GetMaxSessionTime(cd CallDescriptor, resp *float64) error {
return rcc.Client.Call("Responder.GetMaxSessionTime", cd, resp)
}

View File

@@ -109,7 +109,8 @@ type CdrStorage interface {
Storage
SetCdr(utils.RawCDR) error
SetRatedCdr(*utils.StoredCdr, string) error
GetStoredCdrs([]string, string, string, string, string, string, string, string, string, string, string, time.Time, time.Time, bool, bool) ([]*utils.StoredCdr, error)
GetStoredCdrs([]string, []string, []string, []string, []string, []string, []string, []string, []string, []string, []string,
time.Time, time.Time, bool, bool) ([]*utils.StoredCdr, error)
RemStoredCdrs([]string) error
}

View File

@@ -51,6 +51,8 @@ func (ms *MapStorage) Flush() error {
func (ms *MapStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []string) error {
if dKeys == nil {
cache2go.RemPrefixKey(DESTINATION_PREFIX)
} else {
CleanStalePrefixes(dKeys)
}
if rpKeys == nil {
cache2go.RemPrefixKey(RATING_PLAN_PREFIX)

View File

@@ -76,6 +76,7 @@ func (rs *RedisStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []s
cache2go.RemPrefixKey(DESTINATION_PREFIX)
} else if len(dKeys) != 0 {
Logger.Info(fmt.Sprintf("Caching destinations: %v", dKeys))
CleanStalePrefixes(dKeys)
}
for _, key := range dKeys {
if _, err = rs.GetDestination(key[len(DESTINATION_PREFIX):]); err != nil {

View File

@@ -577,116 +577,196 @@ 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 []string, runId string, cdrHost, cdrSource, reqType, direction, tenant, tor, account, subject, destPrefix string,
func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqTypes, directions, tenants, tors, accounts, subjects, destPrefixes []string,
timeStart, timeEnd time.Time, ignoreErr, ignoreRated bool) ([]*utils.StoredCdr, error) {
var cdrs []*utils.StoredCdr
q := fmt.Sprintf("SELECT %s.cgrid,accid,cdrhost,cdrsource,reqtype,direction,tenant,tor,account,%s.subject,destination,setup_time,answer_time,duration,extra_fields,runid,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_EXTRA, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_CDRS_PRIMARY, utils.TBL_RATED_CDRS)
fltr := ""
q := bytes.NewBufferString(fmt.Sprintf("SELECT %s.cgrid,accid,cdrhost,cdrsource,reqtype,direction,tenant,tor,account,%s.subject,destination,setup_time,answer_time,duration,extra_fields,runid,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_EXTRA, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_CDRS_PRIMARY, utils.TBL_RATED_CDRS))
fltr := new(bytes.Buffer)
if len(cgrIds) != 0 {
qIds := " ("
qIds := bytes.NewBufferString(" (")
for idxId, cgrId := range cgrIds {
if idxId != 0 {
qIds += " OR"
qIds.WriteString(" OR")
}
qIds += fmt.Sprintf(" %s.cgrid='%s'", utils.TBL_CDRS_PRIMARY, cgrId)
qIds.WriteString(fmt.Sprintf(" %s.cgrid='%s'", utils.TBL_CDRS_PRIMARY, cgrId))
}
qIds += " )"
if len(fltr) != 0 {
fltr += " AND"
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr += qIds
fltr.Write(qIds.Bytes())
}
if len(runId) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(runIds) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, runId := range runIds {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" runid='%s'", runId))
}
fltr += fmt.Sprintf(" runid='%s'", runId)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(cdrHost) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(cdrHosts) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, host := range cdrHosts {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" cdrhost='%s'", host))
}
fltr += fmt.Sprintf(" cdrhost='%s'", cdrHost)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(cdrSource) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(cdrSources) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, src := range cdrSources {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" cdrsource='%s'", src))
}
fltr += fmt.Sprintf(" cdrsource='%s'", cdrSource)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(reqType) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(reqTypes) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, reqType := range reqTypes {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" reqtype='%s'", reqType))
}
fltr += fmt.Sprintf(" reqtype='%s'", reqType)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(direction) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(directions) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, direction := range directions {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" direction='%s'", direction))
}
fltr += fmt.Sprintf(" direction='%s'", direction)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(tenant) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(tenants) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, tenant := range tenants {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" tenant='%s'", tenant))
}
fltr += fmt.Sprintf(" tenant='%s'", tenant)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(tor) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(tors) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, tor := range tors {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" tor='%s'", tor))
}
fltr += fmt.Sprintf(" tor='%s'", tor)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(account) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(accounts) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, account := range accounts {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" account='%s'", account))
}
fltr += fmt.Sprintf(" account='%s'", account)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(subject) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(subjects) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, subject := range subjects {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" %s.subject='%s'", utils.TBL_CDRS_PRIMARY, subject))
}
fltr += fmt.Sprintf(" %s.subject='%s'", utils.TBL_CDRS_PRIMARY, subject)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if len(destPrefix) != 0 {
if len(fltr) != 0 {
fltr += " AND"
if len(destPrefixes) != 0 {
qIds := bytes.NewBufferString(" (")
for idx, destPrefix := range destPrefixes {
if idx != 0 {
qIds.WriteString(" OR")
}
qIds.WriteString(fmt.Sprintf(" destination LIKE '%s%%'", destPrefix))
}
fltr += fmt.Sprintf(" destination LIKE '%s%%'", destPrefix)
qIds.WriteString(" )")
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr.Write(qIds.Bytes())
}
if !timeStart.IsZero() {
if len(fltr) != 0 {
fltr += " AND"
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr += fmt.Sprintf(" answer_time>='%s'", timeStart)
fltr.WriteString(fmt.Sprintf(" answer_time>='%s'", timeStart))
}
if !timeEnd.IsZero() {
if len(fltr) != 0 {
fltr += " AND"
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr += fmt.Sprintf(" answer_time<'%s'", timeEnd)
fltr.WriteString(fmt.Sprintf(" answer_time<'%s'", timeEnd))
}
if ignoreRated {
if len(fltr) != 0 {
fltr += " AND"
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
if ignoreErr {
fltr += " cost IS NULL"
fltr.WriteString(" cost IS NULL")
} else {
fltr += " (cost=-1 OR cost IS NULL)"
fltr.WriteString(" (cost=-1 OR cost IS NULL)")
}
} else if ignoreErr {
if len(fltr) != 0 {
fltr += " AND"
if fltr.Len() != 0 {
fltr.WriteString(" AND")
}
fltr += " (cost!=-1 OR cost IS NULL)"
fltr.WriteString(" (cost!=-1 OR cost IS NULL)")
}
if len(fltr) != 0 {
q += fmt.Sprintf(" WHERE %s", fltr)
if fltr.Len() != 0 {
q.WriteString(fmt.Sprintf(" WHERE %s", fltr.String()))
}
rows, err := self.Db.Query(q)
rows, err := self.Db.Query(q.String())
if err != nil {
return nil, err
}
@@ -704,7 +784,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds []string, runId string, cdrHost, cd
return nil, err
}
if err := json.Unmarshal(extraFields, &extraFieldsMp); err != nil {
return nil, err
return nil, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %s, error: %s", cgrid, runid, err.Error())
}
storCdr := &utils.StoredCdr{
CgrId: cgrid, AccId: accid, CdrHost: cdrhost, CdrSource: cdrsrc, ReqType: reqtype, Direction: direction, Tenant: tenant,

View File

@@ -162,7 +162,7 @@ func TestSetCdr(t *testing.T) {
SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC),
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201}
strCdr2 := &utils.StoredCdr{CgrId: utils.FSCgrId("bbb2"), AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: TEST_SQL, ReqType: "prepaid",
strCdr2 := &utils.StoredCdr{CgrId: utils.FSCgrId("bbb2"), AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN2", ReqType: "prepaid",
Direction: "*out", Tenant: "cgrates.org", TOR: "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),
Duration: time.Duration(12) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
@@ -189,13 +189,13 @@ func TestSetRatedCdr(t *testing.T) {
SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC),
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
MediationRunId: utils.DEFAULT_RUNID, Cost: 1.201}
strCdr2 := &utils.StoredCdr{CgrId: utils.FSCgrId("bbb2"), AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: TEST_SQL, ReqType: "prepaid",
strCdr2 := &utils.StoredCdr{CgrId: utils.FSCgrId("bbb2"), AccId: "bbb2", CdrHost: "192.168.1.2", CdrSource: "UNKNOWN", ReqType: "prepaid",
Direction: "*out", Tenant: "cgrates.org", TOR: "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),
Duration: time.Duration(12) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
MediationRunId: utils.DEFAULT_RUNID, Cost: 0.201}
strCdr3 := &utils.StoredCdr{CgrId: utils.FSCgrId("bbb3"), AccId: "bbb3", CdrHost: "192.168.1.1", CdrSource: TEST_SQL, ReqType: "rated",
Direction: "*out", Tenant: "itsyscom.com", TOR: "call", Account: "1002", Subject: "1002", Destination: "+4986517174963",
Direction: "*out", Tenant: "itsyscom.com", TOR: "call", Account: "1002", Subject: "1002", Destination: "+4986517174964",
SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC),
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"},
MediationRunId: "wholesale_run", Cost: 1.201}
@@ -213,107 +213,164 @@ func TestGetStoredCdrs(t *testing.T) {
}
var timeStart, timeEnd time.Time
// All CDRs, no filter
if storedCdrs, err := mysql.GetStoredCdrs(nil, "", "", "", "", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 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 cgrids
if storedCdrs, err := mysql.GetStoredCdrs([]string{utils.FSCgrId("bbb1"), utils.FSCgrId("bbb2")},
"", "", "", "", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 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 cgrids plus reqType
if storedCdrs, err := mysql.GetStoredCdrs([]string{utils.FSCgrId("bbb1"), utils.FSCgrId("bbb2")},
"", "", "", "prepaid", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
nil, nil, nil, []string{"prepaid"}, nil, nil, nil, nil, nil, nil, 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, utils.DEFAULT_RUNID, "", "", "", "", "", "", "", "", "", 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, 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 cdrHost
if storedCdrs, err := mysql.GetStoredCdrs(nil, "", "192.168.1.2", "", "", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, []string{"192.168.1.2"}, nil, nil, nil, nil, nil, nil, nil, nil, 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,
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, "", "", "UNKNOWN", "", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, []string{"UNKNOWN"}, nil, nil, nil, nil, nil, nil, nil, 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 reqType
if storedCdrs, err := mysql.GetStoredCdrs(nil, "", "", "", "prepaid", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
// Filter on multiple cdrSource
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, []string{"UNKNOWN", "UNKNOWN2"}, nil, nil, nil, nil, nil, nil, nil, 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, 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,
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, "", "", "", "", "*out", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, []string{"*out"}, nil, nil, nil, nil, nil, 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, "", "", "", "", "", "itsyscom.com", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, []string{"itsyscom.com"}, nil, nil, nil, nil, 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,
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, "", "", "", "", "", "", "premium_call", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, []string{"premium_call"}, nil, nil, nil, 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, 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, "", "", "", "", "", "", "", "1002", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, []string{"1002"}, nil, nil, 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, 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, "", "", "", "", "", "", "", "", "1000", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, []string{"1000"}, nil, 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, 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"}, 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"}, 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, "", "", "", "", "", "", "", "", "", "", timeStart, timeEnd, true, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 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
if storedCdrs, err := mysql.GetStoredCdrs(nil, "", "", "", "", "", "", "", "", "", "", timeStart, timeEnd, false, true); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, timeStart, timeEnd, false, true); 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, "", "", "", "", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 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, "", "", "", "", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 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, "", "", "", "rated", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, []string{"rated"}, nil, nil, nil, nil, nil, nil, timeStart, timeEnd, false, false); err != nil {
t.Error(err.Error())
} else if len(storedCdrs) != 1 {
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
@@ -355,7 +412,7 @@ func TestRemStoredCdrs(t *testing.T) {
if err := mysql.RemStoredCdrs([]string{utils.FSCgrId("bbb1")}); err != nil {
t.Error(err.Error())
}
if storedCdrs, err := mysql.GetStoredCdrs(nil, "", "", "", "", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, timeStart, timeEnd, false, false); err != nil {
t.Error(err.Error())
} else if len(storedCdrs) != 7 {
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)
@@ -364,7 +421,7 @@ func TestRemStoredCdrs(t *testing.T) {
utils.FSCgrId("bbb2"), utils.FSCgrId("bbb3")}); err != nil {
t.Error(err.Error())
}
if storedCdrs, err := mysql.GetStoredCdrs(nil, "", "", "", "", "", "", "", "", "", "", timeStart, timeEnd, false, false); err != nil {
if storedCdrs, err := mysql.GetStoredCdrs(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, timeStart, timeEnd, false, false); err != nil {
t.Error(err.Error())
} else if len(storedCdrs) != 0 {
t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs)

View File

@@ -147,7 +147,7 @@ func GetUB() *Account {
ub := &Account{
Id: "rif",
AllowNegative: true,
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}, MINUTES: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, DATA + OUTBOUND: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}, MINUTES: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
UnitCounters: []*UnitsCounter{uc, uc},
ActionTriggers: ActionTriggerPriotityList{at, at, at},
}