mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-24 00:28:44 +05:00
Merge branch 'master' into lcr
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user