mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-16 13:49:53 +05:00
most engine tests passing
ResetAccountPending
This commit is contained in:
@@ -22,7 +22,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/cache2go"
|
||||
@@ -258,6 +257,7 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ub.InitCounters()
|
||||
ub.ExecuteActionTriggers(nil)
|
||||
return nil
|
||||
}
|
||||
@@ -588,22 +588,27 @@ func (acc *Account) ExecuteActionTriggers(a *Action) {
|
||||
// the next reset (see RESET_TRIGGERS action type)
|
||||
continue
|
||||
}
|
||||
|
||||
if !at.Match(a) {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(at.ThresholdType, "counter") {
|
||||
for _, uc := range acc.UnitCounters {
|
||||
if uc.BalanceType == at.Balance.GetType() &&
|
||||
strings.Contains(at.ThresholdType, uc.CounterType[1:]) {
|
||||
for _, b := range uc.Balances {
|
||||
if strings.HasPrefix(at.ThresholdType, "*max") {
|
||||
if b.MatchActionTrigger(at) && b.GetValue() >= at.ThresholdValue {
|
||||
at.Execute(acc, nil)
|
||||
}
|
||||
} else { //MIN
|
||||
if b.MatchActionTrigger(at) && b.GetValue() <= at.ThresholdValue {
|
||||
at.Execute(acc, nil)
|
||||
if (at.Balance.ID == nil || *at.Balance.ID != "") && at.UniqueID != "" {
|
||||
at.Balance.ID = utils.StringPointer(at.UniqueID)
|
||||
}
|
||||
for _, counters := range acc.UnitCounters {
|
||||
for _, uc := range counters {
|
||||
if strings.Contains(at.ThresholdType, uc.CounterType[1:]) {
|
||||
for _, c := range uc.Counters {
|
||||
//log.Print("C: ", utils.ToJSON(c))
|
||||
if strings.HasPrefix(at.ThresholdType, "*max") {
|
||||
if c.Filter.Equal(at.Balance) && c.Value >= at.ThresholdValue {
|
||||
//log.Print("HERE")
|
||||
at.Execute(acc, nil)
|
||||
}
|
||||
} else { //MIN
|
||||
if c.Filter.Equal(at.Balance) && c.Value <= at.ThresholdValue {
|
||||
at.Execute(acc, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -643,7 +648,7 @@ func (acc *Account) ResetActionTriggers(a *Action) {
|
||||
}
|
||||
at.Executed = false
|
||||
}
|
||||
acc.ExecuteActionTriggers(a)
|
||||
acc.ExecuteActionTriggers(a) //will trigger infinite loop when executed from ExecuteActionTriggers
|
||||
}
|
||||
|
||||
// Sets/Unsets recurrent flag for action triggers
|
||||
@@ -665,9 +670,10 @@ func (acc *Account) countUnits(amount float64, kind string, cc *CallCost, b *Bal
|
||||
// Create counters for all triggered actions
|
||||
func (acc *Account) InitCounters() {
|
||||
oldUcs := acc.UnitCounters
|
||||
acc.UnitCounters = nil
|
||||
acc.UnitCounters = make(UnitCounters)
|
||||
ucTempMap := make(map[string]*UnitCounter)
|
||||
for _, at := range acc.ActionTriggers {
|
||||
//log.Print("AT: ", utils.ToJSON(at))
|
||||
if !strings.Contains(at.ThresholdType, "counter") {
|
||||
continue
|
||||
}
|
||||
@@ -675,28 +681,36 @@ func (acc *Account) InitCounters() {
|
||||
if strings.Contains(at.ThresholdType, "balance") {
|
||||
ct = utils.COUNTER_BALANCE
|
||||
}
|
||||
log.Print(at.Balance.GetType() + ct)
|
||||
uc, exists := ucTempMap[at.Balance.GetType()+ct]
|
||||
//log.Print("CT: ", at.Balance.GetType()+ct)
|
||||
if !exists {
|
||||
log.Print("HERE!")
|
||||
uc = &UnitCounter{
|
||||
BalanceType: at.Balance.GetType(),
|
||||
CounterType: ct,
|
||||
}
|
||||
ucTempMap[at.Balance.GetType()+ct] = uc
|
||||
uc.Balances = BalanceChain{}
|
||||
acc.UnitCounters = append(acc.UnitCounters, uc)
|
||||
uc.Counters = make(CounterFilters, 0)
|
||||
acc.UnitCounters[at.Balance.GetType()] = append(acc.UnitCounters[at.Balance.GetType()], uc)
|
||||
}
|
||||
b := at.Balance.CreateBalance()
|
||||
if !uc.Balances.HasBalance(b) {
|
||||
uc.Balances = append(uc.Balances, b)
|
||||
c := &CounterFilter{Filter: at.Balance}
|
||||
if (c.Filter.ID == nil || *c.Filter.ID == "") && at.UniqueID != "" {
|
||||
c.Filter.ID = utils.StringPointer(at.UniqueID)
|
||||
}
|
||||
//log.Print("C: ", utils.ToJSON(c))
|
||||
if !uc.Counters.HasCounter(c) {
|
||||
uc.Counters = append(uc.Counters, c)
|
||||
}
|
||||
}
|
||||
// copy old counter values
|
||||
for _, uc := range acc.UnitCounters {
|
||||
for _, oldUc := range oldUcs {
|
||||
if uc.CopyCounterValues(oldUc) {
|
||||
break
|
||||
for key, counters := range acc.UnitCounters {
|
||||
oldCounters, found := oldUcs[key]
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
for _, uc := range counters {
|
||||
for _, oldUc := range oldCounters {
|
||||
if uc.CopyCounterValues(oldUc) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -908,30 +922,32 @@ func (acc *Account) AsOldStructure() interface{} {
|
||||
AllowNegative: acc.AllowNegative,
|
||||
Disabled: acc.Disabled,
|
||||
}
|
||||
for i, uc := range acc.UnitCounters {
|
||||
if uc == nil {
|
||||
continue
|
||||
}
|
||||
result.UnitCounters[i] = &UnitsCounter{
|
||||
BalanceType: uc.BalanceType,
|
||||
Balances: make(BalanceChain, len(uc.Balances)),
|
||||
}
|
||||
if len(uc.Balances) > 0 {
|
||||
result.UnitCounters[i].Direction = uc.Balances[0].Directions.String()
|
||||
for j, b := range uc.Balances {
|
||||
result.UnitCounters[i].Balances[j] = &Balance{
|
||||
Uuid: b.Uuid,
|
||||
Id: b.Id,
|
||||
Value: b.Value,
|
||||
ExpirationDate: b.ExpirationDate,
|
||||
Weight: b.Weight,
|
||||
DestinationIds: b.DestinationIds.String(),
|
||||
RatingSubject: b.RatingSubject,
|
||||
Category: b.Categories.String(),
|
||||
SharedGroup: b.SharedGroups.String(),
|
||||
Timings: b.Timings,
|
||||
TimingIDs: b.TimingIDs.String(),
|
||||
Disabled: b.Disabled,
|
||||
for balanceType, counters := range acc.UnitCounters {
|
||||
for i, uc := range counters {
|
||||
if uc == nil {
|
||||
continue
|
||||
}
|
||||
result.UnitCounters[i] = &UnitsCounter{
|
||||
BalanceType: balanceType,
|
||||
Balances: make(BalanceChain, len(uc.Counters)),
|
||||
}
|
||||
if len(uc.Counters) > 0 {
|
||||
result.UnitCounters[i].Direction = (*uc.Counters[0].Filter.Directions).String()
|
||||
for j, c := range uc.Counters {
|
||||
result.UnitCounters[i].Balances[j] = &Balance{
|
||||
Uuid: c.Filter.GetUuid(),
|
||||
Id: c.Filter.GetID(),
|
||||
Value: c.Filter.GetValue(),
|
||||
ExpirationDate: c.Filter.GetExpirationDate(),
|
||||
Weight: c.Filter.GetWeight(),
|
||||
DestinationIds: c.Filter.GetDestinationIDs().String(),
|
||||
RatingSubject: c.Filter.GetRatingSubject(),
|
||||
Category: c.Filter.GetCategories().String(),
|
||||
SharedGroup: c.Filter.GetSharedGroups().String(),
|
||||
Timings: c.Filter.Timings,
|
||||
TimingIDs: c.Filter.GetTimingIDs().String(),
|
||||
Disabled: c.Filter.GetDisabled(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -817,12 +816,12 @@ func TestAccountdebitBalance(t *testing.T) {
|
||||
newMb := &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Weight: utils.Float64Pointer(20),
|
||||
DestinationIds: utils.StringMapPointer(utils.StringMap{"NEW": true}),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"NEW": true}),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
}
|
||||
a := &Action{Balance: newMb}
|
||||
ub.debitBalanceAction(a, false)
|
||||
if len(ub.BalanceMap[utils.VOICE]) != 3 || !ub.BalanceMap[utils.VOICE][2].DestinationIds.Equal(*newMb.DestinationIds) {
|
||||
if len(ub.BalanceMap[utils.VOICE]) != 3 || !ub.BalanceMap[utils.VOICE][2].DestinationIds.Equal(*newMb.DestinationIDs) {
|
||||
t.Errorf("Error adding minute bucket! %d %+v %+v", len(ub.BalanceMap[utils.VOICE]), ub.BalanceMap[utils.VOICE][2], newMb)
|
||||
}
|
||||
}
|
||||
@@ -860,7 +859,7 @@ func TestAccountdebitBalanceExists(t *testing.T) {
|
||||
Value: utils.Float64Pointer(-10),
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Weight: utils.Float64Pointer(20),
|
||||
DestinationIds: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
}
|
||||
a := &Action{Balance: newMb}
|
||||
@@ -886,19 +885,19 @@ func TestAccountAddMinutBucketEmpty(t *testing.T) {
|
||||
mb1 := &BalanceFilter{
|
||||
Value: utils.Float64Pointer(-10),
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
DestinationIds: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
}
|
||||
mb2 := &BalanceFilter{
|
||||
Value: utils.Float64Pointer(-10),
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
DestinationIds: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
}
|
||||
mb3 := &BalanceFilter{
|
||||
Value: utils.Float64Pointer(-10),
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
DestinationIds: utils.StringMapPointer(utils.StringMap{"OTHER": true}),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"OTHER": true}),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
}
|
||||
ub := &Account{}
|
||||
@@ -923,7 +922,7 @@ func TestAccountExecuteTriggeredActions(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.StringMap{utils.OUT: true}}, &Balance{Weight: 10, DestinationIds: utils.StringMap{"RET": true}}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.StringMap{utils.OUT: true}}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.StringMap{utils.OUT: true})}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ActionsId: "TEST_ACTIONS"}},
|
||||
}
|
||||
ub.countUnits(1, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
|
||||
@@ -947,7 +946,7 @@ func TestAccountExecuteTriggeredActionsBalance(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 100}}, utils.VOICE: BalanceChain{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 10, Weight: 20, DestinationIds: utils.StringMap{"NAT": true}}, &Balance{Directions: utils.NewStringMap(utils.OUT), Weight: 10, DestinationIds: utils.StringMap{"RET": true}}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Filter: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, Value: 1.0}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 100, ThresholdType: utils.TRIGGER_MIN_EVENT_COUNTER, ActionsId: "TEST_ACTIONS"}},
|
||||
}
|
||||
ub.countUnits(1, utils.MONETARY, nil, nil)
|
||||
@@ -960,14 +959,14 @@ func TestAccountExecuteTriggeredActionsOrder(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB_OREDER",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 100}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ActionsId: "TEST_ACTIONS_ORDER"}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Type: utils.StringPointer(utils.MONETARY)}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ActionsId: "TEST_ACTIONS_ORDER"}},
|
||||
}
|
||||
|
||||
ub.countUnits(1, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
|
||||
if len(ub.BalanceMap[utils.MONETARY]) != 1 || ub.BalanceMap[utils.MONETARY][0].GetValue() != 10 {
|
||||
|
||||
t.Errorf("Error executing triggered actions in order %v BAL: %+v", ub.BalanceMap[utils.MONETARY][0].GetValue(), ub.BalanceMap[utils.MONETARY][1])
|
||||
t.Errorf("Error executing triggered actions in order %v", ub.BalanceMap[utils.MONETARY][0].GetValue())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,24 +979,22 @@ func TestAccountExecuteTriggeredDayWeek(t *testing.T) {
|
||||
&ActionTrigger{UniqueID: "week_trigger", Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 100, ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ActionsId: "TEST_ACTIONS"},
|
||||
},
|
||||
}
|
||||
log.Print("==============")
|
||||
ub.InitCounters()
|
||||
log.Print("==============")
|
||||
if len(ub.UnitCounters) != 1 || len(ub.UnitCounters[0].Balances) != 2 {
|
||||
log.Print("Error initializing counters: ", ub.UnitCounters[0].Balances[0])
|
||||
if len(ub.UnitCounters) != 1 || len(ub.UnitCounters[utils.MONETARY][0].Counters) != 2 {
|
||||
t.Error("Error initializing counters: ", ub.UnitCounters[utils.MONETARY][0].Counters[0])
|
||||
}
|
||||
|
||||
ub.countUnits(1, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
|
||||
if ub.UnitCounters[0].Balances[0].Value != 1 ||
|
||||
ub.UnitCounters[0].Balances[1].Value != 1 {
|
||||
t.Error("Error incrementing both counters", ub.UnitCounters[0].Balances[0].Value, ub.UnitCounters[0].Balances[1].Value)
|
||||
if ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 1 ||
|
||||
ub.UnitCounters[utils.MONETARY][0].Counters[1].Value != 1 {
|
||||
t.Error("Error incrementing both counters", ub.UnitCounters[utils.MONETARY][0].Counters[0].Value, ub.UnitCounters[utils.MONETARY][0].Counters[1].Value)
|
||||
}
|
||||
|
||||
// we can reset them
|
||||
resetCountersAction(ub, nil, &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Id: utils.StringPointer("day_trigger")}}, nil)
|
||||
if ub.UnitCounters[0].Balances[0].Value != 0 ||
|
||||
ub.UnitCounters[0].Balances[1].Value != 1 {
|
||||
t.Error("Error reseting both counters", ub.UnitCounters[0].Balances[0].Value, ub.UnitCounters[0].Balances[1].Value)
|
||||
resetCountersAction(ub, nil, &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), ID: utils.StringPointer("day_trigger")}}, nil)
|
||||
if ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 0 ||
|
||||
ub.UnitCounters[utils.MONETARY][0].Counters[1].Value != 1 {
|
||||
t.Error("Error reseting both counters", ub.UnitCounters[utils.MONETARY][0].Counters[0].Value, ub.UnitCounters[utils.MONETARY][0].Counters[1].Value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1087,45 +1084,45 @@ func TestCleanExpired(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAccountUnitCounting(t *testing.T) {
|
||||
ub := &Account{UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 0}}}}}
|
||||
ub := &Account{UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 0}}}}}}
|
||||
ub.countUnits(10, utils.MONETARY, &CallCost{}, nil)
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 10 {
|
||||
if len(ub.UnitCounters[utils.MONETARY]) != 1 || ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 10 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
ub.countUnits(10, utils.MONETARY, &CallCost{}, nil)
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 20 {
|
||||
if len(ub.UnitCounters[utils.MONETARY]) != 1 || ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 20 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccountUnitCountingOutbound(t *testing.T) {
|
||||
ub := &Account{UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 0, Directions: utils.NewStringMap(utils.OUT)}}}}}
|
||||
ub := &Account{UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 0, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}}
|
||||
ub.countUnits(10, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 10 {
|
||||
if len(ub.UnitCounters[utils.MONETARY]) != 1 || ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 10 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
ub.countUnits(10, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 20 {
|
||||
if len(ub.UnitCounters[utils.MONETARY]) != 1 || ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 20 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
ub.countUnits(10, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 30 {
|
||||
if len(ub.UnitCounters[utils.MONETARY]) != 1 || ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 30 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccountUnitCountingOutboundInbound(t *testing.T) {
|
||||
ub := &Account{UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 0, Directions: utils.NewStringMap(utils.OUT)}}}}}
|
||||
ub := &Account{UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 0, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}}}
|
||||
ub.countUnits(10, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 10 {
|
||||
t.Errorf("Error counting units: %+v", ub.UnitCounters[0].Balances[0])
|
||||
if len(ub.UnitCounters[utils.MONETARY]) != 1 || ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 10 {
|
||||
t.Errorf("Error counting units: %+v", ub.UnitCounters[utils.MONETARY][0].Counters[0])
|
||||
}
|
||||
ub.countUnits(10, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 20 {
|
||||
if len(ub.UnitCounters[utils.MONETARY]) != 1 || ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 20 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
ub.countUnits(10, utils.MONETARY, &CallCost{Direction: utils.IN}, nil)
|
||||
if len(ub.UnitCounters) != 1 || (ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 20) {
|
||||
if len(ub.UnitCounters[utils.MONETARY]) != 1 || ub.UnitCounters[utils.MONETARY][0].Counters[0].Value != 20 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
}
|
||||
@@ -1654,15 +1651,18 @@ func TestAccountInitCounters(t *testing.T) {
|
||||
},
|
||||
}
|
||||
a.InitCounters()
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[0].Balances) != 2 ||
|
||||
len(a.UnitCounters[1].Balances) != 1 ||
|
||||
len(a.UnitCounters[2].Balances) != 1 ||
|
||||
len(a.UnitCounters[3].Balances) != 1 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.MONETARY][0].Counters) != 2 ||
|
||||
len(a.UnitCounters[utils.VOICE][0].Counters) != 1 ||
|
||||
len(a.UnitCounters[utils.VOICE][1].Counters) != 1 ||
|
||||
len(a.UnitCounters[utils.SMS][0].Counters) != 1 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, c := range uc.Counters {
|
||||
t.Logf("B: %+v", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error Initializing unit counters: %v", len(a.UnitCounters))
|
||||
@@ -1730,15 +1730,18 @@ func TestAccountDoubleInitCounters(t *testing.T) {
|
||||
}
|
||||
a.InitCounters()
|
||||
a.InitCounters()
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[0].Balances) != 2 ||
|
||||
len(a.UnitCounters[1].Balances) != 1 ||
|
||||
len(a.UnitCounters[2].Balances) != 1 ||
|
||||
len(a.UnitCounters[3].Balances) != 1 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.MONETARY][0].Counters) != 2 ||
|
||||
len(a.UnitCounters[utils.VOICE][0].Counters) != 1 ||
|
||||
len(a.UnitCounters[utils.VOICE][1].Counters) != 1 ||
|
||||
len(a.UnitCounters[utils.SMS][0].Counters) != 1 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, c := range uc.Counters {
|
||||
t.Logf("B: %+v", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error Initializing unit counters: %v", len(a.UnitCounters))
|
||||
|
||||
130
engine/action.go
130
engine/action.go
@@ -48,134 +48,6 @@ type Action struct {
|
||||
Balance *BalanceFilter
|
||||
}
|
||||
|
||||
type BalanceFilter struct {
|
||||
Uuid *string
|
||||
Id *string
|
||||
Type *string
|
||||
Value *float64
|
||||
Directions *utils.StringMap
|
||||
ExpirationDate *time.Time
|
||||
Weight *float64
|
||||
DestinationIds *utils.StringMap
|
||||
RatingSubject *string
|
||||
Categories *utils.StringMap
|
||||
SharedGroups *utils.StringMap
|
||||
TimingIDs *utils.StringMap
|
||||
Timings []*RITiming
|
||||
Disabled *bool
|
||||
Factor *ValueFactor
|
||||
Blocker *bool
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) CreateBalance() *Balance {
|
||||
b := &Balance{}
|
||||
if bp.Uuid != nil {
|
||||
b.Uuid = *bp.Uuid
|
||||
}
|
||||
if bp.Id != nil {
|
||||
b.Id = *bp.Id
|
||||
}
|
||||
if bp.Value != nil {
|
||||
b.Value = *bp.Value
|
||||
}
|
||||
if bp.Directions != nil {
|
||||
b.Directions = *bp.Directions
|
||||
}
|
||||
if bp.ExpirationDate != nil {
|
||||
b.ExpirationDate = *bp.ExpirationDate
|
||||
}
|
||||
if bp.Weight != nil {
|
||||
b.Weight = *bp.Weight
|
||||
}
|
||||
if bp.DestinationIds != nil {
|
||||
b.DestinationIds = *bp.DestinationIds
|
||||
}
|
||||
if bp.RatingSubject != nil {
|
||||
b.RatingSubject = *bp.RatingSubject
|
||||
}
|
||||
if bp.Categories != nil {
|
||||
b.Categories = *bp.Categories
|
||||
}
|
||||
if bp.SharedGroups != nil {
|
||||
b.SharedGroups = *bp.SharedGroups
|
||||
}
|
||||
if bp.TimingIDs != nil {
|
||||
b.TimingIDs = *bp.TimingIDs
|
||||
}
|
||||
if bp.Disabled != nil {
|
||||
b.Disabled = *bp.Disabled
|
||||
}
|
||||
if bp.Factor != nil {
|
||||
b.Factor = *bp.Factor
|
||||
}
|
||||
if bp.Blocker != nil {
|
||||
b.Blocker = *bp.Blocker
|
||||
}
|
||||
return b.Clone()
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) LoadFromBalance(b *Balance) {
|
||||
if b.Uuid != "" {
|
||||
bp.Uuid = &b.Uuid
|
||||
}
|
||||
if b.Id != "" {
|
||||
bp.Id = &b.Id
|
||||
}
|
||||
if b.Value != 0 {
|
||||
bp.Value = &b.Value
|
||||
}
|
||||
if len(b.Directions) != 0 {
|
||||
bp.Directions = &b.Directions
|
||||
}
|
||||
if !b.ExpirationDate.IsZero() {
|
||||
bp.ExpirationDate = &b.ExpirationDate
|
||||
}
|
||||
if b.Weight != 0 {
|
||||
bp.Weight = &b.Weight
|
||||
}
|
||||
if len(b.DestinationIds) != 0 {
|
||||
bp.DestinationIds = &b.DestinationIds
|
||||
}
|
||||
if b.RatingSubject != "" {
|
||||
bp.RatingSubject = &b.RatingSubject
|
||||
}
|
||||
if len(b.Categories) != 0 {
|
||||
bp.Categories = &b.Categories
|
||||
}
|
||||
if len(b.SharedGroups) != 0 {
|
||||
bp.SharedGroups = &b.SharedGroups
|
||||
}
|
||||
if len(b.TimingIDs) != 0 {
|
||||
bp.TimingIDs = &b.TimingIDs
|
||||
}
|
||||
if len(b.Factor) != 0 {
|
||||
bp.Factor = &b.Factor
|
||||
}
|
||||
bp.Disabled = &b.Disabled
|
||||
bp.Blocker = &b.Blocker
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetType() string {
|
||||
if bp.Type == nil {
|
||||
return ""
|
||||
}
|
||||
return *bp.Type
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetValue() float64 {
|
||||
if bp.Value == nil {
|
||||
return 0.0
|
||||
}
|
||||
return *bp.Value
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) SetValue(v float64) {
|
||||
if bp.Value == nil {
|
||||
bp.Value = new(float64)
|
||||
}
|
||||
*bp.Value = v
|
||||
}
|
||||
|
||||
const (
|
||||
LOG = "*log"
|
||||
RESET_TRIGGERS = "*reset_triggers"
|
||||
@@ -301,7 +173,7 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action)
|
||||
case "AccountID":
|
||||
parsedValue += rsrFld.ParseValue(acnt.Id)
|
||||
case "Directions":
|
||||
parsedValue += rsrFld.ParseValue(action.Balance.Directions.String())
|
||||
parsedValue += rsrFld.ParseValue(b.Directions.String())
|
||||
case utils.TENANT:
|
||||
parsedValue += rsrFld.ParseValue(dta.Tenant)
|
||||
case utils.ACCOUNT:
|
||||
|
||||
@@ -307,7 +307,7 @@ func (at *ActionTiming) Execute() (err error) {
|
||||
continue // disabled acocunts are not removed from action plan
|
||||
//return 0, fmt.Errorf("Account %s is disabled", accID)
|
||||
}
|
||||
if expDate, parseErr := utils.ParseDate(a.ExpirationString); (a.Balance == nil || a.Balance.ExpirationDate.IsZero()) && parseErr == nil && !expDate.IsZero() {
|
||||
if expDate, parseErr := utils.ParseDate(a.ExpirationString); (a.Balance == nil || a.Balance.HasExpirationDate()) && parseErr == nil && !expDate.IsZero() {
|
||||
a.Balance.ExpirationDate = &time.Time{}
|
||||
*a.Balance.ExpirationDate = expDate
|
||||
}
|
||||
@@ -337,8 +337,7 @@ func (at *ActionTiming) Execute() (err error) {
|
||||
}
|
||||
if len(at.accountIDs) == 0 { // action timing executing without accounts
|
||||
for _, a := range aac {
|
||||
|
||||
if expDate, parseErr := utils.ParseDate(a.ExpirationString); (a.Balance == nil || a.Balance.ExpirationDate.IsZero()) &&
|
||||
if expDate, parseErr := utils.ParseDate(a.ExpirationString); (a.Balance == nil || a.Balance.HasExpirationDate()) &&
|
||||
parseErr == nil && !expDate.IsZero() {
|
||||
a.Balance.ExpirationDate = &time.Time{}
|
||||
*a.Balance.ExpirationDate = expDate
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
@@ -112,10 +113,37 @@ func (at *ActionTrigger) Execute(ub *Account, sq *StatsQueueTriggered) (err erro
|
||||
// returns true if the field of the action timing are equeal to the non empty
|
||||
// fields of the action
|
||||
func (at *ActionTrigger) Match(a *Action) bool {
|
||||
if a == nil {
|
||||
if a == nil || a.Balance == nil {
|
||||
return true
|
||||
}
|
||||
return at.Balance.CreateBalance().MatchFilter(a.Balance, false)
|
||||
if a.Balance.Type != nil && a.Balance.GetType() != at.Balance.GetType() {
|
||||
return false
|
||||
}
|
||||
var thresholdType bool
|
||||
if a.ExtraParameters != "" {
|
||||
t := struct {
|
||||
GroupID string
|
||||
UniqueID string
|
||||
ThresholdType string
|
||||
}{}
|
||||
json.Unmarshal([]byte(a.ExtraParameters), &t)
|
||||
// check Ids first
|
||||
if t.GroupID != "" {
|
||||
return at.ID == t.GroupID
|
||||
}
|
||||
if t.UniqueID != "" {
|
||||
return at.UniqueID == t.UniqueID
|
||||
}
|
||||
thresholdType = t.ThresholdType == "" || at.ThresholdType == t.ThresholdType
|
||||
}
|
||||
|
||||
return thresholdType && at.Balance.CreateBalance().MatchFilter(a.Balance, false)
|
||||
}
|
||||
|
||||
func (at *ActionTrigger) CreateBalance() *Balance {
|
||||
b := at.Balance.CreateBalance()
|
||||
b.Id = at.UniqueID
|
||||
return b
|
||||
}
|
||||
|
||||
// makes a shallow copy of the receiver
|
||||
|
||||
@@ -613,7 +613,7 @@ func TestActionTriggerMatchSomeFalse(t *testing.T) {
|
||||
ThresholdType: utils.TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*in"}`, utils.TRIGGER_MAX_BALANCE, 2)}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%s"}`, utils.TRIGGER_MAX_BALANCE_COUNTER)}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -628,7 +628,7 @@ func TestActionTriggerMatcBalanceFalse(t *testing.T) {
|
||||
ThresholdType: utils.TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*out"}`, utils.TRIGGER_MAX_BALANCE, 3.0)}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ExtraParameters: fmt.Sprintf(`{"GroupID":"%s", "ThresholdType":"%s"}`, "TEST", utils.TRIGGER_MAX_BALANCE)}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -643,7 +643,7 @@ func TestActionTriggerMatcAllFalse(t *testing.T) {
|
||||
ThresholdType: utils.TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*in"}`, utils.TRIGGER_MAX_EVENT_COUNTER, 3)}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"UniqueID":"ZIP", "GroupID":"%s", "ThresholdType":"%s"}`, "TEST", utils.TRIGGER_MAX_BALANCE)}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -651,18 +651,28 @@ func TestActionTriggerMatcAllFalse(t *testing.T) {
|
||||
|
||||
func TestActionTriggerMatchAll(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
ID: "TEST",
|
||||
UniqueID: "ZIP",
|
||||
ThresholdType: "TT",
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
RatingSubject: utils.StringPointer("test1"),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
Value: utils.Float64Pointer(2),
|
||||
Weight: utils.Float64Pointer(1.0),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
SharedGroups: utils.StringMapPointer(utils.NewStringMap("test2")),
|
||||
},
|
||||
ThresholdType: utils.TRIGGER_MAX_BALANCE,
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ExtraParameters: fmt.Sprintf(`{"BalanceDirections":"*out", "ThresholdType":"%v", "ThresholdValue": %v, "DestinationIds": "%v", "BalanceWeight": %v, "BalanceRatingSubject": "%v", "BalanceSharedGroup": "%v"}`, utils.TRIGGER_MAX_BALANCE, 2, "NAT", 1.0, "test1", "test2")}
|
||||
a := &Action{Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
RatingSubject: utils.StringPointer("test1"),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
Value: utils.Float64Pointer(2),
|
||||
Weight: utils.Float64Pointer(1.0),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
SharedGroups: utils.StringMapPointer(utils.NewStringMap("test2")),
|
||||
}, ExtraParameters: fmt.Sprintf(`{"UniqueID":"ZIP", "GroupID":"TEST", "ThresholdType":"TT"}`)}
|
||||
if !at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -684,7 +694,7 @@ func TestActionResetTriggres(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 10}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetTriggersAction(ub, nil, nil, nil)
|
||||
@@ -697,7 +707,7 @@ func TestActionResetTriggresExecutesThem(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 10}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetTriggersAction(ub, nil, nil, nil)
|
||||
@@ -710,7 +720,7 @@ func TestActionResetTriggresActionFilter(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 10}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetTriggersAction(ub, nil, &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}}, nil)
|
||||
@@ -723,7 +733,7 @@ func TestActionSetPostpaid(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
allowNegativeAction(ub, nil, nil, nil)
|
||||
@@ -737,7 +747,7 @@ func TestActionSetPrepaid(t *testing.T) {
|
||||
Id: "TEST_UB",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
denyNegativeAction(ub, nil, nil, nil)
|
||||
@@ -751,7 +761,7 @@ func TestActionResetPrepaid(t *testing.T) {
|
||||
Id: "TEST_UB",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetAccountAction(ub, nil, nil, nil)
|
||||
@@ -761,7 +771,7 @@ func TestActionResetPrepaid(t *testing.T) {
|
||||
ub.BalanceMap[utils.VOICE][0].GetValue() != 0 ||
|
||||
ub.ActionTriggers[0].Executed == true || ub.ActionTriggers[1].Executed == true {
|
||||
t.Log(ub.BalanceMap)
|
||||
t.Error("Reset prepaid action failed!")
|
||||
t.Error("Reset account action failed!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,7 +779,7 @@ func TestActionResetPostpaid(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.SMS)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetAccountAction(ub, nil, nil, nil)
|
||||
@@ -777,7 +787,7 @@ func TestActionResetPostpaid(t *testing.T) {
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
ub.BalanceMap[utils.VOICE][0].GetValue() != 0 ||
|
||||
ub.ActionTriggers[0].Executed == true || ub.ActionTriggers[1].Executed == true {
|
||||
t.Error("Reset postpaid action failed!")
|
||||
t.Error("Reset account action failed!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,17 +795,17 @@ func TestActionTopupResetCredit(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupResetAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 10 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters) != 0 || // InitCounters finds no counters
|
||||
len(ub.BalanceMap[utils.VOICE]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Errorf("Topup reset action failed: %+v", ub.BalanceMap[utils.MONETARY][0])
|
||||
t.Errorf("Topup reset action failed: %+s", utils.ToIJSON(ub))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -828,7 +838,7 @@ func TestActionTopupResetCreditId(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Id: utils.StringPointer("TEST_B"), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), ID: utils.StringPointer("TEST_B"), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupResetAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 110 ||
|
||||
@@ -862,15 +872,15 @@ func TestActionTopupResetMinutes(t *testing.T) {
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
utils.MONETARY: BalanceChain{&Balance{Value: 100}},
|
||||
utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupResetAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.VOICE].GetTotalValue() != 5 ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
len(ub.BalanceMap[utils.VOICE]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Errorf("Topup reset minutes action failed: %+v", ub.BalanceMap[utils.VOICE][0])
|
||||
@@ -881,14 +891,14 @@ func TestActionTopupCredit(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 110 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
len(ub.BalanceMap[utils.VOICE]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Topup action failed!", ub.BalanceMap[utils.MONETARY].GetTotalValue())
|
||||
@@ -899,15 +909,15 @@ func TestActionTopupMinutes(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.VOICE].GetTotalValue() != 15 ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
len(ub.BalanceMap[utils.VOICE]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Topup minutes action failed!", ub.BalanceMap[utils.VOICE])
|
||||
@@ -918,17 +928,17 @@ func TestActionDebitCredit(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
debitAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 90 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
len(ub.BalanceMap[utils.VOICE]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Debit action failed!", ub.BalanceMap[utils.MONETARY].GetTotalValue())
|
||||
t.Error("Debit action failed!", utils.ToIJSON(ub))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -936,15 +946,15 @@ func TestActionDebitMinutes(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
debitAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.VOICE][0].GetValue() != 5 ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
len(ub.BalanceMap[utils.VOICE]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Debit minutes action failed!", ub.BalanceMap[utils.VOICE][0])
|
||||
@@ -961,24 +971,24 @@ func TestActionResetAllCounters(t *testing.T) {
|
||||
&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)},
|
||||
&Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET"), Directions: utils.NewStringMap(utils.OUT)}}},
|
||||
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ThresholdValue: 2, Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")), Weight: utils.Float64Pointer(20)}, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, ThresholdValue: 2, Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Weight: utils.Float64Pointer(20)}, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
ub.InitCounters()
|
||||
resetCountersAction(ub, nil, nil, nil)
|
||||
if !ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters[0].Balances) != 1 ||
|
||||
len(ub.UnitCounters[utils.MONETARY][0].Counters) != 1 ||
|
||||
len(ub.BalanceMap[utils.MONETARY]) != 1 ||
|
||||
ub.ActionTriggers[0].Executed != true {
|
||||
t.Errorf("Reset counters action failed: %+v %+v %+v", ub.UnitCounters, ub.UnitCounters[0], ub.UnitCounters[0].Balances[0])
|
||||
t.Errorf("Reset counters action failed: %+v %+v %+v", ub.UnitCounters, ub.UnitCounters[utils.MONETARY][0], ub.UnitCounters[utils.MONETARY][0].Counters[0])
|
||||
}
|
||||
if len(ub.UnitCounters) < 1 {
|
||||
t.FailNow()
|
||||
}
|
||||
mb := ub.UnitCounters[0].Balances[0]
|
||||
if mb.Weight != 20 || mb.GetValue() != 0 || mb.DestinationIds["NAT"] == false {
|
||||
t.Errorf("Balance cloned incorrectly: %+v", mb)
|
||||
c := ub.UnitCounters[utils.MONETARY][0].Counters[0]
|
||||
if c.Filter.GetWeight() != 20 || c.Value != 0 || c.Filter.GetDestinationIDs()["NAT"] == false {
|
||||
t.Errorf("Balance cloned incorrectly: %+v", c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -997,20 +1007,20 @@ func TestActionResetCounterOnlyDefault(t *testing.T) {
|
||||
if !ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters[0].Balances) != 1 ||
|
||||
len(ub.UnitCounters[utils.MONETARY][0].Counters) != 1 ||
|
||||
len(ub.BalanceMap[utils.VOICE]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true {
|
||||
for _, b := range ub.UnitCounters[0].Balances {
|
||||
for _, b := range ub.UnitCounters[utils.MONETARY][0].Counters {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
t.Errorf("Reset counters action failed: %+v", ub.UnitCounters)
|
||||
}
|
||||
if len(ub.UnitCounters) < 1 || len(ub.UnitCounters[0].Balances) < 1 {
|
||||
if len(ub.UnitCounters) < 1 || len(ub.UnitCounters[utils.MONETARY][0].Counters) < 1 {
|
||||
t.FailNow()
|
||||
}
|
||||
mb := ub.UnitCounters[0].Balances[0]
|
||||
if mb.Weight != 0 || mb.GetValue() != 0 || len(mb.DestinationIds) != 0 {
|
||||
t.Errorf("Balance cloned incorrectly: %+v!", mb)
|
||||
c := ub.UnitCounters[utils.MONETARY][0].Counters[0]
|
||||
if c.Filter.GetWeight() != 0 || c.Value != 0 || len(c.Filter.GetDestinationIDs()) != 0 {
|
||||
t.Errorf("Balance cloned incorrectly: %+v!", c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,7 +1029,7 @@ func TestActionResetCounterCredit(t *testing.T) {
|
||||
Id: "TEST_UB",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}, &UnitCounter{BalanceType: utils.SMS, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}, utils.SMS: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}}
|
||||
@@ -1039,7 +1049,7 @@ func TestActionTriggerLogging(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
},
|
||||
ThresholdValue: 100.0,
|
||||
Weight: 10.0,
|
||||
@@ -1142,7 +1152,7 @@ func TestTopupAction(t *testing.T) {
|
||||
initialUb, _ := accountingStorage.GetAccount("vdf:minu")
|
||||
a := &Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(25), DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)},
|
||||
}
|
||||
|
||||
at := &ActionTiming{
|
||||
@@ -1163,7 +1173,7 @@ func TestTopupActionLoaded(t *testing.T) {
|
||||
initialUb, _ := accountingStorage.GetAccount("vdf:minitsboy")
|
||||
a := &Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(25), DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)},
|
||||
}
|
||||
|
||||
at := &ActionTiming{
|
||||
@@ -1190,7 +1200,7 @@ func TestActionCdrlogEmpty(t *testing.T) {
|
||||
err := cdrLogAction(acnt, nil, cdrlog, Actions{
|
||||
&Action{
|
||||
ActionType: DEBIT,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1212,11 +1222,11 @@ func TestActionCdrlogWithParams(t *testing.T) {
|
||||
err := cdrLogAction(acnt, nil, cdrlog, Actions{
|
||||
&Action{
|
||||
ActionType: DEBIT,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
&Action{
|
||||
ActionType: DEBIT_RESET,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1239,11 +1249,11 @@ func TestActionCdrLogParamsWithOverload(t *testing.T) {
|
||||
err := cdrLogAction(acnt, nil, cdrlog, Actions{
|
||||
&Action{
|
||||
ActionType: DEBIT,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
&Action{
|
||||
ActionType: DEBIT_RESET,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1373,7 +1383,43 @@ func TestActionTransactionBalanceType(t *testing.T) {
|
||||
if err != nil || acc == nil {
|
||||
t.Error("Error getting account: ", acc, err)
|
||||
}
|
||||
if acc.BalanceMap[utils.MONETARY][0].Value != 10 {
|
||||
if acc.BalanceMap[utils.MONETARY][0].Value != 11.1 {
|
||||
t.Errorf("Transaction didn't work: %v", acc.BalanceMap[utils.MONETARY][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionTransactionBalanceNotType(t *testing.T) {
|
||||
err := accountingStorage.SetAccount(&Account{
|
||||
Id: "cgrates.org:trans",
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
utils.MONETARY: BalanceChain{&Balance{
|
||||
Value: 10,
|
||||
}},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Error("Error setting account: ", err)
|
||||
}
|
||||
at := &ActionTiming{
|
||||
accountIDs: utils.StringMap{"cgrates.org:trans": true},
|
||||
Timing: &RateInterval{},
|
||||
actions: []*Action{
|
||||
&Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(1.1), Type: utils.StringPointer(utils.VOICE)},
|
||||
},
|
||||
&Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer("test")},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = at.Execute()
|
||||
acc, err := accountingStorage.GetAccount("cgrates.org:trans")
|
||||
if err != nil || acc == nil {
|
||||
t.Error("Error getting account: ", acc, err)
|
||||
}
|
||||
if acc.BalanceMap[utils.MONETARY][0].Value != 10.0 {
|
||||
t.Errorf("Transaction didn't work: %v", acc.BalanceMap[utils.MONETARY][0].Value)
|
||||
}
|
||||
}
|
||||
@@ -1453,7 +1499,7 @@ func TestActionRemoveBalance(t *testing.T) {
|
||||
ActionType: REMOVE_BALANCE,
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT", "RET")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT", "RET")),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1850,43 +1896,58 @@ func TestActionConditionalDisabledIfNegative(t *testing.T) {
|
||||
}
|
||||
|
||||
a1 := &Action{
|
||||
ActionType: "*enable_disable_balance",
|
||||
ActionType: "*set_balance",
|
||||
Filter: "{\"*and\":[{\"Value\":{\"*lt\":0}},{\"Id\":{\"*eq\":\"*default\"}}]}",
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer("*sms"),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
ID: utils.StringPointer("for_v3hsillmilld500m_sms_ill"),
|
||||
Disabled: utils.BoolPointer(true),
|
||||
},
|
||||
Weight: 9,
|
||||
}
|
||||
a2 := &Action{
|
||||
ActionType: "*enable_disable_balance",
|
||||
ActionType: "*set_balance",
|
||||
Filter: "{\"*and\":[{\"Value\":{\"*lt\":0}},{\"Id\":{\"*eq\":\"*default\"}}]}",
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer("*sms"),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("FRANCE_NATIONAL")),
|
||||
ID: utils.StringPointer("for_v3hsillmilld500m_mms_ill"),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("FRANCE_NATIONAL")),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
Disabled: utils.BoolPointer(true),
|
||||
},
|
||||
Weight: 8,
|
||||
}
|
||||
a3 := &Action{
|
||||
ActionType: "*enable_disable_balance",
|
||||
ActionType: "*set_balance",
|
||||
Filter: "{\"*and\":[{\"Value\":{\"*lt\":0}},{\"Id\":{\"*eq\":\"*default\"}}]}",
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer("*sms"),
|
||||
ID: utils.StringPointer("for_v3hsillmilld500m_sms_ill"),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("FRANCE_NATIONAL")),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
Disabled: utils.BoolPointer(true),
|
||||
},
|
||||
Weight: 8,
|
||||
}
|
||||
a4 := &Action{
|
||||
ActionType: "*set_balance",
|
||||
Filter: "{\"*and\":[{\"Value\":{\"*lt\":0}},{\"Id\":{\"*eq\":\"*default\"}}]}",
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer("*data"),
|
||||
Uuid: utils.StringPointer("fc927edb-1bd6-425e-a2a3-9fd8bafaa524"),
|
||||
RatingSubject: utils.StringPointer("for_v3hsillmilld500m_data_forfait"),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
Disabled: utils.BoolPointer(true),
|
||||
},
|
||||
Weight: 7,
|
||||
}
|
||||
a4 := &Action{
|
||||
ActionType: "*enable_disable_balance",
|
||||
a5 := &Action{
|
||||
ActionType: "*set_balance",
|
||||
Filter: "{\"*and\":[{\"Value\":{\"*lt\":0}},{\"Id\":{\"*eq\":\"*default\"}}]}",
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer("*voice"),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("FRANCE_NATIONAL")),
|
||||
ID: utils.StringPointer("for_v3hsillmilld500m_voice_3_h"),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("FRANCE_NATIONAL")),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
Disabled: utils.BoolPointer(true),
|
||||
},
|
||||
@@ -1895,7 +1956,7 @@ func TestActionConditionalDisabledIfNegative(t *testing.T) {
|
||||
|
||||
at := &ActionTiming{
|
||||
accountIDs: utils.StringMap{"cgrates.org:af": true},
|
||||
actions: Actions{a1, a2, a3, a4},
|
||||
actions: Actions{a1, a2, a3, a4, a5},
|
||||
}
|
||||
at.Execute()
|
||||
|
||||
@@ -1957,7 +2018,7 @@ func TestActionSetBalance(t *testing.T) {
|
||||
a := &Action{
|
||||
ActionType: SET_BALANCE,
|
||||
Balance: &BalanceFilter{
|
||||
Id: utils.StringPointer("m2"),
|
||||
ID: utils.StringPointer("m2"),
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Value: utils.Float64Pointer(11),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
|
||||
220
engine/balance_filter.go
Normal file
220
engine/balance_filter.go
Normal file
@@ -0,0 +1,220 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type BalanceFilter struct {
|
||||
Uuid *string
|
||||
ID *string
|
||||
Type *string
|
||||
Value *float64
|
||||
Directions *utils.StringMap
|
||||
ExpirationDate *time.Time
|
||||
Weight *float64
|
||||
DestinationIDs *utils.StringMap
|
||||
RatingSubject *string
|
||||
Categories *utils.StringMap
|
||||
SharedGroups *utils.StringMap
|
||||
TimingIDs *utils.StringMap
|
||||
Timings []*RITiming
|
||||
Disabled *bool
|
||||
Factor *ValueFactor
|
||||
Blocker *bool
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) CreateBalance() *Balance {
|
||||
b := &Balance{
|
||||
Uuid: bp.GetUuid(),
|
||||
Id: bp.GetID(),
|
||||
Value: bp.GetValue(),
|
||||
Directions: bp.GetDirections(),
|
||||
ExpirationDate: bp.GetExpirationDate(),
|
||||
Weight: bp.GetWeight(),
|
||||
DestinationIds: bp.GetDestinationIDs(),
|
||||
RatingSubject: bp.GetRatingSubject(),
|
||||
Categories: bp.GetCategories(),
|
||||
SharedGroups: bp.GetSharedGroups(),
|
||||
Timings: bp.Timings,
|
||||
TimingIDs: bp.GetTimingIDs(),
|
||||
Disabled: bp.GetDisabled(),
|
||||
Factor: bp.GetFactor(),
|
||||
Blocker: bp.GetBlocker(),
|
||||
}
|
||||
return b.Clone()
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) LoadFromBalance(b *Balance) *BalanceFilter {
|
||||
if b.Uuid != "" {
|
||||
bp.Uuid = &b.Uuid
|
||||
}
|
||||
if b.Id != "" {
|
||||
bp.ID = &b.Id
|
||||
}
|
||||
if b.Value != 0 {
|
||||
bp.Value = &b.Value
|
||||
}
|
||||
if len(b.Directions) != 0 {
|
||||
bp.Directions = &b.Directions
|
||||
}
|
||||
if !b.ExpirationDate.IsZero() {
|
||||
bp.ExpirationDate = &b.ExpirationDate
|
||||
}
|
||||
if b.Weight != 0 {
|
||||
bp.Weight = &b.Weight
|
||||
}
|
||||
if len(b.DestinationIds) != 0 {
|
||||
bp.DestinationIDs = &b.DestinationIds
|
||||
}
|
||||
if b.RatingSubject != "" {
|
||||
bp.RatingSubject = &b.RatingSubject
|
||||
}
|
||||
if len(b.Categories) != 0 {
|
||||
bp.Categories = &b.Categories
|
||||
}
|
||||
if len(b.SharedGroups) != 0 {
|
||||
bp.SharedGroups = &b.SharedGroups
|
||||
}
|
||||
if len(b.TimingIDs) != 0 {
|
||||
bp.TimingIDs = &b.TimingIDs
|
||||
}
|
||||
if len(b.Factor) != 0 {
|
||||
bp.Factor = &b.Factor
|
||||
}
|
||||
if b.Disabled {
|
||||
bp.Disabled = &b.Disabled
|
||||
}
|
||||
if b.Blocker {
|
||||
bp.Blocker = &b.Blocker
|
||||
}
|
||||
return bp
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) Equal(o *BalanceFilter) bool {
|
||||
if bp.ID != nil && o.ID != nil {
|
||||
return *bp.ID == *o.ID
|
||||
}
|
||||
return reflect.DeepEqual(bp, o)
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetType() string {
|
||||
if bp == nil || bp.Type == nil {
|
||||
return ""
|
||||
}
|
||||
return *bp.Type
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetValue() float64 {
|
||||
if bp == nil || bp.Value == nil {
|
||||
return 0.0
|
||||
}
|
||||
return *bp.Value
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) SetValue(v float64) {
|
||||
if bp.Value == nil {
|
||||
bp.Value = new(float64)
|
||||
}
|
||||
*bp.Value = v
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetUuid() string {
|
||||
if bp == nil || bp.Uuid == nil {
|
||||
return ""
|
||||
}
|
||||
return *bp.Uuid
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetID() string {
|
||||
if bp == nil || bp.ID == nil {
|
||||
return ""
|
||||
}
|
||||
return *bp.ID
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetDirections() utils.StringMap {
|
||||
if bp == nil || bp.Directions == nil {
|
||||
return utils.StringMap{}
|
||||
}
|
||||
return *bp.Directions
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetDestinationIDs() utils.StringMap {
|
||||
if bp == nil || bp.DestinationIDs == nil {
|
||||
return utils.StringMap{}
|
||||
}
|
||||
return *bp.DestinationIDs
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetCategories() utils.StringMap {
|
||||
if bp == nil || bp.Categories == nil {
|
||||
return utils.StringMap{}
|
||||
}
|
||||
return *bp.Categories
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetTimingIDs() utils.StringMap {
|
||||
if bp == nil || bp.TimingIDs == nil {
|
||||
return utils.StringMap{}
|
||||
}
|
||||
return *bp.TimingIDs
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetSharedGroups() utils.StringMap {
|
||||
if bp == nil || bp.SharedGroups == nil {
|
||||
return utils.StringMap{}
|
||||
}
|
||||
return *bp.SharedGroups
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetWeight() float64 {
|
||||
if bp == nil || bp.Weight == nil {
|
||||
return 0.0
|
||||
}
|
||||
return *bp.Weight
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetRatingSubject() string {
|
||||
if bp == nil || bp.RatingSubject == nil {
|
||||
return ""
|
||||
}
|
||||
return *bp.RatingSubject
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetDisabled() bool {
|
||||
if bp == nil || bp.Disabled == nil {
|
||||
return false
|
||||
}
|
||||
return *bp.Disabled
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetBlocker() bool {
|
||||
if bp == nil || bp.Blocker == nil {
|
||||
return false
|
||||
}
|
||||
return *bp.Blocker
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetExpirationDate() time.Time {
|
||||
if bp == nil || bp.ExpirationDate == nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return *bp.ExpirationDate
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetFactor() ValueFactor {
|
||||
if bp == nil || bp.Factor == nil {
|
||||
return ValueFactor{}
|
||||
}
|
||||
return *bp.Factor
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) HasExpirationDate() bool {
|
||||
if bp.ExpirationDate == nil {
|
||||
return true
|
||||
}
|
||||
return (*bp.ExpirationDate).IsZero()
|
||||
}
|
||||
@@ -79,14 +79,14 @@ func (b *Balance) MatchFilter(o *BalanceFilter, skipIds bool) bool {
|
||||
if !skipIds && o.Uuid != nil && *o.Uuid != "" {
|
||||
return b.Uuid == *o.Uuid
|
||||
}
|
||||
if !skipIds && o.Id != nil && *o.Id != "" {
|
||||
return b.Id == *o.Id
|
||||
if !skipIds && o.ID != nil && *o.ID != "" {
|
||||
return b.Id == *o.ID
|
||||
}
|
||||
return (o.ExpirationDate == nil || b.ExpirationDate.Equal(*o.ExpirationDate)) &&
|
||||
(o.Weight == nil || b.Weight == *o.Weight) &&
|
||||
(o.Blocker == nil || b.Blocker == *o.Blocker) &&
|
||||
(o.Disabled == nil || b.Disabled == *o.Disabled) &&
|
||||
(o.DestinationIds == nil || b.DestinationIds.Includes(*o.DestinationIds)) &&
|
||||
(o.DestinationIDs == nil || b.DestinationIds.Includes(*o.DestinationIDs)) &&
|
||||
(o.Directions == nil || b.Directions.Includes(*o.Directions)) &&
|
||||
(o.Categories == nil || b.Categories.Includes(*o.Categories)) &&
|
||||
(o.TimingIDs == nil || b.TimingIDs.Includes(*o.TimingIDs)) &&
|
||||
@@ -101,14 +101,14 @@ func (b *Balance) HardMatchFilter(o *BalanceFilter, skipIds bool) bool {
|
||||
if !skipIds && o.Uuid != nil && *o.Uuid != "" {
|
||||
return b.Uuid == *o.Uuid
|
||||
}
|
||||
if !skipIds && o.Id != nil && *o.Id != "" {
|
||||
return b.Id == *o.Id
|
||||
if !skipIds && o.ID != nil && *o.ID != "" {
|
||||
return b.Id == *o.ID
|
||||
}
|
||||
return (o.ExpirationDate == nil || b.ExpirationDate.Equal(*o.ExpirationDate)) &&
|
||||
(o.Weight == nil || b.Weight == *o.Weight) &&
|
||||
(o.Blocker == nil || b.Blocker == *o.Blocker) &&
|
||||
(o.Disabled == nil || b.Disabled == *o.Disabled) &&
|
||||
(o.DestinationIds == nil || b.DestinationIds.Equal(*o.DestinationIds)) &&
|
||||
(o.DestinationIDs == nil || b.DestinationIds.Equal(*o.DestinationIDs)) &&
|
||||
(o.Directions == nil || b.Directions.Equal(*o.Directions)) &&
|
||||
(o.Categories == nil || b.Categories.Equal(*o.Categories)) &&
|
||||
(o.TimingIDs == nil || b.TimingIDs.Equal(*o.TimingIDs)) &&
|
||||
@@ -116,40 +116,6 @@ func (b *Balance) HardMatchFilter(o *BalanceFilter, skipIds bool) bool {
|
||||
(o.RatingSubject == nil || b.RatingSubject == *o.RatingSubject)
|
||||
}
|
||||
|
||||
func (b *Balance) MatchCCFilter(cc *CallCost) bool {
|
||||
if len(b.Categories) > 0 && cc.Category != "" && b.Categories[cc.Category] == false {
|
||||
return false
|
||||
}
|
||||
if len(b.Directions) > 0 && cc.Direction != "" && b.Directions[cc.Direction] == false {
|
||||
return false
|
||||
}
|
||||
|
||||
// match destination ids
|
||||
foundMatchingDestId := false
|
||||
if len(b.DestinationIds) > 0 && cc.Destination != "" {
|
||||
for _, p := range utils.SplitPrefix(cc.Destination, MIN_PREFIX_MATCH) {
|
||||
if x, err := cache2go.Get(utils.DESTINATION_PREFIX + p); err == nil {
|
||||
destIds := x.(map[interface{}]struct{})
|
||||
for filterDestId := range b.DestinationIds {
|
||||
if _, ok := destIds[filterDestId]; ok {
|
||||
foundMatchingDestId = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if foundMatchingDestId {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foundMatchingDestId = true
|
||||
}
|
||||
if !foundMatchingDestId {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// the default balance has standard Id
|
||||
func (b *Balance) IsDefault() bool {
|
||||
return b.Id == utils.META_DEFAULT
|
||||
|
||||
@@ -90,7 +90,7 @@ func TestBalanceEqual(t *testing.T) {
|
||||
|
||||
func TestBalanceMatchFilter(t *testing.T) {
|
||||
mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
|
||||
mb2 := &BalanceFilter{Weight: utils.Float64Pointer(1), RatingSubject: nil, DestinationIds: nil}
|
||||
mb2 := &BalanceFilter{Weight: utils.Float64Pointer(1), RatingSubject: nil, DestinationIDs: nil}
|
||||
if !mb1.MatchFilter(mb2, false) {
|
||||
t.Errorf("Match filter failure: %+v == %+v", mb1, mb2)
|
||||
}
|
||||
@@ -106,7 +106,7 @@ func TestBalanceMatchFilterEmpty(t *testing.T) {
|
||||
|
||||
func TestBalanceMatchFilterId(t *testing.T) {
|
||||
mb1 := &Balance{Id: "T1", Weight: 2, precision: 2, RatingSubject: "2", DestinationIds: utils.NewStringMap("NAT")}
|
||||
mb2 := &BalanceFilter{Id: utils.StringPointer("T1"), Weight: utils.Float64Pointer(1), RatingSubject: utils.StringPointer("1"), DestinationIds: nil}
|
||||
mb2 := &BalanceFilter{ID: utils.StringPointer("T1"), Weight: utils.Float64Pointer(1), RatingSubject: utils.StringPointer("1"), DestinationIDs: nil}
|
||||
if !mb1.MatchFilter(mb2, false) {
|
||||
t.Errorf("Match filter failure: %+v == %+v", mb1, mb2)
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func TestBalanceMatchFilterId(t *testing.T) {
|
||||
|
||||
func TestBalanceMatchFilterDiffId(t *testing.T) {
|
||||
mb1 := &Balance{Id: "T1", Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
|
||||
mb2 := &BalanceFilter{Id: utils.StringPointer("T2"), Weight: utils.Float64Pointer(1), RatingSubject: utils.StringPointer("1"), DestinationIds: nil}
|
||||
mb2 := &BalanceFilter{ID: utils.StringPointer("T2"), Weight: utils.Float64Pointer(1), RatingSubject: utils.StringPointer("1"), DestinationIDs: nil}
|
||||
if mb1.MatchFilter(mb2, false) {
|
||||
t.Errorf("Match filter failure: %+v != %+v", mb1, mb2)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func TestBalanceClone(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBalanceMatchActionTriggerId(t *testing.T) {
|
||||
at := &ActionTrigger{Balance: &BalanceFilter{Id: utils.StringPointer("test")}}
|
||||
at := &ActionTrigger{Balance: &BalanceFilter{ID: utils.StringPointer("test")}}
|
||||
b := &Balance{Id: "test"}
|
||||
if !b.MatchActionTrigger(at) {
|
||||
t.Errorf("Error matching action trigger: %+v %+v", b, at)
|
||||
@@ -143,14 +143,14 @@ func TestBalanceMatchActionTriggerId(t *testing.T) {
|
||||
t.Errorf("Error matching action trigger: %+v %+v", b, at)
|
||||
}
|
||||
b.Id = "test"
|
||||
at.Balance.Id = nil
|
||||
at.Balance.ID = nil
|
||||
if !b.MatchActionTrigger(at) {
|
||||
t.Errorf("Error matching action trigger: %+v %+v", b, at)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBalanceMatchActionTriggerDestination(t *testing.T) {
|
||||
at := &ActionTrigger{Balance: &BalanceFilter{DestinationIds: utils.StringMapPointer(utils.NewStringMap("test"))}}
|
||||
at := &ActionTrigger{Balance: &BalanceFilter{DestinationIDs: utils.StringMapPointer(utils.NewStringMap("test"))}}
|
||||
b := &Balance{DestinationIds: utils.NewStringMap("test")}
|
||||
if !b.MatchActionTrigger(at) {
|
||||
t.Errorf("Error matching action trigger: %+v %+v", b, at)
|
||||
@@ -164,7 +164,7 @@ func TestBalanceMatchActionTriggerDestination(t *testing.T) {
|
||||
t.Errorf("Error matching action trigger: %+v %+v", b, at)
|
||||
}
|
||||
b.DestinationIds = utils.NewStringMap("test")
|
||||
at.Balance.DestinationIds = nil
|
||||
at.Balance.DestinationIDs = nil
|
||||
if !b.MatchActionTrigger(at) {
|
||||
t.Errorf("Error matching action trigger: %+v %+v", b, at)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/cache2go"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -180,3 +181,40 @@ func (cc *CallCost) updateCost() {
|
||||
}
|
||||
cc.Cost = cost
|
||||
}
|
||||
|
||||
func (cc *CallCost) MatchCCFilter(bf *BalanceFilter) bool {
|
||||
if bf == nil {
|
||||
return true
|
||||
}
|
||||
if bf.Categories != nil && cc.Category != "" && (*bf.Categories)[cc.Category] == false {
|
||||
return false
|
||||
}
|
||||
if bf.Directions != nil && cc.Direction != "" && (*bf.Directions)[cc.Direction] == false {
|
||||
return false
|
||||
}
|
||||
|
||||
// match destination ids
|
||||
foundMatchingDestID := false
|
||||
if bf.DestinationIDs != nil && cc.Destination != "" {
|
||||
for _, p := range utils.SplitPrefix(cc.Destination, MIN_PREFIX_MATCH) {
|
||||
if x, err := cache2go.Get(utils.DESTINATION_PREFIX + p); err == nil {
|
||||
destIds := x.(map[interface{}]struct{})
|
||||
for filterDestID := range *bf.DestinationIDs {
|
||||
if _, ok := destIds[filterDestID]; ok {
|
||||
foundMatchingDestID = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if foundMatchingDestID {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foundMatchingDestID = true
|
||||
}
|
||||
if !foundMatchingDestID {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func init() {
|
||||
func populateDB() {
|
||||
ats := []*Action{
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10)}},
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Weight: utils.Float64Pointer(20), Value: utils.Float64Pointer(10), DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT"))}},
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Weight: utils.Float64Pointer(20), Value: utils.Float64Pointer(10), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT"))}},
|
||||
}
|
||||
|
||||
ats1 := []*Action{
|
||||
|
||||
@@ -832,10 +832,12 @@ func TestLoadActions(t *testing.T) {
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
Value: utils.Float64Pointer(10),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
DestinationIds: nil,
|
||||
DestinationIDs: nil,
|
||||
TimingIDs: nil,
|
||||
SharedGroups: nil,
|
||||
Categories: nil,
|
||||
Disabled: utils.BoolPointer(false),
|
||||
Blocker: utils.BoolPointer(false),
|
||||
},
|
||||
},
|
||||
&Action{
|
||||
@@ -851,10 +853,12 @@ func TestLoadActions(t *testing.T) {
|
||||
Value: utils.Float64Pointer(100),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
RatingSubject: utils.StringPointer("test"),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
TimingIDs: nil,
|
||||
SharedGroups: nil,
|
||||
Categories: nil,
|
||||
Disabled: utils.BoolPointer(false),
|
||||
Blocker: utils.BoolPointer(false),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -871,13 +875,15 @@ func TestLoadActions(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
DestinationIds: nil,
|
||||
DestinationIDs: nil,
|
||||
Uuid: as2[0].Balance.Uuid,
|
||||
Value: utils.Float64Pointer(100),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
SharedGroups: utils.StringMapPointer(utils.NewStringMap("SG1")),
|
||||
TimingIDs: nil,
|
||||
Categories: nil,
|
||||
Disabled: utils.BoolPointer(false),
|
||||
Blocker: utils.BoolPointer(false),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -894,11 +900,12 @@ func TestLoadActions(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
Uuid: as3[0].Balance.Uuid,
|
||||
Directions: nil,
|
||||
DestinationIds: nil,
|
||||
DestinationIDs: nil,
|
||||
TimingIDs: nil,
|
||||
Categories: nil,
|
||||
SharedGroups: nil,
|
||||
Blocker: utils.BoolPointer(false),
|
||||
Disabled: utils.BoolPointer(false),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1048,19 +1055,22 @@ func TestLoadActionTriggers(t *testing.T) {
|
||||
ThresholdType: utils.TRIGGER_MIN_EVENT_COUNTER,
|
||||
ThresholdValue: 10,
|
||||
Balance: &BalanceFilter{
|
||||
ID: utils.StringPointer("st0"),
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("GERMANY_O2")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("GERMANY_O2")),
|
||||
Categories: nil,
|
||||
TimingIDs: nil,
|
||||
SharedGroups: nil,
|
||||
Disabled: nil,
|
||||
Blocker: nil,
|
||||
},
|
||||
Weight: 10,
|
||||
ActionsId: "SOME_1",
|
||||
Executed: false,
|
||||
}
|
||||
if !reflect.DeepEqual(atr, expected) {
|
||||
t.Errorf("Error loading action trigger: %+v", atr)
|
||||
t.Errorf("Error loading action trigger: %+v", utils.ToIJSON(atr.Balance))
|
||||
}
|
||||
atr = csvr.actionsTriggers["STANDARD_TRIGGER"][1]
|
||||
expected = &ActionTrigger{
|
||||
@@ -1071,7 +1081,7 @@ func TestLoadActionTriggers(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("GERMANY")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("GERMANY")),
|
||||
Categories: nil,
|
||||
TimingIDs: nil,
|
||||
SharedGroups: nil,
|
||||
@@ -1093,18 +1103,22 @@ func TestLoadAccountActions(t *testing.T) {
|
||||
expected := &Account{
|
||||
Id: "vdf:minitsboy",
|
||||
UnitCounters: UnitCounters{
|
||||
&UnitCounter{
|
||||
BalanceType: "*voice",
|
||||
CounterType: "*event",
|
||||
Balances: BalanceChain{
|
||||
&Balance{
|
||||
Id: "2c2ce3c9-d62b-49dc-82a5-2a17bdc6eb4e",
|
||||
Value: 0,
|
||||
Directions: utils.NewStringMap("*out"),
|
||||
DestinationIds: utils.NewStringMap("GERMANY_O2"),
|
||||
SharedGroups: nil,
|
||||
Categories: nil,
|
||||
TimingIDs: nil,
|
||||
utils.VOICE: []*UnitCounter{
|
||||
&UnitCounter{
|
||||
CounterType: "*event",
|
||||
Counters: CounterFilters{
|
||||
&CounterFilter{
|
||||
Value: 0,
|
||||
Filter: &BalanceFilter{
|
||||
ID: utils.StringPointer("st0"),
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap("*out")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("GERMANY_O2")),
|
||||
SharedGroups: nil,
|
||||
Categories: nil,
|
||||
TimingIDs: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1115,11 +1129,11 @@ func TestLoadAccountActions(t *testing.T) {
|
||||
for i, atr := range aa.ActionTriggers {
|
||||
csvr.actionsTriggers["STANDARD_TRIGGER"][i].ID = atr.ID
|
||||
}
|
||||
for i, b := range aa.UnitCounters[0].Balances {
|
||||
expected.UnitCounters[0].Balances[i].Id = b.Id
|
||||
for i, b := range aa.UnitCounters[utils.VOICE][0].Counters {
|
||||
expected.UnitCounters[utils.VOICE][0].Counters[i].Filter.ID = b.Filter.ID
|
||||
}
|
||||
if !reflect.DeepEqual(aa.UnitCounters[0].Balances[0], expected.UnitCounters[0].Balances[0]) {
|
||||
t.Errorf("Error loading account action: %+v \n %+v", aa.UnitCounters[0].Balances[0], expected.UnitCounters[0].Balances[0])
|
||||
if !reflect.DeepEqual(aa.UnitCounters[utils.VOICE][0].Counters[0], expected.UnitCounters[utils.VOICE][0].Counters[0]) {
|
||||
t.Errorf("Error loading account action: %+v", utils.ToIJSON(aa.UnitCounters[utils.VOICE][0].Counters[0].Filter))
|
||||
}
|
||||
// test that it does not overwrite balances
|
||||
existing, err := accountingStorage.GetAccount(aa.Id)
|
||||
|
||||
@@ -265,8 +265,8 @@ func TestTPActionsAsExportSlice(t *testing.T) {
|
||||
},
|
||||
}
|
||||
expectedSlc := [][]string{
|
||||
[]string{"TEST_ACTIONS", "*topup_reset", "", "", "", "*monetary", utils.OUT, "call", "*any", "special1", "GROUP1", "*never", "", "5", "10", "false", "false", "10"},
|
||||
[]string{"TEST_ACTIONS", "*http_post", "http://localhost/¶m1=value1", "", "", "", "", "", "", "", "", "", "", "0", "0", "false", "false", "20"},
|
||||
[]string{"TEST_ACTIONS", "*topup_reset", "", "", "", "*monetary", utils.OUT, "call", "*any", "special1", "GROUP1", "*never", "", "5.0", "10.0", "", "", "10"},
|
||||
[]string{"TEST_ACTIONS", "*http_post", "http://localhost/¶m1=value1", "", "", "", "", "", "", "", "", "", "", "0.0", "0.0", "", "", "20"},
|
||||
}
|
||||
|
||||
ms := APItoModelAction(tpActs)
|
||||
@@ -597,8 +597,8 @@ func TestTPActionPlanAsExportSlice(t *testing.T) {
|
||||
},
|
||||
}
|
||||
expectedSlc := [][]string{
|
||||
[]string{"STANDARD_TRIGGERS", "1", "*min_balance", "2", "false", "0", "", "", "b1", "*monetary", "*out", "call", "", "special1", "SHARED_1", "*never", "T1", "0", "false", "false", "0", "LOG_WARNING", "10"},
|
||||
[]string{"STANDARD_TRIGGERS", "2", "*max_event_counter", "5", "false", "0", "", "", "b2", "*monetary", "*out", "call", "FS_USERS", "special1", "SHARED_1", "*never", "T1", "0", "false", "false", "0", "LOG_WARNING", "10"},
|
||||
[]string{"STANDARD_TRIGGERS", "1", "*min_balance", "2", "false", "0", "", "", "b1", "*monetary", "*out", "call", "", "special1", "SHARED_1", "*never", "T1", "0.0", "false", "false", "0", "LOG_WARNING", "10"},
|
||||
[]string{"STANDARD_TRIGGERS", "2", "*max_event_counter", "5", "false", "0", "", "", "b2", "*monetary", "*out", "call", "FS_USERS", "special1", "SHARED_1", "*never", "T1", "0.0", "false", "false", "0", "LOG_WARNING", "10"},
|
||||
}
|
||||
ms := APItoModelActionTrigger(at)
|
||||
var slc [][]string
|
||||
|
||||
@@ -311,8 +311,7 @@ func TestStorageTask(t *testing.T) {
|
||||
|
||||
func GetUB() *Account {
|
||||
uc := &UnitCounter{
|
||||
BalanceType: utils.SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}},
|
||||
Counters: CounterFilters{&CounterFilter{Value: 1}, &CounterFilter{Filter: &BalanceFilter{Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT"))}}, &CounterFilter{Filter: &BalanceFilter{Weight: utils.Float64Pointer(10), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET"))}}},
|
||||
}
|
||||
at := &ActionTrigger{
|
||||
ID: "some_uuid",
|
||||
@@ -320,7 +319,7 @@ func GetUB() *Account {
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
},
|
||||
Weight: 10.0,
|
||||
ActionsId: "Commando",
|
||||
@@ -331,7 +330,7 @@ func GetUB() *Account {
|
||||
Id: "rif",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{utils.SMS: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, utils.DATA: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}, utils.VOICE: BalanceChain{&Balance{Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
|
||||
UnitCounters: UnitCounters{uc, uc},
|
||||
UnitCounters: UnitCounters{utils.SMS: []*UnitCounter{uc, uc}},
|
||||
ActionTriggers: ActionTriggers{at, at, at},
|
||||
}
|
||||
return ub
|
||||
|
||||
@@ -524,7 +524,7 @@ func (tpr *TpReader) LoadActions() (err error) {
|
||||
Balance: &BalanceFilter{},
|
||||
}
|
||||
if tpact.BalanceId != "" && tpact.BalanceId != utils.ANY {
|
||||
acts[idx].Balance.Id = utils.StringPointer(tpact.BalanceId)
|
||||
acts[idx].Balance.ID = utils.StringPointer(tpact.BalanceId)
|
||||
}
|
||||
if tpact.BalanceType != "" && tpact.BalanceType != utils.ANY {
|
||||
acts[idx].Balance.Type = utils.StringPointer(tpact.BalanceType)
|
||||
@@ -563,7 +563,7 @@ func (tpr *TpReader) LoadActions() (err error) {
|
||||
acts[idx].Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(tpact.Directions))
|
||||
}
|
||||
if tpact.DestinationIds != "" && tpact.DestinationIds != utils.ANY {
|
||||
acts[idx].Balance.DestinationIds = utils.StringMapPointer(utils.ParseStringMap(tpact.DestinationIds))
|
||||
acts[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(tpact.DestinationIds))
|
||||
}
|
||||
if tpact.SharedGroups != "" && tpact.SharedGroups != utils.ANY {
|
||||
acts[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(tpact.SharedGroups))
|
||||
@@ -706,7 +706,7 @@ func (tpr *TpReader) LoadActionTriggers() (err error) {
|
||||
MinQueuedItems: atr.MinQueuedItems,
|
||||
}
|
||||
if atr.BalanceId != "" && atr.BalanceId != utils.ANY {
|
||||
atrs[idx].Balance.Id = utils.StringPointer(atr.BalanceId)
|
||||
atrs[idx].Balance.ID = utils.StringPointer(atr.BalanceId)
|
||||
}
|
||||
|
||||
if atr.BalanceType != "" && atr.BalanceType != utils.ANY {
|
||||
@@ -738,7 +738,7 @@ func (tpr *TpReader) LoadActionTriggers() (err error) {
|
||||
atrs[idx].Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDirections))
|
||||
}
|
||||
if atr.BalanceDestinationIds != "" && atr.BalanceDestinationIds != utils.ANY {
|
||||
atrs[idx].Balance.DestinationIds = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDestinationIds))
|
||||
atrs[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDestinationIds))
|
||||
}
|
||||
if atr.BalanceSharedGroups != "" && atr.BalanceSharedGroups != utils.ANY {
|
||||
atrs[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceSharedGroups))
|
||||
@@ -906,7 +906,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
|
||||
ActionsId: atr.ActionsId,
|
||||
}
|
||||
if atr.BalanceId != "" && atr.BalanceId != utils.ANY {
|
||||
atrs[idx].Balance.Id = utils.StringPointer(atr.BalanceId)
|
||||
atrs[idx].Balance.ID = utils.StringPointer(atr.BalanceId)
|
||||
}
|
||||
|
||||
if atr.BalanceType != "" && atr.BalanceType != utils.ANY {
|
||||
@@ -938,7 +938,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
|
||||
atrs[idx].Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDirections))
|
||||
}
|
||||
if atr.BalanceDestinationIds != "" && atr.BalanceDestinationIds != utils.ANY {
|
||||
atrs[idx].Balance.DestinationIds = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDestinationIds))
|
||||
atrs[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDestinationIds))
|
||||
}
|
||||
if atr.BalanceSharedGroups != "" && atr.BalanceSharedGroups != utils.ANY {
|
||||
atrs[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceSharedGroups))
|
||||
@@ -1006,7 +1006,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
|
||||
Balance: &BalanceFilter{},
|
||||
}
|
||||
if tpact.BalanceId != "" && tpact.BalanceId != utils.ANY {
|
||||
acts[idx].Balance.Id = utils.StringPointer(tpact.BalanceId)
|
||||
acts[idx].Balance.ID = utils.StringPointer(tpact.BalanceId)
|
||||
}
|
||||
if tpact.BalanceType != "" && tpact.BalanceType != utils.ANY {
|
||||
acts[idx].Balance.Type = utils.StringPointer(tpact.BalanceType)
|
||||
@@ -1038,7 +1038,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
|
||||
acts[idx].Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(tpact.Directions))
|
||||
}
|
||||
if tpact.DestinationIds != "" && tpact.DestinationIds != utils.ANY {
|
||||
acts[idx].Balance.DestinationIds = utils.StringMapPointer(utils.ParseStringMap(tpact.DestinationIds))
|
||||
acts[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(tpact.DestinationIds))
|
||||
}
|
||||
if tpact.SharedGroups != "" && tpact.SharedGroups != utils.ANY {
|
||||
acts[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(tpact.SharedGroups))
|
||||
@@ -1243,7 +1243,7 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
|
||||
ActionsId: atr.ActionsId,
|
||||
}
|
||||
if atr.BalanceId != "" && atr.BalanceId != utils.ANY {
|
||||
atrs[idx].Balance.Id = utils.StringPointer(atr.BalanceId)
|
||||
atrs[idx].Balance.ID = utils.StringPointer(atr.BalanceId)
|
||||
}
|
||||
|
||||
if atr.BalanceType != "" && atr.BalanceType != utils.ANY {
|
||||
@@ -1275,7 +1275,7 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
|
||||
atrs[idx].Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDirections))
|
||||
}
|
||||
if atr.BalanceDestinationIds != "" && atr.BalanceDestinationIds != utils.ANY {
|
||||
atrs[idx].Balance.DestinationIds = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDestinationIds))
|
||||
atrs[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDestinationIds))
|
||||
}
|
||||
if atr.BalanceSharedGroups != "" && atr.BalanceSharedGroups != utils.ANY {
|
||||
atrs[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceSharedGroups))
|
||||
@@ -1352,7 +1352,7 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
|
||||
Balance: &BalanceFilter{},
|
||||
}
|
||||
if tpact.BalanceId != "" && tpact.BalanceId != utils.ANY {
|
||||
acts[idx].Balance.Id = utils.StringPointer(tpact.BalanceId)
|
||||
acts[idx].Balance.ID = utils.StringPointer(tpact.BalanceId)
|
||||
}
|
||||
if tpact.BalanceType != "" && tpact.BalanceType != utils.ANY {
|
||||
acts[idx].Balance.Type = utils.StringPointer(tpact.BalanceType)
|
||||
@@ -1384,7 +1384,7 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
|
||||
acts[idx].Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(tpact.Directions))
|
||||
}
|
||||
if tpact.DestinationIds != "" && tpact.DestinationIds != utils.ANY {
|
||||
acts[idx].Balance.DestinationIds = utils.StringMapPointer(utils.ParseStringMap(tpact.DestinationIds))
|
||||
acts[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(tpact.DestinationIds))
|
||||
}
|
||||
if tpact.SharedGroups != "" && tpact.SharedGroups != utils.ANY {
|
||||
acts[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(tpact.SharedGroups))
|
||||
|
||||
@@ -18,29 +18,40 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
import "github.com/cgrates/cgrates/utils"
|
||||
|
||||
// Amount of a trafic of a certain type
|
||||
type UnitCounter struct {
|
||||
BalanceType string // *monetary/*voice/*sms/etc
|
||||
CounterType string // *event or *balance
|
||||
Balances BalanceChain // first balance is the general one (no destination)
|
||||
CounterType string // *event or *balance
|
||||
Counters CounterFilters // first balance is the general one (no destination)
|
||||
}
|
||||
|
||||
type CounterFilter struct {
|
||||
Value float64
|
||||
Filter *BalanceFilter
|
||||
}
|
||||
|
||||
type CounterFilters []*CounterFilter
|
||||
|
||||
func (cfs CounterFilters) HasCounter(cf *CounterFilter) bool {
|
||||
for _, c := range cfs {
|
||||
if c.Filter.Equal(cf.Filter) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Returns true if the counters were of the same type
|
||||
// Copies the value from old balances
|
||||
func (uc *UnitCounter) CopyCounterValues(oldUc *UnitCounter) bool {
|
||||
if uc.BalanceType+uc.CounterType != oldUc.BalanceType+oldUc.CounterType { // type check
|
||||
if uc.CounterType != oldUc.CounterType { // type check
|
||||
return false
|
||||
}
|
||||
for _, b := range uc.Balances {
|
||||
for _, oldB := range oldUc.Balances {
|
||||
if b.Equal(oldB) {
|
||||
b.Value = oldB.Value
|
||||
for _, c := range uc.Counters {
|
||||
for _, oldC := range oldUc.Counters {
|
||||
if c.Filter.Equal(oldC.Filter) {
|
||||
c.Value = oldC.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -48,30 +59,28 @@ func (uc *UnitCounter) CopyCounterValues(oldUc *UnitCounter) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type UnitCounters []*UnitCounter
|
||||
type UnitCounters map[string][]*UnitCounter
|
||||
|
||||
func (ucs UnitCounters) addUnits(amount float64, kind string, cc *CallCost, b *Balance) {
|
||||
for _, uc := range ucs {
|
||||
counters, found := ucs[kind]
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
for _, uc := range counters {
|
||||
if uc == nil { // safeguard
|
||||
continue
|
||||
}
|
||||
if uc.BalanceType != kind {
|
||||
continue
|
||||
}
|
||||
if uc.CounterType == "" {
|
||||
uc.CounterType = utils.COUNTER_EVENT
|
||||
}
|
||||
for _, bal := range uc.Balances {
|
||||
log.Print(b)
|
||||
if uc.CounterType == utils.COUNTER_EVENT && cc != nil && bal.MatchCCFilter(cc) {
|
||||
log.Print("HERE")
|
||||
bal.AddValue(amount)
|
||||
for _, c := range uc.Counters {
|
||||
if uc.CounterType == utils.COUNTER_EVENT && cc != nil && cc.MatchCCFilter(c.Filter) {
|
||||
c.Value += amount
|
||||
continue
|
||||
}
|
||||
bp := &BalanceFilter{}
|
||||
bp.LoadFromBalance(bal)
|
||||
if uc.CounterType == utils.COUNTER_BALANCE && b != nil && b.MatchFilter(bp, true) {
|
||||
bal.AddValue(amount)
|
||||
|
||||
if uc.CounterType == utils.COUNTER_BALANCE && b != nil && b.MatchFilter(c.Filter, true) {
|
||||
c.Value += amount
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -80,16 +89,18 @@ func (ucs UnitCounters) addUnits(amount float64, kind string, cc *CallCost, b *B
|
||||
}
|
||||
|
||||
func (ucs UnitCounters) resetCounters(a *Action) {
|
||||
for _, uc := range ucs {
|
||||
if uc == nil { // safeguard
|
||||
for key, counters := range ucs {
|
||||
if a != nil && a.Balance.Type != nil && a.Balance.GetType() != key {
|
||||
continue
|
||||
}
|
||||
if a != nil && a.Balance.Type != nil && a.Balance.GetType() != uc.BalanceType {
|
||||
continue
|
||||
}
|
||||
for _, b := range uc.Balances {
|
||||
if a == nil || a.Balance == nil || b.MatchFilter(a.Balance, false) {
|
||||
b.Value = 0
|
||||
for _, c := range counters {
|
||||
if c == nil { // safeguard
|
||||
continue
|
||||
}
|
||||
for _, cf := range c.Counters {
|
||||
if a == nil || a.Balance == nil || cf.Filter.Equal(a.Balance) {
|
||||
cf.Value = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,22 +26,20 @@ import (
|
||||
|
||||
func TestUnitsCounterAddBalance(t *testing.T) {
|
||||
uc := &UnitCounter{
|
||||
BalanceType: utils.SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}},
|
||||
Counters: CounterFilters{&CounterFilter{Value: 1}, &CounterFilter{Filter: &BalanceFilter{Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT"))}}, &CounterFilter{Filter: &BalanceFilter{Weight: utils.Float64Pointer(10), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET"))}}},
|
||||
}
|
||||
UnitCounters{uc}.addUnits(20, utils.SMS, &CallCost{Destination: "test"}, nil)
|
||||
if len(uc.Balances) != 3 {
|
||||
t.Error("Error adding minute bucket: ", uc.Balances)
|
||||
UnitCounters{utils.SMS: []*UnitCounter{uc}}.addUnits(20, utils.SMS, &CallCost{Destination: "test"}, nil)
|
||||
if len(uc.Counters) != 3 {
|
||||
t.Error("Error adding minute bucket: ", uc.Counters)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnitsCounterAddBalanceExists(t *testing.T) {
|
||||
uc := &UnitCounter{
|
||||
BalanceType: utils.SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}},
|
||||
Counters: CounterFilters{&CounterFilter{Value: 1}, &CounterFilter{Value: 10, Filter: &BalanceFilter{Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT"))}}, &CounterFilter{Filter: &BalanceFilter{Weight: utils.Float64Pointer(10), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET"))}}},
|
||||
}
|
||||
UnitCounters{uc}.addUnits(5, utils.SMS, &CallCost{Destination: "0723"}, nil)
|
||||
if len(uc.Balances) != 3 || uc.Balances[1].GetValue() != 15 {
|
||||
UnitCounters{utils.SMS: []*UnitCounter{uc}}.addUnits(5, utils.SMS, &CallCost{Destination: "0723"}, nil)
|
||||
if len(uc.Counters) != 3 || uc.Counters[1].Value != 15 {
|
||||
t.Error("Error adding minute bucket!")
|
||||
}
|
||||
}
|
||||
@@ -108,14 +106,17 @@ func TestUnitCountersCountAllMonetary(t *testing.T) {
|
||||
a.InitCounters()
|
||||
a.UnitCounters.addUnits(10, utils.MONETARY, &CallCost{}, nil)
|
||||
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[0].Balances) != 2 ||
|
||||
a.UnitCounters[0].Balances[0].Value != 10 ||
|
||||
a.UnitCounters[0].Balances[1].Value != 10 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.MONETARY][0].Counters) != 2 ||
|
||||
a.UnitCounters[utils.MONETARY][0].Counters[0].Value != 10 ||
|
||||
a.UnitCounters[utils.MONETARY][0].Counters[1].Value != 10 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Counters {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error Initializing adding unit counters: %v", len(a.UnitCounters))
|
||||
@@ -183,15 +184,17 @@ func TestUnitCountersCountAllMonetaryId(t *testing.T) {
|
||||
}
|
||||
a.InitCounters()
|
||||
a.UnitCounters.addUnits(10, utils.MONETARY, nil, &Balance{Weight: 20, Directions: utils.NewStringMap(utils.OUT)})
|
||||
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[0].Balances) != 2 ||
|
||||
a.UnitCounters[0].Balances[0].Value != 0 ||
|
||||
a.UnitCounters[0].Balances[1].Value != 10 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.MONETARY][0].Counters) != 2 ||
|
||||
a.UnitCounters[utils.MONETARY][0].Counters[0].Value != 0 ||
|
||||
a.UnitCounters[utils.MONETARY][0].Counters[1].Value != 10 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Counters {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error adding unit counters: %v", len(a.UnitCounters))
|
||||
@@ -225,7 +228,7 @@ func TestUnitCountersCountAllVoiceDestinationEvent(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
},
|
||||
},
|
||||
@@ -234,7 +237,7 @@ func TestUnitCountersCountAllVoiceDestinationEvent(t *testing.T) {
|
||||
ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
},
|
||||
},
|
||||
@@ -270,14 +273,17 @@ func TestUnitCountersCountAllVoiceDestinationEvent(t *testing.T) {
|
||||
a.InitCounters()
|
||||
a.UnitCounters.addUnits(10, utils.VOICE, &CallCost{Destination: "0723045326"}, nil)
|
||||
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[1].Balances) != 2 ||
|
||||
a.UnitCounters[1].Balances[0].Value != 10 ||
|
||||
a.UnitCounters[1].Balances[1].Value != 10 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.VOICE][0].Counters) != 2 ||
|
||||
a.UnitCounters[utils.VOICE][0].Counters[0].Value != 10 ||
|
||||
a.UnitCounters[utils.VOICE][0].Counters[1].Value != 10 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Counters {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error adding unit counters: %v", len(a.UnitCounters))
|
||||
@@ -311,7 +317,7 @@ func TestUnitCountersKeepValuesAfterInit(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
},
|
||||
},
|
||||
@@ -320,7 +326,7 @@ func TestUnitCountersKeepValuesAfterInit(t *testing.T) {
|
||||
ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
DestinationIds: utils.StringMapPointer(utils.NewStringMap("RET")),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")),
|
||||
Weight: utils.Float64Pointer(10),
|
||||
},
|
||||
},
|
||||
@@ -356,28 +362,34 @@ func TestUnitCountersKeepValuesAfterInit(t *testing.T) {
|
||||
a.InitCounters()
|
||||
a.UnitCounters.addUnits(10, utils.VOICE, &CallCost{Destination: "0723045326"}, nil)
|
||||
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[1].Balances) != 2 ||
|
||||
a.UnitCounters[1].Balances[0].Value != 10 ||
|
||||
a.UnitCounters[1].Balances[1].Value != 10 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.VOICE][0].Counters) != 2 ||
|
||||
a.UnitCounters[utils.VOICE][0].Counters[0].Value != 10 ||
|
||||
a.UnitCounters[utils.VOICE][0].Counters[1].Value != 10 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Counters {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error adding unit counters: %v", len(a.UnitCounters))
|
||||
}
|
||||
a.InitCounters()
|
||||
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[1].Balances) != 2 ||
|
||||
a.UnitCounters[1].Balances[0].Value != 10 ||
|
||||
a.UnitCounters[1].Balances[1].Value != 10 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.VOICE][0].Counters) != 2 ||
|
||||
a.UnitCounters[utils.VOICE][0].Counters[0].Value != 10 ||
|
||||
a.UnitCounters[utils.VOICE][0].Counters[1].Value != 10 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Counters {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error keeping counter values after init: %v", len(a.UnitCounters))
|
||||
@@ -446,14 +458,17 @@ func TestUnitCountersResetCounterById(t *testing.T) {
|
||||
a.InitCounters()
|
||||
a.UnitCounters.addUnits(10, utils.MONETARY, &CallCost{}, nil)
|
||||
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[0].Balances) != 2 ||
|
||||
a.UnitCounters[0].Balances[0].Value != 10 ||
|
||||
a.UnitCounters[0].Balances[1].Value != 10 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.MONETARY][0].Counters) != 2 ||
|
||||
a.UnitCounters[utils.MONETARY][0].Counters[0].Value != 10 ||
|
||||
a.UnitCounters[utils.MONETARY][0].Counters[1].Value != 10 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Counters {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error Initializing adding unit counters: %v", len(a.UnitCounters))
|
||||
@@ -461,17 +476,20 @@ func TestUnitCountersResetCounterById(t *testing.T) {
|
||||
a.UnitCounters.resetCounters(&Action{
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Id: utils.StringPointer("TestTR11"),
|
||||
ID: utils.StringPointer("TestTR11"),
|
||||
},
|
||||
})
|
||||
if len(a.UnitCounters) != 4 ||
|
||||
len(a.UnitCounters[0].Balances) != 2 ||
|
||||
a.UnitCounters[0].Balances[0].Value != 10 ||
|
||||
a.UnitCounters[0].Balances[1].Value != 0 {
|
||||
for _, uc := range a.UnitCounters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
if len(a.UnitCounters) != 3 ||
|
||||
len(a.UnitCounters[utils.MONETARY][0].Counters) != 2 ||
|
||||
a.UnitCounters[utils.MONETARY][0].Counters[0].Value != 10 ||
|
||||
a.UnitCounters[utils.MONETARY][0].Counters[1].Value != 0 {
|
||||
for key, counters := range a.UnitCounters {
|
||||
t.Log(key)
|
||||
for _, uc := range counters {
|
||||
t.Logf("UC: %+v", uc)
|
||||
for _, b := range uc.Counters {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Errorf("Error Initializing adding unit counters: %v", len(a.UnitCounters))
|
||||
|
||||
Reference in New Issue
Block a user