diff --git a/apier/v1/accounts.go b/apier/v1/accounts.go
index 4331f4c24..14768acfb 100644
--- a/apier/v1/accounts.go
+++ b/apier/v1/accounts.go
@@ -188,6 +188,7 @@ func (self *ApierV1) SetAccount(attr utils.AttrSetAccount, reply *string) error
return 0, err
}
ub.ActionTriggers = atrs
+ ub.InitCounters()
}
if attr.AllowNegative != nil {
ub.AllowNegative = *attr.AllowNegative
diff --git a/engine/account.go b/engine/account.go
index 90b7ce49b..4ed5f534a 100644
--- a/engine/account.go
+++ b/engine/account.go
@@ -22,7 +22,6 @@ import (
"encoding/json"
"errors"
"fmt"
- "log"
"time"
"github.com/cgrates/cgrates/cache2go"
@@ -117,7 +116,7 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error {
continue // just to be safe (cleaned expired balances above)
}
b.account = ub
- if b.MatchFilter(a.Balance) {
+ if b.MatchFilter(a.Balance, false) {
if reset {
b.SetValue(0)
}
@@ -185,7 +184,7 @@ func (ub *Account) enableDisableBalanceAction(a *Action) error {
id := a.BalanceType
ub.CleanExpiredBalances()
for _, b := range ub.BalanceMap[id] {
- if b.MatchFilter(a.Balance) {
+ if b.MatchFilter(a.Balance, false) {
b.Disabled = a.Balance.Disabled
b.dirty = true
found = true
@@ -500,7 +499,6 @@ func (ub *Account) executeActionTriggers(a *Action) {
uc.CounterType == counter {
for _, mb := range uc.Balances {
if limit == "*max" {
- log.Print("HERE: ", mb.MatchActionTrigger(at))
if mb.MatchActionTrigger(at) && mb.GetValue() >= at.ThresholdValue {
// run the actions
at.Execute(ub, nil)
@@ -537,19 +535,19 @@ func (ub *Account) executeActionTriggers(a *Action) {
// Mark all action trigers as ready for execution
// If the action is not nil it acts like a filter
-func (ub *Account) ResetActionTriggers(a *Action) {
- for _, at := range ub.ActionTriggers {
+func (acc *Account) ResetActionTriggers(a *Action) {
+ for _, at := range acc.ActionTriggers {
if !at.Match(a) {
continue
}
at.Executed = false
}
- ub.executeActionTriggers(a)
+ acc.executeActionTriggers(a)
}
// Sets/Unsets recurrent flag for action triggers
-func (ub *Account) SetRecurrent(a *Action, recurrent bool) {
- for _, at := range ub.ActionTriggers {
+func (acc *Account) SetRecurrent(a *Action, recurrent bool) {
+ for _, at := range acc.ActionTriggers {
if !at.Match(a) {
continue
}
@@ -558,49 +556,51 @@ func (ub *Account) SetRecurrent(a *Action, recurrent bool) {
}
// Increments the counter for the type
-func (ub *Account) countUnits(amount float64, kind string, cc *CallCost, b *Balance) {
- ub.UnitCounters.addUnits(amount, kind, cc, b)
- ub.executeActionTriggers(nil)
+func (acc *Account) countUnits(amount float64, kind string, cc *CallCost, b *Balance) {
+ acc.UnitCounters.addUnits(amount, kind, cc, b)
+ acc.executeActionTriggers(nil)
}
-// Create counters for all triggered actions that have actions opertating on balances
-func (acc *Account) initCounters() {
- ucTempMap := make(map[string]*UnitsCounter)
- // add default balance
+// Create counters for all triggered actions
+func (acc *Account) InitCounters() {
+ acc.UnitCounters = make(UnitCounters, 0)
+ ucTempMap := make(map[string]*UnitCounter)
for _, at := range acc.ActionTriggers {
if !strings.Contains(at.ThresholdType, "counter") {
- // only get actions for counter type action triggers
continue
}
- uc, exists := ucTempMap[at.BalanceType]
+ _, ct, _ := at.GetThresholdTypeInfo()
+ uc, exists := ucTempMap[at.BalanceType+ct]
if !exists {
- _, ct, _ := at.GetThresholdTypeInfo()
- uc = &UnitsCounter{
+ uc = &UnitCounter{
BalanceType: at.BalanceType,
CounterType: ct,
}
- ucTempMap[at.BalanceType] = uc
+ ucTempMap[at.BalanceType+ct] = uc
uc.Balances = BalanceChain{}
acc.UnitCounters = append(acc.UnitCounters, uc)
}
- uc.Balances = append(uc.Balances, at.CreateBalance())
+ b := at.CreateBalance()
+ if !uc.Balances.HasBalance(b) {
+ uc.Balances = append(uc.Balances, b)
+ }
}
}
-func (ub *Account) CleanExpiredBalances() {
- for key, bm := range ub.BalanceMap {
+func (acc *Account) CleanExpiredBalances() {
+ for key, bm := range acc.BalanceMap {
for i := 0; i < len(bm); i++ {
if bm[i].IsExpired() {
// delete it
bm = append(bm[:i], bm[i+1:]...)
}
}
- ub.BalanceMap[key] = bm
+ acc.BalanceMap[key] = bm
}
}
-func (ub *Account) allBalancesExpired() bool {
- for _, bm := range ub.BalanceMap {
+func (acc *Account) allBalancesExpired() bool {
+ for _, bm := range acc.BalanceMap {
for i := 0; i < len(bm); i++ {
if !bm[i].IsExpired() {
return false
@@ -611,8 +611,8 @@ func (ub *Account) allBalancesExpired() bool {
}
// returns the shared groups that this user balance belnongs to
-func (ub *Account) GetSharedGroups() (groups []string) {
- for _, balanceChain := range ub.BalanceMap {
+func (acc *Account) GetSharedGroups() (groups []string) {
+ for _, balanceChain := range acc.BalanceMap {
for _, b := range balanceChain {
for sg := range b.SharedGroups {
groups = append(groups, sg)
diff --git a/engine/account_test.go b/engine/account_test.go
index 4712b5a69..e579232c8 100644
--- a/engine/account_test.go
+++ b/engine/account_test.go
@@ -19,7 +19,6 @@ along with this program. If not, see
package engine
import (
- "log"
"testing"
"time"
@@ -889,12 +888,10 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.StringMap{utils.OUT: true}}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.StringMap{utils.OUT: true}}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.StringMap{utils.OUT: true}, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_EVENT_COUNTER, ActionsId: "TEST_ACTIONS"}},
}
- log.Print("==============")
ub.countUnits(1, utils.MONETARY, &CallCost{Direction: utils.OUT}, nil)
- log.Print("==============")
if ub.BalanceMap[utils.MONETARY][0].GetValue() != 110 || ub.BalanceMap[utils.VOICE][0].GetValue() != 20 {
t.Error("Error executing triggered actions", ub.BalanceMap[utils.MONETARY][0].GetValue(), ub.BalanceMap[utils.VOICE][0].GetValue())
}
@@ -915,7 +912,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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Directions: utils.NewStringMap(utils.OUT), Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 100, ThresholdType: TRIGGER_MIN_EVENT_COUNTER, ActionsId: "TEST_ACTIONS"}},
}
ub.countUnits(1, utils.MONETARY, nil, nil)
@@ -928,10 +925,11 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_EVENT_COUNTER, ActionsId: "TEST_ACTIONS_ORDER"}},
}
- ub.countUnits(1, utils.MONETARY, nil, nil)
+
+ 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])
@@ -959,45 +957,45 @@ func TestCleanExpired(t *testing.T) {
}
func TestAccountUnitCounting(t *testing.T) {
- ub := &Account{}
- ub.countUnits(10, utils.MONETARY, nil, nil)
+ ub := &Account{UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{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 {
t.Error("Error counting units")
}
- ub.countUnits(10, utils.MONETARY, nil, nil)
+ 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 {
t.Error("Error counting units")
}
}
func TestAccountUnitCountingOutbound(t *testing.T) {
- ub := &Account{}
- ub.countUnits(10, utils.MONETARY, nil, nil)
+ ub := &Account{UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 0, Directions: 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.Error("Error counting units")
}
- ub.countUnits(10, utils.MONETARY, nil, nil)
+ 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 {
t.Error("Error counting units")
}
- ub.countUnits(10, utils.MONETARY, nil, nil)
+ 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 {
t.Error("Error counting units")
}
}
func TestAccountUnitCountingOutboundInbound(t *testing.T) {
- ub := &Account{}
- ub.countUnits(1, utils.MONETARY, nil, nil)
+ ub := &Account{UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 0, Directions: 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])
+ t.Errorf("Error counting units: %+v", ub.UnitCounters[0].Balances[0])
}
- ub.countUnits(10, utils.MONETARY, nil, nil)
+ 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 {
t.Error("Error counting units")
}
- ub.countUnits(10, utils.MONETARY, nil, nil)
- if len(ub.UnitCounters) != 1 || (ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 30) { // for the moment no in/out distinction
+ 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) {
t.Error("Error counting units")
}
}
@@ -1439,6 +1437,133 @@ func TestAccountGetDefaultMoneyBalance(t *testing.T) {
}
}
+func TestAccountInitCounters(t *testing.T) {
+ a := &Account{
+ ActionTriggers: ActionTriggers{
+ &ActionTrigger{
+ Id: "TestTR1",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR11",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR2",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR3",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR4",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR5",
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ },
+ }
+ 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)
+ }
+ }
+ t.Errorf("Error Initializing unit counters: %v", len(a.UnitCounters))
+ }
+}
+
+func TestAccountDoubleInitCounters(t *testing.T) {
+ a := &Account{
+ ActionTriggers: ActionTriggers{
+ &ActionTrigger{
+ Id: "TestTR1",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR11",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR2",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR3",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR4",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR5",
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ },
+ }
+ 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)
+ }
+ }
+ t.Errorf("Error Initializing unit counters: %v", len(a.UnitCounters))
+ }
+}
+
/*********************************** Benchmarks *******************************/
func BenchmarkGetSecondForPrefix(b *testing.B) {
diff --git a/engine/action.go b/engine/action.go
index 619af3fbc..f7be99cde 100644
--- a/engine/action.go
+++ b/engine/action.go
@@ -60,7 +60,6 @@ const (
TOPUP = "*topup"
DEBIT_RESET = "*debit_reset"
DEBIT = "*debit"
- RESET_COUNTER = "*reset_counter"
RESET_COUNTERS = "*reset_counters"
ENABLE_ACCOUNT = "*enable_account"
DISABLE_ACCOUNT = "*disable_account"
@@ -112,8 +111,6 @@ func getActionFunc(typ string) (actionTypeFunc, bool) {
return debitResetAction, true
case DEBIT:
return debitAction, true
- case RESET_COUNTER:
- return resetCounterAction, true
case RESET_COUNTERS:
return resetCountersAction, true
case ENABLE_ACCOUNT:
@@ -354,26 +351,11 @@ func debitAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (
return
}
-func resetCounterAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) {
- if ub == nil {
- return errors.New("nil user balance")
- }
- //uc := ub.getUnitCounter(a.ActionType)
- var uc *UnitsCounter
- if uc == nil {
- uc = &UnitsCounter{BalanceType: a.BalanceType}
- ub.UnitCounters = append(ub.UnitCounters, uc)
- }
- uc.initBalances(ub.ActionTriggers)
- return
-}
-
func resetCountersAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) {
if ub == nil {
return errors.New("nil user balance")
}
- ub.UnitCounters = make([]*UnitsCounter, 0)
- ub.initCounters()
+ ub.UnitCounters.resetCounters(a)
return
}
@@ -422,7 +404,7 @@ func genericReset(ub *Account) error {
for k, _ := range ub.BalanceMap {
ub.BalanceMap[k] = BalanceChain{&Balance{Value: 0}}
}
- ub.UnitCounters = make([]*UnitsCounter, 0)
+ ub.UnitCounters = make(UnitCounters, 0)
ub.ResetActionTriggers(nil)
return nil
}
diff --git a/engine/action_trigger.go b/engine/action_trigger.go
index 54f225d6b..7ab63c864 100644
--- a/engine/action_trigger.go
+++ b/engine/action_trigger.go
@@ -157,6 +157,7 @@ func (at *ActionTrigger) Clone() *ActionTrigger {
func (at *ActionTrigger) CreateBalance() *Balance {
return &Balance{
+ Id: at.Id,
Directions: at.BalanceDirections,
ExpirationDate: at.BalanceExpirationDate,
DestinationIds: at.BalanceDestinationIds,
diff --git a/engine/actions_test.go b/engine/actions_test.go
index 28c15dcf8..320977ae3 100644
--- a/engine/actions_test.go
+++ b/engine/actions_test.go
@@ -649,7 +649,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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
resetTriggersAction(ub, nil, nil, nil)
@@ -662,7 +662,7 @@ func TestActionResetTriggresExecutesThem(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 10}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
resetTriggersAction(ub, nil, nil, nil)
@@ -675,7 +675,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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
resetTriggersAction(ub, nil, &Action{BalanceType: utils.SMS}, nil)
@@ -688,7 +688,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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
allowNegativeAction(ub, nil, nil, nil)
@@ -702,7 +702,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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
denyNegativeAction(ub, nil, nil, nil)
@@ -716,7 +716,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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
resetAccountAction(ub, nil, nil, nil)
@@ -734,7 +734,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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
resetAccountAction(ub, nil, nil, nil)
@@ -750,7 +750,7 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
a := &Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}}
@@ -827,7 +827,7 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
a := &Action{BalanceType: utils.VOICE, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}}
@@ -846,7 +846,7 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
a := &Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}}
@@ -864,7 +864,7 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
a := &Action{BalanceType: utils.VOICE, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}}
@@ -883,7 +883,7 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
a := &Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}}
@@ -901,7 +901,7 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
+ UnitCounters: UnitCounters{&UnitCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
a := &Action{BalanceType: utils.VOICE, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}}
@@ -925,22 +925,23 @@ func TestActionResetAllCounters(t *testing.T) {
utils.VOICE: BalanceChain{
&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)}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{ThresholdType: "*max_counter", BalanceType: utils.MONETARY, ThresholdValue: 2, BalanceDestinationIds: utils.NewStringMap("NAT"), BalanceWeight: 20, ActionsId: "TEST_ACTIONS", Executed: true}},
+
+ ActionTriggers: ActionTriggers{&ActionTrigger{ThresholdType: TRIGGER_MAX_EVENT_COUNTER, BalanceType: utils.MONETARY, ThresholdValue: 2, BalanceDestinationIds: utils.NewStringMap("NAT"), BalanceWeight: 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) != 2 ||
+ len(ub.UnitCounters[0].Balances) != 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)
+ t.Errorf("Reset counters action failed: %+v %+v %+v", ub.UnitCounters, ub.UnitCounters[0], ub.UnitCounters[0].Balances[0])
}
if len(ub.UnitCounters) < 1 {
t.FailNow()
}
- mb := ub.UnitCounters[0].Balances[1]
+ mb := ub.UnitCounters[0].Balances[0]
if mb.Weight != 20 || mb.GetValue() != 0 || mb.DestinationIds["NAT"] == false {
t.Errorf("Balance cloned incorrectly: %+v", mb)
}
@@ -953,11 +954,11 @@ func TestActionResetCounterOnlyDefault(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")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdType: "*max_counter", ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
+ ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdType: TRIGGER_MAX_EVENT_COUNTER, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
a := &Action{BalanceType: utils.MONETARY}
- resetCounterAction(ub, nil, a, nil)
+ ub.InitCounters()
+ resetCountersAction(ub, nil, a, nil)
if !ub.AllowNegative ||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
len(ub.UnitCounters) != 1 ||
@@ -973,7 +974,7 @@ func TestActionResetCounterOnlyDefault(t *testing.T) {
t.FailNow()
}
mb := ub.UnitCounters[0].Balances[0]
- if mb.Weight != 0 || mb.GetValue() != 0 || mb.DestinationIds[utils.ANY] != true {
+ if mb.Weight != 0 || mb.GetValue() != 0 || len(mb.DestinationIds) != 0 {
t.Errorf("Balance cloned incorrectly: %+v!", mb)
}
}
@@ -983,11 +984,11 @@ 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: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}, &UnitsCounter{BalanceType: utils.SMS, Balances: BalanceChain{&Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}}}},
+ 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)}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
a := &Action{BalanceType: utils.MONETARY}
- resetCounterAction(ub, nil, a, nil)
+ resetCountersAction(ub, nil, a, nil)
if !ub.AllowNegative ||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
len(ub.UnitCounters) != 2 ||
diff --git a/engine/balances.go b/engine/balances.go
index a93b2e87e..4f9d055f1 100644
--- a/engine/balances.go
+++ b/engine/balances.go
@@ -70,11 +70,11 @@ func (b *Balance) Equal(o *Balance) bool {
b.Disabled == o.Disabled
}
-func (b *Balance) MatchFilter(o *Balance) bool {
- if o.Uuid != "" {
+func (b *Balance) MatchFilter(o *Balance, skipIds bool) bool {
+ if !skipIds && o.Uuid != "" {
return b.Uuid == o.Uuid
}
- if o.Id != "" {
+ if !skipIds && o.Id != "" {
return b.Id == o.Id
}
if len(b.DestinationIds) == 0 {
diff --git a/engine/balances_test.go b/engine/balances_test.go
index 608db65ba..163ab79ec 100644
--- a/engine/balances_test.go
+++ b/engine/balances_test.go
@@ -91,7 +91,7 @@ func TestBalanceEqual(t *testing.T) {
func TestBalanceMatchFilter(t *testing.T) {
mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
mb2 := &Balance{Weight: 1, precision: 1, RatingSubject: "", DestinationIds: utils.StringMap{}}
- if !mb1.MatchFilter(mb2) {
+ if !mb1.MatchFilter(mb2, false) {
t.Errorf("Match filter failure: %+v == %+v", mb1, mb2)
}
}
@@ -99,7 +99,7 @@ func TestBalanceMatchFilter(t *testing.T) {
func TestBalanceMatchFilterEmpty(t *testing.T) {
mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
mb2 := &Balance{}
- if !mb1.MatchFilter(mb2) {
+ if !mb1.MatchFilter(mb2, false) {
t.Errorf("Match filter failure: %+v == %+v", mb1, mb2)
}
}
@@ -107,7 +107,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 := &Balance{Id: "T1", Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
- if !mb1.MatchFilter(mb2) {
+ if !mb1.MatchFilter(mb2, false) {
t.Errorf("Match filter failure: %+v == %+v", mb1, mb2)
}
}
@@ -115,7 +115,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 := &Balance{Id: "T2", Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
- if mb1.MatchFilter(mb2) {
+ if mb1.MatchFilter(mb2, false) {
t.Errorf("Match filter failure: %+v != %+v", mb1, mb2)
}
}
diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go
index 9ec034544..dd01947a9 100644
--- a/engine/loader_csv_test.go
+++ b/engine/loader_csv_test.go
@@ -183,9 +183,9 @@ POST_AT,NEG,*asap,10
actionTriggers = `
STANDARD_TRIGGER,st0,*min_event_counter,10,false,0,,*voice,*out,,GERMANY_O2,,,,,,,,SOME_1,10
-STANDARD_TRIGGER,st1,*max_event_balance,200,false,0,,*voice,*out,,GERMANY,,,,,,,,SOME_2,10
-STANDARD_TRIGGERS,,*min_event_balance,2,false,0,,*monetary,*out,,,,,,,,,,LOG_WARNING,10
-STANDARD_TRIGGERS,,*max_event_balance,20,false,0,,*monetary,*out,,,,,,,,,,LOG_WARNING,10
+STANDARD_TRIGGER,st1,*max_balance,200,false,0,,*voice,*out,,GERMANY,,,,,,,,SOME_2,10
+STANDARD_TRIGGERS,,*min_balance,2,false,0,,*monetary,*out,,,,,,,,,,LOG_WARNING,10
+STANDARD_TRIGGERS,,*max_balance,20,false,0,,*monetary,*out,,,,,,,,,,LOG_WARNING,10
STANDARD_TRIGGERS,,*max_event_counter,5,false,0,,*monetary,*out,,FS_USERS,,,,,,,,LOG_WARNING,10
CDRST1_WARN_ASR,,*min_asr,45,true,1h,,,,,,,,,,,,3,CDRST_WARN_HTTP,10
CDRST1_WARN_ACD,,*min_acd,10,true,1h,,,,,,,,,,,,5,CDRST_WARN_HTTP,10
diff --git a/engine/storage_test.go b/engine/storage_test.go
index 3332cec8b..306c9289b 100644
--- a/engine/storage_test.go
+++ b/engine/storage_test.go
@@ -275,7 +275,7 @@ func TestDifferentUuid(t *testing.T) {
/************************** Benchmarks *****************************/
func GetUB() *Account {
- uc := &UnitsCounter{
+ uc := &UnitCounter{
BalanceType: utils.SMS,
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}},
}
@@ -294,7 +294,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: []*UnitsCounter{uc, uc},
+ UnitCounters: UnitCounters{uc, uc},
ActionTriggers: ActionTriggers{at, at, at},
}
return ub
diff --git a/engine/tp_reader.go b/engine/tp_reader.go
index 75165cd84..3c2ef32fe 100644
--- a/engine/tp_reader.go
+++ b/engine/tp_reader.go
@@ -517,8 +517,8 @@ func (tpr *TpReader) LoadActions() (err error) {
Categories: utils.ParseStringMap(tpact.Categories),
Directions: utils.ParseStringMap(tpact.Directions),
DestinationIds: utils.ParseStringMap(tpact.DestinationIds),
- SharedGroups: utils.ParseStringMap(tpact.SharedGroups),
- TimingIDs: utils.ParseStringMap(tpact.TimingTags),
+ SharedGroups: utils.ParseStringMap(tpact.SharedGroups),
+ TimingIDs: utils.ParseStringMap(tpact.TimingTags),
},
}
// load action timings from tags
@@ -624,7 +624,7 @@ func (tpr *TpReader) LoadActionTriggers() (err error) {
BalanceTimingTags: utils.ParseStringMap(atr.BalanceTimingTags),
BalanceRatingSubject: atr.BalanceRatingSubject,
BalanceCategories: utils.ParseStringMap(atr.BalanceCategories),
- BalanceSharedGroups: utils.ParseStringMap(atr.BalanceSharedGroups),
+ BalanceSharedGroups: utils.ParseStringMap(atr.BalanceSharedGroups),
Weight: atr.Weight,
ActionsId: atr.ActionsId,
MinQueuedItems: atr.MinQueuedItems,
@@ -762,7 +762,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
BalanceExpirationDate: expTime,
BalanceRatingSubject: apiAtr.BalanceRatingSubject,
BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories),
- BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups),
+ BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups),
Weight: apiAtr.Weight,
ActionsId: apiAtr.ActionsId,
}
@@ -808,8 +808,8 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
RatingSubject: tpact.RatingSubject,
Directions: utils.ParseStringMap(tpact.Directions),
DestinationIds: utils.ParseStringMap(tpact.DestinationIds),
- SharedGroups: utils.ParseStringMap(tpact.SharedGroups),
- TimingIDs: utils.ParseStringMap(tpact.TimingTags),
+ SharedGroups: utils.ParseStringMap(tpact.SharedGroups),
+ TimingIDs: utils.ParseStringMap(tpact.TimingTags),
},
}
}
@@ -830,7 +830,8 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
}
}
ub.ActionTriggers = actionTriggers.Clone()
-
+ // init counters
+ ub.InitCounters()
if err := tpr.accountingStorage.SetAccount(ub); err != nil {
return err
}
@@ -966,8 +967,8 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
BalanceExpirationDate: expTime,
BalanceRatingSubject: apiAtr.BalanceRatingSubject,
BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories),
- BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups),
- BalanceTimingTags: utils.ParseStringMap(apiAtr.BalanceTimingTags),
+ BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups),
+ BalanceTimingTags: utils.ParseStringMap(apiAtr.BalanceTimingTags),
Weight: apiAtr.Weight,
ActionsId: apiAtr.ActionsId,
}
@@ -1022,8 +1023,8 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
RatingSubject: tpact.RatingSubject,
Directions: utils.ParseStringMap(tpact.Directions),
DestinationIds: utils.ParseStringMap(tpact.DestinationIds),
- SharedGroups: utils.ParseStringMap(tpact.SharedGroups),
- TimingIDs: utils.ParseStringMap(tpact.TimingTags),
+ SharedGroups: utils.ParseStringMap(tpact.SharedGroups),
+ TimingIDs: utils.ParseStringMap(tpact.TimingTags),
},
}
}
diff --git a/engine/units_counter.go b/engine/units_counter.go
index 2cc4b9304..b07065eed 100644
--- a/engine/units_counter.go
+++ b/engine/units_counter.go
@@ -18,35 +18,16 @@ along with this program. If not, see
package engine
-import (
- "log"
- "strings"
-
- "github.com/cgrates/cgrates/utils"
-)
+import "github.com/cgrates/cgrates/utils"
// Amount of a trafic of a certain type
-type UnitsCounter struct {
+type UnitCounter struct {
BalanceType string // *monetary/*voice/*sms/etc
CounterType string // *event or *balance
Balances BalanceChain // first balance is the general one (no destination)
}
-// clears balances for this counter
-// makes sure there are balances for all action triggers
-func (uc *UnitsCounter) initBalances(ats []*ActionTrigger) {
- uc.Balances = BalanceChain{}
- for _, at := range ats {
- if !strings.Contains(at.ThresholdType, "counter") ||
- at.BalanceType != uc.BalanceType {
- // only get actions for counter type action triggers and with the same type
- continue
- }
- uc.Balances = append(uc.Balances, at.CreateBalance())
- }
-}
-
-type UnitCounters []*UnitsCounter
+type UnitCounters []*UnitCounter
func (ucs UnitCounters) addUnits(amount float64, kind string, cc *CallCost, b *Balance) {
for _, uc := range ucs {
@@ -58,11 +39,10 @@ func (ucs UnitCounters) addUnits(amount float64, kind string, cc *CallCost, b *B
}
for _, bal := range uc.Balances {
if uc.CounterType == utils.COUNTER_EVENT && cc != nil && bal.MatchCCFilter(cc) {
- log.Print("MATCHCC")
bal.AddValue(amount)
continue
}
- if uc.CounterType == utils.COUNTER_BALANCE && b != nil && b.MatchFilter(bal) {
+ if uc.CounterType == utils.COUNTER_BALANCE && b != nil && b.MatchFilter(bal, true) {
bal.AddValue(amount)
continue
}
@@ -70,3 +50,16 @@ func (ucs UnitCounters) addUnits(amount float64, kind string, cc *CallCost, b *B
}
}
+
+func (ucs UnitCounters) resetCounters(a *Action) {
+ for _, uc := range ucs {
+ if a != nil && a.BalanceType != "" && a.BalanceType != uc.BalanceType {
+ continue
+ }
+ for _, b := range uc.Balances {
+ if a == nil || a.Balance == nil || b.MatchFilter(a.Balance, false) {
+ b.Value = 0
+ }
+ }
+ }
+}
diff --git a/engine/units_counter_test.go b/engine/units_counter_test.go
index 48ff87578..a8ec56785 100644
--- a/engine/units_counter_test.go
+++ b/engine/units_counter_test.go
@@ -25,7 +25,7 @@ import (
)
func TestUnitsCounterAddBalance(t *testing.T) {
- uc := &UnitsCounter{
+ uc := &UnitCounter{
BalanceType: utils.SMS,
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}},
}
@@ -36,7 +36,7 @@ func TestUnitsCounterAddBalance(t *testing.T) {
}
func TestUnitsCounterAddBalanceExists(t *testing.T) {
- uc := &UnitsCounter{
+ 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")}},
}
@@ -45,3 +45,203 @@ func TestUnitsCounterAddBalanceExists(t *testing.T) {
t.Error("Error adding minute bucket!")
}
}
+
+func TestUnitCountersCountAllMonetary(t *testing.T) {
+ a := &Account{
+ ActionTriggers: ActionTriggers{
+ &ActionTrigger{
+ Id: "TestTR1",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR11",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR2",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR3",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR4",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR5",
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT, utils.IN),
+ BalanceWeight: 10,
+ },
+ },
+ }
+ 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)
+ }
+ }
+ t.Errorf("Error Initializing adding unit counters: %v", len(a.UnitCounters))
+ }
+}
+
+func TestUnitCountersCountAllMonetaryId(t *testing.T) {
+ a := &Account{
+ ActionTriggers: ActionTriggers{
+ &ActionTrigger{
+ Id: "TestTR1",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR11",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 20,
+ },
+ &ActionTrigger{
+ Id: "TestTR2",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR3",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR4",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR5",
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ },
+ }
+ 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)
+ }
+ }
+ t.Errorf("Error adding unit counters: %v", len(a.UnitCounters))
+ }
+}
+
+func TestUnitCountersCountAllVoiceDestinationEvent(t *testing.T) {
+ a := &Account{
+ ActionTriggers: ActionTriggers{
+ &ActionTrigger{
+ Id: "TestTR1",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR11",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.MONETARY,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 20,
+ },
+ &ActionTrigger{
+ Id: "TestTR2",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceDestinationIds: utils.NewStringMap("NAT"),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR22",
+ ThresholdType: TRIGGER_MAX_EVENT_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDestinationIds: utils.NewStringMap("RET"),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR3",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.VOICE,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR4",
+ ThresholdType: TRIGGER_MAX_BALANCE_COUNTER,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ &ActionTrigger{
+ Id: "TestTR5",
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ BalanceType: utils.SMS,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceWeight: 10,
+ },
+ },
+ }
+ 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)
+ }
+ }
+ t.Errorf("Error adding unit counters: %v", len(a.UnitCounters))
+ }
+}