diff --git a/apier/v1/accounts.go b/apier/v1/accounts.go
index 2b18af8d0..4331f4c24 100644
--- a/apier/v1/accounts.go
+++ b/apier/v1/accounts.go
@@ -52,7 +52,7 @@ func (self *ApierV1) GetAccountActionPlan(attrs AttrAcntAction, reply *[]*Accoun
}
for _, ats := range allATs {
for _, at := range ats {
- if utils.IsSliceMember(at.AccountIds, utils.AccountKey(attrs.Tenant, attrs.Account, attrs.Direction)) {
+ if utils.IsSliceMember(at.AccountIds, utils.AccountKey(attrs.Tenant, attrs.Account)) {
accountATs = append(accountATs, &AccountActionTiming{Uuid: at.Uuid, ActionPlanId: at.Id, ActionsId: at.ActionsId, NextExecTime: at.GetNextStartTime(time.Now())})
}
}
@@ -87,7 +87,7 @@ func (self *ApierV1) RemActionTiming(attrs AttrRemActionTiming, reply *string) e
} else if len(ats) == 0 {
return 0, utils.ErrNotFound
}
- ats = engine.RemActionPlan(ats, attrs.ActionTimingId, utils.AccountKey(attrs.Tenant, attrs.Account, attrs.Direction))
+ ats = engine.RemActionPlan(ats, attrs.ActionTimingId, utils.AccountKey(attrs.Tenant, attrs.Account))
if err := self.RatingDb.SetActionPlans(attrs.ActionPlanId, ats); err != nil {
return 0, err
}
@@ -109,7 +109,7 @@ func (self *ApierV1) GetAccountActionTriggers(attrs AttrAcntAction, reply *engin
if missing := utils.MissingStructFields(&attrs, []string{"Tenant", "Account", "Direction"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
- if balance, err := self.AccountDb.GetAccount(utils.AccountKey(attrs.Tenant, attrs.Account, attrs.Direction)); err != nil {
+ if balance, err := self.AccountDb.GetAccount(utils.AccountKey(attrs.Tenant, attrs.Account)); err != nil {
return utils.NewErrServerError(err)
} else {
*reply = balance.ActionTriggers
@@ -129,7 +129,7 @@ func (self *ApierV1) RemAccountActionTriggers(attrs AttrRemAcntActionTriggers, r
if missing := utils.MissingStructFields(&attrs, []string{"Tenant", "Account", "Direction"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
- balanceId := utils.AccountKey(attrs.Tenant, attrs.Account, attrs.Direction)
+ balanceId := utils.AccountKey(attrs.Tenant, attrs.Account)
_, err := engine.Guardian.Guard(func() (interface{}, error) {
ub, err := self.AccountDb.GetAccount(balanceId)
if err != nil {
@@ -160,7 +160,7 @@ func (self *ApierV1) SetAccount(attr utils.AttrSetAccount, reply *string) error
if missing := utils.MissingStructFields(&attr, []string{"Tenant", "Direction", "Account"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
- balanceId := utils.AccountKey(attr.Tenant, attr.Account, attr.Direction)
+ balanceId := utils.AccountKey(attr.Tenant, attr.Account)
var ub *engine.Account
var ats engine.ActionPlans
_, err := engine.Guardian.Guard(func() (interface{}, error) {
@@ -227,7 +227,7 @@ func (self *ApierV1) RemoveAccount(attr utils.AttrRemoveAccount, reply *string)
if missing := utils.MissingStructFields(&attr, []string{"Tenant", "Direction", "Account"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
- accountId := utils.AccountKey(attr.Tenant, attr.Account, attr.Direction)
+ accountId := utils.AccountKey(attr.Tenant, attr.Account)
_, err := engine.Guardian.Guard(func() (interface{}, error) {
if err := self.AccountDb.RemoveAccount(accountId); err != nil {
return 0, err
@@ -242,17 +242,14 @@ func (self *ApierV1) RemoveAccount(attr utils.AttrRemoveAccount, reply *string)
return nil
}
-func (self *ApierV1) GetAccounts(attr utils.AttrGetAccounts, reply *[]*engine.Account) error {
+func (self *ApierV1) GetAccounts(attr utils.AttrGetAccounts, reply *[]interface{}) error {
if len(attr.Tenant) == 0 {
return utils.NewErrMandatoryIeMissing("Tenanat")
}
- if len(attr.Direction) == 0 {
- attr.Direction = utils.OUT
- }
var accountKeys []string
var err error
if len(attr.AccountIds) == 0 {
- if accountKeys, err = self.AccountDb.GetKeysForPrefix(utils.ACCOUNT_PREFIX + utils.ConcatenatedKey(attr.Direction, attr.Tenant)); err != nil {
+ if accountKeys, err = self.AccountDb.GetKeysForPrefix(utils.ACCOUNT_PREFIX + utils.ConcatenatedKey(attr.Tenant)); err != nil {
return err
}
} else {
@@ -260,7 +257,7 @@ func (self *ApierV1) GetAccounts(attr utils.AttrGetAccounts, reply *[]*engine.Ac
if len(acntId) == 0 { // Source of error returned from redis (key not found)
continue
}
- accountKeys = append(accountKeys, utils.ACCOUNT_PREFIX+utils.ConcatenatedKey(attr.Direction, attr.Tenant, acntId))
+ accountKeys = append(accountKeys, utils.ACCOUNT_PREFIX+utils.ConcatenatedKey(attr.Tenant, acntId))
}
}
if len(accountKeys) == 0 {
@@ -273,12 +270,12 @@ func (self *ApierV1) GetAccounts(attr utils.AttrGetAccounts, reply *[]*engine.Ac
} else {
limitedAccounts = accountKeys[attr.Offset:]
}
- retAccounts := make([]*engine.Account, 0)
+ retAccounts := make([]interface{}, 0)
for _, acntKey := range limitedAccounts {
if acnt, err := self.AccountDb.GetAccount(acntKey[len(utils.ACCOUNT_PREFIX):]); err != nil && err != utils.ErrNotFound { // Not found is not an error here
return err
} else if acnt != nil {
- retAccounts = append(retAccounts, acnt)
+ retAccounts = append(retAccounts, acnt.AsOldStructure())
}
}
*reply = retAccounts
diff --git a/apier/v1/accounts_test.go b/apier/v1/accounts_test.go
index 474588c90..51a5ce573 100644
--- a/apier/v1/accounts_test.go
+++ b/apier/v1/accounts_test.go
@@ -41,15 +41,15 @@ func TestSetAccounts(t *testing.T) {
cgrTenant := "cgrates.org"
iscTenant := "itsyscom.com"
b10 := &engine.Balance{Value: 10, Weight: 10}
- cgrAcnt1 := &engine.Account{Id: utils.ConcatenatedKey(utils.OUT, cgrTenant, "account1"),
+ cgrAcnt1 := &engine.Account{Id: utils.ConcatenatedKey(cgrTenant, "account1"),
BalanceMap: map[string]engine.BalanceChain{utils.MONETARY + utils.OUT: engine.BalanceChain{b10}}}
- cgrAcnt2 := &engine.Account{Id: utils.ConcatenatedKey(utils.OUT, cgrTenant, "account2"),
+ cgrAcnt2 := &engine.Account{Id: utils.ConcatenatedKey(cgrTenant, "account2"),
BalanceMap: map[string]engine.BalanceChain{utils.MONETARY + utils.OUT: engine.BalanceChain{b10}}}
- cgrAcnt3 := &engine.Account{Id: utils.ConcatenatedKey(utils.OUT, cgrTenant, "account3"),
+ cgrAcnt3 := &engine.Account{Id: utils.ConcatenatedKey(cgrTenant, "account3"),
BalanceMap: map[string]engine.BalanceChain{utils.MONETARY + utils.OUT: engine.BalanceChain{b10}}}
- iscAcnt1 := &engine.Account{Id: utils.ConcatenatedKey(utils.OUT, iscTenant, "account1"),
+ iscAcnt1 := &engine.Account{Id: utils.ConcatenatedKey(iscTenant, "account1"),
BalanceMap: map[string]engine.BalanceChain{utils.MONETARY + utils.OUT: engine.BalanceChain{b10}}}
- iscAcnt2 := &engine.Account{Id: utils.ConcatenatedKey(utils.OUT, iscTenant, "account2"),
+ iscAcnt2 := &engine.Account{Id: utils.ConcatenatedKey(iscTenant, "account2"),
BalanceMap: map[string]engine.BalanceChain{utils.MONETARY + utils.OUT: engine.BalanceChain{b10}}}
for _, account := range []*engine.Account{cgrAcnt1, cgrAcnt2, cgrAcnt3, iscAcnt1, iscAcnt2} {
if err := apierAcntsAcntStorage.SetAccount(account); err != nil {
@@ -72,7 +72,7 @@ func TestGetAccountIds(t *testing.T) {
*/
func TestGetAccounts(t *testing.T) {
- var accounts []*engine.Account
+ var accounts []interface{}
var attrs utils.AttrGetAccounts
if err := apierAcnts.GetAccounts(utils.AttrGetAccounts{Tenant: "cgrates.org"}, &accounts); err != nil {
t.Error("Unexpected error", err.Error())
diff --git a/apier/v1/apier.go b/apier/v1/apier.go
index 34b196e65..123f24b57 100644
--- a/apier/v1/apier.go
+++ b/apier/v1/apier.go
@@ -104,7 +104,7 @@ func (self *ApierV1) GetRatingPlan(rplnId string, reply *engine.RatingPlan) erro
// Get balance
func (self *ApierV1) GetAccount(attr *utils.AttrGetAccount, reply *engine.Account) error {
- tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
+ tag := fmt.Sprintf("%s:%s", attr.Tenant, attr.Account)
userBalance, err := self.AccountDb.GetAccount(tag)
if err != nil {
return err
@@ -115,20 +115,20 @@ func (self *ApierV1) GetAccount(attr *utils.AttrGetAccount, reply *engine.Accoun
}
type AttrAddBalance struct {
- Tenant string
- Account string
- BalanceUuid string
- BalanceId string
- BalanceType string
- Direction string
- Value float64
- ExpiryTime string
- RatingSubject string
- DestinationId string
- Weight float64
- SharedGroup string
- Overwrite bool // When true it will reset if the balance is already there
- Disabled bool
+ Tenant string
+ Account string
+ BalanceUuid string
+ BalanceId string
+ BalanceType string
+ Directions string
+ Value float64
+ ExpiryTime string
+ RatingSubject string
+ DestinationIds string
+ Weight float64
+ SharedGroups string
+ Overwrite bool // When true it will reset if the balance is already there
+ Disabled bool
}
func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error {
@@ -137,7 +137,7 @@ func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error {
*reply = err.Error()
return err
}
- tag := utils.ConcatenatedKey(attr.Direction, attr.Tenant, attr.Account)
+ tag := utils.ConcatenatedKey(attr.Tenant, attr.Account)
if _, err := self.AccountDb.GetAccount(tag); err != nil {
// create user balance if not exists
account := &engine.Account{
@@ -151,9 +151,6 @@ func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error {
at := &engine.ActionPlan{
AccountIds: []string{tag},
}
- if attr.Direction == "" {
- attr.Direction = utils.OUT
- }
aType := engine.DEBIT
// reverse the sign as it is a debit
attr.Value = -attr.Value
@@ -165,16 +162,16 @@ func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error {
&engine.Action{
ActionType: aType,
BalanceType: attr.BalanceType,
- Direction: attr.Direction,
Balance: &engine.Balance{
Uuid: attr.BalanceUuid,
Id: attr.BalanceId,
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
- DestinationIds: attr.DestinationId,
+ Directions: utils.ParseStringMap(attr.Directions),
+ DestinationIds: utils.ParseStringMap(attr.DestinationIds),
Weight: attr.Weight,
- SharedGroup: attr.SharedGroup,
+ SharedGroups: utils.ParseStringMap(attr.SharedGroups),
Disabled: attr.Disabled,
},
},
@@ -193,30 +190,27 @@ func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) e
*reply = err.Error()
return err
}
- tag := utils.ConcatenatedKey(attr.Direction, attr.Tenant, attr.Account)
+ tag := utils.ConcatenatedKey(attr.Tenant, attr.Account)
if _, err := self.AccountDb.GetAccount(tag); err != nil {
return utils.ErrNotFound
}
at := &engine.ActionPlan{
AccountIds: []string{tag},
}
- if attr.Direction == "" {
- attr.Direction = utils.OUT
- }
at.SetActions(engine.Actions{
&engine.Action{
ActionType: engine.ENABLE_DISABLE_BALANCE,
BalanceType: attr.BalanceType,
- Direction: attr.Direction,
Balance: &engine.Balance{
Uuid: attr.BalanceUuid,
Id: attr.BalanceId,
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
- DestinationIds: attr.DestinationId,
+ Directions: utils.ParseStringMap(attr.Directions),
+ DestinationIds: utils.ParseStringMap(attr.DestinationIds),
Weight: attr.Weight,
- SharedGroup: attr.SharedGroup,
+ SharedGroups: utils.ParseStringMap(attr.SharedGroups),
Disabled: attr.Disabled,
},
},
@@ -230,7 +224,7 @@ func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) e
}
func (self *ApierV1) ExecuteAction(attr *utils.AttrExecuteAction, reply *string) error {
- tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
+ tag := fmt.Sprintf("%s:%s", attr.Tenant, attr.Account)
at := &engine.ActionPlan{
AccountIds: []string{tag},
ActionsId: attr.ActionsId,
@@ -616,7 +610,6 @@ func (self *ApierV1) SetActions(attrs utils.AttrSetActions, reply *string) error
Id: utils.GenUUID(),
ActionType: apiAct.Identifier,
BalanceType: apiAct.BalanceType,
- Direction: apiAct.Direction,
Weight: apiAct.Weight,
ExpirationString: apiAct.ExpiryTime,
ExtraParameters: apiAct.ExtraParameters,
@@ -625,9 +618,10 @@ func (self *ApierV1) SetActions(attrs utils.AttrSetActions, reply *string) error
Id: apiAct.BalanceId,
Value: apiAct.Units,
Weight: apiAct.BalanceWeight,
- DestinationIds: apiAct.DestinationIds,
+ Directions: utils.ParseStringMap(apiAct.Directions),
+ DestinationIds: utils.ParseStringMap(apiAct.DestinationIds),
RatingSubject: apiAct.RatingSubject,
- SharedGroup: apiAct.SharedGroup,
+ SharedGroups: utils.ParseStringMap(apiAct.SharedGroups),
},
}
storeActions[idx] = a
@@ -653,16 +647,16 @@ func (self *ApierV1) GetActions(actsId string, reply *[]*utils.TPAction) error {
for _, engAct := range engActs {
act := &utils.TPAction{Identifier: engAct.ActionType,
BalanceType: engAct.BalanceType,
- Direction: engAct.Direction,
ExpiryTime: engAct.ExpirationString,
ExtraParameters: engAct.ExtraParameters,
Weight: engAct.Weight,
}
if engAct.Balance != nil {
act.Units = engAct.Balance.GetValue()
- act.DestinationIds = engAct.Balance.DestinationIds
+ act.Directions = engAct.Balance.Directions.String()
+ act.DestinationIds = engAct.Balance.DestinationIds.String()
act.RatingSubject = engAct.Balance.RatingSubject
- act.SharedGroup = engAct.Balance.SharedGroup
+ act.SharedGroups = engAct.Balance.SharedGroups.String()
act.BalanceWeight = engAct.Balance.Weight
}
acts = append(acts, act)
@@ -773,8 +767,8 @@ func (self *ApierV1) AddTriggeredAction(attr AttrAddActionTrigger, reply *string
ThresholdValue: attr.ThresholdValue,
BalanceId: attr.BalanceId,
BalanceType: attr.BalanceType,
- BalanceDirection: attr.BalanceDirection,
- BalanceDestinationIds: attr.BalanceDestinationIds,
+ BalanceDirections: utils.ParseStringMap(attr.BalanceDirection),
+ BalanceDestinationIds: utils.ParseStringMap(attr.BalanceDestinationIds),
BalanceWeight: attr.BalanceWeight,
BalanceExpirationDate: balExpiryTime,
Weight: attr.Weight,
@@ -782,7 +776,7 @@ func (self *ApierV1) AddTriggeredAction(attr AttrAddActionTrigger, reply *string
Executed: false,
}
- tag := utils.AccountKey(attr.Tenant, attr.Account, attr.BalanceDirection)
+ tag := utils.AccountKey(attr.Tenant, attr.Account)
_, err = engine.Guardian.Guard(func() (interface{}, error) {
userBalance, err := self.AccountDb.GetAccount(tag)
if err != nil {
@@ -808,7 +802,7 @@ type AttrResetTriggeredAction struct {
Id string
Tenant string
Account string
- Direction string
+ Directions string
BalanceType string
ThresholdType string
ThresholdValue float64
@@ -824,21 +818,20 @@ func (self *ApierV1) ResetTriggeredActions(attr AttrResetTriggeredAction, reply
// we can identify the trigge by the id
a = &engine.Action{Id: attr.Id}
} else {
- if attr.Direction == "" {
- attr.Direction = utils.OUT
- }
extraParameters, err := json.Marshal(struct {
ThresholdType string
ThresholdValue float64
DestinationId string
BalanceWeight float64
BalanceRatingSubject string
+ BalanceDirections string
BalanceSharedGroup string
}{
attr.ThresholdType,
attr.ThresholdValue,
attr.DestinationId,
attr.BalanceWeight,
+ attr.Directions,
attr.BalanceRatingSubject,
attr.BalanceSharedGroup,
})
@@ -848,11 +841,10 @@ func (self *ApierV1) ResetTriggeredActions(attr AttrResetTriggeredAction, reply
}
a = &engine.Action{
BalanceType: attr.BalanceType,
- Direction: attr.Direction,
ExtraParameters: string(extraParameters),
}
}
- accID := utils.AccountKey(attr.Tenant, attr.Account, attr.Direction)
+ accID := utils.AccountKey(attr.Tenant, attr.Account)
_, err := engine.Guardian.Guard(func() (interface{}, error) {
acc, err := self.AccountDb.GetAccount(accID)
if err != nil {
@@ -910,7 +902,6 @@ func (self *ApierV1) ReloadScheduler(input string, reply *string) error {
self.Sched.Restart()
*reply = OK
return nil
-
}
func (self *ApierV1) ReloadCache(attrs utils.ApiReloadCache, reply *string) error {
diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go
index 19275a329..2c9cc9db1 100644
--- a/apier/v1/apier_local_test.go
+++ b/apier/v1/apier_local_test.go
@@ -488,7 +488,7 @@ func TestApierTPActions(t *testing.T) {
}
reply := ""
act := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: "PREPAID_10", Actions: []*utils.TPAction{
- &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Direction: "*out", Units: 10, ExpiryTime: "*unlimited",
+ &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited",
DestinationIds: "*any", BalanceWeight: 10, Weight: 10},
}}
actWarn := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: "WARN_VIA_HTTP", Actions: []*utils.TPAction{
@@ -601,7 +601,7 @@ func TestApierTPActionTriggers(t *testing.T) {
}
reply := ""
at := &utils.TPActionTriggers{TPid: utils.TEST_SQL, ActionTriggersId: "STANDARD_TRIGGERS", ActionTriggers: []*utils.TPActionTrigger{
- &utils.TPActionTrigger{Id: "MYFIRSTTRIGGER", BalanceType: "*monetary", BalanceDirection: "*out", ThresholdType: "*min_balance", ThresholdValue: 2, ActionsId: "LOG_BALANCE", Weight: 10},
+ &utils.TPActionTrigger{Id: "MYFIRSTTRIGGER", BalanceType: "*monetary", BalanceDirections: "*out", ThresholdType: "*min_balance", ThresholdValue: 2, ActionsId: "LOG_BALANCE", Weight: 10},
}}
atTst := new(utils.TPActionTriggers)
*atTst = *at
@@ -655,15 +655,15 @@ func TestApierTPAccountActions(t *testing.T) {
}
reply := ""
aa1 := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org",
- Account: "1001", Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ Account: "1001", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
aa2 := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org",
- Account: "1002", Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ Account: "1002", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
aa3 := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org",
- Account: "1003", Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ Account: "1003", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
aa4 := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org",
- Account: "1004", Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ Account: "1004", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
aa5 := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org",
- Account: "1005", Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ Account: "1005", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
aaTst := new(utils.TPAccountActions)
*aaTst = *aa1
aaTst.Account = utils.TEST_SQL
@@ -683,7 +683,7 @@ func TestApierTPAccountActions(t *testing.T) {
// Check missing params
if err := rater.Call("ApierV1.SetTPAccountActions", new(utils.TPAccountActions), &reply); err == nil {
t.Error("Calling ApierV1.SetTPAccountActions, expected error, received: ", reply)
- } else if err.Error() != "MANDATORY_IE_MISSING:[TPid LoadId Tenant Account Direction ActionPlanId ActionTriggersId]" {
+ } else if err.Error() != "MANDATORY_IE_MISSING:[TPid LoadId Tenant Account ActionPlanId ActionTriggersId]" {
t.Error("Calling ApierV1.SetTPAccountActions got unexpected error: ", err.Error())
}
// Test get
@@ -784,7 +784,7 @@ func TestApierLoadAccountActions(t *testing.T) {
return
}
reply := ""
- aa1 := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ aa1 := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001"}
if err := rater.Call("ApierV1.LoadAccountActions", aa1, &reply); err != nil {
t.Error("Got error on ApierV1.LoadAccountActions: ", err.Error())
} else if reply != "OK" {
@@ -905,43 +905,43 @@ func TestApierAddBalance(t *testing.T) {
return
}
reply := ""
- attrs := &AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Direction: "*out", Value: 1.5}
+ attrs := &AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Value: 1.5}
if err := rater.Call("ApierV1.AddBalance", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
t.Errorf("Calling ApierV1.AddBalance received: %s", reply)
}
- attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan", BalanceType: "*monetary", Direction: "*out", Value: 1.5}
+ attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan", BalanceType: "*monetary", Value: 1.5}
if err := rater.Call("ApierV1.AddBalance", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
t.Errorf("Calling ApierV1.AddBalance received: %s", reply)
}
- attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan2", BalanceType: "*monetary", Direction: "*out", Value: 1.5}
+ attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan2", BalanceType: "*monetary", Value: 1.5}
if err := rater.Call("ApierV1.AddBalance", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
t.Errorf("Calling ApierV1.AddBalance received: %s", reply)
}
- attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan3", BalanceType: "*monetary", Direction: "*out", Value: 1.5}
+ attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan3", BalanceType: "*monetary", Value: 1.5}
if err := rater.Call("ApierV1.AddBalance", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
t.Errorf("Calling ApierV1.AddBalance received: %s", reply)
}
- attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan3", BalanceType: "*monetary", Direction: "*out", Value: 2.1}
+ attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan3", BalanceType: "*monetary", Value: 2.1}
if err := rater.Call("ApierV1.AddBalance", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
t.Errorf("Calling ApierV1.AddBalance received: %s", reply)
}
- attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan6", BalanceType: "*monetary", Direction: "*out", Value: 2.1}
+ attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan6", BalanceType: "*monetary", Value: 2.1}
if err := rater.Call("ApierV1.AddBalance", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
t.Errorf("Calling ApierV1.AddBalance received: %s", reply)
}
- attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan6", BalanceType: "*monetary", Direction: "*out", Value: 1, Overwrite: true}
+ attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan6", BalanceType: "*monetary", Value: 1, Overwrite: true}
if err := rater.Call("ApierV1.AddBalance", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
@@ -957,7 +957,7 @@ func TestApierExecuteAction(t *testing.T) {
}
reply := ""
// Add balance to a previously known account
- attrs := utils.AttrExecuteAction{Direction: "*out", Tenant: "cgrates.org", Account: "dan2", ActionsId: "PREPAID_10"}
+ attrs := utils.AttrExecuteAction{Tenant: "cgrates.org", Account: "dan2", ActionsId: "PREPAID_10"}
if err := rater.Call("ApierV1.ExecuteAction", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.ExecuteAction: ", err.Error())
} else if reply != "OK" {
@@ -965,7 +965,7 @@ func TestApierExecuteAction(t *testing.T) {
}
reply2 := ""
// Add balance to an account which does n exist
- attrs = utils.AttrExecuteAction{Direction: "*out", Tenant: "cgrates.org", Account: "dan2", ActionsId: "DUMMY_ACTION"}
+ attrs = utils.AttrExecuteAction{Tenant: "cgrates.org", Account: "dan2", ActionsId: "DUMMY_ACTION"}
if err := rater.Call("ApierV1.ExecuteAction", attrs, &reply2); err == nil || reply2 == "OK" {
t.Error("Expecting error on ApierV1.ExecuteAction.", err, reply2)
}
@@ -975,7 +975,7 @@ func TestApierSetActions(t *testing.T) {
if !*testLocal {
return
}
- act1 := &utils.TPAction{Identifier: engine.TOPUP_RESET, BalanceType: utils.MONETARY, Direction: utils.OUT, Units: 75.0, ExpiryTime: engine.UNLIMITED, Weight: 20.0}
+ act1 := &utils.TPAction{Identifier: engine.TOPUP_RESET, BalanceType: utils.MONETARY, Directions: utils.OUT, Units: 75.0, ExpiryTime: engine.UNLIMITED, Weight: 20.0}
attrs1 := &utils.AttrSetActions{ActionsId: "ACTS_1", Actions: []*utils.TPAction{act1}}
reply1 := ""
if err := rater.Call("ApierV1.SetActions", attrs1, &reply1); err != nil {
@@ -994,7 +994,7 @@ func TestApierGetActions(t *testing.T) {
return
}
expectActs := []*utils.TPAction{
- &utils.TPAction{Identifier: engine.TOPUP_RESET, BalanceType: utils.MONETARY, Direction: utils.OUT, Units: 75.0, ExpiryTime: engine.UNLIMITED, Weight: 20.0}}
+ &utils.TPAction{Identifier: engine.TOPUP_RESET, BalanceType: utils.MONETARY, Directions: utils.OUT, Units: 75.0, ExpiryTime: engine.UNLIMITED, Weight: 20.0}}
var reply []*utils.TPAction
if err := rater.Call("ApierV1.GetActions", "ACTS_1", &reply); err != nil {
@@ -1093,7 +1093,7 @@ func TestApierSetAccount(t *testing.T) {
return
}
reply := ""
- attrs := &utils.AttrSetAccount{Tenant: "cgrates.org", Direction: "*out", Account: "dan7", ActionPlanId: "ATMS_1"}
+ attrs := &utils.AttrSetAccount{Tenant: "cgrates.org", Account: "dan7", ActionPlanId: "ATMS_1"}
if err := rater.Call("ApierV1.SetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.SetAccount: ", err.Error())
} else if reply != "OK" {
@@ -1154,36 +1154,36 @@ func TestApierGetAccount(t *testing.T) {
return
}
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 11.5 { // We expect 11.5 since we have added in the previous test 1.5
- t.Errorf("Calling ApierV1.GetBalance expected: 11.5, received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 11.5 { // We expect 11.5 since we have added in the previous test 1.5
+ t.Errorf("Calling ApierV1.GetBalance expected: 11.5, received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan"}
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 1.5 {
- t.Errorf("Calling ApierV1.GetAccount expected: 1.5, received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 1.5 {
+ t.Errorf("Calling ApierV1.GetAccount expected: 1.5, received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
// The one we have topped up though executeAction
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan2", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan2"}
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 11.5 {
- t.Errorf("Calling ApierV1.GetAccount expected: 10, received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 11.5 {
+ t.Errorf("Calling ApierV1.GetAccount expected: 10, received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan3", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan3"}
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 3.6 {
- t.Errorf("Calling ApierV1.GetAccount expected: 3.6, received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 3.6 {
+ t.Errorf("Calling ApierV1.GetAccount expected: 3.6, received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan6", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan6"}
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 1 {
- t.Errorf("Calling ApierV1.GetAccount expected: 1, received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 1 {
+ t.Errorf("Calling ApierV1.GetAccount expected: 1, received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
}
@@ -1193,13 +1193,13 @@ func TestApierTriggersExecute(t *testing.T) {
return
}
reply := ""
- attrs := &utils.AttrSetAccount{Tenant: "cgrates.org", Direction: "*out", Account: "dan8"}
+ attrs := &utils.AttrSetAccount{Tenant: "cgrates.org", Account: "dan8"}
if err := rater.Call("ApierV1.SetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.SetAccount: ", err.Error())
} else if reply != "OK" {
t.Errorf("Calling ApierV1.SetAccount received: %s", reply)
}
- attrAddBlnc := &AttrAddBalance{Tenant: "cgrates.org", Account: "1008", BalanceType: "*monetary", Direction: "*out", Value: 2}
+ attrAddBlnc := &AttrAddBalance{Tenant: "cgrates.org", Account: "1008", BalanceType: "*monetary", Value: 2}
if err := rater.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
@@ -1289,11 +1289,11 @@ func TestApierGetAccountAfterLoad(t *testing.T) {
return
}
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 11 {
- t.Errorf("Calling ApierV1.GetBalance expected: 11, received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 11 {
+ t.Errorf("Calling ApierV1.GetBalance expected: 11, received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
}
diff --git a/apier/v1/scheduler.go b/apier/v1/scheduler.go
index 216feb41a..ec02807a5 100644
--- a/apier/v1/scheduler.go
+++ b/apier/v1/scheduler.go
@@ -98,14 +98,14 @@ import (
*/
type AttrsGetScheduledActions struct {
- Direction, Tenant, Account string
- TimeStart, TimeEnd time.Time // Filter based on next runTime
+ Tenant, Account string
+ TimeStart, TimeEnd time.Time // Filter based on next runTime
utils.Paginator
}
type ScheduledActions struct {
NextRunTime time.Time
- Accounts []*utils.DirectionTenantAccount
+ Accounts []*utils.TenantAccount
ActionsId, ActionPlanId, ActionPlanUuid string
}
@@ -142,22 +142,18 @@ func (self *ApierV1) GetScheduledActions(attrs AttrsGetScheduledActions, reply *
}
acntFiltersMatch := false
for _, acntKey := range qActions.AccountIds {
- directionMatched := len(attrs.Direction) == 0
tenantMatched := len(attrs.Tenant) == 0
accountMatched := len(attrs.Account) == 0
- dta, _ := utils.NewDTAFromAccountKey(acntKey)
+ dta, _ := utils.NewTAFromAccountKey(acntKey)
sas.Accounts = append(sas.Accounts, dta)
// One member matching
- if !directionMatched && attrs.Direction == dta.Direction {
- directionMatched = true
- }
if !tenantMatched && attrs.Tenant == dta.Tenant {
tenantMatched = true
}
if !accountMatched && attrs.Account == dta.Account {
accountMatched = true
}
- if directionMatched && tenantMatched && accountMatched {
+ if tenantMatched && accountMatched {
acntFiltersMatch = true
}
}
diff --git a/apier/v1/tpaccountactions.go b/apier/v1/tpaccountactions.go
index ab8bf2799..b83938a5c 100644
--- a/apier/v1/tpaccountactions.go
+++ b/apier/v1/tpaccountactions.go
@@ -26,7 +26,7 @@ import (
// Creates a new AccountActions profile within a tariff plan
func (self *ApierV1) SetTPAccountActions(attrs utils.TPAccountActions, reply *string) error {
if missing := utils.MissingStructFields(&attrs,
- []string{"TPid", "LoadId", "Tenant", "Account", "Direction", "ActionPlanId", "ActionTriggersId"}); len(missing) != 0 {
+ []string{"TPid", "LoadId", "Tenant", "Account", "ActionPlanId", "ActionTriggersId"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
aas := engine.APItoModelAccountAction(&attrs)
@@ -46,7 +46,7 @@ type AttrGetTPAccountActionsByLoadId struct {
func (self *ApierV1) GetTPAccountActionsByLoadId(attrs utils.TPAccountActions, reply *[]*utils.TPAccountActions) error {
mndtryFlds := []string{"TPid", "LoadId"}
if len(attrs.Account) != 0 { // If account provided as filter, make all related fields mandatory
- mndtryFlds = append(mndtryFlds, "Tenant", "Account", "Direction")
+ mndtryFlds = append(mndtryFlds, "Tenant", "Account")
}
if missing := utils.MissingStructFields(&attrs, mndtryFlds); len(missing) != 0 { //Params missing
return utils.NewErrMandatoryIeMissing(missing...)
@@ -150,14 +150,14 @@ func (self *ApierV1) GetTPAccountActionIds(attrs AttrGetTPAccountActionIds, repl
// Removes specific AccountActions on Tariff plan
func (self *ApierV1) RemTPAccountActions(attrs AttrGetTPAccountActions, reply *string) error {
- if missing := utils.MissingStructFields(&attrs, []string{"TPid", "LoadId", "Tenant", "Account", "Direction"}); len(missing) != 0 { //Params missing
+ if missing := utils.MissingStructFields(&attrs, []string{"TPid", "LoadId", "Tenant", "Account"}); len(missing) != 0 { //Params missing
return utils.NewErrMandatoryIeMissing(missing...)
}
aa := engine.TpAccountAction{Tpid: attrs.TPid}
if err := aa.SetAccountActionId(attrs.AccountActionsId); err != nil {
return err
}
- if err := self.StorDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.Tpid, map[string]string{"loadid": aa.Loadid, "direction": aa.Direction, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
+ if err := self.StorDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.Tpid, map[string]string{"loadid": aa.Loadid, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
return utils.NewErrServerError(err)
} else {
*reply = "OK"
diff --git a/apier/v2/accounts.go b/apier/v2/accounts.go
new file mode 100644
index 000000000..72cebd7c6
--- /dev/null
+++ b/apier/v2/accounts.go
@@ -0,0 +1,66 @@
+/*
+Real-time Charging System for Telecom & ISP environments
+Copyright (C) 2012-2015 ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package v2
+
+import (
+ "math"
+
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func (self *ApierV2) GetAccounts(attr utils.AttrGetAccounts, reply *[]*engine.Account) error {
+ if len(attr.Tenant) == 0 {
+ return utils.NewErrMandatoryIeMissing("Tenanat")
+ }
+ var accountKeys []string
+ var err error
+ if len(attr.AccountIds) == 0 {
+ if accountKeys, err = self.AccountDb.GetKeysForPrefix(utils.ACCOUNT_PREFIX + utils.ConcatenatedKey(attr.Tenant)); err != nil {
+ return err
+ }
+ } else {
+ for _, acntId := range attr.AccountIds {
+ if len(acntId) == 0 { // Source of error returned from redis (key not found)
+ continue
+ }
+ accountKeys = append(accountKeys, utils.ACCOUNT_PREFIX+utils.ConcatenatedKey(attr.Tenant, acntId))
+ }
+ }
+ if len(accountKeys) == 0 {
+ return nil
+ }
+ var limitedAccounts []string
+ if attr.Limit != 0 {
+ max := math.Min(float64(attr.Offset+attr.Limit), float64(len(accountKeys)))
+ limitedAccounts = accountKeys[attr.Offset:int(max)]
+ } else {
+ limitedAccounts = accountKeys[attr.Offset:]
+ }
+ retAccounts := make([]*engine.Account, 0)
+ for _, acntKey := range limitedAccounts {
+ if acnt, err := self.AccountDb.GetAccount(acntKey[len(utils.ACCOUNT_PREFIX):]); err != nil && err != utils.ErrNotFound { // Not found is not an error here
+ return err
+ } else if acnt != nil {
+ retAccounts = append(retAccounts, acnt)
+ }
+ }
+ *reply = retAccounts
+ return nil
+}
diff --git a/cmd/cgr-loader/cgr-loader.go b/cmd/cgr-loader/cgr-loader.go
index d958881a6..17c368cd8 100644
--- a/cmd/cgr-loader/cgr-loader.go
+++ b/cmd/cgr-loader/cgr-loader.go
@@ -24,6 +24,7 @@ import (
"log"
"net/rpc"
"path"
+ "strconv"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
@@ -34,6 +35,7 @@ import (
var (
//separator = flag.String("separator", ",", "Default field separator")
cgrConfig, _ = config.NewDefaultCGRConfig()
+ migrateRC8 = flag.Bool("migrate_rc8", false, "Migrate Accounts, Actions and ActionTriggers to RC8 structures")
tpdb_type = flag.String("tpdb_type", cgrConfig.TpDbType, "The type of the TariffPlan database ")
tpdb_host = flag.String("tpdb_host", cgrConfig.TpDbHost, "The TariffPlan host to connect to.")
tpdb_port = flag.String("tpdb_port", cgrConfig.TpDbPort, "The TariffPlan port to bind to.")
@@ -88,6 +90,52 @@ func main() {
var storDb engine.LoadStorage
var rater, cdrstats, users *rpc.Client
var loader engine.LoadReader
+ if *migrateRC8 {
+ var db_nb int
+ db_nb, err = strconv.Atoi(*datadb_name)
+ if err != nil {
+ log.Print("Redis db name must be an integer!")
+ return
+ }
+ host := *datadb_host
+ if *datadb_port != "" {
+ host += ":" + *datadb_port
+ }
+ migratorRC8acc, err := NewMigratorRC8(host, db_nb, *datadb_pass, *dbdata_encoding)
+ if err != nil {
+ log.Print(err.Error())
+ return
+ }
+ if err := migratorRC8acc.migrateAccounts(); err != nil {
+ log.Print(err.Error())
+ return
+ }
+
+ db_nb, err = strconv.Atoi(*tpdb_name)
+ if err != nil {
+ log.Print("Redis db name must be an integer!")
+ return
+ }
+ host = *tpdb_host
+ if *tpdb_port != "" {
+ host += ":" + *tpdb_port
+ }
+ migratorRC8rat, err := NewMigratorRC8(host, db_nb, *tpdb_pass, *dbdata_encoding)
+ if err != nil {
+ log.Print(err.Error())
+ return
+ }
+ if err := migratorRC8rat.migrateActionTriggers(); err != nil {
+ log.Print(err.Error())
+ return
+ }
+ if err := migratorRC8rat.migrateActions(); err != nil {
+ log.Print(err.Error())
+ return
+ }
+ log.Print("Done!")
+ return
+ }
// Init necessary db connections, only if not already
if !*dryRun { // make sure we do not need db connections on dry run, also not importing into any stordb
if *fromStorDb {
diff --git a/cmd/cgr-loader/migrator_rc8.go b/cmd/cgr-loader/migrator_rc8.go
new file mode 100644
index 000000000..3fc97d2bd
--- /dev/null
+++ b/cmd/cgr-loader/migrator_rc8.go
@@ -0,0 +1,359 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "strings"
+ "time"
+
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+ "github.com/hoisie/redis"
+)
+
+const OLD_ACCOUNT_PREFIX = "ubl_"
+
+type MigratorRC8 struct {
+ dbNb int
+ db *redis.Client
+ ms engine.Marshaler
+}
+
+func NewMigratorRC8(address string, db int, pass, mrshlerStr string) (*MigratorRC8, error) {
+ ndb := &redis.Client{Addr: address, Db: db, Password: pass}
+
+ var mrshler engine.Marshaler
+ if mrshlerStr == utils.MSGPACK {
+ mrshler = engine.NewCodecMsgpackMarshaler()
+ } else if mrshlerStr == utils.JSON {
+ mrshler = new(engine.JSONMarshaler)
+ } else {
+ return nil, fmt.Errorf("Unsupported marshaler: %v", mrshlerStr)
+ }
+ return &MigratorRC8{db: ndb, dbNb: db, ms: mrshler}, nil
+}
+
+type Account struct {
+ Id string
+ BalanceMap map[string]BalanceChain
+ UnitCounters []*UnitsCounter
+ ActionTriggers ActionTriggers
+ AllowNegative bool
+ Disabled bool
+}
+type BalanceChain []*Balance
+
+type Balance struct {
+ Uuid string //system wide unique
+ Id string // account wide unique
+ Value float64
+ ExpirationDate time.Time
+ Weight float64
+ DestinationIds string
+ RatingSubject string
+ Category string
+ SharedGroup string
+ Timings []*engine.RITiming
+ TimingIDs string
+ Disabled bool
+ precision int
+ account *Account
+ dirty bool
+}
+
+func (b *Balance) IsDefault() bool {
+ return (b.DestinationIds == "" || b.DestinationIds == utils.ANY) &&
+ b.RatingSubject == "" &&
+ b.Category == "" &&
+ b.ExpirationDate.IsZero() &&
+ b.SharedGroup == "" &&
+ b.Weight == 0 &&
+ b.Disabled == false
+}
+
+type UnitsCounter struct {
+ Direction string
+ BalanceType string
+ // Units float64
+ Balances BalanceChain // first balance is the general one (no destination)
+}
+
+type ActionTriggers []*ActionTrigger
+
+type ActionTrigger struct {
+ Id string
+ ThresholdType string
+ ThresholdValue float64
+ Recurrent bool
+ MinSleep time.Duration
+ BalanceId string
+ BalanceType string
+ BalanceDirection string
+ BalanceDestinationIds string
+ BalanceWeight float64
+ BalanceExpirationDate time.Time
+ BalanceTimingTags string
+ BalanceRatingSubject string
+ BalanceCategory string
+ BalanceSharedGroup string
+ BalanceDisabled bool
+ Weight float64
+ ActionsId string
+ MinQueuedItems int
+ Executed bool
+}
+type Actions []*Action
+
+type Action struct {
+ Id string
+ ActionType string
+ BalanceType string
+ Direction string
+ ExtraParameters string
+ ExpirationString string
+ Weight float64
+ Balance *Balance
+}
+
+func (mig MigratorRC8) migrateAccounts() error {
+ keys, err := mig.db.Keys(OLD_ACCOUNT_PREFIX + "*")
+ if err != nil {
+ return err
+ }
+ newAccounts := make([]*engine.Account, len(keys))
+ // get existing accounts
+ for keyIndex, key := range keys {
+ log.Printf("Migrating account: %s...", key)
+ values, err := mig.db.Get(key)
+ if err != nil {
+ continue
+ }
+ var oldAcc Account
+ if err = mig.ms.Unmarshal(values, &oldAcc); err != nil {
+ return err
+ }
+ // transfer data into new structurse
+ newAcc := &engine.Account{
+ Id: oldAcc.Id,
+ BalanceMap: make(map[string]engine.BalanceChain, len(oldAcc.BalanceMap)),
+ UnitCounters: make([]*engine.UnitsCounter, len(oldAcc.UnitCounters)),
+ ActionTriggers: make(engine.ActionTriggers, len(oldAcc.ActionTriggers)),
+ AllowNegative: oldAcc.AllowNegative,
+ Disabled: oldAcc.Disabled,
+ }
+ // fix id
+ idElements := strings.Split(newAcc.Id, utils.CONCATENATED_KEY_SEP)
+ if len(idElements) != 3 {
+ return fmt.Errorf("Malformed account ID %s", oldAcc.Id)
+ }
+ newAcc.Id = fmt.Sprintf("%s:%s", idElements[1], idElements[2])
+ // balances
+ for oldBalKey, oldBalChain := range oldAcc.BalanceMap {
+ keyElements := strings.Split(oldBalKey, "*")
+ if len(keyElements) != 3 {
+ return fmt.Errorf("Malformed balance key in %s: %s", oldAcc.Id, oldBalKey)
+ }
+ newBalKey := "*" + keyElements[1]
+ newBalDirection := "*" + keyElements[2]
+ newAcc.BalanceMap[newBalKey] = make(engine.BalanceChain, len(oldBalChain))
+ for index, oldBal := range oldBalChain {
+ // check default to set new id
+ if oldBal.IsDefault() {
+ oldBal.Id = utils.META_DEFAULT
+ }
+ newAcc.BalanceMap[newBalKey][index] = &engine.Balance{
+ Uuid: oldBal.Uuid,
+ Id: oldBal.Id,
+ Value: oldBal.Value,
+ Directions: utils.ParseStringMap(newBalDirection),
+ ExpirationDate: oldBal.ExpirationDate,
+ Weight: oldBal.Weight,
+ DestinationIds: utils.ParseStringMap(oldBal.DestinationIds),
+ RatingSubject: oldBal.RatingSubject,
+ Categories: utils.ParseStringMap(oldBal.Category),
+ SharedGroups: utils.ParseStringMap(oldBal.SharedGroup),
+ Timings: oldBal.Timings,
+ TimingIDs: utils.ParseStringMap(oldBal.TimingIDs),
+ Disabled: oldBal.Disabled,
+ }
+ }
+ }
+ // unit counters
+ for _, oldUc := range oldAcc.UnitCounters {
+ newUc := &engine.UnitsCounter{
+ BalanceType: oldUc.BalanceType,
+ Balances: make(engine.BalanceChain, len(oldUc.Balances)),
+ }
+ for index, oldUcBal := range oldUc.Balances {
+ newUc.Balances[index] = &engine.Balance{
+ Uuid: oldUcBal.Uuid,
+ Id: oldUcBal.Id,
+ Value: oldUcBal.Value,
+ Directions: utils.ParseStringMap(oldUc.Direction),
+ ExpirationDate: oldUcBal.ExpirationDate,
+ Weight: oldUcBal.Weight,
+ DestinationIds: utils.ParseStringMap(oldUcBal.DestinationIds),
+ RatingSubject: oldUcBal.RatingSubject,
+ Categories: utils.ParseStringMap(oldUcBal.Category),
+ SharedGroups: utils.ParseStringMap(oldUcBal.SharedGroup),
+ Timings: oldUcBal.Timings,
+ TimingIDs: utils.ParseStringMap(oldUcBal.TimingIDs),
+ Disabled: oldUcBal.Disabled,
+ }
+ }
+ }
+ // action triggers
+ for index, oldAtr := range oldAcc.ActionTriggers {
+ newAcc.ActionTriggers[index] = &engine.ActionTrigger{
+ Id: oldAtr.Id,
+ ThresholdType: oldAtr.ThresholdType,
+ ThresholdValue: oldAtr.ThresholdValue,
+ Recurrent: oldAtr.Recurrent,
+ MinSleep: oldAtr.MinSleep,
+ BalanceId: oldAtr.BalanceId,
+ BalanceType: oldAtr.BalanceType,
+ BalanceDirections: utils.ParseStringMap(oldAtr.BalanceDirection),
+ BalanceDestinationIds: utils.ParseStringMap(oldAtr.BalanceDestinationIds),
+ BalanceWeight: oldAtr.BalanceWeight,
+ BalanceExpirationDate: oldAtr.BalanceExpirationDate,
+ BalanceTimingTags: utils.ParseStringMap(oldAtr.BalanceTimingTags),
+ BalanceRatingSubject: oldAtr.BalanceRatingSubject,
+ BalanceCategories: utils.ParseStringMap(oldAtr.BalanceCategory),
+ BalanceSharedGroups: utils.ParseStringMap(oldAtr.BalanceSharedGroup),
+ BalanceDisabled: oldAtr.BalanceDisabled,
+ Weight: oldAtr.Weight,
+ ActionsId: oldAtr.ActionsId,
+ MinQueuedItems: oldAtr.MinQueuedItems,
+ Executed: oldAtr.Executed,
+ }
+ }
+ newAccounts[keyIndex] = newAcc
+ }
+ // write data back
+ for _, newAcc := range newAccounts {
+ result, err := mig.ms.Marshal(newAcc)
+ if err != nil {
+ return err
+ }
+ if err := mig.db.Set(utils.ACCOUNT_PREFIX+newAcc.Id, result); err != nil {
+ return err
+ }
+ }
+ // delete old data
+ log.Printf("Deleting old accounts: %s...", OLD_ACCOUNT_PREFIX+"*")
+ for _, key := range keys {
+ _, err = mig.db.Del(key)
+ }
+ return err
+}
+
+func (mig MigratorRC8) migrateActionTriggers() error {
+ keys, err := mig.db.Keys(utils.ACTION_TRIGGER_PREFIX + "*")
+ if err != nil {
+ return err
+ }
+ newAtrsMap := make(map[string]engine.ActionTriggers, len(keys))
+ for _, key := range keys {
+ log.Printf("Migrating action trigger: %s...", key)
+ var oldAtrs ActionTriggers
+ var values []byte
+ if values, err = mig.db.Get(key); err == nil {
+ if err := mig.ms.Unmarshal(values, &oldAtrs); err != nil {
+ return err
+ }
+ }
+ newAtrs := make(engine.ActionTriggers, len(oldAtrs))
+ for index, oldAtr := range oldAtrs {
+ newAtrs[index] = &engine.ActionTrigger{
+ Id: oldAtr.Id,
+ ThresholdType: oldAtr.ThresholdType,
+ ThresholdValue: oldAtr.ThresholdValue,
+ Recurrent: oldAtr.Recurrent,
+ MinSleep: oldAtr.MinSleep,
+ BalanceId: oldAtr.BalanceId,
+ BalanceType: oldAtr.BalanceType,
+ BalanceDirections: utils.ParseStringMap(oldAtr.BalanceDirection),
+ BalanceDestinationIds: utils.ParseStringMap(oldAtr.BalanceDestinationIds),
+ BalanceWeight: oldAtr.BalanceWeight,
+ BalanceExpirationDate: oldAtr.BalanceExpirationDate,
+ BalanceTimingTags: utils.ParseStringMap(oldAtr.BalanceTimingTags),
+ BalanceRatingSubject: oldAtr.BalanceRatingSubject,
+ BalanceCategories: utils.ParseStringMap(oldAtr.BalanceCategory),
+ BalanceSharedGroups: utils.ParseStringMap(oldAtr.BalanceSharedGroup),
+ BalanceDisabled: oldAtr.BalanceDisabled,
+ Weight: oldAtr.Weight,
+ ActionsId: oldAtr.ActionsId,
+ MinQueuedItems: oldAtr.MinQueuedItems,
+ Executed: oldAtr.Executed,
+ }
+ }
+ newAtrsMap[key] = newAtrs
+ }
+ // write data back
+ for key, atrs := range newAtrsMap {
+ result, err := mig.ms.Marshal(&atrs)
+ if err != nil {
+ return err
+ }
+ if err = mig.db.Set(key, result); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (mig MigratorRC8) migrateActions() error {
+ keys, err := mig.db.Keys(utils.ACTION_PREFIX + "*")
+ if err != nil {
+ return err
+ }
+ newAcsMap := make(map[string]engine.Actions, len(keys))
+ for _, key := range keys {
+ log.Printf("Migrating action: %s...", key)
+ var oldAcs Actions
+ var values []byte
+ if values, err = mig.db.Get(key); err == nil {
+ if err := mig.ms.Unmarshal(values, &oldAcs); err != nil {
+ return err
+ }
+ }
+ newAcs := make(engine.Actions, len(oldAcs))
+ for index, oldAc := range oldAcs {
+ newAcs[index] = &engine.Action{
+ Id: oldAc.Id,
+ ActionType: oldAc.ActionType,
+ BalanceType: oldAc.BalanceType,
+ ExtraParameters: oldAc.ExtraParameters,
+ ExpirationString: oldAc.ExpirationString,
+ Weight: oldAc.Weight,
+ Balance: &engine.Balance{
+ Uuid: oldAc.Balance.Uuid,
+ Id: oldAc.Balance.Id,
+ Value: oldAc.Balance.Value,
+ Directions: utils.ParseStringMap(oldAc.Direction),
+ ExpirationDate: oldAc.Balance.ExpirationDate,
+ Weight: oldAc.Balance.Weight,
+ DestinationIds: utils.ParseStringMap(oldAc.Balance.DestinationIds),
+ RatingSubject: oldAc.Balance.RatingSubject,
+ Categories: utils.ParseStringMap(oldAc.Balance.Category),
+ SharedGroups: utils.ParseStringMap(oldAc.Balance.SharedGroup),
+ Timings: oldAc.Balance.Timings,
+ TimingIDs: utils.ParseStringMap(oldAc.Balance.TimingIDs),
+ Disabled: oldAc.Balance.Disabled,
+ },
+ }
+ }
+ newAcsMap[key] = newAcs
+ }
+ // write data back
+ for key, acs := range newAcsMap {
+ result, err := mig.ms.Marshal(&acs)
+ if err != nil {
+ return err
+ }
+ if err = mig.db.Set(key, result); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/config/config_defaults.go b/config/config_defaults.go
index 59dbede2d..30032dd42 100644
--- a/config/config_defaults.go
+++ b/config/config_defaults.go
@@ -29,7 +29,7 @@ const CGRATES_CFG_JSON = `
"general": {
"http_skip_tls_verify": false, // if enabled Http Client will accept any TLS certificate
- "rounding_decimals": 10, // system level precision for floats
+ "rounding_decimals": 5, // system level precision for floats
"dbdata_encoding": "msgpack", // encoding used to store object data in strings:
"tpexport_dir": "/var/log/cgrates/tpe", // path towards export folder for offline Tariff Plans
"http_failed_dir": "/var/log/cgrates/http_failed", // directory path where we store failed http requests
diff --git a/config/config_json_test.go b/config/config_json_test.go
index 4c1c0e690..e7a622993 100644
--- a/config/config_json_test.go
+++ b/config/config_json_test.go
@@ -39,7 +39,7 @@ func TestDfNewdfCgrJsonCfgFromReader(t *testing.T) {
func TestDfGeneralJsonCfg(t *testing.T) {
eCfg := &GeneralJsonCfg{
Http_skip_tls_verify: utils.BoolPointer(false),
- Rounding_decimals: utils.IntPointer(10),
+ Rounding_decimals: utils.IntPointer(5),
Dbdata_encoding: utils.StringPointer("msgpack"),
Tpexport_dir: utils.StringPointer("/var/log/cgrates/tpe"),
Http_failed_dir: utils.StringPointer("/var/log/cgrates/http_failed"),
diff --git a/console/account_add.go b/console/account_add.go
index 315caa1b6..5875a4fce 100644
--- a/console/account_add.go
+++ b/console/account_add.go
@@ -47,7 +47,7 @@ func (self *CmdAddAccount) RpcMethod() string {
func (self *CmdAddAccount) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
- self.rpcParams = &utils.AttrSetAccount{Direction: utils.OUT}
+ self.rpcParams = &utils.AttrSetAccount{}
}
return self.rpcParams
}
diff --git a/console/account_remove.go b/console/account_remove.go
index 10380d32f..da0ca5d7e 100644
--- a/console/account_remove.go
+++ b/console/account_remove.go
@@ -47,7 +47,7 @@ func (self *CmdRemoveAccount) RpcMethod() string {
func (self *CmdRemoveAccount) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
- self.rpcParams = &utils.AttrRemoveAccount{Direction: utils.OUT}
+ self.rpcParams = &utils.AttrRemoveAccount{}
}
return self.rpcParams
}
diff --git a/console/accounts.go b/console/accounts.go
index 0e7ce79f9..c9030290e 100644
--- a/console/accounts.go
+++ b/console/accounts.go
@@ -26,8 +26,8 @@ import (
func init() {
c := &CmdGetAccounts{
name: "accounts",
- rpcMethod: "ApierV1.GetAccounts",
- rpcParams: &utils.AttrGetAccounts{Direction: "*out"},
+ rpcMethod: "ApierV2.GetAccounts",
+ rpcParams: &utils.AttrGetAccounts{},
}
commands[c.Name()] = c
c.CommandExecuter = &CommandExecuter{c}
@@ -51,7 +51,7 @@ func (self *CmdGetAccounts) RpcMethod() string {
func (self *CmdGetAccounts) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
- self.rpcParams = &utils.AttrGetAccounts{Direction: "*out"}
+ self.rpcParams = &utils.AttrGetAccounts{}
}
return self.rpcParams
}
diff --git a/console/action_execute.go b/console/action_execute.go
index 15ee3838c..52eb40fe6 100644
--- a/console/action_execute.go
+++ b/console/action_execute.go
@@ -26,7 +26,7 @@ func init() {
c := &CmdExecuteAction{
name: "action_execute",
rpcMethod: "ApierV1.ExecuteAction",
- rpcParams: &utils.AttrExecuteAction{Direction: utils.OUT},
+ rpcParams: &utils.AttrExecuteAction{},
}
commands[c.Name()] = c
c.CommandExecuter = &CommandExecuter{c}
@@ -50,7 +50,7 @@ func (self *CmdExecuteAction) RpcMethod() string {
func (self *CmdExecuteAction) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
- self.rpcParams = &utils.AttrExecuteAction{Direction: utils.OUT}
+ self.rpcParams = &utils.AttrExecuteAction{}
}
return self.rpcParams
}
diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql
index 08ebd76b4..3b4edd513 100644
--- a/data/storage/mysql/create_tariffplan_tables.sql
+++ b/data/storage/mysql/create_tariffplan_tables.sql
@@ -151,13 +151,13 @@ CREATE TABLE `tp_actions` (
`action` varchar(24) NOT NULL,
`balance_tag` varchar(64) NOT NULL,
`balance_type` varchar(24) NOT NULL,
- `direction` varchar(8) NOT NULL,
+ `directions` varchar(8) NOT NULL,
`units` DECIMAL(20,4) NOT NULL,
`expiry_time` varchar(24) NOT NULL,
`timing_tags` varchar(128) NOT NULL,
`destination_tags` varchar(64) NOT NULL,
`rating_subject` varchar(64) NOT NULL,
- `category` varchar(32) NOT NULL,
+ `categories` varchar(32) NOT NULL,
`shared_group` varchar(64) NOT NULL,
`balance_weight` DECIMAL(8,2) NOT NULL,
`balance_disabled` BOOLEAN NOT NULL,
@@ -166,7 +166,7 @@ CREATE TABLE `tp_actions` (
`created_at` TIMESTAMP,
PRIMARY KEY (`id`),
KEY `tpid` (`tpid`),
- UNIQUE KEY `unique_action` (`tpid`,`tag`,`action`,`balance_tag`,`balance_type`,`direction`,`expiry_time`,`timing_tags`,`destination_tags`,`shared_group`,`balance_weight`,`weight`)
+ UNIQUE KEY `unique_action` (`tpid`,`tag`,`action`,`balance_tag`,`balance_type`,`directions`,`expiry_time`,`timing_tags`,`destination_tags`,`shared_group`,`balance_weight`,`weight`)
);
--
@@ -203,8 +203,8 @@ CREATE TABLE `tp_action_triggers` (
`min_sleep` varchar(16) NOT NULL,
`balance_tag` varchar(64) NOT NULL,
`balance_type` varchar(24) NOT NULL,
- `balance_direction` varchar(8) NOT NULL,
- `balance_category` varchar(32) NOT NULL,
+ `balance_directions` varchar(8) NOT NULL,
+ `balance_categories` varchar(32) NOT NULL,
`balance_destination_tags` varchar(64) NOT NULL,
`balance_rating_subject` varchar(64) NOT NULL,
`balance_shared_group` varchar(64) NOT NULL,
@@ -218,7 +218,7 @@ CREATE TABLE `tp_action_triggers` (
`created_at` TIMESTAMP,
PRIMARY KEY (`id`),
KEY `tpid` (`tpid`),
- UNIQUE KEY `unique_trigger_definition` (`tpid`,`tag`,`balance_tag`,`balance_type`,`balance_direction`,`threshold_type`,`threshold_value`,`balance_destination_tags`,`actions_tag`)
+ UNIQUE KEY `unique_trigger_definition` (`tpid`,`tag`,`balance_tag`,`balance_type`,`balance_directions`,`threshold_type`,`threshold_value`,`balance_destination_tags`,`actions_tag`)
);
--
@@ -232,7 +232,6 @@ CREATE TABLE `tp_account_actions` (
`loadid` varchar(64) NOT NULL,
`tenant` varchar(64) NOT NULL,
`account` varchar(64) NOT NULL,
- `direction` varchar(8) NOT NULL,
`action_plan_tag` varchar(64),
`action_triggers_tag` varchar(64),
`allow_negative` BOOLEAN NOT NULL,
@@ -240,7 +239,7 @@ CREATE TABLE `tp_account_actions` (
`created_at` TIMESTAMP,
PRIMARY KEY (`id`),
KEY `tpid` (`tpid`),
- UNIQUE KEY `unique_tp_account` (`tpid`,`loadid`,`tenant`,`account`,`direction`)
+ UNIQUE KEY `unique_tp_account` (`tpid`,`loadid`,`tenant`,`account`)
);
--
diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql
index 0f0485d02..bf02bfa51 100644
--- a/data/storage/postgres/create_tariffplan_tables.sql
+++ b/data/storage/postgres/create_tariffplan_tables.sql
@@ -146,20 +146,20 @@ CREATE TABLE tp_actions (
action VARCHAR(24) NOT NULL,
balance_tag VARCHAR(64) NOT NULL,
balance_type VARCHAR(24) NOT NULL,
- direction VARCHAR(8) NOT NULL,
+ directions VARCHAR(8) NOT NULL,
units NUMERIC(20,4) NOT NULL,
expiry_time VARCHAR(24) NOT NULL,
timing_tags VARCHAR(128) NOT NULL,
destination_tags VARCHAR(64) NOT NULL,
rating_subject VARCHAR(64) NOT NULL,
- category VARCHAR(32) NOT NULL,
+ categories VARCHAR(32) NOT NULL,
shared_group VARCHAR(64) NOT NULL,
balance_weight NUMERIC(8,2) NOT NULL,
balance_disabled BOOLEAN NOT NULL,
extra_parameters VARCHAR(256) NOT NULL,
weight NUMERIC(8,2) NOT NULL,
created_at TIMESTAMP,
- UNIQUE (tpid, tag, action, balance_tag, balance_type, direction, expiry_time, timing_tags, destination_tags, shared_group, balance_weight, weight)
+ UNIQUE (tpid, tag, action, balance_tag, balance_type, directions, expiry_time, timing_tags, destination_tags, shared_group, balance_weight, weight)
);
CREATE INDEX tpactions_tpid_idx ON tp_actions (tpid);
CREATE INDEX tpactions_idx ON tp_actions (tpid,tag);
@@ -198,8 +198,8 @@ CREATE TABLE tp_action_triggers (
min_sleep VARCHAR(16) NOT NULL,
balance_tag VARCHAR(64) NOT NULL,
balance_type VARCHAR(24) NOT NULL,
- balance_direction VARCHAR(8) NOT NULL,
- balance_category VARCHAR(32) NOT NULL,
+ balance_directions VARCHAR(8) NOT NULL,
+ balance_categories VARCHAR(32) NOT NULL,
balance_destination_tags VARCHAR(64) NOT NULL,
balance_rating_subject VARCHAR(64) NOT NULL,
balance_shared_group VARCHAR(64) NOT NULL,
@@ -211,7 +211,7 @@ CREATE TABLE tp_action_triggers (
actions_tag VARCHAR(64) NOT NULL,
weight NUMERIC(8,2) NOT NULL,
created_at TIMESTAMP,
- UNIQUE (tpid, tag, balance_tag, balance_type, balance_direction, threshold_type, threshold_value, balance_destination_tags, actions_tag)
+ UNIQUE (tpid, tag, balance_tag, balance_type, balance_directions, threshold_type, threshold_value, balance_destination_tags, actions_tag)
);
CREATE INDEX tpactiontrigers_tpid_idx ON tp_action_triggers (tpid);
CREATE INDEX tpactiontrigers_idx ON tp_action_triggers (tpid,tag);
@@ -227,16 +227,15 @@ CREATE TABLE tp_account_actions (
loadid VARCHAR(64) NOT NULL,
tenant VARCHAR(64) NOT NULL,
account VARCHAR(64) NOT NULL,
- direction VARCHAR(8) NOT NULL,
action_plan_tag VARCHAR(64),
action_triggers_tag VARCHAR(64),
allow_negative BOOLEAN NOT NULL,
disabled BOOLEAN NOT NULL,
created_at TIMESTAMP,
- UNIQUE (tpid, loadid, tenant, account, direction)
+ UNIQUE (tpid, loadid, tenant, account)
);
CREATE INDEX tpaccountactions_tpid_idx ON tp_account_actions (tpid);
-CREATE INDEX tpaccountactions_idx ON tp_account_actions (tpid,loadid,tenant,account,direction);
+CREATE INDEX tpaccountactions_idx ON tp_account_actions (tpid,loadid,tenant,account);
--
-- Table structure for table `tp_lcr_rules`
diff --git a/data/tariffplans/cdrstats/ActionTriggers.csv b/data/tariffplans/cdrstats/ActionTriggers.csv
index 5839ff3e8..061f0d531 100644
--- a/data/tariffplans/cdrstats/ActionTriggers.csv
+++ b/data/tariffplans/cdrstats/ActionTriggers.csv
@@ -1,4 +1,4 @@
-#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirection[8],BalanceCategory[9],BalanceDestinationTag[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingTags[14],BalanceWeight[15],BalanceDisabled[16],StatsMinQueuedItems[17],ActionsTag[18],Weight[19]
+#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirections[8],BalanceCategories[9],BalanceDestinationTags[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingTags[14],BalanceWeight[15],BalanceDisabled[16],StatsMinQueuedItems[17],ActionsTag[18],Weight[19]
CDRST3_WARN_ASR,,*min_asr,45,true,1h,,,,,,,,,,,,3,CDRST_LOG,10
CDRST3_WARN_ACD,,*min_acd,10,true,1h,,,,,,,,,,,,5,CDRST_LOG,10
CDRST3_WARN_ACC,,*max_acc,10,true,10m,,,,,,,,,,,,5,CDRST_LOG,10
diff --git a/data/tariffplans/cdrstats/Actions.csv b/data/tariffplans/cdrstats/Actions.csv
index 216f22141..09e0c5a14 100644
--- a/data/tariffplans/cdrstats/Actions.csv
+++ b/data/tariffplans/cdrstats/Actions.csv
@@ -1,2 +1,2 @@
-#ActionsTag,Action,BalanceTag,BalanceType,Direction,Units,ExpiryTime,TimingTags,DestinationTag,RatingSubject,Category,BalanceWeight,SharedGroup,ExtraParameters,Weight
+#ActionsTag,Action,BalanceTag,BalanceType,Directions,Units,ExpiryTime,TimingTags,DestinationTags,RatingSubject,Categories,BalanceWeight,SharedGroup,ExtraParameters,Weight
CDRST_LOG,*log,,,,,,,,,,,,,false,10
diff --git a/data/tariffplans/prepaid1centpsec/AccountActions.csv b/data/tariffplans/prepaid1centpsec/AccountActions.csv
index 7f23f8664..1e3d995b5 100644
--- a/data/tariffplans/prepaid1centpsec/AccountActions.csv
+++ b/data/tariffplans/prepaid1centpsec/AccountActions.csv
@@ -1,6 +1,6 @@
-#Tenant,Account,Direction,ActionPlanId,ActionTriggersId,AllowNegative,Disabled
-cgrates.org,1001,*out,PREPAID_10,STANDARD_TRIGGERS,,
-cgrates.org,1002,*out,PREPAID_10,STANDARD_TRIGGERS,,
-cgrates.org,1003,*out,PREPAID_10,STANDARD_TRIGGERS,,
-cgrates.org,1004,*out,PREPAID_10,STANDARD_TRIGGERS,,
-cgrates.org,1005,*out,PREPAID_10,STANDARD_TRIGGERS,,
+#Tenant,Account,ActionPlanId,ActionTriggersId,AllowNegative,Disabled
+cgrates.org,1001,PREPAID_10,STANDARD_TRIGGERS,,
+cgrates.org,1002,PREPAID_10,STANDARD_TRIGGERS,,
+cgrates.org,1003,PREPAID_10,STANDARD_TRIGGERS,,
+cgrates.org,1004,PREPAID_10,STANDARD_TRIGGERS,,
+cgrates.org,1005,PREPAID_10,STANDARD_TRIGGERS,,
diff --git a/data/tariffplans/prepaid1centpsec/ActionTriggers.csv b/data/tariffplans/prepaid1centpsec/ActionTriggers.csv
index 75c532d48..d4bdcff5f 100644
--- a/data/tariffplans/prepaid1centpsec/ActionTriggers.csv
+++ b/data/tariffplans/prepaid1centpsec/ActionTriggers.csv
@@ -1,4 +1,4 @@
-#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirection[8],BalanceCategory[9],BalanceDestinationTag[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingTags[14],BalanceWeight[15],BalanceDisabled[16],StatsMinQueuedItems[17],ActionsTag[18],Weight[19]
+#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirections[8],BalanceCategories[9],BalanceDestinationTags[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingTags[14],BalanceWeight[15],BalanceDisabled[16],StatsMinQueuedItems[17],ActionsTag[18],Weight[19]
STANDARD_TRIGGERS,,*min_balance,2,false,0,,*monetary,*out,,,,,,,,,,LOG_BALANCE,10
STANDARD_TRIGGERS,,*max_balance,20,false,0,,*monetary,*out,,,,,,,,,,LOG_BALANCE,10
STANDARD_TRIGGERS,,*max_counter,15,false,0,,*monetary,*out,,FS_USERS,,,,,,,,LOG_BALANCE,10
diff --git a/data/tariffplans/prepaid1centpsec/Actions.csv b/data/tariffplans/prepaid1centpsec/Actions.csv
index 6b50b35ef..6680eccaa 100644
--- a/data/tariffplans/prepaid1centpsec/Actions.csv
+++ b/data/tariffplans/prepaid1centpsec/Actions.csv
@@ -1,4 +1,4 @@
-#ActionsTag[0],Action[1],ActionExtraParameters[2],BalanceTag[3],BalanceType[4],Direction[5],Category[6],DestinationTag[7],RatingSubject[8],SharedGroup[9],ExpiryTime[10],TimingTags[11],Units[12],BalanceWeight[13],BalanceDisabled[14],Weight[15]
+#ActionsTag[0],Action[1],ActionExtraParameters[2],BalanceTag[3],BalanceType[4],Directions[5],Categories[6],DestinationIds[7],RatingSubject[8],SharedGroup[9],ExpiryTime[10],TimingTags[11],Units[12],BalanceWeight[13],BalanceDisabled[14],Weight[15]
PREPAID_10,*topup_reset,,,*monetary,*out,,*any,,,*unlimited,,10,10,false,10
BONUS_1,*topup,,,*monetary,*out,,*any,,,*unlimited,,1,10,false,10
LOG_BALANCE,*log,,,,,,,,,,,,,false,10
diff --git a/data/tariffplans/tutorial/AccountActions.csv b/data/tariffplans/tutorial/AccountActions.csv
index 2a6f2fd6a..97bcd5f64 100644
--- a/data/tariffplans/tutorial/AccountActions.csv
+++ b/data/tariffplans/tutorial/AccountActions.csv
@@ -1,6 +1,6 @@
-#Tenant,Account,Direction,ActionPlanId,ActionTriggersId,AllowNegative,Disabled
-cgrates.org,1001,*out,PACKAGE_1001,STANDARD_TRIGGERS,,
-cgrates.org,1002,*out,PACKAGE_10,STANDARD_TRIGGERS,,
-cgrates.org,1003,*out,PACKAGE_10,STANDARD_TRIGGERS,,
-cgrates.org,1004,*out,PACKAGE_10,STANDARD_TRIGGERS,,
-cgrates.org,1007,*out,USE_SHARED_A,STANDARD_TRIGGERS,,
+#Tenant,Account,ActionPlanId,ActionTriggersId,AllowNegative,Disabled
+cgrates.org,1001,PACKAGE_1001,STANDARD_TRIGGERS,,
+cgrates.org,1002,PACKAGE_10,STANDARD_TRIGGERS,,
+cgrates.org,1003,PACKAGE_10,STANDARD_TRIGGERS,,
+cgrates.org,1004,PACKAGE_10,STANDARD_TRIGGERS,,
+cgrates.org,1007,USE_SHARED_A,STANDARD_TRIGGERS,,
diff --git a/data/tariffplans/tutorial/ActionTriggers.csv b/data/tariffplans/tutorial/ActionTriggers.csv
index e9d756396..b5b0b3922 100644
--- a/data/tariffplans/tutorial/ActionTriggers.csv
+++ b/data/tariffplans/tutorial/ActionTriggers.csv
@@ -1,4 +1,4 @@
-#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirection[8],BalanceCategory[9],BalanceDestinationId[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingIds[14],BalanceWeight[15],BalanceDisabled[16],StatsMinQueuedItems[17],ActionsId[18],Weight[19]
+#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirections[8],BalanceCategories[9],BalanceDestinationIds[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingIds[14],BalanceWeight[15],BalanceDisabled[16],StatsMinQueuedItems[17],ActionsId[18],Weight[19]
STANDARD_TRIGGERS,,*min_balance,2,false,0,,*monetary,*out,,,,,,,,,,LOG_WARNING,10
STANDARD_TRIGGERS,,*max_counter,5,false,0,,*monetary,*out,,FS_USERS,,,,,,,,LOG_WARNING,10
STANDARD_TRIGGERS,,*max_balance,20,false,0,,*monetary,*out,,,,,,,,,,LOG_WARNING,10
diff --git a/data/tariffplans/tutorial/Actions.csv b/data/tariffplans/tutorial/Actions.csv
index d16f5bc2e..ede6ee591 100644
--- a/data/tariffplans/tutorial/Actions.csv
+++ b/data/tariffplans/tutorial/Actions.csv
@@ -1,4 +1,4 @@
-#ActionsId[0],Action[1],ExtraParameters[2],BalanceId[3],BalanceType[4],Direction[5],Category[6],DestinationId[7],RatingSubject[8],SharedGroup[9],ExpiryTime[10],TimingIds[11],Units[12],BalanceWeight[13],BalanceDisabled[14],Weight[15]
+#ActionsId[0],Action[1],ExtraParameters[2],BalanceId[3],BalanceType[4],Directions[5],Categories[6],DestinationIds[7],RatingSubject[8],SharedGroup[9],ExpiryTime[10],TimingIds[11],Units[12],BalanceWeight[13],BalanceDisabled[14],Weight[15]
TOPUP_RST_10,*topup_reset,,,*monetary,*out,,*any,,,*unlimited,,10,10,false,10
TOPUP_RST_5,*topup_reset,,,*monetary,*out,,*any,,,*unlimited,,5,20,false,10
TOPUP_RST_5,*topup_reset,,,*voice,*out,,DST_1002,SPECIAL_1002,,*unlimited,,90,20,false,10
diff --git a/engine/account.go b/engine/account.go
index 6f8a6ef5b..ec86d0536 100644
--- a/engine/account.go
+++ b/engine/account.go
@@ -19,6 +19,7 @@ along with this program. If not, see
package engine
import (
+ "encoding/json"
"errors"
"fmt"
"time"
@@ -52,16 +53,19 @@ type Account struct {
// User's available minutes for the specified destination
func (ub *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duration, credit float64, balances BalanceChain) {
- creditBalances := ub.getBalancesForPrefix(cd.Destination, cd.Category, ub.BalanceMap[utils.MONETARY+cd.Direction], "")
- unitBalances := ub.getBalancesForPrefix(cd.Destination, cd.Category, ub.BalanceMap[cd.TOR+cd.Direction], "")
+ creditBalances := ub.getBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, utils.MONETARY, "")
+
+ unitBalances := ub.getBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, cd.TOR, "")
// gather all balances from shared groups
var extendedCreditBalances BalanceChain
for _, cb := range creditBalances {
- if cb.SharedGroup != "" {
- if sharedGroup, _ := ratingStorage.GetSharedGroup(cb.SharedGroup, false); sharedGroup != nil {
- sgb := sharedGroup.GetBalances(cd.Destination, cd.Category, utils.MONETARY+cd.Direction, ub)
- sgb = sharedGroup.SortBalancesByStrategy(cb, sgb)
- extendedCreditBalances = append(extendedCreditBalances, sgb...)
+ if len(cb.SharedGroups) > 0 {
+ for sg := range cb.SharedGroups {
+ if sharedGroup, _ := ratingStorage.GetSharedGroup(sg, false); sharedGroup != nil {
+ sgb := sharedGroup.GetBalances(cd.Destination, cd.Category, cd.Direction, utils.MONETARY, ub)
+ sgb = sharedGroup.SortBalancesByStrategy(cb, sgb)
+ extendedCreditBalances = append(extendedCreditBalances, sgb...)
+ }
}
} else {
extendedCreditBalances = append(extendedCreditBalances, cb)
@@ -69,11 +73,13 @@ func (ub *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duratio
}
var extendedMinuteBalances BalanceChain
for _, mb := range unitBalances {
- if mb.SharedGroup != "" {
- if sharedGroup, _ := ratingStorage.GetSharedGroup(mb.SharedGroup, false); sharedGroup != nil {
- sgb := sharedGroup.GetBalances(cd.Destination, cd.Category, cd.TOR+cd.Direction, ub)
- sgb = sharedGroup.SortBalancesByStrategy(mb, sgb)
- extendedMinuteBalances = append(extendedMinuteBalances, sgb...)
+ if len(mb.SharedGroups) > 0 {
+ for sg := range mb.SharedGroups {
+ if sharedGroup, _ := ratingStorage.GetSharedGroup(sg, false); sharedGroup != nil {
+ sgb := sharedGroup.GetBalances(cd.Destination, cd.Category, cd.Direction, cd.TOR, ub)
+ sgb = sharedGroup.SortBalancesByStrategy(mb, sgb)
+ extendedMinuteBalances = append(extendedMinuteBalances, sgb...)
+ }
}
} else {
extendedMinuteBalances = append(extendedMinuteBalances, mb)
@@ -101,10 +107,7 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error {
ub.BalanceMap = make(map[string]BalanceChain, 1)
}
found := false
- if a.Direction == "" {
- a.Direction = utils.OUT
- }
- id := a.BalanceType + a.Direction
+ id := a.BalanceType
ub.CleanExpiredBalances()
for _, b := range ub.BalanceMap[id] {
if b.IsExpired() {
@@ -121,21 +124,40 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error {
}
// if it is not found then we add it to the list
if !found {
- if bClone.GetValue() != 0 {
- bClone.SetValue(-bClone.GetValue())
+ // check if the Id is *default (user trying to create the default balance)
+ // use only it's value value
+ if bClone.Id == utils.META_DEFAULT {
+ bClone = &Balance{
+ Id: utils.META_DEFAULT,
+ Value: -bClone.GetValue(),
+ }
+ } else {
+ if bClone.GetValue() != 0 {
+ bClone.SetValue(-bClone.GetValue())
+ }
}
bClone.dirty = true // Mark the balance as dirty since we have modified and it should be checked by action triggers
if bClone.Uuid == "" {
bClone.Uuid = utils.GenUUID()
}
+ // load ValueFactor if defined in extra parametrs
+ if a.ExtraParameters != "" {
+ vf := ValueFactor{}
+ err := json.Unmarshal([]byte(a.ExtraParameters), &vf)
+ if err == nil {
+ bClone.Factor = vf
+ } else {
+ utils.Logger.Warning(fmt.Sprintf("Could load value factor from actions: extra parametrs: %s", a.ExtraParameters))
+ }
+ }
ub.BalanceMap[id] = append(ub.BalanceMap[id], bClone)
}
- if a.Balance.SharedGroup != "" {
+ for sgId := range a.Balance.SharedGroups {
// add shared group member
- sg, err := ratingStorage.GetSharedGroup(a.Balance.SharedGroup, false)
+ sg, err := ratingStorage.GetSharedGroup(sgId, false)
if err != nil || sg == nil {
//than problem
- utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", a.Balance.SharedGroup))
+ utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgId))
} else {
if !utils.IsSliceMember(sg.MemberIds, ub.Id) {
// add member and save
@@ -157,7 +179,7 @@ func (ub *Account) enableDisableBalanceAction(a *Action) error {
ub.BalanceMap = make(map[string]BalanceChain)
}
found := false
- id := a.BalanceType + a.Direction
+ id := a.BalanceType
ub.CleanExpiredBalances()
for _, b := range ub.BalanceMap[id] {
if b.MatchFilter(a.Balance) {
@@ -172,34 +194,39 @@ func (ub *Account) enableDisableBalanceAction(a *Action) error {
return nil
}
-func (ub *Account) getBalancesForPrefix(prefix, category string, balances BalanceChain, sharedGroup string) BalanceChain {
+func (ub *Account) getBalancesForPrefix(prefix, category, direction, tor string, sharedGroup string) BalanceChain {
+ var balances BalanceChain
+ balances = append(balances, ub.BalanceMap[tor]...)
+ if tor != utils.MONETARY && tor != utils.GENERIC {
+ balances = append(balances, ub.BalanceMap[utils.GENERIC]...)
+ }
var usefulBalances BalanceChain
for _, b := range balances {
if b.Disabled {
continue
}
- if b.IsExpired() || (b.SharedGroup == "" && b.GetValue() <= 0) {
+ if b.IsExpired() || (len(b.SharedGroups) == 0 && b.GetValue() <= 0) {
continue
}
- if sharedGroup != "" && b.SharedGroup != sharedGroup {
+ if sharedGroup != "" && b.SharedGroups[sharedGroup] == false {
continue
}
if !b.MatchCategory(category) {
continue
}
+ if b.HasDirection() && b.Directions[direction] == false {
+ continue
+ }
b.account = ub
- if b.DestinationIds != "" && b.DestinationIds != utils.ANY {
- balDestIds := strings.Split(b.DestinationIds, utils.INFIELD_SEP)
+ if len(b.DestinationIds) > 0 && b.DestinationIds[utils.ANY] == false {
for _, p := range utils.SplitPrefix(prefix, MIN_PREFIX_MATCH) {
if x, err := cache2go.Get(utils.DESTINATION_PREFIX + p); err == nil {
destIds := x.(map[interface{}]struct{})
for dId, _ := range destIds {
- for _, balDestID := range balDestIds {
- if dId == strings.TrimSpace(balDestID) {
- b.precision = len(p)
- usefulBalances = append(usefulBalances, b)
- break
- }
+ if b.DestinationIds[dId.(string)] == true {
+ b.precision = len(p)
+ usefulBalances = append(usefulBalances, b)
+ break
}
if b.precision > 0 {
break
@@ -224,18 +251,20 @@ func (ub *Account) getBalancesForPrefix(prefix, category string, balances Balanc
}
// like getBalancesForPrefix but expanding shared balances
-func (account *Account) getAlldBalancesForPrefix(destination, category, balanceType string) (bc BalanceChain) {
- balances := account.getBalancesForPrefix(destination, category, account.BalanceMap[balanceType], "")
+func (account *Account) getAlldBalancesForPrefix(destination, category, direction, balanceType string) (bc BalanceChain) {
+ balances := account.getBalancesForPrefix(destination, category, direction, balanceType, "")
for _, b := range balances {
- if b.SharedGroup != "" {
- sharedGroup, err := ratingStorage.GetSharedGroup(b.SharedGroup, false)
- if err != nil {
- utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", b.SharedGroup))
- continue
+ if len(b.SharedGroups) > 0 {
+ for sgId := range b.SharedGroups {
+ sharedGroup, err := ratingStorage.GetSharedGroup(sgId, false)
+ if err != nil {
+ utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgId))
+ continue
+ }
+ sharedBalances := sharedGroup.GetBalances(destination, category, direction, balanceType, account)
+ sharedBalances = sharedGroup.SortBalancesByStrategy(b, sharedBalances)
+ bc = append(bc, sharedBalances...)
}
- sharedBalances := sharedGroup.GetBalances(destination, category, balanceType, account)
- sharedBalances = sharedGroup.SortBalancesByStrategy(b, sharedBalances)
- bc = append(bc, sharedBalances...)
} else {
bc = append(bc, b)
}
@@ -244,8 +273,8 @@ func (account *Account) getAlldBalancesForPrefix(destination, category, balanceT
}
func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun bool, goNegative bool) (cc *CallCost, err error) {
- usefulUnitBalances := ub.getAlldBalancesForPrefix(cd.Destination, cd.Category, cd.TOR+cd.Direction)
- usefulMoneyBalances := ub.getAlldBalancesForPrefix(cd.Destination, cd.Category, utils.MONETARY+cd.Direction)
+ usefulUnitBalances := ub.getAlldBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, cd.TOR)
+ usefulMoneyBalances := ub.getAlldBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, utils.MONETARY)
//log.Print(usefulMoneyBalances, usefulUnitBalances)
//log.Print("STARTCD: ", cd)
var leftCC *CallCost
@@ -372,13 +401,13 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo
}
for _, increment := range ts.Increments {
cost := increment.Cost
- defaultBalance := ub.GetDefaultMoneyBalance(leftCC.Direction)
+ defaultBalance := ub.GetDefaultMoneyBalance()
defaultBalance.SubstractValue(cost)
increment.BalanceInfo.MoneyBalanceUuid = defaultBalance.Uuid
increment.BalanceInfo.AccountId = ub.Id
increment.paid = true
if count {
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: leftCC.Direction, Balance: &Balance{Value: cost, DestinationIds: leftCC.Destination}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{leftCC.Direction: true}, Value: cost, DestinationIds: utils.NewStringMap(leftCC.Destination)}})
}
}
}
@@ -394,46 +423,43 @@ COMMIT:
return
}
-func (ub *Account) GetDefaultMoneyBalance(direction string) *Balance {
- if direction == "" {
- direction = utils.OUT
- }
- for _, balance := range ub.BalanceMap[utils.MONETARY+direction] {
+func (ub *Account) GetDefaultMoneyBalance() *Balance {
+ for _, balance := range ub.BalanceMap[utils.MONETARY] {
if balance.IsDefault() {
return balance
}
}
// create default balance
defaultBalance := &Balance{
- Uuid: "D" + utils.GenUUID()[1:],
- Weight: 0,
+ Uuid: utils.GenUUID(),
+ Id: utils.META_DEFAULT,
} // minimum weight
if ub.BalanceMap == nil {
ub.BalanceMap = make(map[string]BalanceChain)
}
- ub.BalanceMap[utils.MONETARY+direction] = append(ub.BalanceMap[utils.MONETARY+direction], defaultBalance)
+ ub.BalanceMap[utils.MONETARY] = append(ub.BalanceMap[utils.MONETARY], defaultBalance)
return defaultBalance
}
-func (ub *Account) refundIncrement(increment *Increment, direction, unitType string, count bool) {
+func (ub *Account) refundIncrement(increment *Increment, unitType string, count bool) {
var balance *Balance
if increment.BalanceInfo.UnitBalanceUuid != "" {
- if balance = ub.BalanceMap[unitType+direction].GetBalance(increment.BalanceInfo.UnitBalanceUuid); balance == nil {
+ if balance = ub.BalanceMap[unitType].GetBalance(increment.BalanceInfo.UnitBalanceUuid); balance == nil {
return
}
balance.AddValue(increment.Duration.Seconds())
if count {
- ub.countUnits(&Action{BalanceType: unitType, Direction: direction, Balance: &Balance{Value: -increment.Duration.Seconds()}})
+ ub.countUnits(&Action{BalanceType: unitType, Balance: &Balance{Value: -increment.Duration.Seconds()}})
}
}
// check money too
if increment.BalanceInfo.MoneyBalanceUuid != "" {
- if balance = ub.BalanceMap[utils.MONETARY+direction].GetBalance(increment.BalanceInfo.MoneyBalanceUuid); balance == nil {
+ if balance = ub.BalanceMap[utils.MONETARY].GetBalance(increment.BalanceInfo.MoneyBalanceUuid); balance == nil {
return
}
balance.AddValue(increment.Cost)
if count {
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: direction, Balance: &Balance{Value: -increment.Cost}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: -increment.Cost}})
}
}
}
@@ -474,7 +500,7 @@ func (ub *Account) executeActionTriggers(a *Action) {
}
}
} else { // BALANCE
- for _, b := range ub.BalanceMap[at.BalanceType+at.BalanceDirection] {
+ for _, b := range ub.BalanceMap[at.BalanceType] {
if !b.dirty { // do not check clean balances
continue
}
@@ -519,11 +545,7 @@ func (ub *Account) SetRecurrent(a *Action, recurrent bool) {
// Returns the unit counter that matches the specified action type
func (ub *Account) getUnitCounter(a *Action) *UnitsCounter {
for _, uc := range ub.UnitCounters {
- direction := a.Direction
- if direction == "" {
- direction = utils.OUT
- }
- if uc.BalanceType == a.BalanceType && uc.Direction == direction {
+ if uc.BalanceType == a.BalanceType {
return uc
}
}
@@ -536,11 +558,7 @@ func (ub *Account) countUnits(a *Action) {
unitsCounter := ub.getUnitCounter(a)
// if not found add the counter
if unitsCounter == nil {
- direction := a.Direction
- if direction == "" {
- direction = utils.OUT
- }
- unitsCounter = &UnitsCounter{BalanceType: a.BalanceType, Direction: direction}
+ unitsCounter = &UnitsCounter{BalanceType: a.BalanceType}
ub.UnitCounters = append(ub.UnitCounters, unitsCounter)
}
@@ -548,31 +566,30 @@ func (ub *Account) countUnits(a *Action) {
ub.executeActionTriggers(nil)
}
-// Create minute counters for all triggered actions that have actions opertating on balances
-func (ub *Account) initCounters() {
- ucTempMap := make(map[string]*UnitsCounter, 2)
- for _, at := range ub.ActionTriggers {
+// Create counters for all triggered actions that have actions opertating on balances
+func (acc *Account) initCounters() {
+ ucTempMap := make(map[string]*UnitsCounter)
+ // add default balance
+ for _, at := range acc.ActionTriggers {
acs, err := ratingStorage.GetActions(at.ActionsId, false)
if err != nil {
continue
}
for _, a := range acs {
if a.Balance != nil {
- direction := at.BalanceDirection
- if direction == "" {
- direction = utils.OUT
- }
- uc, exists := ucTempMap[direction]
+ uc, exists := ucTempMap[a.BalanceType]
if !exists {
- uc = &UnitsCounter{BalanceType: a.BalanceType, Direction: direction}
- ucTempMap[direction] = uc
+ uc = &UnitsCounter{BalanceType: a.BalanceType}
+ ucTempMap[a.BalanceType] = uc
uc.Balances = BalanceChain{}
- ub.UnitCounters = append(ub.UnitCounters, uc)
+ acc.UnitCounters = append(acc.UnitCounters, uc)
}
b := a.Balance.Clone()
b.SetValue(0)
- uc.Balances = append(uc.Balances, b)
- uc.Balances.Sort()
+ if !uc.Balances.HasBalance(b) {
+ uc.Balances = append(uc.Balances, b)
+ }
+ //uc.Balances.Sort() // do not sort
}
}
}
@@ -605,8 +622,8 @@ func (ub *Account) allBalancesExpired() bool {
func (ub *Account) GetSharedGroups() (groups []string) {
for _, balanceChain := range ub.BalanceMap {
for _, b := range balanceChain {
- if b.SharedGroup != "" {
- groups = append(groups, b.SharedGroup)
+ for sg := range b.SharedGroups {
+ groups = append(groups, sg)
}
}
}
@@ -615,13 +632,13 @@ func (ub *Account) GetSharedGroups() (groups []string) {
func (account *Account) GetUniqueSharedGroupMembers(cd *CallDescriptor) ([]string, error) {
var balances []*Balance
- balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, account.BalanceMap[utils.MONETARY+cd.Direction], "")...)
- balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, account.BalanceMap[cd.TOR+cd.Direction], "")...)
+ balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, utils.MONETARY, "")...)
+ balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, cd.TOR, "")...)
// gather all shared group ids
var sharedGroupIds []string
for _, b := range balances {
- if b.SharedGroup != "" {
- sharedGroupIds = append(sharedGroupIds, b.SharedGroup)
+ for sg := range b.SharedGroups {
+ sharedGroupIds = append(sharedGroupIds, sg)
}
}
var memberIds []string
@@ -669,7 +686,7 @@ func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balance
b.SubstractValue(connectFee)
// the conect fee is not refundable!
if count {
- acc.countUnits(&Action{BalanceType: utils.MONETARY, Direction: cc.Direction, Balance: &Balance{Value: connectFee, DestinationIds: cc.Destination}})
+ acc.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: connectFee, DestinationIds: utils.StringMap{cc.Destination: true}}})
}
connectFeePaid = true
break
@@ -678,11 +695,151 @@ func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balance
// debit connect fee
if connectFee > 0 && !connectFeePaid {
// there are no money for the connect fee; go negative
- acc.GetDefaultMoneyBalance(cc.Direction).SubstractValue(connectFee)
+ acc.GetDefaultMoneyBalance().SubstractValue(connectFee)
// the conect fee is not refundable!
if count {
- acc.countUnits(&Action{BalanceType: utils.MONETARY, Direction: cc.Direction, Balance: &Balance{Value: connectFee, DestinationIds: cc.Destination}})
+ acc.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: connectFee, DestinationIds: utils.StringMap{cc.Destination: true}}})
}
}
}
}
+
+// used in some api for transition
+func (acc *Account) AsOldStructure() interface{} {
+ type Balance struct {
+ Uuid string //system wide unique
+ Id string // account wide unique
+ Value float64
+ ExpirationDate time.Time
+ Weight float64
+ DestinationIds string
+ RatingSubject string
+ Category string
+ SharedGroup string
+ Timings []*RITiming
+ TimingIDs string
+ Disabled bool
+ precision int
+ account *Account
+ dirty bool
+ }
+ type BalanceChain []*Balance
+ type UnitsCounter struct {
+ Direction string
+ BalanceType string
+ // Units float64
+ Balances BalanceChain // first balance is the general one (no destination)
+ }
+ type ActionTrigger struct {
+ Id string
+ ThresholdType string
+ ThresholdValue float64
+ Recurrent bool
+ MinSleep time.Duration
+ BalanceId string
+ BalanceType string
+ BalanceDirection string
+ BalanceDestinationIds string
+ BalanceWeight float64
+ BalanceExpirationDate time.Time
+ BalanceTimingTags string
+ BalanceRatingSubject string
+ BalanceCategory string
+ BalanceSharedGroup string
+ BalanceDisabled bool
+ Weight float64
+ ActionsId string
+ MinQueuedItems int
+ Executed bool
+ }
+ type ActionTriggers []*ActionTrigger
+ type Account struct {
+ Id string
+ BalanceMap map[string]BalanceChain
+ UnitCounters []*UnitsCounter
+ ActionTriggers ActionTriggers
+ AllowNegative bool
+ Disabled bool
+ }
+
+ result := &Account{
+ Id: acc.Id,
+ BalanceMap: make(map[string]BalanceChain, len(acc.BalanceMap)),
+ UnitCounters: make([]*UnitsCounter, len(acc.UnitCounters)),
+ ActionTriggers: make(ActionTriggers, len(acc.ActionTriggers)),
+ AllowNegative: acc.AllowNegative,
+ Disabled: acc.Disabled,
+ }
+ for i, uc := range acc.UnitCounters {
+ 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 i, at := range acc.ActionTriggers {
+ result.ActionTriggers[i] = &ActionTrigger{
+ Id: at.Id,
+ ThresholdType: at.ThresholdType,
+ ThresholdValue: at.ThresholdValue,
+ Recurrent: at.Recurrent,
+ MinSleep: at.MinSleep,
+ BalanceId: at.BalanceId,
+ BalanceType: at.BalanceType,
+ BalanceDirection: at.BalanceDirections.String(),
+ BalanceDestinationIds: at.BalanceDestinationIds.String(),
+ BalanceWeight: at.BalanceWeight,
+ BalanceExpirationDate: at.BalanceExpirationDate,
+ BalanceTimingTags: at.BalanceTimingTags.String(),
+ BalanceRatingSubject: at.BalanceRatingSubject,
+ BalanceCategory: at.BalanceCategories.String(),
+ BalanceSharedGroup: at.BalanceSharedGroups.String(),
+ BalanceDisabled: at.BalanceDisabled,
+ Weight: at.Weight,
+ ActionsId: at.ActionsId,
+ MinQueuedItems: at.MinQueuedItems,
+ Executed: at.Executed,
+ }
+ }
+ for key, values := range acc.BalanceMap {
+ if len(values) > 0 {
+ key += values[0].Directions.String()
+ result.BalanceMap[key] = make(BalanceChain, len(values))
+ for i, b := range values {
+ result.BalanceMap[key][i] = &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,
+ }
+ }
+ }
+ }
+ return result
+}
diff --git a/engine/account_test.go b/engine/account_test.go
index 73b1826f8..799177a78 100644
--- a/engine/account_test.go
+++ b/engine/account_test.go
@@ -43,8 +43,9 @@ func TestBalanceStoreRestore(t *testing.T) {
if err != nil {
t.Error("Error restoring balance: ", err)
}
+ t.Logf("INITIAL: %+v", b)
if !b.Equal(b1) {
- t.Errorf("Balance store/restore failed: expected %v was %v", b, b1)
+ t.Errorf("Balance store/restore failed: expected %+v was %+v", b, b1)
}
}
@@ -82,21 +83,21 @@ func TestBalanceChainStoreRestore(t *testing.T) {
}
func TestAccountStorageStoreRestore(t *testing.T) {
- b1 := &Balance{Value: 10, Weight: 10, DestinationIds: "NAT"}
- b2 := &Balance{Value: 100, Weight: 20, DestinationIds: "RET"}
- rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b1, b2}, utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}}}}
+ b1 := &Balance{Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}}
+ b2 := &Balance{Value: 100, Weight: 20, DestinationIds: utils.StringMap{"RET": true}}
+ rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b1, b2}, utils.MONETARY: BalanceChain{&Balance{Value: 21}}}}
accountingStorage.SetAccount(rifsBalance)
ub1, err := accountingStorage.GetAccount("other")
- if err != nil || !ub1.BalanceMap[utils.MONETARY+utils.OUT].Equal(rifsBalance.BalanceMap[utils.MONETARY+utils.OUT]) {
+ if err != nil || !ub1.BalanceMap[utils.MONETARY].Equal(rifsBalance.BalanceMap[utils.MONETARY]) {
t.Log("UB: ", ub1)
- t.Errorf("Expected %v was %v", rifsBalance.BalanceMap[utils.MONETARY+utils.OUT], ub1.BalanceMap[utils.MONETARY+utils.OUT])
+ t.Errorf("Expected %v was %v", rifsBalance.BalanceMap[utils.MONETARY], ub1.BalanceMap[utils.MONETARY])
}
}
func TestGetSecondsForPrefix(t *testing.T) {
- b1 := &Balance{Value: 10, Weight: 10, DestinationIds: "NAT"}
- b2 := &Balance{Value: 100, Weight: 20, DestinationIds: "RET"}
- ub1 := &Account{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b1, b2}, utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 200}}}}
+ b1 := &Balance{Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}}
+ b2 := &Balance{Value: 100, Weight: 20, DestinationIds: utils.StringMap{"RET": true}}
+ ub1 := &Account{Id: "CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b1, b2}, utils.MONETARY: BalanceChain{&Balance{Value: 200}}}}
cd := &CallDescriptor{
Category: "0",
Tenant: "vdf",
@@ -117,14 +118,14 @@ func TestGetSecondsForPrefix(t *testing.T) {
}
func TestGetSpecialPricedSeconds(t *testing.T) {
- b1 := &Balance{Value: 10, Weight: 10, DestinationIds: "NAT", RatingSubject: "minu"}
- b2 := &Balance{Value: 100, Weight: 20, DestinationIds: "RET", RatingSubject: "minu"}
+ b1 := &Balance{Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "minu"}
+ b2 := &Balance{Value: 100, Weight: 20, DestinationIds: utils.StringMap{"RET": true}, RatingSubject: "minu"}
ub1 := &Account{
Id: "OUT:CUSTOMER_1:rif",
BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1, b2},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}},
+ utils.VOICE: BalanceChain{b1, b2},
+ utils.MONETARY: BalanceChain{&Balance{Value: 21}},
},
}
cd := &CallDescriptor{
@@ -146,22 +147,22 @@ func TestGetSpecialPricedSeconds(t *testing.T) {
}
func TestAccountStorageStore(t *testing.T) {
- b1 := &Balance{Value: 10, Weight: 10, DestinationIds: "NAT"}
- b2 := &Balance{Value: 100, Weight: 20, DestinationIds: "RET"}
- rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b1, b2}, utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}}}}
+ b1 := &Balance{Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}}
+ b2 := &Balance{Value: 100, Weight: 20, DestinationIds: utils.StringMap{"RET": true}}
+ rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b1, b2}, utils.MONETARY: BalanceChain{&Balance{Value: 21}}}}
accountingStorage.SetAccount(rifsBalance)
result, err := accountingStorage.GetAccount(rifsBalance.Id)
if err != nil || rifsBalance.Id != result.Id ||
- len(rifsBalance.BalanceMap[utils.VOICE+utils.OUT]) < 2 || len(result.BalanceMap[utils.VOICE+utils.OUT]) < 2 ||
- !(rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].Equal(result.BalanceMap[utils.VOICE+utils.OUT][0])) ||
- !(rifsBalance.BalanceMap[utils.VOICE+utils.OUT][1].Equal(result.BalanceMap[utils.VOICE+utils.OUT][1])) ||
- !rifsBalance.BalanceMap[utils.MONETARY+utils.OUT].Equal(result.BalanceMap[utils.MONETARY+utils.OUT]) {
+ len(rifsBalance.BalanceMap[utils.VOICE]) < 2 || len(result.BalanceMap[utils.VOICE]) < 2 ||
+ !(rifsBalance.BalanceMap[utils.VOICE][0].Equal(result.BalanceMap[utils.VOICE][0])) ||
+ !(rifsBalance.BalanceMap[utils.VOICE][1].Equal(result.BalanceMap[utils.VOICE][1])) ||
+ !rifsBalance.BalanceMap[utils.MONETARY].Equal(result.BalanceMap[utils.MONETARY]) {
t.Errorf("Expected %v was %v", rifsBalance, result)
}
}
func TestDebitCreditZeroSecond(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Value: 10, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1s"}
+ b1 := &Balance{Uuid: "testb", Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1s"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -184,7 +185,7 @@ func TestDebitCreditZeroSecond(t *testing.T) {
TOR: utils.VOICE,
testCallcost: cc,
}
- rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b1}, utils.MONETARY + utils.OUT: BalanceChain{&Balance{Category: "0", Value: 21}}}}
+ rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b1}, utils.MONETARY: BalanceChain{&Balance{Categories: utils.NewStringMap("0"), Value: 21}}}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
if err != nil {
@@ -194,14 +195,14 @@ func TestDebitCreditZeroSecond(t *testing.T) {
t.Logf("%+v", cc.Timespans[0])
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 0 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 21 {
- t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0])
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 0 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 21 {
+ t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.VOICE][0])
}
}
func TestDebitCreditZeroMinute(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1m"}
+ b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1m"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -225,8 +226,8 @@ func TestDebitCreditZeroMinute(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}},
+ utils.VOICE: BalanceChain{b1},
+ utils.MONETARY: BalanceChain{&Balance{Value: 21}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -238,16 +239,16 @@ func TestDebitCreditZeroMinute(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != time.Minute {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 10 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 21 {
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 10 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 21 {
t.Error("Error extracting minutes from balance: ",
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0])
+ rifsBalance.BalanceMap[utils.VOICE][0])
}
}
func TestDebitCreditZeroMixedMinute(t *testing.T) {
- b1 := &Balance{Uuid: "testm", Value: 70, Weight: 5, DestinationIds: "NAT", RatingSubject: "*zero1m"}
- b2 := &Balance{Uuid: "tests", Value: 10, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1s"}
+ b1 := &Balance{Uuid: "testm", Value: 70, Weight: 5, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1m"}
+ b2 := &Balance{Uuid: "tests", Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1s"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -272,8 +273,8 @@ func TestDebitCreditZeroMixedMinute(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1, b2},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}},
+ utils.VOICE: BalanceChain{b1, b2},
+ utils.MONETARY: BalanceChain{&Balance{Value: 21}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -284,17 +285,17 @@ func TestDebitCreditZeroMixedMinute(t *testing.T) {
cc.Timespans[1].Increments[0].BalanceInfo.UnitBalanceUuid != "testm" {
t.Error("Error setting balance id to increment: ", cc.Timespans)
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][1].GetValue() != 0 ||
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 10 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 21 {
+ if rifsBalance.BalanceMap[utils.VOICE][1].GetValue() != 0 ||
+ rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 10 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 21 {
t.Logf("TS0: %+v", cc.Timespans[0])
t.Logf("TS1: %+v", cc.Timespans[1])
- t.Errorf("Error extracting minutes from balance: %+v", rifsBalance.BalanceMap[utils.VOICE+utils.OUT][1])
+ t.Errorf("Error extracting minutes from balance: %+v", rifsBalance.BalanceMap[utils.VOICE][1])
}
}
func TestDebitCreditNoCredit(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1m"}
+ b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1m"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -324,7 +325,7 @@ func TestDebitCreditNoCredit(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1},
+ utils.VOICE: BalanceChain{b1},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -335,9 +336,9 @@ func TestDebitCreditNoCredit(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != time.Minute {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 10 {
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 10 {
t.Error("Error extracting minutes from balance: ",
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0])
+ rifsBalance.BalanceMap[utils.VOICE][0])
}
if len(cc.Timespans) != 1 || cc.Timespans[0].GetDuration() != time.Minute {
t.Error("Error truncating extra timespans: ", cc.Timespans)
@@ -345,7 +346,7 @@ func TestDebitCreditNoCredit(t *testing.T) {
}
func TestDebitCreditHasCredit(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1m"}
+ b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1m"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -375,8 +376,8 @@ func TestDebitCreditHasCredit(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneya", Value: 110}},
+ utils.VOICE: BalanceChain{b1},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneya", Value: 110}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -387,10 +388,10 @@ func TestDebitCreditHasCredit(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != time.Minute {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 10 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 30 {
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 10 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 30 {
t.Errorf("Error extracting minutes from balance: %+v, %+v",
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ rifsBalance.BalanceMap[utils.VOICE][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
if len(cc.Timespans) != 3 || cc.Timespans[0].GetDuration() != time.Minute {
t.Error("Error truncating extra timespans: ", cc.Timespans)
@@ -398,7 +399,7 @@ func TestDebitCreditHasCredit(t *testing.T) {
}
func TestDebitCreditSplitMinutesMoney(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Value: 10, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1s"}
+ b1 := &Balance{Uuid: "testb", Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1s"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -423,8 +424,8 @@ func TestDebitCreditSplitMinutesMoney(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneya", Value: 50}},
+ utils.VOICE: BalanceChain{b1},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneya", Value: 50}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -435,10 +436,10 @@ func TestDebitCreditSplitMinutesMoney(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != 1*time.Second {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0].Duration)
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 0 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 30 {
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 0 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 30 {
t.Errorf("Error extracting minutes from balance: %+v, %+v",
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ rifsBalance.BalanceMap[utils.VOICE][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
if len(cc.Timespans) != 2 || cc.Timespans[0].GetDuration() != 10*time.Second || cc.Timespans[1].GetDuration() != 20*time.Second {
t.Error("Error truncating extra timespans: ", cc.Timespans[1].GetDuration())
@@ -446,7 +447,7 @@ func TestDebitCreditSplitMinutesMoney(t *testing.T) {
}
func TestDebitCreditMoreTimespans(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Value: 150, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1m"}
+ b1 := &Balance{Uuid: "testb", Value: 150, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1m"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -476,7 +477,7 @@ func TestDebitCreditMoreTimespans(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1},
+ utils.VOICE: BalanceChain{b1},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -487,15 +488,15 @@ func TestDebitCreditMoreTimespans(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != time.Minute {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 30 {
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 30 {
t.Error("Error extracting minutes from balance: ",
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0])
+ rifsBalance.BalanceMap[utils.VOICE][0])
}
}
func TestDebitCreditMoreTimespansMixed(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1m"}
- b2 := &Balance{Uuid: "testa", Value: 150, Weight: 5, DestinationIds: "NAT", RatingSubject: "*zero1s"}
+ b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1m"}
+ b2 := &Balance{Uuid: "testa", Value: 150, Weight: 5, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1s"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -525,7 +526,7 @@ func TestDebitCreditMoreTimespansMixed(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1, b2},
+ utils.VOICE: BalanceChain{b1, b2},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -536,15 +537,15 @@ func TestDebitCreditMoreTimespansMixed(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != time.Minute {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 10 ||
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][1].GetValue() != 130 {
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 10 ||
+ rifsBalance.BalanceMap[utils.VOICE][1].GetValue() != 130 {
t.Error("Error extracting minutes from balance: ",
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][1], cc.Timespans[1])
+ rifsBalance.BalanceMap[utils.VOICE][1], cc.Timespans[1])
}
}
func TestDebitCreditNoConectFeeCredit(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: "NAT", RatingSubject: "*zero1m"}
+ b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "*zero1m"}
cc := &CallCost{
Direction: utils.OUT,
Destination: "0723045326",
@@ -575,7 +576,7 @@ func TestDebitCreditNoConectFeeCredit(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1},
+ utils.VOICE: BalanceChain{b1},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -583,8 +584,8 @@ func TestDebitCreditNoConectFeeCredit(t *testing.T) {
t.Error("Error showing debiting balance error: ", err)
}
- if len(cc.Timespans) != 1 || rifsBalance.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() != 0 {
- t.Error("Error cutting at no connect fee: ", rifsBalance.BalanceMap[utils.MONETARY+utils.OUT])
+ if len(cc.Timespans) != 1 || rifsBalance.BalanceMap[utils.MONETARY].GetTotalValue() != 0 {
+ t.Error("Error cutting at no connect fee: ", rifsBalance.BalanceMap[utils.MONETARY])
}
}
@@ -619,7 +620,7 @@ func TestDebitCreditMoneyOnly(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "money", Value: 50}},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "money", Value: 50}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -631,9 +632,9 @@ func TestDebitCreditMoneyOnly(t *testing.T) {
t.Logf("%+v", cc.Timespans[0].Increments)
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0].BalanceInfo)
}
- if rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 0 {
+ if rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 0 {
t.Error("Error extracting minutes from balance: ",
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0])
+ rifsBalance.BalanceMap[utils.MONETARY][0])
}
if len(cc.Timespans) != 2 ||
cc.Timespans[0].GetDuration() != 10*time.Second ||
@@ -643,7 +644,7 @@ func TestDebitCreditMoneyOnly(t *testing.T) {
}
func TestDebitCreditSubjectMinutes(t *testing.T) {
- b1 := &Balance{Uuid: "testb", Category: "0", Value: 250, Weight: 10, DestinationIds: "NAT", RatingSubject: "minu"}
+ b1 := &Balance{Uuid: "testb", Categories: utils.NewStringMap("0"), Value: 250, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "minu"}
cc := &CallCost{
Tenant: "vdf",
Category: "0",
@@ -672,8 +673,8 @@ func TestDebitCreditSubjectMinutes(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneya", Value: 350}},
+ utils.VOICE: BalanceChain{b1},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneya", Value: 350}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -685,10 +686,10 @@ func TestDebitCreditSubjectMinutes(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != 10*time.Second {
t.Errorf("Error setting balance id to increment: %+v", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 180 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 280 {
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 180 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 280 {
t.Errorf("Error extracting minutes from balance: %+v, %+v",
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ rifsBalance.BalanceMap[utils.VOICE][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
if len(cc.Timespans) != 1 || cc.Timespans[0].GetDuration() != 70*time.Second {
for _, ts := range cc.Timespans {
@@ -727,7 +728,7 @@ func TestDebitCreditSubjectMoney(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneya", Value: 75, DestinationIds: "NAT", RatingSubject: "minu"}},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneya", Value: 75, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "minu"}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -738,9 +739,9 @@ func TestDebitCreditSubjectMoney(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != 10*time.Second {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 5 {
+ if rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 5 {
t.Errorf("Error extracting minutes from balance: %+v",
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
if len(cc.Timespans) != 1 || cc.Timespans[0].GetDuration() != 70*time.Second {
t.Error("Error truncating extra timespans: ", cc.Timespans)
@@ -777,8 +778,8 @@ func TestDebitCreditSubjectMoney(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{b1},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneya", Value: 19500, RatingSubject: "minu"}},
+ utils.VOICE: BalanceChain{b1},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneya", Value: 19500, RatingSubject: "minu"}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -790,10 +791,10 @@ func TestDebitCreditSubjectMoney(t *testing.T) {
cc.Timespans[0].Increments[0].Duration != 10*time.Second {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 0 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 7 {
+ if rifsBalance.BalanceMap[utils.VOICE][0].GetValue() != 0 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 7 {
t.Errorf("Error extracting minutes from balance: %+v, %+v",
- rifsBalance.BalanceMap[utils.VOICE+utils.OUT][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ rifsBalance.BalanceMap[utils.VOICE][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
if len(cc.Timespans) != 2 || cc.Timespans[0].GetDuration() != 40*time.Second {
for _, ts := range cc.Timespans {
@@ -807,13 +808,13 @@ func TestAccountdebitBalance(t *testing.T) {
ub := &Account{
Id: "rif",
AllowNegative: true,
- BalanceMap: map[string]BalanceChain{utils.SMS: BalanceChain{&Balance{Value: 14}}, utils.DATA: BalanceChain{&Balance{Value: 1204}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ BalanceMap: map[string]BalanceChain{utils.SMS: BalanceChain{&Balance{Value: 14}}, utils.DATA: BalanceChain{&Balance{Value: 1204}}, utils.VOICE: BalanceChain{&Balance{Weight: 20, DestinationIds: utils.StringMap{"NAT": true}}, &Balance{Weight: 10, DestinationIds: utils.StringMap{"RET": true}}}},
}
- newMb := &Balance{Weight: 20, DestinationIds: "NEW"}
- a := &Action{BalanceType: utils.VOICE, Direction: utils.OUT, Balance: newMb}
+ newMb := &Balance{Weight: 20, DestinationIds: utils.StringMap{"NEW": true}, Directions: utils.NewStringMap(utils.OUT)}
+ a := &Action{BalanceType: utils.VOICE, Balance: newMb}
ub.debitBalanceAction(a, false)
- if len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 3 || ub.BalanceMap[utils.VOICE+utils.OUT][2].DestinationIds != newMb.DestinationIds {
- t.Errorf("Error adding minute bucket! %d %+v %+v", len(ub.BalanceMap[utils.VOICE+utils.OUT]), ub.BalanceMap[utils.VOICE+utils.OUT][2], newMb)
+ 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)
}
}
@@ -821,13 +822,16 @@ func TestAccountDisableBalance(t *testing.T) {
ub := &Account{
Id: "rif",
AllowNegative: true,
- BalanceMap: map[string]BalanceChain{utils.SMS: BalanceChain{&Balance{Value: 14}}, utils.DATA: BalanceChain{&Balance{Value: 1204}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ BalanceMap: map[string]BalanceChain{utils.SMS: BalanceChain{&Balance{Value: 14}}, utils.DATA: BalanceChain{&Balance{Value: 1204}}, utils.VOICE: BalanceChain{&Balance{Weight: 20, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIds: utils.StringMap{"RET": true}}}},
}
- newMb := &Balance{Weight: 20, DestinationIds: "NAT", Disabled: true}
- a := &Action{BalanceType: utils.VOICE, Direction: utils.OUT, Balance: newMb}
+ newMb := &Balance{Weight: 20, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.NewStringMap(utils.OUT), Disabled: true}
+ a := &Action{BalanceType: utils.VOICE, Balance: newMb}
ub.enableDisableBalanceAction(a)
- if len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 || ub.BalanceMap[utils.VOICE+utils.OUT][0].Disabled != true {
- t.Errorf("Error disabling balance! %d %+v %+v", len(ub.BalanceMap[utils.VOICE+utils.OUT]), ub.BalanceMap[utils.VOICE+utils.OUT][0], newMb)
+ if len(ub.BalanceMap[utils.VOICE]) != 2 || ub.BalanceMap[utils.VOICE][0].Disabled != true {
+ for _, b := range ub.BalanceMap[utils.VOICE] {
+ t.Logf("Balance: %+v", b)
+ }
+ t.Errorf("Error disabling balance! %d %+v %+v", len(ub.BalanceMap[utils.VOICE]), ub.BalanceMap[utils.VOICE][0], newMb)
}
}
@@ -836,12 +840,12 @@ func TestAccountdebitBalanceExists(t *testing.T) {
ub := &Account{
Id: "rif",
AllowNegative: true,
- BalanceMap: map[string]BalanceChain{utils.SMS + utils.OUT: BalanceChain{&Balance{Value: 14}}, utils.DATA + utils.OUT: BalanceChain{&Balance{Value: 1024}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 15, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ BalanceMap: map[string]BalanceChain{utils.SMS: BalanceChain{&Balance{Value: 14}}, utils.DATA: BalanceChain{&Balance{Value: 1024}}, utils.VOICE: BalanceChain{&Balance{Value: 15, Weight: 20, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIds: utils.StringMap{"RET": true}}}},
}
- newMb := &Balance{Value: -10, Weight: 20, DestinationIds: "NAT"}
- a := &Action{BalanceType: utils.VOICE, Direction: utils.OUT, Balance: newMb}
+ newMb := &Balance{Value: -10, Weight: 20, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.NewStringMap(utils.OUT)}
+ a := &Action{BalanceType: utils.VOICE, Balance: newMb}
ub.debitBalanceAction(a, false)
- if len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 || ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 25 {
+ if len(ub.BalanceMap[utils.VOICE]) != 2 || ub.BalanceMap[utils.VOICE][0].GetValue() != 25 {
t.Error("Error adding minute bucket!")
}
}
@@ -850,113 +854,114 @@ func TestAccountAddMinuteNil(t *testing.T) {
ub := &Account{
Id: "rif",
AllowNegative: true,
- BalanceMap: map[string]BalanceChain{utils.SMS + utils.OUT: BalanceChain{&Balance{Value: 14}}, utils.DATA + utils.OUT: BalanceChain{&Balance{Value: 1024}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ BalanceMap: map[string]BalanceChain{utils.SMS: BalanceChain{&Balance{Value: 14}}, utils.DATA: BalanceChain{&Balance{Value: 1024}}, utils.VOICE: BalanceChain{&Balance{Weight: 20, DestinationIds: utils.StringMap{"NAT": true}}, &Balance{Weight: 10, DestinationIds: utils.StringMap{"RET": true}}}},
}
ub.debitBalanceAction(nil, false)
- if len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 {
+ if len(ub.BalanceMap[utils.VOICE]) != 2 {
t.Error("Error adding minute bucket!")
}
}
func TestAccountAddMinutBucketEmpty(t *testing.T) {
- mb1 := &Balance{Value: -10, DestinationIds: "NAT"}
- mb2 := &Balance{Value: -10, DestinationIds: "NAT"}
- mb3 := &Balance{Value: -10, DestinationIds: "OTHER"}
+ mb1 := &Balance{Value: -10, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.StringMap{utils.OUT: true}}
+ mb2 := &Balance{Value: -10, DestinationIds: utils.StringMap{"NAT": true}, Directions: utils.StringMap{utils.OUT: true}}
+ mb3 := &Balance{Value: -10, DestinationIds: utils.StringMap{"OTHER": true}, Directions: utils.StringMap{utils.OUT: true}}
ub := &Account{}
- a := &Action{BalanceType: utils.VOICE, Direction: utils.OUT, Balance: mb1}
+ a := &Action{BalanceType: utils.VOICE, Balance: mb1}
ub.debitBalanceAction(a, false)
- if len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 1 {
- t.Error("Error adding minute bucket: ", ub.BalanceMap[utils.VOICE+utils.OUT])
+ if len(ub.BalanceMap[utils.VOICE]) != 1 {
+ t.Error("Error adding minute bucket: ", ub.BalanceMap[utils.VOICE])
}
- a = &Action{BalanceType: utils.VOICE, Direction: utils.OUT, Balance: mb2}
+ a = &Action{BalanceType: utils.VOICE, Balance: mb2}
ub.debitBalanceAction(a, false)
- if len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 1 || ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 20 {
- t.Error("Error adding minute bucket: ", ub.BalanceMap[utils.VOICE+utils.OUT])
+ if len(ub.BalanceMap[utils.VOICE]) != 1 || ub.BalanceMap[utils.VOICE][0].GetValue() != 20 {
+ t.Error("Error adding minute bucket: ", ub.BalanceMap[utils.VOICE])
}
- a = &Action{BalanceType: utils.VOICE, Direction: utils.OUT, Balance: mb3}
+ a = &Action{BalanceType: utils.VOICE, Balance: mb3}
ub.debitBalanceAction(a, false)
- if len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 {
- t.Error("Error adding minute bucket: ", ub.BalanceMap[utils.VOICE+utils.OUT])
+ if len(ub.BalanceMap[utils.VOICE]) != 2 {
+ t.Error("Error adding minute bucket: ", ub.BalanceMap[utils.VOICE])
}
}
func TestAccountExecuteTriggeredActions(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS"}},
+ 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}}}}},
+ ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.StringMap{utils.OUT: true}, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS"}},
}
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 1}})
- if ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 110 || ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 20 {
- t.Error("Error executing triggered actions", ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue(), ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue())
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}})
+ 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())
}
// are set to executed
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 1}})
- if ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 110 || ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 20 {
- t.Error("Error executing triggered actions", ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue(), ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue())
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 1, Directions: utils.NewStringMap(utils.OUT)}})
+ 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())
}
// we can reset them
ub.ResetActionTriggers(nil)
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}})
- if ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 120 || ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 30 {
- t.Error("Error executing triggered actions", ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue(), ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue())
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}})
+ if ub.BalanceMap[utils.MONETARY][0].GetValue() != 120 || ub.BalanceMap[utils.VOICE][0].GetValue() != 30 {
+ t.Error("Error executing triggered actions", ub.BalanceMap[utils.MONETARY][0].GetValue(), ub.BalanceMap[utils.VOICE][0].GetValue())
}
}
func TestAccountExecuteTriggeredActionsBalance(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 100, ThresholdType: TRIGGER_MIN_COUNTER, ActionsId: "TEST_ACTIONS"}},
+ 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}}}},
+ ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 100, ThresholdType: TRIGGER_MIN_COUNTER, ActionsId: "TEST_ACTIONS"}},
}
ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 1}})
- if ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 110 || ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 20 {
- t.Error("Error executing triggered actions", ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue(), ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue())
+ 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(), len(ub.BalanceMap[utils.MONETARY]))
}
}
func TestAccountExecuteTriggeredActionsOrder(t *testing.T) {
ub := &Account{
Id: "TEST_UB_OREDER",
- BalanceMap: map[string]BalanceChain{utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 100}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS_ORDER"}},
+ 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)}}}},
+ ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS_ORDER"}},
}
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 1}})
- if len(ub.BalanceMap[utils.MONETARY+utils.OUT]) != 1 || ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 10 {
- t.Error("Error executing triggered actions in order", ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 1}})
+ 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])
}
}
func TestCleanExpired(t *testing.T) {
ub := &Account{
Id: "TEST_UB_OREDER",
- BalanceMap: map[string]BalanceChain{utils.MONETARY + utils.OUT: BalanceChain{
+ BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{
&Balance{ExpirationDate: time.Now().Add(10 * time.Second)},
&Balance{ExpirationDate: time.Date(2013, 7, 18, 14, 33, 0, 0, time.UTC)},
- &Balance{ExpirationDate: time.Now().Add(10 * time.Second)}}, utils.VOICE + utils.OUT: BalanceChain{
+ &Balance{ExpirationDate: time.Now().Add(10 * time.Second)}}, utils.VOICE: BalanceChain{
&Balance{ExpirationDate: time.Date(2013, 7, 18, 14, 33, 0, 0, time.UTC)},
&Balance{ExpirationDate: time.Now().Add(10 * time.Second)},
}},
}
ub.CleanExpiredBalances()
- if len(ub.BalanceMap[utils.MONETARY+utils.OUT]) != 2 {
+ if len(ub.BalanceMap[utils.MONETARY]) != 2 {
t.Error("Error cleaning expired balances!")
}
- if len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 1 {
+ if len(ub.BalanceMap[utils.VOICE]) != 1 {
t.Error("Error cleaning expired minute buckets!")
}
}
func TestAccountUnitCounting(t *testing.T) {
ub := &Account{}
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}})
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(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}})
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 20 {
t.Error("Error counting units")
}
@@ -964,15 +969,15 @@ func TestAccountUnitCounting(t *testing.T) {
func TestAccountUnitCountingOutbound(t *testing.T) {
ub := &Account{}
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}})
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(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}})
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(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}})
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 30 {
t.Error("Error counting units")
}
@@ -984,12 +989,12 @@ func TestAccountUnitCountingOutboundInbound(t *testing.T) {
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])
}
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}})
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(&Action{BalanceType: utils.MONETARY, Direction: utils.IN, Balance: &Balance{Value: 10}})
- if len(ub.UnitCounters) != 2 && ub.UnitCounters[1].BalanceType != utils.MONETARY || ub.UnitCounters[0].Balances[0].GetValue() != 20 || ub.UnitCounters[1].Balances[0].GetValue() != 10 {
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.IN)}})
+ 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
t.Error("Error counting units")
}
}
@@ -997,12 +1002,12 @@ func TestAccountUnitCountingOutboundInbound(t *testing.T) {
func TestAccountRefund(t *testing.T) {
ub := &Account{
BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{
+ utils.MONETARY: BalanceChain{
&Balance{Uuid: "moneya", Value: 100},
},
- utils.VOICE + utils.OUT: BalanceChain{
- &Balance{Uuid: "minutea", Value: 10, Weight: 20, DestinationIds: "NAT"},
- &Balance{Uuid: "minuteb", Value: 10, DestinationIds: "RET"},
+ utils.VOICE: BalanceChain{
+ &Balance{Uuid: "minutea", Value: 10, Weight: 20, DestinationIds: utils.StringMap{"NAT": true}},
+ &Balance{Uuid: "minuteb", Value: 10, DestinationIds: utils.StringMap{"RET": true}},
},
},
}
@@ -1012,12 +1017,12 @@ func TestAccountRefund(t *testing.T) {
&Increment{Duration: 4 * time.Second, BalanceInfo: &BalanceInfo{UnitBalanceUuid: "minuteb", MoneyBalanceUuid: ""}},
}
for _, increment := range increments {
- ub.refundIncrement(increment, utils.OUT, utils.VOICE, false)
+ ub.refundIncrement(increment, utils.VOICE, false)
}
- if ub.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 104 ||
- ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 13 ||
- ub.BalanceMap[utils.VOICE+utils.OUT][1].GetValue() != 14 {
- t.Error("Error refounding money: ", ub.BalanceMap[utils.VOICE+utils.OUT][1].GetValue())
+ if ub.BalanceMap[utils.MONETARY][0].GetValue() != 104 ||
+ ub.BalanceMap[utils.VOICE][0].GetValue() != 13 ||
+ ub.BalanceMap[utils.VOICE][1].GetValue() != 14 {
+ t.Error("Error refounding money: ", ub.BalanceMap[utils.VOICE][1].GetValue())
}
}
@@ -1049,10 +1054,10 @@ func TestDebitShared(t *testing.T) {
testCallcost: cc,
}
rif := &Account{Id: "rif", BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneya", Value: 0, SharedGroup: "SG_TEST"}},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneya", Value: 0, SharedGroups: utils.NewStringMap("SG_TEST")}},
}}
groupie := &Account{Id: "groupie", BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneyc", Value: 130, SharedGroup: "SG_TEST"}},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneyc", Value: 130, SharedGroups: utils.NewStringMap("SG_TEST")}},
}}
sg := &SharedGroup{Id: "SG_TEST", MemberIds: []string{rif.Id, groupie.Id}, AccountParameters: map[string]*SharingParameters{"*any": &SharingParameters{Strategy: STRATEGY_MINE_RANDOM}}}
@@ -1064,12 +1069,12 @@ func TestDebitShared(t *testing.T) {
if err != nil {
t.Error("Error debiting balance: ", err)
}
- if rif.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 0 {
- t.Errorf("Error debiting from shared group: %+v", rif.BalanceMap[utils.MONETARY+utils.OUT][0])
+ if rif.BalanceMap[utils.MONETARY][0].GetValue() != 0 {
+ t.Errorf("Error debiting from shared group: %+v", rif.BalanceMap[utils.MONETARY][0])
}
groupie, _ = accountingStorage.GetAccount("groupie")
- if groupie.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 10 {
- t.Errorf("Error debiting from shared group: %+v", groupie.BalanceMap[utils.MONETARY+utils.OUT][0])
+ if groupie.BalanceMap[utils.MONETARY][0].GetValue() != 10 {
+ t.Errorf("Error debiting from shared group: %+v", groupie.BalanceMap[utils.MONETARY][0])
}
if len(cc.Timespans) != 1 {
@@ -1119,10 +1124,10 @@ func TestMaxDurationShared(t *testing.T) {
testCallcost: cc,
}
rif := &Account{Id: "rif", BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneya", Value: 0, SharedGroup: "SG_TEST"}},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneya", Value: 0, SharedGroups: utils.NewStringMap("SG_TEST")}},
}}
groupie := &Account{Id: "groupie", BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Uuid: "moneyc", Value: 130, SharedGroup: "SG_TEST"}},
+ utils.MONETARY: BalanceChain{&Balance{Uuid: "moneyc", Value: 130, SharedGroups: utils.NewStringMap("SG_TEST")}},
}}
sg := &SharedGroup{Id: "SG_TEST", MemberIds: []string{rif.Id, groupie.Id}, AccountParameters: map[string]*SharingParameters{"*any": &SharingParameters{Strategy: STRATEGY_MINE_RANDOM}}}
@@ -1165,8 +1170,8 @@ func TestDebitSMS(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.SMS + utils.OUT: BalanceChain{&Balance{Uuid: "testm", Value: 100, Weight: 5, DestinationIds: "NAT"}},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}},
+ utils.SMS: BalanceChain{&Balance{Uuid: "testm", Value: 100, Weight: 5, DestinationIds: utils.StringMap{"NAT": true}}},
+ utils.MONETARY: BalanceChain{&Balance{Value: 21}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -1176,10 +1181,10 @@ func TestDebitSMS(t *testing.T) {
if cc.Timespans[0].Increments[0].BalanceInfo.UnitBalanceUuid != "testm" {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.SMS+utils.OUT][0].GetValue() != 99 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 21 {
+ if rifsBalance.BalanceMap[utils.SMS][0].GetValue() != 99 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 21 {
t.Log(cc.Timespans[0].Increments)
- t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.SMS+utils.OUT][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.SMS][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
}
@@ -1208,8 +1213,8 @@ func TestDebitGeneric(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.GENERIC + utils.OUT: BalanceChain{&Balance{Uuid: "testm", Value: 100, Weight: 5, DestinationIds: "NAT"}},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}},
+ utils.GENERIC: BalanceChain{&Balance{Uuid: "testm", Value: 100, Weight: 5, DestinationIds: utils.StringMap{"NAT": true}}},
+ utils.MONETARY: BalanceChain{&Balance{Value: 21}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -1219,10 +1224,96 @@ func TestDebitGeneric(t *testing.T) {
if cc.Timespans[0].Increments[0].BalanceInfo.UnitBalanceUuid != "testm" {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
- if rifsBalance.BalanceMap[utils.GENERIC+utils.OUT][0].GetValue() != 99 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 21 {
+ if rifsBalance.BalanceMap[utils.GENERIC][0].GetValue() != 99 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 21 {
t.Log(cc.Timespans[0].Increments)
- t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.GENERIC+utils.OUT][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.GENERIC][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
+ }
+}
+
+func TestDebitGenericBalance(t *testing.T) {
+ cc := &CallCost{
+ Direction: utils.OUT,
+ Destination: "0723045326",
+ Timespans: []*TimeSpan{
+ &TimeSpan{
+ TimeStart: time.Date(2013, 9, 24, 10, 48, 0, 0, time.UTC),
+ TimeEnd: time.Date(2013, 9, 24, 10, 48, 30, 0, time.UTC),
+ ratingInfo: &RatingInfo{},
+ DurationIndex: 0,
+ RateInterval: &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 100, RateIncrement: 1 * time.Second, RateUnit: time.Second}}}},
+ },
+ },
+ TOR: utils.VOICE,
+ }
+ cd := &CallDescriptor{
+ TimeStart: cc.Timespans[0].TimeStart,
+ TimeEnd: cc.Timespans[0].TimeEnd,
+ Direction: cc.Direction,
+ Destination: cc.Destination,
+ TOR: cc.TOR,
+ DurationIndex: cc.GetDuration(),
+ testCallcost: cc,
+ }
+ rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
+ utils.GENERIC: BalanceChain{&Balance{Uuid: "testm", Value: 100, Weight: 5, DestinationIds: utils.StringMap{"NAT": true}, Factor: ValueFactor{utils.VOICE: 60.0}}},
+ utils.MONETARY: BalanceChain{&Balance{Value: 21}},
+ }}
+ var err error
+ cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
+ if err != nil {
+ t.Error("Error debiting balance: ", err)
+ }
+ if cc.Timespans[0].Increments[0].BalanceInfo.UnitBalanceUuid != "testm" {
+ t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
+ }
+ if rifsBalance.BalanceMap[utils.GENERIC][0].GetValue() != 99.4999 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 21 {
+ t.Logf("%+v", cc.Timespans[0].Increments[0])
+ t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.GENERIC][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
+ }
+}
+
+func TestDebitGenericBalanceWithRatingSubject(t *testing.T) {
+ cc := &CallCost{
+ Direction: utils.OUT,
+ Destination: "0723045326",
+ Timespans: []*TimeSpan{
+ &TimeSpan{
+ TimeStart: time.Date(2013, 9, 24, 10, 48, 0, 0, time.UTC),
+ TimeEnd: time.Date(2013, 9, 24, 10, 48, 30, 0, time.UTC),
+ ratingInfo: &RatingInfo{},
+ DurationIndex: 0,
+ RateInterval: &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 0, RateIncrement: time.Second, RateUnit: time.Second}}}},
+ },
+ },
+ TOR: utils.VOICE,
+ }
+ cd := &CallDescriptor{
+ TimeStart: cc.Timespans[0].TimeStart,
+ TimeEnd: cc.Timespans[0].TimeEnd,
+ Direction: cc.Direction,
+ Destination: cc.Destination,
+ TOR: cc.TOR,
+ DurationIndex: cc.GetDuration(),
+ testCallcost: cc,
+ }
+ rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
+ utils.GENERIC: BalanceChain{&Balance{Uuid: "testm", Value: 100, Weight: 5, DestinationIds: utils.StringMap{"NAT": true}, Factor: ValueFactor{utils.VOICE: 60.0}, RatingSubject: "free"}},
+ utils.MONETARY: BalanceChain{&Balance{Value: 21}},
+ }}
+ var err error
+ cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
+ if err != nil {
+ t.Error("Error debiting balance: ", err)
+ }
+ if cc.Timespans[0].Increments[0].BalanceInfo.UnitBalanceUuid != "testm" {
+ t.Error("Error setting balance id to increment: ", cc.Timespans[0])
+ }
+ if rifsBalance.BalanceMap[utils.GENERIC][0].GetValue() != 99.4999 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 21 {
+ t.Logf("%+v", cc.Timespans[0].Increments[0])
+ t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.GENERIC][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
}
@@ -1258,8 +1349,8 @@ func TestDebitDataUnits(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.DATA + utils.OUT: BalanceChain{&Balance{Uuid: "testm", Value: 100, Weight: 5, DestinationIds: "NAT"}},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}},
+ utils.DATA: BalanceChain{&Balance{Uuid: "testm", Value: 100, Weight: 5, DestinationIds: utils.StringMap{"NAT": true}}},
+ utils.MONETARY: BalanceChain{&Balance{Value: 21}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
@@ -1274,10 +1365,10 @@ func TestDebitDataUnits(t *testing.T) {
if ts.Increments[0].BalanceInfo.UnitBalanceUuid != "testm" {
t.Error("Error setting balance id to increment: ", ts.Increments[0])
}
- if rifsBalance.BalanceMap[utils.DATA+utils.OUT][0].GetValue() != 20 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 21 {
+ if rifsBalance.BalanceMap[utils.DATA][0].GetValue() != 20 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 21 {
t.Log(ts.Increments)
- t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.DATA+utils.OUT][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.DATA][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
}
@@ -1312,23 +1403,23 @@ func TestDebitDataMoney(t *testing.T) {
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
- utils.DATA + utils.OUT: BalanceChain{&Balance{Uuid: "testm", Value: 0, Weight: 5, DestinationIds: "NAT"}},
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 160}},
+ utils.DATA: BalanceChain{&Balance{Uuid: "testm", Value: 0, Weight: 5, DestinationIds: utils.StringMap{"NAT": true}}},
+ utils.MONETARY: BalanceChain{&Balance{Value: 160}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
if err != nil {
t.Error("Error debiting balance: ", err)
}
- if rifsBalance.BalanceMap[utils.DATA+utils.OUT][0].GetValue() != 0 ||
- rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 0 {
- t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.DATA+utils.OUT][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue())
+ if rifsBalance.BalanceMap[utils.DATA][0].GetValue() != 0 ||
+ rifsBalance.BalanceMap[utils.MONETARY][0].GetValue() != 0 {
+ t.Error("Error extracting minutes from balance: ", rifsBalance.BalanceMap[utils.DATA][0].GetValue(), rifsBalance.BalanceMap[utils.MONETARY][0].GetValue())
}
}
func TestAccountGetDefaultMoneyBalanceEmpty(t *testing.T) {
acc := &Account{}
- defBal := acc.GetDefaultMoneyBalance(utils.OUT)
+ defBal := acc.GetDefaultMoneyBalance()
if defBal == nil || len(acc.BalanceMap) != 1 || !defBal.IsDefault() {
t.Errorf("Bad default money balance: %+v", defBal)
}
@@ -1337,9 +1428,9 @@ func TestAccountGetDefaultMoneyBalanceEmpty(t *testing.T) {
func TestAccountGetDefaultMoneyBalance(t *testing.T) {
acc := &Account{}
acc.BalanceMap = make(map[string]BalanceChain)
- tag := utils.MONETARY + utils.OUT
+ tag := utils.MONETARY
acc.BalanceMap[tag] = append(acc.BalanceMap[tag], &Balance{Weight: 10})
- defBal := acc.GetDefaultMoneyBalance(utils.OUT)
+ defBal := acc.GetDefaultMoneyBalance()
if defBal == nil || len(acc.BalanceMap[tag]) != 2 || !defBal.IsDefault() {
t.Errorf("Bad default money balance: %+v", defBal)
}
@@ -1349,10 +1440,10 @@ func TestAccountGetDefaultMoneyBalance(t *testing.T) {
func BenchmarkGetSecondForPrefix(b *testing.B) {
b.StopTimer()
- b1 := &Balance{Value: 10, Weight: 10, DestinationIds: "NAT"}
- b2 := &Balance{Value: 100, Weight: 20, DestinationIds: "RET"}
+ b1 := &Balance{Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}}
+ b2 := &Balance{Value: 100, Weight: 20, DestinationIds: utils.StringMap{"RET": true}}
- ub1 := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b1, b2}, utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}}}}
+ ub1 := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b1, b2}, utils.MONETARY: BalanceChain{&Balance{Value: 21}}}}
cd := &CallDescriptor{
Destination: "0723",
}
@@ -1363,9 +1454,9 @@ func BenchmarkGetSecondForPrefix(b *testing.B) {
}
func BenchmarkAccountStorageStoreRestore(b *testing.B) {
- b1 := &Balance{Value: 10, Weight: 10, DestinationIds: "NAT"}
- b2 := &Balance{Value: 100, Weight: 20, DestinationIds: "RET"}
- rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b1, b2}, utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}}}}
+ b1 := &Balance{Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}}
+ b2 := &Balance{Value: 100, Weight: 20, DestinationIds: utils.StringMap{"RET": true}}
+ rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b1, b2}, utils.MONETARY: BalanceChain{&Balance{Value: 21}}}}
for i := 0; i < b.N; i++ {
accountingStorage.SetAccount(rifsBalance)
accountingStorage.GetAccount(rifsBalance.Id)
@@ -1373,9 +1464,9 @@ func BenchmarkAccountStorageStoreRestore(b *testing.B) {
}
func BenchmarkGetSecondsForPrefix(b *testing.B) {
- b1 := &Balance{Value: 10, Weight: 10, DestinationIds: "NAT"}
- b2 := &Balance{Value: 100, Weight: 20, DestinationIds: "RET"}
- ub1 := &Account{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b1, b2}, utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 21}}}}
+ b1 := &Balance{Value: 10, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}}
+ b2 := &Balance{Value: 100, Weight: 20, DestinationIds: utils.StringMap{"RET": true}}
+ ub1 := &Account{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b1, b2}, utils.MONETARY: BalanceChain{&Balance{Value: 21}}}}
cd := &CallDescriptor{
Destination: "0723",
}
diff --git a/engine/action.go b/engine/action.go
index 3d586991a..0a2e9d592 100644
--- a/engine/action.go
+++ b/engine/action.go
@@ -41,7 +41,6 @@ type Action struct {
Id string
ActionType string
BalanceType string
- Direction string
ExtraParameters string
ExpirationString string
Weight float64
@@ -78,7 +77,6 @@ func (a *Action) Clone() *Action {
Id: a.Id,
ActionType: a.ActionType,
BalanceType: a.BalanceType,
- Direction: a.Direction,
ExtraParameters: a.ExtraParameters,
ExpirationString: a.ExpirationString,
Weight: a.Weight,
@@ -148,9 +146,9 @@ func logAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (er
// Used by cdrLogAction to dynamically parse values out of account and action
func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action) string {
- dta, err := utils.NewDTAFromAccountKey(acnt.Id) // Account information should be valid
+ dta, err := utils.NewTAFromAccountKey(acnt.Id) // Account information should be valid
if err != nil {
- dta = new(utils.DirectionTenantAccount) // Init with empty values
+ dta = new(utils.TenantAccount) // Init with empty values
}
var parsedValue string // Template values
for _, rsrFld := range rsrFlds {
@@ -158,7 +156,7 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action)
case "account_id":
parsedValue += rsrFld.ParseValue(acnt.Id)
case "direction":
- parsedValue += rsrFld.ParseValue(dta.Direction)
+ parsedValue += rsrFld.ParseValue(action.Balance.Directions.String())
case "tenant":
parsedValue += rsrFld.ParseValue(dta.Tenant)
case "account":
@@ -176,15 +174,15 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action)
case "balance_value":
parsedValue += rsrFld.ParseValue(strconv.FormatFloat(action.Balance.GetValue(), 'f', -1, 64))
case "destination_id":
- parsedValue += rsrFld.ParseValue(action.Balance.DestinationIds)
+ parsedValue += rsrFld.ParseValue(action.Balance.DestinationIds.String())
case "extra_params":
parsedValue += rsrFld.ParseValue(action.ExtraParameters)
case "rating_subject":
parsedValue += rsrFld.ParseValue(action.Balance.RatingSubject)
case "category":
- parsedValue += rsrFld.ParseValue(action.Balance.Category)
+ parsedValue += rsrFld.ParseValue(action.Balance.Categories.String())
case "shared_group":
- parsedValue += rsrFld.ParseValue(action.Balance.SharedGroup)
+ parsedValue += rsrFld.ParseValue(action.Balance.SharedGroups.String())
default:
parsedValue += rsrFld.ParseValue("") // Mostly for static values
}
@@ -362,7 +360,7 @@ func resetCounterAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Act
}
uc := ub.getUnitCounter(a)
if uc == nil {
- uc = &UnitsCounter{BalanceType: a.BalanceType, Direction: a.Direction}
+ uc = &UnitsCounter{BalanceType: a.BalanceType}
ub.UnitCounters = append(ub.UnitCounters, uc)
}
uc.initBalances(ub.ActionTriggers)
diff --git a/engine/action_trigger.go b/engine/action_trigger.go
index c15c0c6f2..57177b2cc 100644
--- a/engine/action_trigger.go
+++ b/engine/action_trigger.go
@@ -23,7 +23,6 @@ import (
"fmt"
"regexp"
"sort"
- "strings"
"time"
"github.com/cgrates/cgrates/utils"
@@ -38,15 +37,15 @@ type ActionTrigger struct {
MinSleep time.Duration // Minimum duration between two executions in case of recurrent triggers
BalanceId string
BalanceType string
- BalanceDirection string
- BalanceDestinationIds string // filter for balance
- BalanceWeight float64 // filter for balance
- BalanceExpirationDate time.Time // filter for balance
- BalanceTimingTags string // filter for balance
- BalanceRatingSubject string // filter for balance
- BalanceCategory string // filter for balance
- BalanceSharedGroup string // filter for balance
- BalanceDisabled bool // filter for balance
+ BalanceDirections utils.StringMap // filter for balance
+ BalanceDestinationIds utils.StringMap // filter for balance
+ BalanceWeight float64 // filter for balance
+ BalanceExpirationDate time.Time // filter for balance
+ BalanceTimingTags utils.StringMap // filter for balance
+ BalanceRatingSubject string // filter for balance
+ BalanceCategories utils.StringMap // filter for balance
+ BalanceSharedGroups utils.StringMap // filter for balance
+ BalanceDisabled bool // filter for balance
Weight float64
ActionsId string
MinQueuedItems int // Trigger actions only if this number is hit (stats only)
@@ -111,36 +110,33 @@ func (at *ActionTrigger) Match(a *Action) bool {
return match
}
id := a.BalanceType == "" || at.BalanceType == a.BalanceType
- direction := a.Direction == "" || at.BalanceDirection == a.Direction
- thresholdType, thresholdValue, destinationId, weight, ratingSubject, category, sharedGroup, disabled := true, true, true, true, true, true, true, true
+ thresholdType, thresholdValue, direction, destinationId, weight, ratingSubject, categories, sharedGroup, timings, disabled := true, true, true, true, true, true, true, true, true, true
if a.ExtraParameters != "" {
t := struct {
ThresholdType string
ThresholdValue float64
- DestinationId string
+ DestinationIds string
+ BalanceDirections string
BalanceWeight float64
BalanceRatingSubject string
- BalanceCategory string
- BalanceSharedGroup string
+ BalanceCategories string
+ BalanceSharedGroups string
+ BalanceTimingTags string
BalanceDisabled bool
}{}
json.Unmarshal([]byte(a.ExtraParameters), &t)
thresholdType = t.ThresholdType == "" || at.ThresholdType == t.ThresholdType
thresholdValue = t.ThresholdValue == 0 || at.ThresholdValue == t.ThresholdValue
- destinationId = t.DestinationId == "" || strings.Contains(at.BalanceDestinationIds, t.DestinationId)
+ direction = len(t.BalanceDirections) == 0 || at.BalanceDirections.Equal(utils.ParseStringMap(t.BalanceDirections))
+ destinationId = len(t.DestinationIds) == 0 || at.BalanceDestinationIds.Equal(utils.ParseStringMap(t.DestinationIds))
+ categories = len(t.BalanceCategories) == 0 || at.BalanceCategories.Equal(utils.ParseStringMap(t.BalanceCategories))
+ timings = len(t.BalanceTimingTags) == 0 || at.BalanceTimingTags.Equal(utils.ParseStringMap(t.BalanceTimingTags))
+ sharedGroup = len(t.BalanceSharedGroups) == 0 || at.BalanceSharedGroups.Equal(utils.ParseStringMap(t.BalanceSharedGroups))
weight = t.BalanceWeight == 0 || at.BalanceWeight == t.BalanceWeight
ratingSubject = t.BalanceRatingSubject == "" || at.BalanceRatingSubject == t.BalanceRatingSubject
- category = t.BalanceCategory == "" || at.BalanceCategory == t.BalanceCategory
- sharedGroup = t.BalanceSharedGroup == "" || at.BalanceSharedGroup == t.BalanceSharedGroup
disabled = at.BalanceDisabled == t.BalanceDisabled
}
- return id && direction && thresholdType && thresholdValue && destinationId && weight && ratingSubject && category && sharedGroup && disabled
-}
-
-func (at *ActionTrigger) sortDestinationIds() string {
- destIds := strings.Split(at.BalanceDestinationIds, utils.INFIELD_SEP)
- sort.StringSlice(destIds).Sort()
- return strings.Join(destIds, utils.INFIELD_SEP)
+ return id && direction && thresholdType && thresholdValue && destinationId && weight && ratingSubject && categories && sharedGroup && timings && disabled
}
// makes a shallow copy of the receiver
@@ -150,6 +146,20 @@ func (at *ActionTrigger) Clone() *ActionTrigger {
return clone
}
+func (at *ActionTrigger) CreateBalance() *Balance {
+ return &Balance{
+ Directions: at.BalanceDirections,
+ ExpirationDate: at.BalanceExpirationDate,
+ Weight: at.BalanceWeight,
+ DestinationIds: at.BalanceDestinationIds,
+ RatingSubject: at.BalanceRatingSubject,
+ Categories: at.BalanceCategories,
+ SharedGroups: at.BalanceSharedGroups,
+ TimingIDs: at.BalanceTimingTags,
+ Disabled: at.BalanceDisabled,
+ }
+}
+
// Structure to store actions according to weight
type ActionTriggers []*ActionTrigger
diff --git a/engine/actions_local_test.go b/engine/actions_local_test.go
index b6da14eba..eea4919f8 100644
--- a/engine/actions_local_test.go
+++ b/engine/actions_local_test.go
@@ -84,14 +84,14 @@ func TestActionsLocalSetCdrlogActions(t *testing.T) {
return
}
var reply string
- attrsSetAccount := &utils.AttrSetAccount{Tenant: "cgrates.org", Direction: utils.OUT, Account: "dan2904"}
+ attrsSetAccount := &utils.AttrSetAccount{Tenant: "cgrates.org", Account: "dan2904"}
if err := actsLclRpc.Call("ApierV1.SetAccount", attrsSetAccount, &reply); err != nil {
t.Error("Got error on ApierV1.SetAccount: ", err.Error())
} else if reply != utils.OK {
t.Errorf("Calling ApierV1.SetAccount received: %s", reply)
}
attrsAA := &utils.AttrSetActions{ActionsId: "ACTS_1", Actions: []*utils.TPAction{
- &utils.TPAction{Identifier: DEBIT, BalanceType: utils.MONETARY, Direction: attrsSetAccount.Direction, Units: 5.0, ExpiryTime: UNLIMITED, Weight: 20.0},
+ &utils.TPAction{Identifier: DEBIT, BalanceType: utils.MONETARY, Units: 5.0, ExpiryTime: UNLIMITED, Weight: 20.0},
&utils.TPAction{Identifier: CDRLOG},
}}
if err := actsLclRpc.Call("ApierV1.SetActions", attrsAA, &reply); err != nil && err.Error() != utils.ErrExists.Error() {
@@ -99,7 +99,7 @@ func TestActionsLocalSetCdrlogActions(t *testing.T) {
} else if reply != utils.OK {
t.Errorf("Calling ApierV1.SetActions received: %s", reply)
}
- attrsEA := &utils.AttrExecuteAction{Direction: attrsSetAccount.Direction, Tenant: attrsSetAccount.Tenant, Account: attrsSetAccount.Account, ActionsId: attrsAA.ActionsId}
+ attrsEA := &utils.AttrExecuteAction{Tenant: attrsSetAccount.Tenant, Account: attrsSetAccount.Account, ActionsId: attrsAA.ActionsId}
if err := actsLclRpc.Call("ApierV1.ExecuteAction", attrsEA, &reply); err != nil {
t.Error("Got error on ApierV1.ExecuteAction: ", err.Error())
} else if reply != utils.OK {
diff --git a/engine/actions_test.go b/engine/actions_test.go
index b4a35883d..7896008bb 100644
--- a/engine/actions_test.go
+++ b/engine/actions_test.go
@@ -514,10 +514,10 @@ func TestActionPlansRemoveMember(t *testing.T) {
func TestActionTriggerMatchNil(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
- BalanceType: utils.MONETARY,
- ThresholdType: TRIGGER_MAX_BALANCE,
- ThresholdValue: 2,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceType: utils.MONETARY,
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
}
var a *Action
if !at.Match(a) {
@@ -527,10 +527,10 @@ func TestActionTriggerMatchNil(t *testing.T) {
func TestActionTriggerMatchAllBlank(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
- BalanceType: utils.MONETARY,
- ThresholdType: TRIGGER_MAX_BALANCE,
- ThresholdValue: 2,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceType: utils.MONETARY,
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
}
a := &Action{}
if !at.Match(a) {
@@ -540,12 +540,12 @@ func TestActionTriggerMatchAllBlank(t *testing.T) {
func TestActionTriggerMatchMinuteBucketBlank(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
- BalanceType: utils.MONETARY,
- ThresholdType: TRIGGER_MAX_BALANCE,
- ThresholdValue: 2,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceType: utils.MONETARY,
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
}
- a := &Action{Direction: utils.OUT, BalanceType: utils.MONETARY}
+ a := &Action{BalanceType: utils.MONETARY, ExtraParameters: `{"BalanceDirections":"*out"}`}
if !at.Match(a) {
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
}
@@ -553,10 +553,10 @@ func TestActionTriggerMatchMinuteBucketBlank(t *testing.T) {
func TestActionTriggerMatchMinuteBucketFull(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
- BalanceType: utils.MONETARY,
- ThresholdType: TRIGGER_MAX_BALANCE,
- ThresholdValue: 2,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceType: utils.MONETARY,
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
}
a := &Action{ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 2)}
if !at.Match(a) {
@@ -566,12 +566,12 @@ func TestActionTriggerMatchMinuteBucketFull(t *testing.T) {
func TestActionTriggerMatchAllFull(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
- BalanceType: utils.MONETARY,
- ThresholdType: TRIGGER_MAX_BALANCE,
- ThresholdValue: 2,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceType: utils.MONETARY,
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
}
- a := &Action{Direction: utils.OUT, BalanceType: utils.MONETARY, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 2)}
+ a := &Action{BalanceType: utils.MONETARY, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*out"}`, TRIGGER_MAX_BALANCE, 2)}
if !at.Match(a) {
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
}
@@ -579,12 +579,12 @@ func TestActionTriggerMatchAllFull(t *testing.T) {
func TestActionTriggerMatchSomeFalse(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
- BalanceType: utils.MONETARY,
- ThresholdType: TRIGGER_MAX_BALANCE,
- ThresholdValue: 2,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceType: utils.MONETARY,
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
}
- a := &Action{Direction: utils.IN, BalanceType: utils.MONETARY, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 2)}
+ a := &Action{BalanceType: utils.MONETARY, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*in"}`, TRIGGER_MAX_BALANCE, 2)}
if at.Match(a) {
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
}
@@ -592,12 +592,12 @@ func TestActionTriggerMatchSomeFalse(t *testing.T) {
func TestActionTriggerMatcBalanceFalse(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
- BalanceType: utils.MONETARY,
- ThresholdType: TRIGGER_MAX_BALANCE,
- ThresholdValue: 2,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceType: utils.MONETARY,
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
}
- a := &Action{Direction: utils.OUT, BalanceType: utils.MONETARY, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 3.0)}
+ a := &Action{BalanceType: utils.MONETARY, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*out"}`, TRIGGER_MAX_BALANCE, 3.0)}
if at.Match(a) {
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
}
@@ -605,12 +605,12 @@ func TestActionTriggerMatcBalanceFalse(t *testing.T) {
func TestActionTriggerMatcAllFalse(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
- BalanceType: utils.MONETARY,
- ThresholdType: TRIGGER_MAX_BALANCE,
- ThresholdValue: 2,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
+ BalanceType: utils.MONETARY,
+ ThresholdType: TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
}
- a := &Action{Direction: utils.IN, BalanceType: utils.VOICE, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_COUNTER, 3)}
+ a := &Action{BalanceType: utils.VOICE, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "BalanceDirections":"*in"}`, TRIGGER_MAX_COUNTER, 3)}
if at.Match(a) {
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
}
@@ -618,16 +618,16 @@ func TestActionTriggerMatcAllFalse(t *testing.T) {
func TestActionTriggerMatchAll(t *testing.T) {
at := &ActionTrigger{
- BalanceDirection: utils.OUT,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
BalanceType: utils.MONETARY,
ThresholdType: TRIGGER_MAX_BALANCE,
ThresholdValue: 2,
- BalanceDestinationIds: "NAT",
+ BalanceDestinationIds: utils.NewStringMap("NAT"),
BalanceWeight: 1.0,
BalanceRatingSubject: "test1",
- BalanceSharedGroup: "test2",
+ BalanceSharedGroups: utils.NewStringMap("test2"),
}
- a := &Action{Direction: utils.OUT, BalanceType: utils.MONETARY, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v, "DestinationIds": "%v", "BalanceWeight": %v, "BalanceRatingSubject": "%v", "BalanceSharedGroup": "%v"}`, TRIGGER_MAX_BALANCE, 2, "NAT", 1.0, "test1", "test2")}
+ a := &Action{BalanceType: utils.MONETARY, ExtraParameters: fmt.Sprintf(`{"BalanceDirections":"*out", "ThresholdType":"%v", "ThresholdValue": %v, "DestinationIds": "%v", "BalanceWeight": %v, "BalanceRatingSubject": "%v", "BalanceSharedGroup": "%v"}`, TRIGGER_MAX_BALANCE, 2, "NAT", 1.0, "test1", "test2")}
if !at.Match(a) {
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
}
@@ -648,7 +648,7 @@ func TestActionTriggers(t *testing.T) {
func TestActionResetTriggres(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 10}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
@@ -674,7 +674,7 @@ func TestActionResetTriggresExecutesThem(t *testing.T) {
func TestActionResetTriggresActionFilter(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 10}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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}}}},
ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
@@ -687,7 +687,7 @@ func TestActionResetTriggresActionFilter(t *testing.T) {
func TestActionSetPostpaid(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
@@ -701,7 +701,7 @@ func TestActionSetPrepaid(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
AllowNegative: true,
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
@@ -715,7 +715,7 @@ func TestActionResetPrepaid(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
AllowNegative: true,
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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.SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
@@ -723,7 +723,7 @@ func TestActionResetPrepaid(t *testing.T) {
if !ub.AllowNegative ||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 0 ||
len(ub.UnitCounters) != 0 ||
- ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 0 ||
+ 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!")
@@ -733,14 +733,14 @@ func TestActionResetPrepaid(t *testing.T) {
func TestActionResetPostpaid(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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.SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
resetAccountAction(ub, nil, nil, nil)
if ub.BalanceMap[utils.MONETARY].GetTotalValue() != 0 ||
len(ub.UnitCounters) != 0 ||
- ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 0 ||
+ ub.BalanceMap[utils.VOICE][0].GetValue() != 0 ||
ub.ActionTriggers[0].Executed == true || ub.ActionTriggers[1].Executed == true {
t.Error("Reset postpaid action failed!")
}
@@ -749,18 +749,37 @@ func TestActionResetPostpaid(t *testing.T) {
func TestActionTopupResetCredit(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
+ 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)}}}},
+ 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, Direction: utils.OUT, Balance: &Balance{Value: 10}}
+ a := &Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}}
topupResetAction(ub, nil, a, nil)
if ub.AllowNegative ||
- ub.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() != 10 ||
+ ub.BalanceMap[utils.MONETARY].GetTotalValue() != 10 ||
len(ub.UnitCounters) != 1 ||
- len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 ||
+ 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+utils.OUT][0])
+ t.Errorf("Topup reset action failed: %+v", ub.BalanceMap[utils.MONETARY][0])
+ }
+}
+
+func TestActionTopupValueFactor(t *testing.T) {
+ ub := &Account{
+ Id: "TEST_UB",
+ BalanceMap: map[string]BalanceChain{},
+ }
+ a := &Action{
+ BalanceType: utils.MONETARY,
+ Balance: &Balance{
+ Value: 10,
+ Directions: utils.NewStringMap(utils.OUT),
+ },
+ ExtraParameters: `{"*monetary":2.0}`,
+ }
+ topupResetAction(ub, nil, a, nil)
+ if len(ub.BalanceMap) != 1 || ub.BalanceMap[utils.MONETARY][0].Factor[utils.MONETARY] != 2.0 {
+ t.Errorf("Topup reset action failed to set Factor: %+v", ub.BalanceMap[utils.MONETARY][0].Factor)
}
}
@@ -768,18 +787,18 @@ func TestActionTopupResetCreditId(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{
+ utils.MONETARY: BalanceChain{
&Balance{Value: 100},
&Balance{Id: "TEST_B", Value: 15},
},
},
}
- a := &Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Id: "TEST_B", Value: 10}}
+ a := &Action{BalanceType: utils.MONETARY, Balance: &Balance{Id: "TEST_B", Value: 10, Directions: utils.NewStringMap(utils.OUT)}}
topupResetAction(ub, nil, a, nil)
if ub.AllowNegative ||
- ub.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() != 110 ||
- len(ub.BalanceMap[utils.MONETARY+utils.OUT]) != 2 {
- t.Errorf("Topup reset action failed: %+v", ub.BalanceMap[utils.MONETARY+utils.OUT][0])
+ ub.BalanceMap[utils.MONETARY].GetTotalValue() != 110 ||
+ len(ub.BalanceMap[utils.MONETARY]) != 2 {
+ t.Errorf("Topup reset action failed: %+v", ub.BalanceMap[utils.MONETARY][0])
}
}
@@ -787,18 +806,18 @@ func TestActionTopupResetCreditNoId(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{
- &Balance{Value: 100},
- &Balance{Id: "TEST_B", Value: 15},
+ utils.MONETARY: BalanceChain{
+ &Balance{Value: 100, Directions: utils.NewStringMap(utils.OUT)},
+ &Balance{Id: "TEST_B", Value: 15, Directions: utils.NewStringMap(utils.OUT)},
},
},
}
- a := &Action{BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}}
+ a := &Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}}
topupResetAction(ub, nil, a, nil)
if ub.AllowNegative ||
- ub.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() != 20 ||
- len(ub.BalanceMap[utils.MONETARY+utils.OUT]) != 2 {
- t.Errorf("Topup reset action failed: %+v", ub.BalanceMap[utils.MONETARY+utils.OUT][1])
+ ub.BalanceMap[utils.MONETARY].GetTotalValue() != 20 ||
+ len(ub.BalanceMap[utils.MONETARY]) != 2 {
+ t.Errorf("Topup reset action failed: %+v", ub.BalanceMap[utils.MONETARY][1])
}
}
@@ -806,94 +825,94 @@ func TestActionTopupResetMinutes(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 100}},
- utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
+ 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)}}}},
+ 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, Direction: utils.OUT, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: "NAT"}}
+ a := &Action{BalanceType: utils.VOICE, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}}
topupResetAction(ub, nil, a, nil)
if ub.AllowNegative ||
- ub.BalanceMap[utils.VOICE+utils.OUT].GetTotalValue() != 5 ||
- ub.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() != 100 ||
+ ub.BalanceMap[utils.VOICE].GetTotalValue() != 5 ||
+ ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
len(ub.UnitCounters) != 1 ||
- len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 ||
+ 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+utils.OUT][0])
+ t.Errorf("Topup reset minutes action failed: %+v", ub.BalanceMap[utils.VOICE][0])
}
}
func TestActionTopupCredit(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
+ 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)}}}},
+ 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, Direction: utils.OUT, Balance: &Balance{Value: 10}}
+ a := &Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}}
topupAction(ub, nil, a, nil)
if ub.AllowNegative ||
- ub.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() != 110 ||
+ ub.BalanceMap[utils.MONETARY].GetTotalValue() != 110 ||
len(ub.UnitCounters) != 1 ||
- len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 ||
+ 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+utils.OUT].GetTotalValue())
+ t.Error("Topup action failed!", ub.BalanceMap[utils.MONETARY].GetTotalValue())
}
}
func TestActionTopupMinutes(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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}}}},
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, Direction: utils.OUT, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: "NAT"}}
+ a := &Action{BalanceType: utils.VOICE, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}}
topupAction(ub, nil, a, nil)
if ub.AllowNegative ||
- ub.BalanceMap[utils.VOICE+utils.OUT].GetTotalValue() != 15 ||
+ ub.BalanceMap[utils.VOICE].GetTotalValue() != 15 ||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
len(ub.UnitCounters) != 1 ||
- len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 ||
+ 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+utils.OUT])
+ t.Error("Topup minutes action failed!", ub.BalanceMap[utils.VOICE])
}
}
func TestActionDebitCredit(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: 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)}}}},
+ 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, Direction: utils.OUT, Balance: &Balance{Value: 10}}
+ a := &Action{BalanceType: utils.MONETARY, Balance: &Balance{Value: 10, Directions: utils.NewStringMap(utils.OUT)}}
debitAction(ub, nil, a, nil)
if ub.AllowNegative ||
- ub.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() != 90 ||
+ ub.BalanceMap[utils.MONETARY].GetTotalValue() != 90 ||
len(ub.UnitCounters) != 1 ||
- len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 ||
+ 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+utils.OUT].GetTotalValue())
+ t.Error("Debit action failed!", ub.BalanceMap[utils.MONETARY].GetTotalValue())
}
}
func TestActionDebitMinutes(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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}}}},
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, Direction: utils.OUT, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: "NAT"}}
+ a := &Action{BalanceType: utils.VOICE, Balance: &Balance{Value: 5, Weight: 20, DestinationIds: utils.NewStringMap("NAT"), Directions: utils.NewStringMap(utils.OUT)}}
debitAction(ub, nil, a, nil)
if ub.AllowNegative ||
- ub.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 5 ||
+ ub.BalanceMap[utils.VOICE][0].GetValue() != 5 ||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
len(ub.UnitCounters) != 1 ||
- len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 ||
+ 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+utils.OUT][0])
+ t.Error("Debit minutes action failed!", ub.BalanceMap[utils.VOICE][0])
}
}
@@ -904,26 +923,27 @@ func TestActionResetAllCounters(t *testing.T) {
BalanceMap: map[string]BalanceChain{
utils.MONETARY: BalanceChain{&Balance{Value: 100}},
utils.VOICE: BalanceChain{
- &Balance{Value: 10, Weight: 20, DestinationIds: "NAT"},
- &Balance{Weight: 10, DestinationIds: "RET"}}},
+ &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{BalanceType: utils.MONETARY, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
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) != 2 ||
+ len(ub.UnitCounters[0].Balances) != 1 ||
+ len(ub.UnitCounters[1].Balances) != 1 ||
len(ub.BalanceMap[utils.VOICE]) != 2 ||
ub.ActionTriggers[0].Executed != true {
- t.Errorf("Reset counters action failed: %+v", ub.UnitCounters)
+ t.Errorf("Reset counters action failed: %+v", ub.UnitCounters[1])
}
if len(ub.UnitCounters) < 1 {
t.FailNow()
}
- mb := ub.UnitCounters[0].Balances[0]
- if mb.Weight != 20 || mb.GetValue() != 0 || mb.DestinationIds != "NAT" {
- t.Errorf("Balance cloned incorrectly: %v!", mb)
+ mb := ub.UnitCounters[1].Balances[0]
+ if mb.Weight != 20 || mb.GetValue() != 0 || mb.DestinationIds["NAT"] == false {
+ t.Errorf("Balance cloned incorrectly: %+v", mb)
}
}
@@ -933,7 +953,7 @@ func TestActionResetCounterMinutes(t *testing.T) {
AllowNegative: true,
BalanceMap: map[string]BalanceChain{
utils.MONETARY: BalanceChain{&Balance{Value: 100}},
- utils.VOICE: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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}},
}
@@ -948,13 +968,13 @@ func TestActionResetCounterMinutes(t *testing.T) {
for _, b := range ub.UnitCounters[1].Balances {
t.Logf("B: %+v", b)
}
- t.Errorf("Reset counters action failed: %+v", ub)
+ t.Errorf("Reset counters action failed: %+v", ub.UnitCounters)
}
if len(ub.UnitCounters) < 2 || len(ub.UnitCounters[1].Balances) < 1 {
t.FailNow()
}
- mb := ub.UnitCounters[1].Balances[0]
- if mb.Weight != 20 || mb.GetValue() != 0 || mb.DestinationIds != "NAT" {
+ mb := ub.UnitCounters[1].Balances[1]
+ if mb.Weight != 20 || mb.GetValue() != 0 || mb.DestinationIds["NAT"] == false {
t.Errorf("Balance cloned incorrectly: %+v!", mb)
}
}
@@ -963,16 +983,16 @@ func TestActionResetCounterCredit(t *testing.T) {
ub := &Account{
Id: "TEST_UB",
AllowNegative: true,
- BalanceMap: map[string]BalanceChain{utils.MONETARY: BalanceChain{&Balance{Value: 100}}, utils.VOICE + utils.OUT: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
- UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: utils.MONETARY, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}, &UnitsCounter{BalanceType: utils.SMS, Direction: utils.OUT, Balances: BalanceChain{&Balance{Value: 1}}}},
- ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirection: utils.OUT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: 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)}}}},
+ ActionTriggers: ActionTriggers{&ActionTrigger{BalanceType: utils.MONETARY, BalanceDirections: utils.NewStringMap(utils.OUT), ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
- a := &Action{BalanceType: utils.MONETARY, Direction: utils.OUT}
+ a := &Action{BalanceType: utils.MONETARY}
resetCounterAction(ub, nil, a, nil)
if !ub.AllowNegative ||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 100 ||
len(ub.UnitCounters) != 2 ||
- len(ub.BalanceMap[utils.VOICE+utils.OUT]) != 2 ||
+ len(ub.BalanceMap[utils.VOICE]) != 2 ||
ub.ActionTriggers[0].Executed != true {
t.Error("Reset counters action failed!", ub.UnitCounters)
}
@@ -982,9 +1002,9 @@ func TestActionTriggerLogging(t *testing.T) {
at := &ActionTrigger{
Id: "some_uuid",
BalanceType: utils.MONETARY,
- BalanceDirection: utils.OUT,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
ThresholdValue: 100.0,
- BalanceDestinationIds: "NAT",
+ BalanceDestinationIds: utils.NewStringMap("NAT"),
Weight: 10.0,
ActionsId: "TEST_ACTIONS",
}
@@ -1065,7 +1085,7 @@ func TestActionMakeNegative(t *testing.T) {
}
func TestRemoveAction(t *testing.T) {
- if _, err := accountingStorage.GetAccount("*out:cgrates.org:remo"); err != nil {
+ if _, err := accountingStorage.GetAccount("cgrates.org:remo"); err != nil {
t.Errorf("account to be removed not found: %v", err)
}
a := &Action{
@@ -1073,59 +1093,57 @@ func TestRemoveAction(t *testing.T) {
}
at := &ActionPlan{
- AccountIds: []string{"*out:cgrates.org:remo"},
+ AccountIds: []string{"cgrates.org:remo"},
actions: Actions{a},
}
at.Execute()
- afterUb, err := accountingStorage.GetAccount("*out:cgrates.org:remo")
+ afterUb, err := accountingStorage.GetAccount("cgrates.org:remo")
if err == nil || afterUb != nil {
t.Error("error removing account: ", err, afterUb)
}
}
func TestTopupAction(t *testing.T) {
- initialUb, _ := accountingStorage.GetAccount("*out:vdf:minu")
+ initialUb, _ := accountingStorage.GetAccount("vdf:minu")
a := &Action{
ActionType: TOPUP,
BalanceType: utils.MONETARY,
- Direction: utils.OUT,
- Balance: &Balance{Value: 25, DestinationIds: "RET", Weight: 20},
+ Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Directions: utils.NewStringMap(utils.OUT), Weight: 20},
}
at := &ActionPlan{
- AccountIds: []string{"*out:vdf:minu"},
+ AccountIds: []string{"vdf:minu"},
actions: Actions{a},
}
at.Execute()
- afterUb, _ := accountingStorage.GetAccount("*out:vdf:minu")
- initialValue := initialUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue()
- afterValue := afterUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue()
- if initialValue != 50 || afterValue != 75 {
+ afterUb, _ := accountingStorage.GetAccount("vdf:minu")
+ initialValue := initialUb.BalanceMap[utils.MONETARY].GetTotalValue()
+ afterValue := afterUb.BalanceMap[utils.MONETARY].GetTotalValue()
+ if afterValue != initialValue+25 {
t.Error("Bad topup before and after: ", initialValue, afterValue)
}
}
func TestTopupActionLoaded(t *testing.T) {
- initialUb, _ := accountingStorage.GetAccount("*out:vdf:minitsboy")
+ initialUb, _ := accountingStorage.GetAccount("vdf:minitsboy")
a := &Action{
ActionType: TOPUP,
BalanceType: utils.MONETARY,
- Direction: utils.OUT,
- Balance: &Balance{Value: 25, DestinationIds: "RET", Weight: 20},
+ Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Directions: utils.NewStringMap(utils.OUT), Weight: 20},
}
at := &ActionPlan{
- AccountIds: []string{"*out:vdf:minitsboy"},
+ AccountIds: []string{"vdf:minitsboy"},
actions: Actions{a},
}
at.Execute()
- afterUb, _ := accountingStorage.GetAccount("*out:vdf:minitsboy")
- initialValue := initialUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue()
- afterValue := afterUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue()
- if initialValue != 100 || afterValue != 125 {
+ afterUb, _ := accountingStorage.GetAccount("vdf:minitsboy")
+ initialValue := initialUb.BalanceMap[utils.MONETARY].GetTotalValue()
+ afterValue := afterUb.BalanceMap[utils.MONETARY].GetTotalValue()
+ if afterValue != initialValue+25 {
t.Logf("Initial: %+v", initialUb)
t.Logf("After: %+v", afterUb)
t.Error("Bad topup before and after: ", initialValue, afterValue)
@@ -1133,14 +1151,14 @@ func TestTopupActionLoaded(t *testing.T) {
}
func TestActionCdrlogEmpty(t *testing.T) {
- acnt := &Account{Id: "*out:cgrates.org:dan2904"}
+ acnt := &Account{Id: "cgrates.org:dan2904"}
cdrlog := &Action{
ActionType: CDRLOG,
}
err := cdrLogAction(acnt, nil, cdrlog, Actions{
&Action{
ActionType: DEBIT,
- Balance: &Balance{Value: 25, DestinationIds: "RET", Weight: 20},
+ Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Weight: 20},
},
})
if err != nil {
@@ -1154,7 +1172,7 @@ func TestActionCdrlogEmpty(t *testing.T) {
}
func TestActionCdrlogWithParams(t *testing.T) {
- acnt := &Account{Id: "*out:cgrates.org:dan2904"}
+ acnt := &Account{Id: "cgrates.org:dan2904"}
cdrlog := &Action{
ActionType: CDRLOG,
ExtraParameters: `{"ReqType":"^*pseudoprepaid","Subject":"^rif", "TOR":"~action_type:s/^\\*(.*)$/did_$1/"}`,
@@ -1162,11 +1180,11 @@ func TestActionCdrlogWithParams(t *testing.T) {
err := cdrLogAction(acnt, nil, cdrlog, Actions{
&Action{
ActionType: DEBIT,
- Balance: &Balance{Value: 25, DestinationIds: "RET", Weight: 20},
+ Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Weight: 20},
},
&Action{
ActionType: DEBIT_RESET,
- Balance: &Balance{Value: 25, DestinationIds: "RET", Weight: 20},
+ Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Weight: 20},
},
})
if err != nil {
@@ -1181,7 +1199,7 @@ func TestActionCdrlogWithParams(t *testing.T) {
}
func TestActionCdrLogParamsWithOverload(t *testing.T) {
- acnt := &Account{Id: "*out:cgrates.org:dan2904"}
+ acnt := &Account{Id: "cgrates.org:dan2904"}
cdrlog := &Action{
ActionType: CDRLOG,
ExtraParameters: `{"Subject":"^rif","Destination":"^1234","TOR":"~action_tag:s/^at(.)$/0$1/","AccountId":"~account_id:s/^\\*(.*)$/$1/"}`,
@@ -1189,11 +1207,11 @@ func TestActionCdrLogParamsWithOverload(t *testing.T) {
err := cdrLogAction(acnt, nil, cdrlog, Actions{
&Action{
ActionType: DEBIT,
- Balance: &Balance{Value: 25, DestinationIds: "RET", Weight: 20},
+ Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Weight: 20},
},
&Action{
ActionType: DEBIT_RESET,
- Balance: &Balance{Value: 25, DestinationIds: "RET", Weight: 20},
+ Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Weight: 20},
},
})
if err != nil {
@@ -1202,14 +1220,14 @@ func TestActionCdrLogParamsWithOverload(t *testing.T) {
cdrs := make([]*StoredCdr, 0)
json.Unmarshal([]byte(cdrlog.ExpirationString), &cdrs)
expectedExtraFields := map[string]string{
- "AccountId": "out:cgrates.org:dan2904",
+ "AccountId": "cgrates.org:dan2904",
}
if len(cdrs) != 2 ||
cdrs[0].Subject != "rif" {
t.Errorf("Wrong cdrlogs: %+v", cdrs[0])
}
if !reflect.DeepEqual(cdrs[0].ExtraFields, expectedExtraFields) {
- t.Errorf("Received extra_fields: %+v", cdrs[0].ExtraFields)
+ t.Errorf("Received extra_fields: %+v %+v", cdrs[0].ExtraFields, expectedExtraFields)
}
}
diff --git a/engine/balances.go b/engine/balances.go
index 689774179..f5a565656 100644
--- a/engine/balances.go
+++ b/engine/balances.go
@@ -35,37 +35,38 @@ type Balance struct {
Uuid string //system wide unique
Id string // account wide unique
Value float64
+ Directions utils.StringMap
ExpirationDate time.Time
Weight float64
- DestinationIds string
+ DestinationIds utils.StringMap
RatingSubject string
- Category string
- SharedGroup string
+ Categories utils.StringMap
+ SharedGroups utils.StringMap
Timings []*RITiming
- TimingIDs string
+ TimingIDs utils.StringMap
Disabled bool
+ Factor ValueFactor
precision int
account *Account // used to store ub reference for shared balances
dirty bool
}
func (b *Balance) Equal(o *Balance) bool {
- if b.DestinationIds == "" {
- b.DestinationIds = utils.ANY
+ if len(b.DestinationIds) == 0 {
+ b.DestinationIds = utils.StringMap{utils.ANY: true}
}
- if o.DestinationIds == "" {
- o.DestinationIds = utils.ANY
+ if len(o.DestinationIds) == 0 {
+ o.DestinationIds = utils.StringMap{utils.ANY: true}
}
- bDestIds := b.sortDestinationIds()
- oDestIds := o.sortDestinationIds()
return b.Uuid == o.Uuid &&
b.Id == o.Id &&
b.ExpirationDate.Equal(o.ExpirationDate) &&
b.Weight == o.Weight &&
- bDestIds == oDestIds &&
+ b.DestinationIds.Equal(o.DestinationIds) &&
+ b.Directions.Equal(o.Directions) &&
b.RatingSubject == o.RatingSubject &&
- b.Category == o.Category &&
- b.SharedGroup == o.SharedGroup &&
+ b.Categories.Equal(o.Categories) &&
+ b.SharedGroups.Equal(o.SharedGroups) &&
b.Disabled == o.Disabled
}
@@ -76,31 +77,25 @@ func (b *Balance) MatchFilter(o *Balance) bool {
if o.Id != "" {
return b.Id == o.Id
}
- if b.DestinationIds == "" {
- b.DestinationIds = utils.ANY
+ if len(b.DestinationIds) == 0 {
+ b.DestinationIds = utils.StringMap{utils.ANY: true}
}
- if o.DestinationIds == "" {
- o.DestinationIds = utils.ANY
+ if len(o.DestinationIds) == 0 {
+ o.DestinationIds = utils.StringMap{utils.ANY: true}
}
- bDestIds := b.sortDestinationIds()
- oDestIds := o.sortDestinationIds()
return (o.ExpirationDate.IsZero() || b.ExpirationDate.Equal(o.ExpirationDate)) &&
(o.Weight == 0 || b.Weight == o.Weight) &&
- (oDestIds == "" || bDestIds == oDestIds) &&
- (o.RatingSubject == "" || b.RatingSubject == o.RatingSubject) &&
- (o.Category == "" || b.Category == o.Category) &&
- (o.SharedGroup == "" || b.SharedGroup == o.SharedGroup)
+ (len(o.DestinationIds) == 0 || b.DestinationIds.Includes(o.DestinationIds)) &&
+ (len(o.Directions) == 0 || b.Directions.Includes(o.Directions)) &&
+ (len(o.Categories) == 0 || b.Categories.Includes(o.Categories)) &&
+ (len(o.TimingIDs) == 0 || b.TimingIDs.Includes(o.TimingIDs)) &&
+ (len(o.SharedGroups) == 0 || b.SharedGroups.Includes(o.SharedGroups)) &&
+ (o.RatingSubject == "" || b.RatingSubject == o.RatingSubject)
}
-// the default balance has no destinationid, Expirationdate or ratesubject
+// the default balance has standard Id
func (b *Balance) IsDefault() bool {
- return (b.DestinationIds == "" || b.DestinationIds == utils.ANY) &&
- b.RatingSubject == "" &&
- b.Category == "" &&
- b.ExpirationDate.IsZero() &&
- b.SharedGroup == "" &&
- b.Weight == 0 &&
- b.Disabled == false
+ return b.Id == utils.META_DEFAULT
}
func (b *Balance) IsExpired() bool {
@@ -126,22 +121,20 @@ func (b *Balance) IsActiveAt(t time.Time) bool {
return false
}
-func (b *Balance) sortDestinationIds() string {
- destIds := strings.Split(b.DestinationIds, utils.INFIELD_SEP)
- sort.StringSlice(destIds).Sort()
- return strings.Join(destIds, utils.INFIELD_SEP)
-}
-
func (b *Balance) MatchCategory(category string) bool {
- return b.Category == "" || b.Category == category
+ return len(b.Categories) == 0 || b.Categories[category] == true
}
func (b *Balance) HasDestination() bool {
- return b.DestinationIds != "" && b.DestinationIds != utils.ANY
+ return len(b.DestinationIds) > 0 && b.DestinationIds[utils.ANY] == false
+}
+
+func (b *Balance) HasDirection() bool {
+ return len(b.Directions) > 0
}
func (b *Balance) MatchDestination(destinationId string) bool {
- return !b.HasDestination() || strings.Contains(b.DestinationIds, destinationId)
+ return !b.HasDestination() || b.DestinationIds[destinationId] == true
}
func (b *Balance) MatchActionTrigger(at *ActionTrigger) bool {
@@ -149,10 +142,12 @@ func (b *Balance) MatchActionTrigger(at *ActionTrigger) bool {
return b.Id == at.BalanceId
}
matchesDestination := true
- if at.BalanceDestinationIds != "" {
- bDestIds := b.sortDestinationIds()
- atDestinationIds := at.sortDestinationIds()
- matchesDestination = (bDestIds == atDestinationIds)
+ if len(at.BalanceDestinationIds) != 0 {
+ matchesDestination = (b.DestinationIds.Equal(at.BalanceDestinationIds))
+ }
+ matchesDirection := true
+ if len(at.BalanceDirections) != 0 {
+ matchesDirection = (b.Directions.Equal(at.BalanceDirections))
}
matchesExpirationDate := true
if !at.BalanceExpirationDate.IsZero() {
@@ -168,15 +163,22 @@ func (b *Balance) MatchActionTrigger(at *ActionTrigger) bool {
}
matchesSharedGroup := true
- if at.BalanceSharedGroup != "" {
- matchesSharedGroup = (at.BalanceSharedGroup == b.SharedGroup)
+ if len(at.BalanceSharedGroups) != 0 {
+ matchesSharedGroup = at.BalanceSharedGroups.Equal(b.SharedGroups)
+ }
+
+ matchesTiming := true
+ if len(at.BalanceTimingTags) != 0 {
+ matchesTiming = at.BalanceTimingTags.Equal(b.TimingIDs)
}
return matchesDestination &&
+ matchesDirection &&
matchesExpirationDate &&
matchesWeight &&
matchesRatingSubject &&
- matchesSharedGroup
+ matchesSharedGroup &&
+ matchesTiming
}
func (b *Balance) Clone() *Balance {
@@ -184,12 +186,13 @@ func (b *Balance) Clone() *Balance {
Uuid: b.Uuid,
Id: b.Id,
Value: b.Value, // this value is in seconds
- DestinationIds: b.DestinationIds,
+ DestinationIds: b.DestinationIds.Clone(),
+ Directions: b.Directions.Clone(),
ExpirationDate: b.ExpirationDate,
Weight: b.Weight,
RatingSubject: b.RatingSubject,
- Category: b.Category,
- SharedGroup: b.SharedGroup,
+ Categories: b.Categories,
+ SharedGroups: b.SharedGroups,
TimingIDs: b.TimingIDs,
Timings: b.Timings, // should not be a problem with aliasing
Disabled: b.Disabled,
@@ -198,18 +201,14 @@ func (b *Balance) Clone() *Balance {
}
func (b *Balance) getMatchingPrefixAndDestId(dest string) (prefix, destId string) {
- if b.DestinationIds != "" && b.DestinationIds != utils.ANY {
+ if len(b.DestinationIds) != 0 && b.DestinationIds[utils.ANY] == false {
for _, p := range utils.SplitPrefix(dest, MIN_PREFIX_MATCH) {
if x, err := cache2go.Get(utils.DESTINATION_PREFIX + p); err == nil {
destIds := x.(map[interface{}]struct{})
for dId, _ := range destIds {
- balDestIds := strings.Split(b.DestinationIds, utils.INFIELD_SEP)
- for _, balDestID := range balDestIds {
- if dId == balDestID {
- return p, balDestID
- }
+ if b.DestinationIds[dId.(string)] == true {
+ return p, dId.(string)
}
-
}
}
}
@@ -321,8 +320,6 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala
TimeEnd: cd.TimeEnd,
})
- seconds := duration.Seconds()
- amount := seconds
ts := cc.Timespans[0]
ts.RoundToDuration(duration)
ts.RateInterval = &RateInterval{
@@ -354,8 +351,10 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala
//log.Printf("CC: %+v", ts)
for incIndex, inc := range ts.Increments {
//log.Printf("INCREMENET: %+v", inc)
- if seconds == 1 {
- amount = inc.Duration.Seconds()
+
+ amount := inc.Duration.Seconds()
+ if b.Factor != nil {
+ amount = utils.Round(amount/b.Factor.GetValue(cd.TOR), globalRoundingDecimals, utils.ROUNDING_UP)
}
if b.GetValue() >= amount {
b.SubstractValue(amount)
@@ -365,7 +364,7 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala
inc.Cost = 0
inc.paid = true
if count {
- ub.countUnits(&Action{BalanceType: cc.TOR, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationIds: cc.Destination}})
+ ub.countUnits(&Action{BalanceType: cc.TOR, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: amount, DestinationIds: utils.StringMap{cc.Destination: true}}})
}
} else {
inc.paid = false
@@ -403,9 +402,11 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala
maxCost, strategy := ts.RateInterval.GetMaxCost()
for incIndex, inc := range ts.Increments {
// debit minutes and money
- seconds := inc.Duration.Seconds()
+ amount := inc.Duration.Seconds()
+ if b.Factor != nil {
+ amount = utils.Round(amount/b.Factor.GetValue(cd.TOR), globalRoundingDecimals, utils.ROUNDING_UP)
+ }
cost := inc.Cost
- //log.Printf("INC: %+v", inc)
inc.paid = false
if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost {
// cat the entire current timespan
@@ -427,7 +428,7 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala
inc.BalanceInfo.AccountId = ub.Id
inc.paid = true
if count {
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: cc.Direction, Balance: &Balance{Value: cost, DestinationIds: cc.Destination}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: cost, DestinationIds: utils.StringMap{cc.Destination: true}}})
}
// go to nextincrement
continue
@@ -439,11 +440,11 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala
break
}
}
- if (cost == 0 || moneyBal != nil) && b.GetValue() >= seconds {
- b.SubstractValue(seconds)
+ if (cost == 0 || moneyBal != nil) && b.GetValue() >= amount {
+ b.SubstractValue(amount)
inc.BalanceInfo.UnitBalanceUuid = b.Uuid
inc.BalanceInfo.AccountId = ub.Id
- inc.UnitInfo = &UnitInfo{cc.Destination, seconds, cc.TOR}
+ inc.UnitInfo = &UnitInfo{cc.Destination, amount, cc.TOR}
if cost != 0 {
inc.BalanceInfo.MoneyBalanceUuid = moneyBal.Uuid
moneyBal.SubstractValue(cost)
@@ -451,9 +452,9 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala
}
inc.paid = true
if count {
- ub.countUnits(&Action{BalanceType: cc.TOR, Direction: cc.Direction, Balance: &Balance{Value: seconds, DestinationIds: cc.Destination}})
+ ub.countUnits(&Action{BalanceType: cc.TOR, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: amount, DestinationIds: utils.StringMap{cc.Destination: true}}})
if cost != 0 {
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: cc.Direction, Balance: &Balance{Value: cost, DestinationIds: cc.Destination}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: cost, DestinationIds: utils.StringMap{cc.Destination: true}}})
}
}
} else {
@@ -528,7 +529,7 @@ func (b *Balance) DebitMoney(cd *CallDescriptor, ub *Account, count bool, dryRun
inc.BalanceInfo.AccountId = ub.Id
inc.paid = true
if count {
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationIds: cc.Destination}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: amount, DestinationIds: utils.StringMap{cc.Destination: true}}})
}
//log.Printf("TS: %+v", cc.Cost)
@@ -543,7 +544,7 @@ func (b *Balance) DebitMoney(cd *CallDescriptor, ub *Account, count bool, dryRun
inc.BalanceInfo.AccountId = ub.Id
inc.paid = true
if count {
- ub.countUnits(&Action{BalanceType: utils.MONETARY, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationIds: cc.Destination}})
+ ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: amount, DestinationIds: utils.StringMap{cc.Destination: true}}})
}
} else {
inc.paid = false
@@ -662,11 +663,12 @@ func (bc BalanceChain) SaveDirtyBalances(acc *Account) {
"Value": strconv.FormatFloat(b.Value, 'f', -1, 64),
"ExpirationDate": b.ExpirationDate.String(),
"Weight": strconv.FormatFloat(b.Weight, 'f', -1, 64),
- "DestinationIds": b.DestinationIds,
+ "DestinationIds": b.DestinationIds.String(),
+ "Directions": b.Directions.String(),
"RatingSubject": b.RatingSubject,
- "Category": b.Category,
- "SharedGroup": b.SharedGroup,
- "TimingIDs": b.TimingIDs,
+ "Categories": b.Categories.String(),
+ "SharedGroups": b.SharedGroups.String(),
+ "TimingIDs": b.TimingIDs.String(),
"Account": accountId,
"AccountAllowNegative": allowNegative,
"AccountDisabled": disabled,
@@ -679,3 +681,12 @@ func (bc BalanceChain) SaveDirtyBalances(acc *Account) {
}
}
}
+
+type ValueFactor map[string]float64
+
+func (f ValueFactor) GetValue(tor string) float64 {
+ if value, ok := f[tor]; ok {
+ return value
+ }
+ return 1.0
+}
diff --git a/engine/balances_test.go b/engine/balances_test.go
index eb8b2587e..608db65ba 100644
--- a/engine/balances_test.go
+++ b/engine/balances_test.go
@@ -19,7 +19,6 @@ along with this program. If not, see
package engine
import (
- "reflect"
"testing"
"github.com/cgrates/cgrates/utils"
@@ -81,24 +80,24 @@ func TestBalanceSortWeightLess(t *testing.T) {
}
func TestBalanceEqual(t *testing.T) {
- mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: ""}
- mb2 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: ""}
- mb3 := &Balance{Weight: 1, precision: 1, RatingSubject: "2", DestinationIds: ""}
+ mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
+ mb2 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
+ mb3 := &Balance{Weight: 1, precision: 1, RatingSubject: "2", DestinationIds: utils.StringMap{}}
if !mb1.Equal(mb2) || mb2.Equal(mb3) {
t.Error("Equal failure!", mb1 == mb2, mb3)
}
}
func TestBalanceMatchFilter(t *testing.T) {
- mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: ""}
- mb2 := &Balance{Weight: 1, precision: 1, RatingSubject: "", DestinationIds: ""}
+ 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) {
t.Errorf("Match filter failure: %+v == %+v", mb1, mb2)
}
}
func TestBalanceMatchFilterEmpty(t *testing.T) {
- mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: ""}
+ mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: utils.StringMap{}}
mb2 := &Balance{}
if !mb1.MatchFilter(mb2) {
t.Errorf("Match filter failure: %+v == %+v", mb1, mb2)
@@ -106,26 +105,26 @@ func TestBalanceMatchFilterEmpty(t *testing.T) {
}
func TestBalanceMatchFilterId(t *testing.T) {
- mb1 := &Balance{Id: "T1", Weight: 2, precision: 2, RatingSubject: "2", DestinationIds: "NAT"}
- mb2 := &Balance{Id: "T1", Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: ""}
+ 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) {
t.Errorf("Match filter failure: %+v == %+v", mb1, mb2)
}
}
func TestBalanceMatchFilterDiffId(t *testing.T) {
- mb1 := &Balance{Id: "T1", Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: ""}
- mb2 := &Balance{Id: "T2", Weight: 1, precision: 1, RatingSubject: "1", DestinationIds: ""}
+ 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) {
t.Errorf("Match filter failure: %+v != %+v", mb1, mb2)
}
}
func TestBalanceClone(t *testing.T) {
- mb1 := &Balance{Value: 1, Weight: 2, RatingSubject: "test", DestinationIds: "5"}
+ mb1 := &Balance{Value: 1, Weight: 2, RatingSubject: "test", DestinationIds: utils.NewStringMap("5")}
mb2 := mb1.Clone()
- if mb1 == mb2 || !reflect.DeepEqual(mb1, mb2) {
- t.Errorf("Cloning failure: \n%v\n%v", mb1, mb2)
+ if mb1 == mb2 || !mb1.Equal(mb2) {
+ t.Errorf("Cloning failure: \n%+v\n%+v", mb1, mb2)
}
}
@@ -151,21 +150,21 @@ func TestBalanceMatchActionTriggerId(t *testing.T) {
}
func TestBalanceMatchActionTriggerDestination(t *testing.T) {
- at := &ActionTrigger{BalanceDestinationIds: "test"}
- b := &Balance{DestinationIds: "test"}
+ at := &ActionTrigger{BalanceDestinationIds: utils.NewStringMap("test")}
+ b := &Balance{DestinationIds: utils.NewStringMap("test")}
if !b.MatchActionTrigger(at) {
t.Errorf("Error matching action trigger: %+v %+v", b, at)
}
- b.DestinationIds = "test1"
+ b.DestinationIds = utils.NewStringMap("test1")
if b.MatchActionTrigger(at) {
t.Errorf("Error matching action trigger: %+v %+v", b, at)
}
- b.DestinationIds = ""
+ b.DestinationIds = utils.NewStringMap("")
if b.MatchActionTrigger(at) {
t.Errorf("Error matching action trigger: %+v %+v", b, at)
}
- b.DestinationIds = "test"
- at.BalanceDestinationIds = ""
+ b.DestinationIds = utils.NewStringMap("test")
+ at.BalanceDestinationIds = utils.NewStringMap("")
if !b.MatchActionTrigger(at) {
t.Errorf("Error matching action trigger: %+v %+v", b, at)
}
@@ -214,21 +213,21 @@ func TestBalanceMatchActionTriggerRatingSubject(t *testing.T) {
}
func TestBalanceMatchActionTriggerSharedGroup(t *testing.T) {
- at := &ActionTrigger{BalanceSharedGroup: "test"}
- b := &Balance{SharedGroup: "test"}
+ at := &ActionTrigger{BalanceSharedGroups: utils.NewStringMap("test")}
+ b := &Balance{SharedGroups: utils.NewStringMap("test")}
if !b.MatchActionTrigger(at) {
t.Errorf("Error matching action trigger: %+v %+v", b, at)
}
- b.SharedGroup = "test1"
+ b.SharedGroups = utils.NewStringMap("test1")
if b.MatchActionTrigger(at) {
t.Errorf("Error matching action trigger: %+v %+v", b, at)
}
- b.SharedGroup = ""
+ b.SharedGroups = utils.NewStringMap("")
if b.MatchActionTrigger(at) {
t.Errorf("Error matching action trigger: %+v %+v", b, at)
}
- b.SharedGroup = "test"
- at.BalanceSharedGroup = ""
+ b.SharedGroups = utils.NewStringMap("test")
+ at.BalanceSharedGroups = utils.NewStringMap("")
if !b.MatchActionTrigger(at) {
t.Errorf("Error matching action trigger: %+v %+v", b, at)
}
@@ -236,31 +235,11 @@ func TestBalanceMatchActionTriggerSharedGroup(t *testing.T) {
func TestBalanceIsDefault(t *testing.T) {
b := &Balance{Weight: 0}
+ if b.IsDefault() {
+ t.Errorf("Balance should not be default: %+v", b)
+ }
+ b = &Balance{Id: utils.META_DEFAULT}
if !b.IsDefault() {
t.Errorf("Balance should be default: %+v", b)
}
}
-
-func TestBalanceSortDestinationIds(t *testing.T) {
- b := Balance{DestinationIds: "a_first;c_third;b_second"}
- sortedDestIds := b.sortDestinationIds()
- if sortedDestIds != "a_first;b_second;c_third" {
- t.Error("Error sorting destination ids: ", sortedDestIds)
- }
-}
-
-func TestBalanceSortDestinationIdsOne(t *testing.T) {
- b := Balance{DestinationIds: utils.ANY}
- sortedDestIds := b.sortDestinationIds()
- if sortedDestIds != utils.ANY {
- t.Error("Error sorting destination ids: ", sortedDestIds)
- }
-}
-
-func TestBalanceSortDestinationEmpty(t *testing.T) {
- b := Balance{DestinationIds: ""}
- sortedDestIds := b.sortDestinationIds()
- if sortedDestIds != "" {
- t.Error("Error sorting destination ids: ", sortedDestIds)
- }
-}
diff --git a/engine/calldesc.go b/engine/calldesc.go
index 1cc40eb89..d0c4517ff 100644
--- a/engine/calldesc.go
+++ b/engine/calldesc.go
@@ -74,7 +74,7 @@ var (
storageLogger LogStorage
cdrStorage CdrStorage
debitPeriod = 10 * time.Second
- globalRoundingDecimals = 10
+ globalRoundingDecimals = 5
historyScribe history.Scribe
pubSubServer PublisherSubscriber
userService UserService
@@ -83,7 +83,7 @@ var (
// Exported method to set the storage getter.
func SetRatingStorage(sg RatingStorage) {
- ratingStorage = sg
+ ratingStorage = sg
}
func SetAccountingStorage(ag AccountingStorage) {
@@ -321,7 +321,7 @@ func (cd *CallDescriptor) GetAccountKey() string {
if cd.Account != "" {
subj = cd.Account
}
- return utils.ConcatenatedKey(cd.Direction, cd.Tenant, subj)
+ return utils.ConcatenatedKey(cd.Tenant, subj)
}
// Splits the received timespan into sub time spans according to the activation periods intervals.
@@ -534,7 +534,7 @@ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Dura
cd := origCD.Clone()
initialDuration := cd.TimeEnd.Sub(cd.TimeStart)
//utils.Logger.Debug(fmt.Sprintf("INITIAL_DURATION: %v", initialDuration))
- defaultBalance := account.GetDefaultMoneyBalance(cd.Direction)
+ defaultBalance := account.GetDefaultMoneyBalance()
//use this to check what increment was payed with debt
initialDefaultBalanceValue := defaultBalance.GetValue()
@@ -600,7 +600,7 @@ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Dura
func (cd *CallDescriptor) GetMaxSessionDuration() (duration time.Duration, err error) {
cd.account = nil // make sure it's not cached
if account, err := cd.getAccount(); err != nil || account == nil {
- utils.Logger.Err(fmt.Sprintf("Could not get user balance for <%s>: %s.", cd.GetAccountKey(), err.Error()))
+ utils.Logger.Err(fmt.Sprintf("Could not get account for <%s>: %s.", cd.GetAccountKey(), err.Error()))
return 0, err
} else {
if memberIds, err := account.GetUniqueSharedGroupMembers(cd); err == nil {
@@ -709,7 +709,7 @@ func (cd *CallDescriptor) RefundIncrements() (left float64, err error) {
defer accountingStorage.SetAccount(account)
}
}
- account.refundIncrement(increment, cd.Direction, cd.TOR, true)
+ account.refundIncrement(increment, cd.TOR, true)
}
return 0.0, err
}
diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go
index 81a281075..6e31a701e 100644
--- a/engine/calldesc_test.go
+++ b/engine/calldesc_test.go
@@ -41,63 +41,63 @@ func init() {
func populateDB() {
ats := []*Action{
- &Action{ActionType: "*topup", BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}},
- &Action{ActionType: "*topup", BalanceType: utils.VOICE, Direction: utils.OUT, Balance: &Balance{Weight: 20, Value: 10, DestinationIds: "NAT"}},
+ &Action{ActionType: "*topup", BalanceType: utils.MONETARY, Balance: &Balance{Value: 10}},
+ &Action{ActionType: "*topup", BalanceType: utils.VOICE, Balance: &Balance{Weight: 20, Value: 10, DestinationIds: utils.NewStringMap("NAT")}},
}
ats1 := []*Action{
- &Action{ActionType: "*topup", BalanceType: utils.MONETARY, Direction: utils.OUT, Balance: &Balance{Value: 10}, Weight: 10},
+ &Action{ActionType: "*topup", BalanceType: utils.MONETARY, Balance: &Balance{Value: 10}, Weight: 10},
&Action{ActionType: "*reset_account", Weight: 20},
}
minu := &Account{
- Id: "*out:vdf:minu",
+ Id: "vdf:minu",
BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{&Balance{Value: 50}},
- utils.VOICE + utils.OUT: BalanceChain{
- &Balance{Value: 200, DestinationIds: "NAT", Weight: 10},
- &Balance{Value: 100, DestinationIds: "RET", Weight: 20},
+ utils.MONETARY: BalanceChain{&Balance{Value: 50}},
+ utils.VOICE: BalanceChain{
+ &Balance{Value: 200, DestinationIds: utils.NewStringMap("NAT"), Weight: 10},
+ &Balance{Value: 100, DestinationIds: utils.NewStringMap("RET"), Weight: 20},
}},
}
broker := &Account{
- Id: "*out:vdf:broker",
+ Id: "vdf:broker",
BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{
- &Balance{Value: 20, DestinationIds: "NAT", Weight: 10, RatingSubject: "rif"},
- &Balance{Value: 100, DestinationIds: "RET", Weight: 20},
+ utils.VOICE: BalanceChain{
+ &Balance{Value: 20, DestinationIds: utils.NewStringMap("NAT"), Weight: 10, RatingSubject: "rif"},
+ &Balance{Value: 100, DestinationIds: utils.NewStringMap("RET"), Weight: 20},
}},
}
luna := &Account{
- Id: "*out:vdf:luna",
+ Id: "vdf:luna",
BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{
+ utils.MONETARY: BalanceChain{
&Balance{Value: 0, Weight: 20},
}},
}
// this is added to test if csv load tests account will not overwrite balances
minitsboy := &Account{
- Id: "*out:vdf:minitsboy",
+ Id: "vdf:minitsboy",
BalanceMap: map[string]BalanceChain{
- utils.VOICE + utils.OUT: BalanceChain{
- &Balance{Value: 20, DestinationIds: "NAT", Weight: 10, RatingSubject: "rif"},
- &Balance{Value: 100, DestinationIds: "RET", Weight: 20},
+ utils.VOICE: BalanceChain{
+ &Balance{Value: 20, DestinationIds: utils.NewStringMap("NAT"), Weight: 10, RatingSubject: "rif"},
+ &Balance{Value: 100, DestinationIds: utils.NewStringMap("RET"), Weight: 20},
},
- utils.MONETARY + utils.OUT: BalanceChain{
+ utils.MONETARY: BalanceChain{
&Balance{Value: 100, Weight: 10},
},
},
}
max := &Account{
- Id: "*out:cgrates.org:max",
+ Id: "cgrates.org:max",
BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{
+ utils.MONETARY: BalanceChain{
&Balance{Value: 11, Weight: 20},
}},
}
money := &Account{
- Id: "*out:cgrates.org:money",
+ Id: "cgrates.org:money",
BalanceMap: map[string]BalanceChain{
- utils.MONETARY + utils.OUT: BalanceChain{
+ utils.MONETARY: BalanceChain{
&Balance{Value: 10000, Weight: 10},
}},
}
@@ -491,6 +491,8 @@ func TestMaxSessionTimeWithMaxRate(t *testing.T) {
for _, at := range ap {
at.Execute()
}
+ //acc, _ := accountingStorage.GetAccount("cgrates.org:12345")
+ //log.Print("ACC: ", utils.ToIJSON(acc))
cd := &CallDescriptor{
Direction: "*out",
Category: "call",
@@ -743,13 +745,13 @@ func TestMaxDebitWithAccountShared(t *testing.T) {
t.Errorf("Wrong callcost in shared debit: %+v, %v", cc, err)
}
acc, _ := cd.getAccount()
- balanceMap := acc.BalanceMap[utils.MONETARY+utils.OUT]
+ balanceMap := acc.BalanceMap[utils.MONETARY]
if len(balanceMap) != 1 || balanceMap[0].GetValue() != 0 {
t.Errorf("Wrong shared balance debited: %+v", balanceMap[0])
}
- other, err := accountingStorage.GetAccount("*out:vdf:empty10")
- if err != nil || other.BalanceMap[utils.MONETARY+utils.OUT][0].GetValue() != 7.5 {
- t.Errorf("Error debiting shared balance: %+v", other.BalanceMap[utils.MONETARY+utils.OUT][0])
+ other, err := accountingStorage.GetAccount("vdf:empty10")
+ if err != nil || other.BalanceMap[utils.MONETARY][0].GetValue() != 7.5 {
+ t.Errorf("Error debiting shared balance: %+v", other.BalanceMap[utils.MONETARY][0])
}
}
@@ -878,7 +880,7 @@ func TestMaxSesionTimeEmptyBalance(t *testing.T) {
Account: "luna",
Destination: "0723",
}
- acc, _ := accountingStorage.GetAccount("*out:vdf:luna")
+ acc, _ := accountingStorage.GetAccount("vdf:luna")
allowedTime, err := cd.getMaxSessionDuration(acc)
if err != nil || allowedTime != 0 {
t.Error("Error get max session for 0 acount", err)
@@ -896,7 +898,7 @@ func TestMaxSesionTimeEmptyBalanceAndNoCost(t *testing.T) {
Account: "luna",
Destination: "112",
}
- acc, _ := accountingStorage.GetAccount("*out:vdf:luna")
+ acc, _ := accountingStorage.GetAccount("vdf:luna")
allowedTime, err := cd.getMaxSessionDuration(acc)
if err != nil || allowedTime == 0 {
t.Error("Error get max session for 0 acount", err)
@@ -913,7 +915,7 @@ func TestMaxSesionTimeLong(t *testing.T) {
Subject: "money",
Destination: "0723",
}
- acc, _ := accountingStorage.GetAccount("*out:cgrates.org:money")
+ acc, _ := accountingStorage.GetAccount("cgrates.org:money")
allowedTime, err := cd.getMaxSessionDuration(acc)
if err != nil || allowedTime != cd.TimeEnd.Sub(cd.TimeStart) {
t.Error("Error get max session for acount:", allowedTime, err)
@@ -930,7 +932,7 @@ func TestMaxSesionTimeLongerThanMoney(t *testing.T) {
Subject: "money",
Destination: "0723",
}
- acc, _ := accountingStorage.GetAccount("*out:cgrates.org:money")
+ acc, _ := accountingStorage.GetAccount("cgrates.org:money")
allowedTime, err := cd.getMaxSessionDuration(acc)
expected, err := time.ParseDuration("2h46m40s")
if err != nil || allowedTime != expected {
@@ -956,7 +958,7 @@ func TestDebitFromShareAndNormal(t *testing.T) {
}
cc, err := cd.MaxDebit()
acc, _ := cd.getAccount()
- balanceMap := acc.BalanceMap[utils.MONETARY+utils.OUT]
+ balanceMap := acc.BalanceMap[utils.MONETARY]
if err != nil || cc.Cost != 2.5 {
t.Errorf("Debit from share and normal error: %+v, %v", cc, err)
}
@@ -988,7 +990,7 @@ func TestDebitFromEmptyShare(t *testing.T) {
t.Errorf("Debit from empty share error: %+v, %v", cc, err)
}
acc, _ := cd.getAccount()
- balanceMap := acc.BalanceMap[utils.MONETARY+utils.OUT]
+ balanceMap := acc.BalanceMap[utils.MONETARY]
if len(balanceMap) != 2 || balanceMap[0].GetValue() != 0 || balanceMap[1].GetValue() != -2.5 {
t.Errorf("Error debiting from empty share: %+v", balanceMap[1].GetValue())
}
@@ -1017,13 +1019,13 @@ func TestDebitNegatve(t *testing.T) {
}
acc, _ := cd.getAccount()
//utils.PrintFull(acc)
- balanceMap := acc.BalanceMap[utils.MONETARY+utils.OUT]
+ balanceMap := acc.BalanceMap[utils.MONETARY]
if len(balanceMap) != 1 || balanceMap[0].GetValue() != -2.5 {
t.Errorf("Error debiting from empty share: %+v", balanceMap[0].GetValue())
}
cc, err = cd.MaxDebit()
acc, _ = cd.getAccount()
- balanceMap = acc.BalanceMap[utils.MONETARY+utils.OUT]
+ balanceMap = acc.BalanceMap[utils.MONETARY]
//utils.LogFull(balanceMap)
if err != nil || cc.Cost != 2.5 {
t.Errorf("Debit from empty share error: %+v, %v", cc, err)
@@ -1106,8 +1108,8 @@ func TestMaxDebitConsumesMinutes(t *testing.T) {
LoopIndex: 0,
DurationIndex: 0}
cd1.MaxDebit()
- if cd1.account.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != 20 {
- t.Error("Error using minutes: ", cd1.account.BalanceMap[utils.VOICE+utils.OUT][0].GetValue())
+ if cd1.account.BalanceMap[utils.VOICE][0].GetValue() != 20 {
+ t.Error("Error using minutes: ", cd1.account.BalanceMap[utils.VOICE][0].GetValue())
}
}
diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go
index d81143d97..84b6069f4 100644
--- a/engine/loader_csv_test.go
+++ b/engine/loader_csv_test.go
@@ -194,16 +194,16 @@ CDRST2_WARN_ASR,,*min_asr,30,true,0,,,,,,,,,,,,5,CDRST_WARN_HTTP,10
CDRST2_WARN_ACD,,*min_acd,3,true,0,,,,,,,,,,,,5,CDRST_WARN_HTTP,10
`
accountActions = `
-vdf,minitsboy,*out,MORE_MINUTES,STANDARD_TRIGGER,,
-cgrates.org,12345,*out,TOPUP10_AT,STANDARD_TRIGGERS,,
-cgrates.org,123456,*out,TOPUP10_AT,STANDARD_TRIGGERS,,
-cgrates.org,remo,*out,TOPUP10_AT,,,
-vdf,empty0,*out,TOPUP_SHARED0_AT,,,
-vdf,empty10,*out,TOPUP_SHARED10_AT,,,
-vdf,emptyX,*out,TOPUP_EMPTY_AT,,,
-vdf,emptyY,*out,TOPUP_EMPTY_AT,,,
-vdf,post,*out,POST_AT,,,
-cgrates.org,alodis,*out,TOPUP_EMPTY_AT,,true,true
+vdf,minitsboy,MORE_MINUTES,STANDARD_TRIGGER,,
+cgrates.org,12345,TOPUP10_AT,STANDARD_TRIGGERS,,
+cgrates.org,123456,TOPUP10_AT,STANDARD_TRIGGERS,,
+cgrates.org,remo,TOPUP10_AT,,,
+vdf,empty0,TOPUP_SHARED0_AT,,,
+vdf,empty10,TOPUP_SHARED10_AT,,,
+vdf,emptyX,TOPUP_EMPTY_AT,,,
+vdf,emptyY,TOPUP_EMPTY_AT,,,
+vdf,post,POST_AT,,,
+cgrates.org,alodis,TOPUP_EMPTY_AT,,true,true
`
derivedCharges = `
@@ -813,30 +813,34 @@ func TestLoadActions(t *testing.T) {
Id: "MINI0",
ActionType: TOPUP_RESET,
BalanceType: utils.MONETARY,
- Direction: utils.OUT,
ExpirationString: UNLIMITED,
ExtraParameters: "",
Weight: 10,
Balance: &Balance{
- Uuid: as1[0].Balance.Uuid,
- Value: 10,
- Weight: 10,
+ Uuid: as1[0].Balance.Uuid,
+ Directions: utils.NewStringMap(utils.OUT),
+ Value: 10,
+ Weight: 10,
+ TimingIDs: utils.StringMap{},
+ SharedGroups: utils.StringMap{},
},
},
&Action{
Id: "MINI1",
ActionType: TOPUP,
BalanceType: utils.VOICE,
- Direction: utils.OUT,
ExpirationString: UNLIMITED,
ExtraParameters: "",
Weight: 10,
Balance: &Balance{
Uuid: as1[1].Balance.Uuid,
+ Directions: utils.NewStringMap(utils.OUT),
Value: 100,
Weight: 10,
RatingSubject: "test",
- DestinationIds: "NAT",
+ DestinationIds: utils.NewStringMap("NAT"),
+ TimingIDs: utils.StringMap{},
+ SharedGroups: utils.StringMap{},
},
},
}
@@ -849,18 +853,20 @@ func TestLoadActions(t *testing.T) {
Id: "SHARED0",
ActionType: TOPUP,
BalanceType: utils.MONETARY,
- Direction: utils.OUT,
ExpirationString: UNLIMITED,
Weight: 10,
Balance: &Balance{
- Uuid: as2[0].Balance.Uuid,
- Value: 100,
- Weight: 10,
- SharedGroup: "SG1",
+ Directions: utils.NewStringMap(utils.OUT),
+ DestinationIds: utils.StringMap{},
+ Uuid: as2[0].Balance.Uuid,
+ Value: 100,
+ Weight: 10,
+ SharedGroups: utils.NewStringMap("SG1"),
+ TimingIDs: utils.StringMap{},
},
},
}
- if !reflect.DeepEqual(as2, expected) {
+ if !reflect.DeepEqual(as2[0], expected[0]) {
t.Errorf("Error loading action: %+v", as2[0].Balance)
}
as3 := csvr.actions["DEFEE"]
@@ -871,12 +877,16 @@ func TestLoadActions(t *testing.T) {
ExtraParameters: `{"Category":"^ddi","MediationRunId":"^did_run"}`,
Weight: 10,
Balance: &Balance{
- Uuid: as3[0].Balance.Uuid,
+ Uuid: as3[0].Balance.Uuid,
+ Directions: utils.StringMap{},
+ DestinationIds: utils.StringMap{},
+ TimingIDs: utils.StringMap{},
+ SharedGroups: utils.StringMap{},
},
},
}
if !reflect.DeepEqual(as3, expected) {
- t.Errorf("Error loading action: %+v", as3[0])
+ t.Errorf("Error loading action: %+v", as3[0].Balance)
}
}
@@ -974,7 +984,7 @@ func TestLoadActionTimings(t *testing.T) {
expected := &ActionPlan{
Uuid: atm.Uuid,
Id: "MORE_MINUTES",
- AccountIds: []string{"*out:vdf:minitsboy"},
+ AccountIds: []string{"vdf:minitsboy"},
Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{2012},
@@ -999,10 +1009,13 @@ func TestLoadActionTriggers(t *testing.T) {
atr := csvr.actionsTriggers["STANDARD_TRIGGER"][0]
expected := &ActionTrigger{
BalanceType: utils.VOICE,
- BalanceDirection: utils.OUT,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
ThresholdType: TRIGGER_MIN_COUNTER,
ThresholdValue: 10,
- BalanceDestinationIds: "GERMANY_O2",
+ BalanceDestinationIds: utils.NewStringMap("GERMANY_O2"),
+ BalanceCategories: utils.StringMap{},
+ BalanceTimingTags: utils.StringMap{},
+ BalanceSharedGroups: utils.StringMap{},
Weight: 10,
ActionsId: "SOME_1",
Executed: false,
@@ -1013,10 +1026,13 @@ func TestLoadActionTriggers(t *testing.T) {
atr = csvr.actionsTriggers["STANDARD_TRIGGER"][1]
expected = &ActionTrigger{
BalanceType: utils.VOICE,
- BalanceDirection: utils.OUT,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
ThresholdType: TRIGGER_MAX_BALANCE,
ThresholdValue: 200,
- BalanceDestinationIds: "GERMANY",
+ BalanceDestinationIds: utils.NewStringMap("GERMANY"),
+ BalanceCategories: utils.StringMap{},
+ BalanceTimingTags: utils.StringMap{},
+ BalanceSharedGroups: utils.StringMap{},
Weight: 10,
ActionsId: "SOME_2",
Executed: false,
@@ -1030,9 +1046,9 @@ func TestLoadAccountActions(t *testing.T) {
if len(csvr.accountActions) != 10 {
t.Error("Failed to load account actions: ", len(csvr.accountActions))
}
- aa := csvr.accountActions["*out:vdf:minitsboy"]
+ aa := csvr.accountActions["vdf:minitsboy"]
expected := &Account{
- Id: "*out:vdf:minitsboy",
+ Id: "vdf:minitsboy",
ActionTriggers: csvr.actionsTriggers["STANDARD_TRIGGER"],
}
// set propper uuid
diff --git a/engine/model_converters.go b/engine/model_converters.go
index 48afbe762..5dace97df 100644
--- a/engine/model_converters.go
+++ b/engine/model_converters.go
@@ -170,14 +170,14 @@ func APItoModelAction(as *utils.TPActions) (result []TpAction) {
Action: a.Identifier,
BalanceTag: a.BalanceId,
BalanceType: a.BalanceType,
- Direction: a.Direction,
+ Directions: a.Directions,
Units: a.Units,
ExpiryTime: a.ExpiryTime,
TimingTags: a.TimingTags,
DestinationTags: a.DestinationIds,
RatingSubject: a.RatingSubject,
- Category: a.Category,
- SharedGroup: a.SharedGroup,
+ Categories: a.Categories,
+ SharedGroups: a.SharedGroups,
BalanceWeight: a.BalanceWeight,
ExtraParameters: a.ExtraParameters,
Weight: a.Weight,
@@ -223,14 +223,14 @@ func APItoModelActionTrigger(ats *utils.TPActionTriggers) (result []TpActionTrig
MinSleep: at.MinSleep,
BalanceTag: at.BalanceId,
BalanceType: at.BalanceType,
- BalanceDirection: at.BalanceDirection,
+ BalanceDirections: at.BalanceDirections,
BalanceDestinationTags: at.BalanceDestinationIds,
BalanceWeight: at.BalanceWeight,
BalanceExpiryTime: at.BalanceExpirationDate,
BalanceTimingTags: at.BalanceTimingTags,
BalanceRatingSubject: at.BalanceRatingSubject,
- BalanceCategory: at.BalanceCategory,
- BalanceSharedGroup: at.BalanceSharedGroup,
+ BalanceCategories: at.BalanceCategories,
+ BalanceSharedGroups: at.BalanceSharedGroups,
BalanceDisabled: at.BalanceDisabled,
MinQueuedItems: at.MinQueuedItems,
ActionsTag: at.ActionsId,
@@ -250,7 +250,6 @@ func APItoModelAccountAction(aa *utils.TPAccountActions) *TpAccountAction {
return &TpAccountAction{
Tpid: aa.TPid,
Loadid: aa.LoadId,
- Direction: aa.Direction,
Tenant: aa.Tenant,
Account: aa.Account,
ActionPlanTag: aa.ActionPlanId,
diff --git a/engine/model_helpers.go b/engine/model_helpers.go
index c1adc5a85..a8254e066 100644
--- a/engine/model_helpers.go
+++ b/engine/model_helpers.go
@@ -387,14 +387,14 @@ func (tps TpActions) GetActions() (map[string][]*utils.TPAction, error) {
Identifier: tpAc.Action,
BalanceId: tpAc.BalanceTag,
BalanceType: tpAc.BalanceType,
- Direction: tpAc.Direction,
+ Directions: tpAc.Directions,
Units: tpAc.Units,
ExpiryTime: tpAc.ExpiryTime,
TimingTags: tpAc.TimingTags,
DestinationIds: tpAc.DestinationTags,
RatingSubject: tpAc.RatingSubject,
- Category: tpAc.Category,
- SharedGroup: tpAc.SharedGroup,
+ Categories: tpAc.Categories,
+ SharedGroups: tpAc.SharedGroups,
BalanceWeight: tpAc.BalanceWeight,
ExtraParameters: tpAc.ExtraParameters,
Weight: tpAc.Weight,
@@ -428,14 +428,14 @@ func (tps TpActionTriggers) GetActionTriggers() (map[string][]*utils.TPActionTri
MinSleep: tpAt.MinSleep,
BalanceId: tpAt.BalanceTag,
BalanceType: tpAt.BalanceType,
- BalanceDirection: tpAt.BalanceDirection,
+ BalanceDirections: tpAt.BalanceDirections,
BalanceDestinationIds: tpAt.BalanceDestinationTags,
BalanceWeight: tpAt.BalanceWeight,
BalanceExpirationDate: tpAt.BalanceExpiryTime,
BalanceTimingTags: tpAt.BalanceTimingTags,
BalanceRatingSubject: tpAt.BalanceRatingSubject,
- BalanceCategory: tpAt.BalanceCategory,
- BalanceSharedGroup: tpAt.BalanceSharedGroup,
+ BalanceCategories: tpAt.BalanceCategories,
+ BalanceSharedGroups: tpAt.BalanceSharedGroups,
BalanceDisabled: tpAt.BalanceDisabled,
Weight: tpAt.Weight,
ActionsId: tpAt.ActionsTag,
@@ -456,7 +456,6 @@ func (tps TpAccountActions) GetAccountActions() (map[string]*utils.TPAccountActi
LoadId: tpAa.Loadid,
Tenant: tpAa.Tenant,
Account: tpAa.Account,
- Direction: tpAa.Direction,
ActionPlanId: tpAa.ActionPlanTag,
ActionTriggersId: tpAa.ActionTriggersTag,
AllowNegative: tpAa.AllowNegative,
diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go
index e19b13da3..58ac02b6e 100644
--- a/engine/model_helpers_test.go
+++ b/engine/model_helpers_test.go
@@ -239,26 +239,26 @@ func TestTPActionsAsExportSlice(t *testing.T) {
&utils.TPAction{
Identifier: "*topup_reset",
BalanceType: "*monetary",
- Direction: utils.OUT,
+ Directions: utils.OUT,
Units: 5.0,
ExpiryTime: "*never",
DestinationIds: "*any",
RatingSubject: "special1",
- Category: "call",
- SharedGroup: "GROUP1",
+ Categories: "call",
+ SharedGroups: "GROUP1",
BalanceWeight: 10.0,
ExtraParameters: "",
Weight: 10.0},
&utils.TPAction{
Identifier: "*http_post",
BalanceType: "",
- Direction: "",
+ Directions: "",
Units: 0.0,
ExpiryTime: "",
DestinationIds: "",
RatingSubject: "",
- Category: "",
- SharedGroup: "",
+ Categories: "",
+ SharedGroups: "",
BalanceWeight: 0.0,
ExtraParameters: "http://localhost/¶m1=value1",
Weight: 20.0},
@@ -557,14 +557,14 @@ func TestTPActionPlanAsExportSlice(t *testing.T) {
MinSleep: "0",
BalanceId: "b1",
BalanceType: "*monetary",
- BalanceDirection: "*out",
+ BalanceDirections: "*out",
BalanceDestinationIds: "",
BalanceWeight: 0.0,
BalanceExpirationDate: "*never",
BalanceTimingTags: "T1",
BalanceRatingSubject: "special1",
- BalanceCategory: "call",
- BalanceSharedGroup: "SHARED_1",
+ BalanceCategories: "call",
+ BalanceSharedGroups: "SHARED_1",
BalanceDisabled: false,
MinQueuedItems: 0,
ActionsId: "LOG_WARNING",
@@ -576,14 +576,14 @@ func TestTPActionPlanAsExportSlice(t *testing.T) {
MinSleep: "0",
BalanceId: "b2",
BalanceType: "*monetary",
- BalanceDirection: "*out",
+ BalanceDirections: "*out",
BalanceDestinationIds: "FS_USERS",
BalanceWeight: 0.0,
BalanceExpirationDate: "*never",
BalanceTimingTags: "T1",
BalanceRatingSubject: "special1",
- BalanceCategory: "call",
- BalanceSharedGroup: "SHARED_1",
+ BalanceCategories: "call",
+ BalanceSharedGroups: "SHARED_1",
BalanceDisabled: false,
MinQueuedItems: 0,
ActionsId: "LOG_WARNING",
@@ -614,12 +614,11 @@ func TestTPAccountActionsAsExportSlice(t *testing.T) {
LoadId: "TEST_LOADID",
Tenant: "cgrates.org",
Account: "1001",
- Direction: "*out",
ActionPlanId: "PACKAGE_10_SHARED_A_5",
ActionTriggersId: "STANDARD_TRIGGERS",
}
expectedSlc := [][]string{
- []string{"cgrates.org", "1001", "*out", "PACKAGE_10_SHARED_A_5", "STANDARD_TRIGGERS", "false", "false"},
+ []string{"cgrates.org", "1001", "PACKAGE_10_SHARED_A_5", "STANDARD_TRIGGERS", "false", "false"},
}
ms := APItoModelAccountAction(aa)
var slc [][]string
diff --git a/engine/models.go b/engine/models.go
index c2698ce30..59aff1737 100644
--- a/engine/models.go
+++ b/engine/models.go
@@ -158,11 +158,11 @@ type TpAction struct {
ExtraParameters string `index:"2" re:"\S+\s*"`
BalanceTag string `index:"3" re:"\w+\s*"`
BalanceType string `index:"4" re:"\*\w+\s*"`
- Direction string `index:"5" re:"\*out\s*"`
- Category string `index:"6" re:"\*?\w+\s*"`
+ Directions string `index:"5" re:""`
+ Categories string `index:"6" re:""`
DestinationTags string `index:"7" re:"\*any|\w+\s*"`
RatingSubject string `index:"8" re:"\w+\s*"`
- SharedGroup string `index:"9" re:"[0-9A-Za-z_;]*"`
+ SharedGroups string `index:"9" re:"[0-9A-Za-z_;]*"`
ExpiryTime string `index:"10" re:"\*\w+\s*|\+\d+[smh]\s*|\d+\s*"`
TimingTags string `index:"11" re:"[0-9A-Za-z_;]*|\*any"`
Units float64 `index:"12" re:"\d+\s*"`
@@ -193,11 +193,11 @@ type TpActionTrigger struct {
MinSleep string `index:"5" re:"\d+[smh]?"`
BalanceTag string `index:"6" re:"\w+\s*"`
BalanceType string `index:"7" re:"\*\w+"`
- BalanceDirection string `index:"8" re:"\*out"`
- BalanceCategory string `index:"9" re:"\w+|\*any"`
+ BalanceDirections string `index:"8" re:"\*out"`
+ BalanceCategories string `index:"9" re:""`
BalanceDestinationTags string `index:"10" re:"\w+|\*any"`
BalanceRatingSubject string `index:"11" re:"\w+|\*any"`
- BalanceSharedGroup string `index:"12" re:"\w+|\*any"`
+ BalanceSharedGroups string `index:"12" re:"\w+|\*any"`
BalanceExpiryTime string `index:"13" re:"\*\w+\s*|\+\d+[smh]\s*|\d+\s*"`
BalanceTimingTags string `index:"14" re:"[0-9A-Za-z_;]*|\*any"`
BalanceWeight float64 `index:"15" re:"\d+\.?\d*"`
@@ -214,28 +214,26 @@ type TpAccountAction struct {
Loadid string
Tenant string `index:"0" re:"\w+\s*"`
Account string `index:"1" re:"(\w+;?)+\s*"`
- Direction string `index:"2" re:"\*out\s*"`
- ActionPlanTag string `index:"3" re:"\w+\s*"`
- ActionTriggersTag string `index:"4" re:"\w+\s*"`
- AllowNegative bool `index:"5" re:""`
- Disabled bool `index:"6" re:""`
+ ActionPlanTag string `index:"2" re:"\w+\s*"`
+ ActionTriggersTag string `index:"3" re:"\w+\s*"`
+ AllowNegative bool `index:"4" re:""`
+ Disabled bool `index:"5" re:""`
CreatedAt time.Time
}
func (aa *TpAccountAction) SetAccountActionId(id string) error {
ids := strings.Split(id, utils.CONCATENATED_KEY_SEP)
- if len(ids) != 4 {
+ if len(ids) != 3 {
return fmt.Errorf("Wrong TP Account Action Id: %s", id)
}
aa.Loadid = ids[0]
- aa.Direction = ids[1]
- aa.Tenant = ids[2]
- aa.Account = ids[3]
+ aa.Tenant = ids[1]
+ aa.Account = ids[2]
return nil
}
func (aa *TpAccountAction) GetAccountActionId() string {
- return utils.AccountKey(aa.Tenant, aa.Account, aa.Direction)
+ return utils.AccountKey(aa.Tenant, aa.Account)
}
type TpSharedGroup struct {
diff --git a/engine/responder_test.go b/engine/responder_test.go
index 2bbf4e0a3..29b1ee2c6 100644
--- a/engine/responder_test.go
+++ b/engine/responder_test.go
@@ -71,10 +71,10 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) {
if err := ratingStorage.SetDestination(deTMobile); err != nil {
t.Error(err)
}
- b10 := &Balance{Value: 10, Weight: 10, DestinationIds: "DE_TMOBILE"}
- b20 := &Balance{Value: 20, Weight: 10, DestinationIds: "DE_TMOBILE"}
- rifsAccount := &Account{Id: utils.ConcatenatedKey(utils.OUT, testTenant, "rif"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b10}}}
- dansAccount := &Account{Id: utils.ConcatenatedKey(utils.OUT, testTenant, "dan"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b20}}}
+ b10 := &Balance{Value: 10, Weight: 10, DestinationIds: utils.NewStringMap("DE_TMOBILE")}
+ b20 := &Balance{Value: 20, Weight: 10, DestinationIds: utils.NewStringMap("DE_TMOBILE")}
+ rifsAccount := &Account{Id: utils.ConcatenatedKey(testTenant, "rif"), BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b10}}}
+ dansAccount := &Account{Id: utils.ConcatenatedKey(testTenant, "dan"), BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b20}}}
if err := accountingStorage.SetAccount(rifsAccount); err != nil {
t.Error(err)
}
@@ -94,17 +94,17 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) {
t.Error("Error on setting DerivedChargers", err.Error())
}
ratingStorage.CacheRatingAll()
- if rifStoredAcnt, err := accountingStorage.GetAccount(utils.ConcatenatedKey(utils.OUT, testTenant, "rif")); err != nil {
+ if rifStoredAcnt, err := accountingStorage.GetAccount(utils.ConcatenatedKey(testTenant, "rif")); err != nil {
t.Error(err)
- //} else if rifStoredAcnt.BalanceMap[utils.VOICE+utils.OUT].Equal(rifsAccount.BalanceMap[utils.VOICE+utils.OUT]) {
- // t.Errorf("Expected: %+v, received: %+v", rifsAccount.BalanceMap[utils.VOICE+utils.OUT][0], rifStoredAcnt.BalanceMap[utils.VOICE+utils.OUT][0])
- } else if rifStoredAcnt.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != rifsAccount.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() {
- t.Error("BalanceValue: ", rifStoredAcnt.BalanceMap[utils.VOICE+utils.OUT][0].GetValue())
+ //} else if rifStoredAcnt.BalanceMap[utils.VOICE].Equal(rifsAccount.BalanceMap[utils.VOICE]) {
+ // t.Errorf("Expected: %+v, received: %+v", rifsAccount.BalanceMap[utils.VOICE][0], rifStoredAcnt.BalanceMap[utils.VOICE][0])
+ } else if rifStoredAcnt.BalanceMap[utils.VOICE][0].GetValue() != rifsAccount.BalanceMap[utils.VOICE][0].GetValue() {
+ t.Error("BalanceValue: ", rifStoredAcnt.BalanceMap[utils.VOICE][0].GetValue())
}
- if danStoredAcnt, err := accountingStorage.GetAccount(utils.ConcatenatedKey(utils.OUT, testTenant, "dan")); err != nil {
+ if danStoredAcnt, err := accountingStorage.GetAccount(utils.ConcatenatedKey(testTenant, "dan")); err != nil {
t.Error(err)
- } else if danStoredAcnt.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() != dansAccount.BalanceMap[utils.VOICE+utils.OUT][0].GetValue() {
- t.Error("BalanceValue: ", danStoredAcnt.BalanceMap[utils.VOICE+utils.OUT][0].GetValue())
+ } else if danStoredAcnt.BalanceMap[utils.VOICE][0].GetValue() != dansAccount.BalanceMap[utils.VOICE][0].GetValue() {
+ t.Error("BalanceValue: ", danStoredAcnt.BalanceMap[utils.VOICE][0].GetValue())
}
var dcs utils.DerivedChargers
attrs := &utils.AttrDerivedChargers{Tenant: testTenant, Category: "call", Direction: "*out", Account: "dan", Subject: "dan"}
@@ -428,10 +428,10 @@ func TestResponderGetLCR(t *testing.T) {
} else if !reflect.DeepEqual(eLcLcr.SupplierCosts, lcrLc.SupplierCosts) {
t.Errorf("Expecting: %+v, received: %+v", eLcLcr.SupplierCosts, lcrLc.SupplierCosts)
}
- bRif12 := &Balance{Value: 40, Weight: 10, DestinationIds: dstDe.Id}
- bIvo12 := &Balance{Value: 60, Weight: 10, DestinationIds: dstDe.Id}
- rif12sAccount := &Account{Id: utils.ConcatenatedKey(utils.OUT, "tenant12", "rif12"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{bRif12}}, AllowNegative: true}
- ivo12sAccount := &Account{Id: utils.ConcatenatedKey(utils.OUT, "tenant12", "ivo12"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{bIvo12}}, AllowNegative: true}
+ bRif12 := &Balance{Value: 40, Weight: 10, DestinationIds: utils.NewStringMap(dstDe.Id)}
+ bIvo12 := &Balance{Value: 60, Weight: 10, DestinationIds: utils.NewStringMap(dstDe.Id)}
+ rif12sAccount := &Account{Id: utils.ConcatenatedKey("tenant12", "rif12"), BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{bRif12}}, AllowNegative: true}
+ ivo12sAccount := &Account{Id: utils.ConcatenatedKey("tenant12", "ivo12"), BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{bIvo12}}, AllowNegative: true}
for _, acnt := range []*Account{rif12sAccount, ivo12sAccount} {
if err := accountingStorage.SetAccount(acnt); err != nil {
t.Error(err)
diff --git a/engine/sharedgroup.go b/engine/sharedgroup.go
index 4f7ef3d9f..4ec1bde23 100644
--- a/engine/sharedgroup.go
+++ b/engine/sharedgroup.go
@@ -90,7 +90,7 @@ func (sg *SharedGroup) SortBalancesByStrategy(myBalance *Balance, bc BalanceChai
}
// Returns all shared group's balances collected from user accounts'
-func (sg *SharedGroup) GetBalances(destination, category, balanceType string, ub *Account) (bc BalanceChain) {
+func (sg *SharedGroup) GetBalances(destination, category, direction, balanceType string, ub *Account) (bc BalanceChain) {
// if len(sg.members) == 0 {
for _, ubId := range sg.MemberIds {
var nUb *Account
@@ -103,7 +103,7 @@ func (sg *SharedGroup) GetBalances(destination, category, balanceType string, ub
}
}
//sg.members = append(sg.members, nUb)
- sb := nUb.getBalancesForPrefix(destination, category, nUb.BalanceMap[balanceType], sg.Id)
+ sb := nUb.getBalancesForPrefix(destination, category, direction, balanceType, sg.Id)
bc = append(bc, sb...)
}
/* } else {
diff --git a/engine/storage_mongo_local_test.go b/engine/storage_mongo_local_test.go
index b097c3471..14e5183a4 100644
--- a/engine/storage_mongo_local_test.go
+++ b/engine/storage_mongo_local_test.go
@@ -245,7 +245,7 @@ func TestMongoSetGetTPActions(t *testing.T) {
}
ACTS_ID := "PREPAID_10"
acts := []*utils.TPAction{
- &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Direction: "*out", Units: 10, ExpiryTime: "*unlimited",
+ &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited",
DestinationIds: "*any", BalanceWeight: 10, Weight: 10}}
tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts}
mas := APItoModelAction(tpActions)
@@ -287,7 +287,7 @@ func TestMongoSetGetTPActionTriggers(t *testing.T) {
atrg := &utils.TPActionTrigger{
Id: "MY_FIRST_ATGR",
BalanceType: "*monetary",
- BalanceDirection: "*out",
+ BalanceDirections: "*out",
ThresholdType: "*min_balance",
ThresholdValue: 2.0,
Recurrent: true,
@@ -315,8 +315,7 @@ func TestMongoSetGetTpAccountActions(t *testing.T) {
if !*testLocal {
return
}
- aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
maa := APItoModelAccountAction(aa)
if err := mongoDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
t.Error(err.Error())
@@ -386,8 +385,7 @@ func TestMongoRemoveTPData(t *testing.T) {
t.Errorf("RatingProfiles different than 0: %+v", rps)
}
// Create AccountActions
- aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
maa := APItoModelAccountAction(aa)
if err := mongoDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
t.Error(err.Error())
@@ -398,7 +396,7 @@ func TestMongoRemoveTPData(t *testing.T) {
t.Error("Could not create TPAccountActions")
}
// Remove AccountActions
- if err := mongoDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "direction": aa.Direction, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
+ if err := mongoDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
t.Error(err.Error())
}
if aas, err := mongoDb.GetTpAccountActions(maa); err != nil {
diff --git a/engine/storage_mongo_tp.go b/engine/storage_mongo_tp.go
index db606efaf..9a30c5287 100644
--- a/engine/storage_mongo_tp.go
+++ b/engine/storage_mongo_tp.go
@@ -336,9 +336,6 @@ func (ms *MongoStorage) GetTpActionTriggers(tpid, tag string) ([]TpActionTrigger
func (ms *MongoStorage) GetTpAccountActions(tp *TpAccountAction) ([]TpAccountAction, error) {
filter := bson.M{"tpid": tp.Tpid}
- if tp.Direction != "" {
- filter["direction"] = tp.Direction
- }
if tp.Tenant != "" {
filter["tenant"] = tp.Tenant
}
@@ -672,11 +669,10 @@ func (ms *MongoStorage) SetTpAccountActions(tps []TpAccountAction) error {
if found, _ := m[tp.GetAccountActionId()]; !found {
m[tp.GetAccountActionId()] = true
tx.Upsert(bson.M{
- "tpid": tp.Tpid,
- "loadid": tp.Loadid,
- "direction": tp.Direction,
- "tenant": tp.Tenant,
- "account": tp.Account}, tp)
+ "tpid": tp.Tpid,
+ "loadid": tp.Loadid,
+ "tenant": tp.Tenant,
+ "account": tp.Account}, tp)
}
}
_, err := tx.Run()
diff --git a/engine/storage_mysql_local_test.go b/engine/storage_mysql_local_test.go
index 6000d307d..d8a35e1d1 100644
--- a/engine/storage_mysql_local_test.go
+++ b/engine/storage_mysql_local_test.go
@@ -260,7 +260,7 @@ func TestMySQLSetGetTPActions(t *testing.T) {
}
ACTS_ID := "PREPAID_10"
acts := []*utils.TPAction{
- &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Direction: "*out", Units: 10, ExpiryTime: "*unlimited",
+ &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited",
DestinationIds: "*any", BalanceWeight: 10, Weight: 10}}
tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts}
mas := APItoModelAction(tpActions)
@@ -302,7 +302,7 @@ func TestMySQLSetGetTPActionTriggers(t *testing.T) {
atrg := &utils.TPActionTrigger{
Id: "MY_FIRST_ATGR",
BalanceType: "*monetary",
- BalanceDirection: "*out",
+ BalanceDirections: "*out",
ThresholdType: "*min_balance",
ThresholdValue: 2.0,
Recurrent: true,
@@ -331,7 +331,7 @@ func TestMySQLSetGetTpAccountActions(t *testing.T) {
return
}
aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
maa := APItoModelAccountAction(aa)
if err := mysqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
t.Error(err.Error())
@@ -402,7 +402,7 @@ func TestMySQLRemoveTPData(t *testing.T) {
}
// Create AccountActions
aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
maa := APItoModelAccountAction(aa)
if err := mysqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
t.Error(err.Error())
@@ -413,7 +413,7 @@ func TestMySQLRemoveTPData(t *testing.T) {
t.Error("Could not create TPAccountActions")
}
// Remove AccountActions
- if err := mysqlDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "direction": aa.Direction, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
+ if err := mysqlDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
t.Error(err.Error())
}
if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil {
diff --git a/engine/storage_psql_local_test.go b/engine/storage_psql_local_test.go
index 765639dee..f1743cc12 100644
--- a/engine/storage_psql_local_test.go
+++ b/engine/storage_psql_local_test.go
@@ -255,7 +255,7 @@ func TestPSQLSetGetTPActions(t *testing.T) {
}
ACTS_ID := "PREPAID_10"
acts := []*utils.TPAction{
- &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Direction: "*out", Units: 10, ExpiryTime: "*unlimited",
+ &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited",
DestinationIds: "*any", BalanceWeight: 10, Weight: 10}}
tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts}
mas := APItoModelAction(tpActions)
@@ -297,7 +297,7 @@ func TestPSQLSetGetTPActionTriggers(t *testing.T) {
atrg := &utils.TPActionTrigger{
Id: "MY_FIRST_ATGR",
BalanceType: "*monetary",
- BalanceDirection: "*out",
+ BalanceDirections: "*out",
ThresholdType: "*min_balance",
ThresholdValue: 2.0,
Recurrent: true,
@@ -326,7 +326,7 @@ func TestPSQLSetGetTpAccountActions(t *testing.T) {
return
}
aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
maa := APItoModelAccountAction(aa)
if err := psqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
t.Error(err.Error())
@@ -397,7 +397,7 @@ func TestPSQLRemoveTPData(t *testing.T) {
}
// Create AccountActions
aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001",
- Direction: "*out", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"}
maa := APItoModelAccountAction(aa)
if err := psqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil {
t.Error(err.Error())
@@ -408,7 +408,7 @@ func TestPSQLRemoveTPData(t *testing.T) {
t.Error("Could not create TPAccountActions")
}
// Remove AccountActions
- if err := psqlDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "direction": aa.Direction, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
+ if err := psqlDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil {
t.Error(err.Error())
}
if aas, err := psqlDb.GetTpAccountActions(maa); err != nil {
diff --git a/engine/storage_sql.go b/engine/storage_sql.go
index 736615c41..9e550d066 100644
--- a/engine/storage_sql.go
+++ b/engine/storage_sql.go
@@ -546,7 +546,7 @@ func (self *SQLStorage) SetTpAccountActions(aas []TpAccountAction) error {
for _, aa := range aas {
if found, _ := m[aa.GetAccountActionId()]; !found {
m[aa.GetAccountActionId()] = true
- if err := tx.Where(&TpAccountAction{Tpid: aa.Tpid, Loadid: aa.Loadid, Direction: aa.Direction, Tenant: aa.Tenant, Account: aa.Account}).Delete(TpAccountAction{}).Error; err != nil {
+ if err := tx.Where(&TpAccountAction{Tpid: aa.Tpid, Loadid: aa.Loadid, Tenant: aa.Tenant, Account: aa.Account}).Delete(TpAccountAction{}).Error; err != nil {
tx.Rollback()
return err
}
@@ -1594,9 +1594,6 @@ func (self *SQLStorage) GetTpAccountActions(filter *TpAccountAction) ([]TpAccoun
var tpAccActs []TpAccountAction
q := self.db.Where("tpid = ?", filter.Tpid)
- if len(filter.Direction) != 0 {
- q = q.Where("direction = ?", filter.Direction)
- }
if len(filter.Tenant) != 0 {
q = q.Where("tenant = ?", filter.Tenant)
}
diff --git a/engine/storage_test.go b/engine/storage_test.go
index a2dbadbff..3332cec8b 100644
--- a/engine/storage_test.go
+++ b/engine/storage_test.go
@@ -238,7 +238,7 @@ func TestStorageCacheRemoveCachedAliases(t *testing.T) {
}
func TestStorageDisabledAccount(t *testing.T) {
- acc, err := accountingStorage.GetAccount("*out:cgrates.org:alodis")
+ acc, err := accountingStorage.GetAccount("cgrates.org:alodis")
if err != nil || acc == nil {
t.Error("Error loading disabled user account: ", err, acc)
}
@@ -258,17 +258,17 @@ func TestStoreInterfaces(t *testing.T) {
}
func TestDifferentUuid(t *testing.T) {
- a1, err := accountingStorage.GetAccount("*out:cgrates.org:12345")
+ a1, err := accountingStorage.GetAccount("cgrates.org:12345")
if err != nil {
t.Error("Error getting account: ", err)
}
- a2, err := accountingStorage.GetAccount("*out:cgrates.org:123456")
+ a2, err := accountingStorage.GetAccount("cgrates.org:123456")
if err != nil {
t.Error("Error getting account: ", err)
}
- if a1.BalanceMap[utils.VOICE+utils.OUT][0].Uuid == a2.BalanceMap[utils.VOICE+utils.OUT][0].Uuid ||
- a1.BalanceMap[utils.MONETARY+utils.OUT][0].Uuid == a2.BalanceMap[utils.MONETARY+utils.OUT][0].Uuid {
- t.Errorf("Identical uuids in different accounts: %+v <-> %+v", a1.BalanceMap[utils.VOICE+utils.OUT][0], a1.BalanceMap[utils.MONETARY+utils.OUT][0])
+ if a1.BalanceMap[utils.VOICE][0].Uuid == a2.BalanceMap[utils.VOICE][0].Uuid ||
+ a1.BalanceMap[utils.MONETARY][0].Uuid == a2.BalanceMap[utils.MONETARY][0].Uuid {
+ t.Errorf("Identical uuids in different accounts: %+v <-> %+v", a1.BalanceMap[utils.VOICE][0], a1.BalanceMap[utils.MONETARY][0])
}
}
@@ -276,16 +276,15 @@ func TestDifferentUuid(t *testing.T) {
func GetUB() *Account {
uc := &UnitsCounter{
- Direction: utils.OUT,
BalanceType: utils.SMS,
- Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}},
+ Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}},
}
at := &ActionTrigger{
Id: "some_uuid",
BalanceType: utils.MONETARY,
- BalanceDirection: utils.OUT,
+ BalanceDirections: utils.NewStringMap(utils.OUT),
ThresholdValue: 100.0,
- BalanceDestinationIds: "NAT",
+ BalanceDestinationIds: utils.NewStringMap("NAT"),
Weight: 10.0,
ActionsId: "Commando",
}
@@ -294,7 +293,7 @@ func GetUB() *Account {
ub := &Account{
Id: "rif",
AllowNegative: true,
- BalanceMap: map[string]BalanceChain{utils.SMS + utils.OUT: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, utils.DATA + utils.OUT: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}, utils.VOICE: BalanceChain{&Balance{Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}}},
+ 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},
ActionTriggers: ActionTriggers{at, at, at},
}
diff --git a/engine/timespans_test.go b/engine/timespans_test.go
index e2b21d1b2..1a4fea010 100644
--- a/engine/timespans_test.go
+++ b/engine/timespans_test.go
@@ -742,7 +742,7 @@ func TestTimespanCreateIncrements(t *testing.T) {
if len(ts.Increments) != 3 {
t.Error("Error creating increment slice: ", len(ts.Increments))
}
- if len(ts.Increments) < 3 || ts.Increments[2].Cost != 20.0666666667 {
+ if len(ts.Increments) < 3 || ts.Increments[2].Cost != 20.06667 {
t.Error("Wrong second slice: ", ts.Increments[2].Cost)
}
}
diff --git a/engine/tp_reader.go b/engine/tp_reader.go
index e2596003b..75165cd84 100644
--- a/engine/tp_reader.go
+++ b/engine/tp_reader.go
@@ -506,7 +506,6 @@ func (tpr *TpReader) LoadActions() (err error) {
Id: tag + strconv.Itoa(idx),
ActionType: tpact.Identifier,
BalanceType: tpact.BalanceType,
- Direction: tpact.Direction,
Weight: tpact.Weight,
ExtraParameters: tpact.ExtraParameters,
ExpirationString: tpact.ExpiryTime,
@@ -514,16 +513,17 @@ func (tpr *TpReader) LoadActions() (err error) {
Id: tpact.BalanceId,
Value: tpact.Units,
Weight: tpact.BalanceWeight,
- TimingIDs: tpact.TimingTags,
RatingSubject: tpact.RatingSubject,
- Category: tpact.Category,
- DestinationIds: tpact.DestinationIds,
- SharedGroup: tpact.SharedGroup,
+ 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),
},
}
// load action timings from tags
- if acts[idx].Balance.TimingIDs != "" {
- timingIds := strings.Split(acts[idx].Balance.TimingIDs, utils.INFIELD_SEP)
+ if tpact.TimingTags != "" {
+ timingIds := strings.Split(tpact.TimingTags, utils.INFIELD_SEP)
for _, timingID := range timingIds {
if timing, found := tpr.timings[timingID]; found {
acts[idx].Balance.Timings = append(acts[idx].Balance.Timings, &RITiming{
@@ -617,14 +617,14 @@ func (tpr *TpReader) LoadActionTriggers() (err error) {
MinSleep: minSleep,
BalanceId: atr.BalanceId,
BalanceType: atr.BalanceType,
- BalanceDirection: atr.BalanceDirection,
- BalanceDestinationIds: atr.BalanceDestinationIds,
+ BalanceDirections: utils.ParseStringMap(atr.BalanceDirections),
+ BalanceDestinationIds: utils.ParseStringMap(atr.BalanceDestinationIds),
BalanceWeight: atr.BalanceWeight,
BalanceExpirationDate: balanceExpirationDate,
- BalanceTimingTags: atr.BalanceTimingTags,
+ BalanceTimingTags: utils.ParseStringMap(atr.BalanceTimingTags),
BalanceRatingSubject: atr.BalanceRatingSubject,
- BalanceCategory: atr.BalanceCategory,
- BalanceSharedGroup: atr.BalanceSharedGroup,
+ BalanceCategories: utils.ParseStringMap(atr.BalanceCategories),
+ BalanceSharedGroups: utils.ParseStringMap(atr.BalanceSharedGroups),
Weight: atr.Weight,
ActionsId: atr.ActionsId,
MinQueuedItems: atr.MinQueuedItems,
@@ -756,13 +756,13 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
MinSleep: minSleep,
BalanceId: apiAtr.BalanceId,
BalanceType: apiAtr.BalanceType,
- BalanceDirection: apiAtr.BalanceDirection,
- BalanceDestinationIds: apiAtr.BalanceDestinationIds,
+ BalanceDirections: utils.ParseStringMap(apiAtr.BalanceDirections),
+ BalanceDestinationIds: utils.ParseStringMap(apiAtr.BalanceDestinationIds),
BalanceWeight: apiAtr.BalanceWeight,
BalanceExpirationDate: expTime,
BalanceRatingSubject: apiAtr.BalanceRatingSubject,
- BalanceCategory: apiAtr.BalanceCategory,
- BalanceSharedGroup: apiAtr.BalanceSharedGroup,
+ BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories),
+ BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups),
Weight: apiAtr.Weight,
ActionsId: apiAtr.ActionsId,
}
@@ -799,7 +799,6 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
Id: tag + strconv.Itoa(idx),
ActionType: tpact.Identifier,
BalanceType: tpact.BalanceType,
- Direction: tpact.Direction,
Weight: tpact.Weight,
ExtraParameters: tpact.ExtraParameters,
ExpirationString: tpact.ExpiryTime,
@@ -807,8 +806,10 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
Value: tpact.Units,
Weight: tpact.BalanceWeight,
RatingSubject: tpact.RatingSubject,
- DestinationIds: tpact.DestinationIds,
- SharedGroup: tpact.SharedGroup,
+ Directions: utils.ParseStringMap(tpact.Directions),
+ DestinationIds: utils.ParseStringMap(tpact.DestinationIds),
+ SharedGroups: utils.ParseStringMap(tpact.SharedGroups),
+ TimingIDs: utils.ParseStringMap(tpact.TimingTags),
},
}
}
@@ -959,13 +960,14 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
MinSleep: minSleep,
BalanceId: apiAtr.BalanceId,
BalanceType: apiAtr.BalanceType,
- BalanceDirection: apiAtr.BalanceDirection,
- BalanceDestinationIds: apiAtr.BalanceDestinationIds,
+ BalanceDirections: utils.ParseStringMap(apiAtr.BalanceDirections),
+ BalanceDestinationIds: utils.ParseStringMap(apiAtr.BalanceDestinationIds),
BalanceWeight: apiAtr.BalanceWeight,
BalanceExpirationDate: expTime,
BalanceRatingSubject: apiAtr.BalanceRatingSubject,
- BalanceCategory: apiAtr.BalanceCategory,
- BalanceSharedGroup: apiAtr.BalanceSharedGroup,
+ BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories),
+ BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups),
+ BalanceTimingTags: utils.ParseStringMap(apiAtr.BalanceTimingTags),
Weight: apiAtr.Weight,
ActionsId: apiAtr.ActionsId,
}
@@ -1011,7 +1013,6 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
Id: tag + strconv.Itoa(idx),
ActionType: tpact.Identifier,
BalanceType: tpact.BalanceType,
- Direction: tpact.Direction,
Weight: tpact.Weight,
ExtraParameters: tpact.ExtraParameters,
ExpirationString: tpact.ExpiryTime,
@@ -1019,8 +1020,10 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
Value: tpact.Units,
Weight: tpact.BalanceWeight,
RatingSubject: tpact.RatingSubject,
- DestinationIds: tpact.DestinationIds,
- SharedGroup: tpact.SharedGroup,
+ Directions: utils.ParseStringMap(tpact.Directions),
+ DestinationIds: utils.ParseStringMap(tpact.DestinationIds),
+ SharedGroups: utils.ParseStringMap(tpact.SharedGroups),
+ TimingIDs: utils.ParseStringMap(tpact.TimingTags),
},
}
}
diff --git a/engine/units_counter.go b/engine/units_counter.go
index d74364f8c..1bf97eed0 100644
--- a/engine/units_counter.go
+++ b/engine/units_counter.go
@@ -27,7 +27,6 @@ import (
// Amount of a trafic of a certain type
type UnitsCounter struct {
- Direction string
BalanceType string
// Units float64
Balances BalanceChain // first balance is the general one (no destination)
@@ -39,7 +38,7 @@ func (uc *UnitsCounter) initBalances(ats []*ActionTrigger) {
uc.Balances = BalanceChain{&Balance{}} // general balance
for _, at := range ats {
if !strings.Contains(at.ThresholdType, "counter") {
- // only get actions fo counter type action triggers
+ // only get actions for counter type action triggers
continue
}
acs, err := ratingStorage.GetActions(at.ActionsId, false)
@@ -56,12 +55,12 @@ func (uc *UnitsCounter) initBalances(ats []*ActionTrigger) {
}
}
}
- uc.Balances.Sort()
+ //uc.Balances.Sort() // should not be sorted, leave default in first position
}
// returns the first balance that has no destination attached
func (uc *UnitsCounter) GetGeneralBalance() *Balance {
- if len(uc.Balances) == 0 { // general balance not present for some reson
+ if len(uc.Balances) == 0 { // general balance not present for some reason
uc.Balances = append(uc.Balances, &Balance{})
}
return uc.Balances[0]
@@ -69,8 +68,9 @@ func (uc *UnitsCounter) GetGeneralBalance() *Balance {
// Adds the units from the received balance to an existing balance if the destination
// is the same or ads the balance to the list if none matches.
-func (uc *UnitsCounter) addUnits(amount float64, prefix string) {
+func (uc *UnitsCounter) addUnits(amount float64, prefixMap utils.StringMap) {
counted := false
+ prefix := prefixMap.String()
if prefix != "" {
for _, mb := range uc.Balances {
if !mb.HasDestination() {
@@ -79,10 +79,15 @@ func (uc *UnitsCounter) addUnits(amount float64, prefix string) {
for _, p := range utils.SplitPrefix(prefix, MIN_PREFIX_MATCH) {
if x, err := cache2go.Get(utils.DESTINATION_PREFIX + p); err == nil {
destIds := x.(map[interface{}]struct{})
- if _, found := destIds[mb.DestinationIds]; found {
- mb.AddValue(amount)
- counted = true
- break
+ for key := range mb.DestinationIds {
+ if _, found := destIds[key]; found {
+ mb.AddValue(amount)
+ counted = true
+ break
+ }
+ if counted {
+ break
+ }
}
}
if counted {
diff --git a/engine/units_counter_test.go b/engine/units_counter_test.go
index 09bdec840..76763c41e 100644
--- a/engine/units_counter_test.go
+++ b/engine/units_counter_test.go
@@ -26,11 +26,10 @@ import (
func TestUnitsCounterAddBalance(t *testing.T) {
uc := &UnitsCounter{
- Direction: utils.OUT,
BalanceType: utils.SMS,
- Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}},
+ Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}},
}
- uc.addUnits(20, "test")
+ uc.addUnits(20, utils.NewStringMap("test"))
if len(uc.Balances) != 3 {
t.Error("Error adding minute bucket: ", uc.Balances)
}
@@ -38,11 +37,10 @@ func TestUnitsCounterAddBalance(t *testing.T) {
func TestUnitsCounterAddBalanceExists(t *testing.T) {
uc := &UnitsCounter{
- Direction: utils.OUT,
BalanceType: utils.SMS,
- Balances: BalanceChain{&Balance{Value: 1}, &Balance{Value: 10, Weight: 20, DestinationIds: "NAT"}, &Balance{Weight: 10, DestinationIds: "RET"}},
+ Balances: BalanceChain{&Balance{Value: 1}, &Balance{Value: 10, Weight: 20, DestinationIds: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIds: utils.NewStringMap("RET")}},
}
- uc.addUnits(5, "0723")
+ uc.addUnits(5, utils.NewStringMap("0723"))
if len(uc.Balances) != 3 || uc.Balances[1].GetValue() != 15 {
t.Error("Error adding minute bucket!")
}
diff --git a/general_tests/acntacts_test.go b/general_tests/acntacts_test.go
index e4348e98e..a0b8a1ff1 100644
--- a/general_tests/acntacts_test.go
+++ b/general_tests/acntacts_test.go
@@ -49,7 +49,7 @@ DISABLE_ACNT,*disable_account,,,,,,,,,,,,,false,10
ENABLE_ACNT,*enable_account,,,,,,,,,,,,,false,10`
actionPlans := `TOPUP10_AT,TOPUP10_AC,ASAP,10`
actionTriggers := ``
- accountActions := `cgrates.org,1,*out,TOPUP10_AT,,,`
+ accountActions := `cgrates.org,1,TOPUP10_AT,,,`
derivedCharges := ``
cdrStats := ``
users := ``
@@ -62,8 +62,8 @@ ENABLE_ACNT,*enable_account,,,,,,,,,,,,,false,10`
csvr.WriteToDatabase(false, false)
ratingDbAcntActs.CacheRatingAll()
acntDbAcntActs.CacheAccountingAll()
- expectAcnt := &engine.Account{Id: "*out:cgrates.org:1"}
- if acnt, err := acntDbAcntActs.GetAccount("*out:cgrates.org:1"); err != nil {
+ expectAcnt := &engine.Account{Id: "cgrates.org:1"}
+ if acnt, err := acntDbAcntActs.GetAccount("cgrates.org:1"); err != nil {
t.Error(err)
} else if acnt == nil {
t.Error("No account created")
@@ -73,7 +73,7 @@ ENABLE_ACNT,*enable_account,,,,,,,,,,,,,false,10`
}
func TestAcntActsDisableAcnt(t *testing.T) {
- acnt1Tag := "*out:cgrates.org:1"
+ acnt1Tag := "cgrates.org:1"
at := &engine.ActionPlan{
AccountIds: []string{acnt1Tag},
ActionsId: "DISABLE_ACNT",
@@ -81,7 +81,7 @@ func TestAcntActsDisableAcnt(t *testing.T) {
if err := at.Execute(); err != nil {
t.Error(err)
}
- expectAcnt := &engine.Account{Id: "*out:cgrates.org:1", Disabled: true}
+ expectAcnt := &engine.Account{Id: "cgrates.org:1", Disabled: true}
if acnt, err := acntDbAcntActs.GetAccount(acnt1Tag); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expectAcnt, acnt) {
@@ -90,7 +90,7 @@ func TestAcntActsDisableAcnt(t *testing.T) {
}
func TestAcntActsEnableAcnt(t *testing.T) {
- acnt1Tag := "*out:cgrates.org:1"
+ acnt1Tag := "cgrates.org:1"
at := &engine.ActionPlan{
AccountIds: []string{acnt1Tag},
ActionsId: "ENABLE_ACNT",
@@ -98,7 +98,7 @@ func TestAcntActsEnableAcnt(t *testing.T) {
if err := at.Execute(); err != nil {
t.Error(err)
}
- expectAcnt := &engine.Account{Id: "*out:cgrates.org:1", Disabled: false}
+ expectAcnt := &engine.Account{Id: "cgrates.org:1", Disabled: false}
if acnt, err := acntDbAcntActs.GetAccount(acnt1Tag); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expectAcnt, acnt) {
diff --git a/general_tests/auth_test.go b/general_tests/auth_test.go
index def8b9aa5..a47948eb2 100644
--- a/general_tests/auth_test.go
+++ b/general_tests/auth_test.go
@@ -59,7 +59,7 @@ RP_ANY,DR_ANY_1CNT,*any,10`
actions := `TOPUP10_AC,*topup_reset,,,*monetary,*out,,*any,,,*unlimited,,0,10,false,10`
actionPlans := `TOPUP10_AT,TOPUP10_AC,*asap,10`
actionTriggers := ``
- accountActions := `cgrates.org,testauthpostpaid1,*out,TOPUP10_AT,,,`
+ accountActions := `cgrates.org,testauthpostpaid1,TOPUP10_AT,,,`
derivedCharges := ``
cdrStats := ``
users := ``
@@ -70,7 +70,7 @@ RP_ANY,DR_ANY_1CNT,*any,10`
t.Fatal(err)
}
csvr.WriteToDatabase(false, false)
- if acnt, err := acntDbAuth.GetAccount("*out:cgrates.org:testauthpostpaid1"); err != nil {
+ if acnt, err := acntDbAuth.GetAccount("cgrates.org:testauthpostpaid1"); err != nil {
t.Error(err)
} else if acnt == nil {
t.Error("No account saved")
diff --git a/general_tests/ddazmbl1_test.go b/general_tests/ddazmbl1_test.go
index 901fc61c4..34c8a2988 100644
--- a/general_tests/ddazmbl1_test.go
+++ b/general_tests/ddazmbl1_test.go
@@ -58,7 +58,7 @@ TOPUP10_AC1,*topup_reset,,,*voice,*out,,DST_UK_Mobile_BIG5,discounted_minutes,,*
actionPlans := `TOPUP10_AT,TOPUP10_AC,ASAP,10
TOPUP10_AT,TOPUP10_AC1,ASAP,10`
actionTriggers := ``
- accountActions := `cgrates.org,12344,*out,TOPUP10_AT,,,`
+ accountActions := `cgrates.org,12344,TOPUP10_AT,,,`
derivedCharges := ``
cdrStats := ``
users := ``
@@ -105,7 +105,7 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10`
t.Fatal(err)
}
csvr.WriteToDatabase(false, false)
- if acnt, err := acntDb.GetAccount("*out:cgrates.org:12344"); err != nil {
+ if acnt, err := acntDb.GetAccount("cgrates.org:12344"); err != nil {
t.Error(err)
} else if acnt == nil {
t.Error("No account saved")
@@ -131,14 +131,14 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10`
func TestExecuteActions(t *testing.T) {
scheduler.NewScheduler().LoadActionPlans(ratingDb)
time.Sleep(time.Millisecond) // Give time to scheduler to topup the account
- if acnt, err := acntDb.GetAccount("*out:cgrates.org:12344"); err != nil {
+ if acnt, err := acntDb.GetAccount("cgrates.org:12344"); err != nil {
t.Error(err)
} else if len(acnt.BalanceMap) != 2 {
t.Error("Account does not have enough balances: ", acnt.BalanceMap)
- } else if acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value != 40 {
- t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value)
- } else if acnt.BalanceMap[utils.MONETARY+utils.OUT][0].Value != 10 {
- t.Error("Account does not have enough monetary balance", acnt.BalanceMap[utils.MONETARY+utils.OUT][0].Value)
+ } else if acnt.BalanceMap[utils.VOICE][0].Value != 40 {
+ t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[utils.VOICE][0].Value)
+ } else if acnt.BalanceMap[utils.MONETARY][0].Value != 10 {
+ t.Error("Account does not have enough monetary balance", acnt.BalanceMap[utils.MONETARY][0].Value)
}
}
@@ -158,14 +158,14 @@ func TestDebit(t *testing.T) {
} else if cc.Cost != 0.01 {
t.Error("Wrong cost returned: ", cc.Cost)
}
- acnt, err := acntDb.GetAccount("*out:cgrates.org:12344")
+ acnt, err := acntDb.GetAccount("cgrates.org:12344")
if err != nil {
t.Error(err)
}
- if acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value != 20 {
- t.Error("Account does not have expected minutes in balance", acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value)
+ if acnt.BalanceMap[utils.VOICE][0].Value != 20 {
+ t.Error("Account does not have expected minutes in balance", acnt.BalanceMap[utils.VOICE][0].Value)
}
- if acnt.BalanceMap[utils.MONETARY+utils.OUT][0].Value != 9.99 {
- t.Error("Account does not have expected monetary balance", acnt.BalanceMap[utils.MONETARY+utils.OUT][0].Value)
+ if acnt.BalanceMap[utils.MONETARY][0].Value != 9.99 {
+ t.Error("Account does not have expected monetary balance", acnt.BalanceMap[utils.MONETARY][0].Value)
}
}
diff --git a/general_tests/ddazmbl2_test.go b/general_tests/ddazmbl2_test.go
index d07c72cc5..1a0004d1a 100644
--- a/general_tests/ddazmbl2_test.go
+++ b/general_tests/ddazmbl2_test.go
@@ -58,7 +58,7 @@ TOPUP10_AC1,*topup_reset,,,*voice,*out,,DST_UK_Mobile_BIG5,discounted_minutes,,*
actionPlans := `TOPUP10_AT,TOPUP10_AC,ASAP,10
TOPUP10_AT,TOPUP10_AC1,ASAP,10`
actionTriggers := ``
- accountActions := `cgrates.org,12345,*out,TOPUP10_AT,,,`
+ accountActions := `cgrates.org,12345,TOPUP10_AT,,,`
derivedCharges := ``
cdrStats := ``
users := ``
@@ -105,7 +105,7 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10`
t.Fatal(err)
}
csvr.WriteToDatabase(false, false)
- if acnt, err := acntDb2.GetAccount("*out:cgrates.org:12345"); err != nil {
+ if acnt, err := acntDb2.GetAccount("cgrates.org:12345"); err != nil {
t.Error(err)
} else if acnt == nil {
t.Error("No account saved")
@@ -130,14 +130,14 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10`
func TestExecuteActions2(t *testing.T) {
scheduler.NewScheduler().LoadActionPlans(ratingDb2)
time.Sleep(time.Millisecond) // Give time to scheduler to topup the account
- if acnt, err := acntDb2.GetAccount("*out:cgrates.org:12345"); err != nil {
+ if acnt, err := acntDb2.GetAccount("cgrates.org:12345"); err != nil {
t.Error(err)
} else if len(acnt.BalanceMap) != 2 {
t.Error("Account does not have enough balances: ", acnt.BalanceMap)
- } else if acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value != 40 {
- t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value)
- } else if acnt.BalanceMap[utils.MONETARY+utils.OUT][0].Value != 0 {
- t.Error("Account does not have enough monetary balance", acnt.BalanceMap[utils.MONETARY+utils.OUT][0].Value)
+ } else if acnt.BalanceMap[utils.VOICE][0].Value != 40 {
+ t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[utils.VOICE][0].Value)
+ } else if acnt.BalanceMap[utils.MONETARY][0].Value != 0 {
+ t.Error("Account does not have enough monetary balance", acnt.BalanceMap[utils.MONETARY][0].Value)
}
}
@@ -157,17 +157,17 @@ func TestDebit2(t *testing.T) {
} else if cc.Cost != 0.01 {
t.Error("Wrong cost returned: ", cc.Cost)
}
- acnt, err := acntDb2.GetAccount("*out:cgrates.org:12345")
+ acnt, err := acntDb2.GetAccount("cgrates.org:12345")
if err != nil {
t.Error(err)
}
if len(acnt.BalanceMap) != 2 {
t.Error("Wrong number of user balances found", acnt.BalanceMap)
}
- if acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value != 20 {
- t.Error("Account does not have expected minutes in balance", acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value)
+ if acnt.BalanceMap[utils.VOICE][0].Value != 20 {
+ t.Error("Account does not have expected minutes in balance", acnt.BalanceMap[utils.VOICE][0].Value)
}
- for _, blnc := range acnt.BalanceMap[utils.MONETARY+utils.OUT] { // Test negative balance for default one
+ for _, blnc := range acnt.BalanceMap[utils.MONETARY] { // Test negative balance for default one
if blnc.Weight == 10 && blnc.Value != 0 {
t.Errorf("Balance with weight: %f, having value: %f ", blnc.Weight, blnc.Value)
} else if blnc.Weight == 0 && blnc.Value != -0.01 {
diff --git a/general_tests/ddazmbl3_test.go b/general_tests/ddazmbl3_test.go
index d1bd74029..0b49f8ea7 100644
--- a/general_tests/ddazmbl3_test.go
+++ b/general_tests/ddazmbl3_test.go
@@ -56,7 +56,7 @@ RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10`
actions := `TOPUP10_AC1,*topup_reset,,,*voice,*out,,DST_UK_Mobile_BIG5,discounted_minutes,,*unlimited,,40,10,false,10`
actionPlans := `TOPUP10_AT,TOPUP10_AC1,ASAP,10`
actionTriggers := ``
- accountActions := `cgrates.org,12346,*out,TOPUP10_AT,,,`
+ accountActions := `cgrates.org,12346,TOPUP10_AT,,,`
derivedCharges := ``
cdrStats := ``
users := ``
@@ -103,7 +103,7 @@ RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10`
t.Fatal(err)
}
csvr.WriteToDatabase(false, false)
- if acnt, err := acntDb3.GetAccount("*out:cgrates.org:12346"); err != nil {
+ if acnt, err := acntDb3.GetAccount("cgrates.org:12346"); err != nil {
t.Error(err)
} else if acnt == nil {
t.Error("No account saved")
@@ -128,12 +128,12 @@ RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10`
func TestExecuteActions3(t *testing.T) {
scheduler.NewScheduler().LoadActionPlans(ratingDb3)
time.Sleep(time.Millisecond) // Give time to scheduler to topup the account
- if acnt, err := acntDb3.GetAccount("*out:cgrates.org:12346"); err != nil {
+ if acnt, err := acntDb3.GetAccount("cgrates.org:12346"); err != nil {
t.Error(err)
} else if len(acnt.BalanceMap) != 1 {
t.Error("Account does not have enough balances: ", acnt.BalanceMap)
- } else if acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value != 40 {
- t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value)
+ } else if acnt.BalanceMap[utils.VOICE][0].Value != 40 {
+ t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[utils.VOICE][0].Value)
}
}
@@ -153,17 +153,17 @@ func TestDebit3(t *testing.T) {
} else if cc.Cost != 0.01 {
t.Error("Wrong cost returned: ", cc.Cost)
}
- acnt, err := acntDb3.GetAccount("*out:cgrates.org:12346")
+ acnt, err := acntDb3.GetAccount("cgrates.org:12346")
if err != nil {
t.Error(err)
}
if len(acnt.BalanceMap) != 2 {
t.Error("Wrong number of user balances found", acnt.BalanceMap)
}
- if acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value != 20 {
- t.Error("Account does not have expected minutes in balance", acnt.BalanceMap[utils.VOICE+utils.OUT][0].Value)
+ if acnt.BalanceMap[utils.VOICE][0].Value != 20 {
+ t.Error("Account does not have expected minutes in balance", acnt.BalanceMap[utils.VOICE][0].Value)
}
- if acnt.BalanceMap[utils.MONETARY+utils.OUT][0].Value != -0.01 {
- t.Error("Account does not have expected monetary balance", acnt.BalanceMap[utils.MONETARY+utils.OUT][0].Value)
+ if acnt.BalanceMap[utils.MONETARY][0].Value != -0.01 {
+ t.Error("Account does not have expected monetary balance", acnt.BalanceMap[utils.MONETARY][0].Value)
}
}
diff --git a/general_tests/tutorial_fs_calls_test.go b/general_tests/tutorial_fs_calls_test.go
index 8ad231481..e0ffb95e7 100644
--- a/general_tests/tutorial_fs_calls_test.go
+++ b/general_tests/tutorial_fs_calls_test.go
@@ -137,37 +137,37 @@ func TestTutFsCallsAccountsBefore(t *testing.T) {
return
}
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutFsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002"}
if err := tutFsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003"}
if err := tutFsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004"}
if err := tutFsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007"}
if err := tutFsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 0.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 0.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005"}
if err := tutFsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err == nil || !strings.HasSuffix(err.Error(), "does not exist") {
t.Error("Got error on ApierV1.GetAccount: %v", err)
}
@@ -315,11 +315,11 @@ func TestTutFsCallsAccount1001(t *testing.T) {
}
time.Sleep(time.Duration(70) * time.Second) // Allow calls to finish before start querying the results
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutFsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() == 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() == 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
} else if reply.Disabled == true {
t.Error("Account disabled")
}
@@ -535,7 +535,7 @@ func TestTutFsCallsAccountFraud1001(t *testing.T) {
return
}
var reply string
- attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Direction: "*out", Value: 101}
+ attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Value: 101}
if err := tutFsCallsRpc.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
@@ -549,7 +549,7 @@ func TestTutFsCallsAccountDisabled1001(t *testing.T) {
return
}
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutFsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
} else if reply.Disabled == false {
diff --git a/general_tests/tutorial_kam_calls_test.go b/general_tests/tutorial_kam_calls_test.go
index 0cade7da6..c9f90885d 100644
--- a/general_tests/tutorial_kam_calls_test.go
+++ b/general_tests/tutorial_kam_calls_test.go
@@ -137,37 +137,37 @@ func TestTutKamCallsAccountsBefore(t *testing.T) {
return
}
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002"}
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003"}
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004"}
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007"}
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 0.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 0.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005"}
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err == nil || !strings.HasSuffix(err.Error(), "does not exist") {
t.Error("Got error on ApierV1.GetAccount: %v", err)
}
@@ -315,11 +315,11 @@ func TestTutKamCallsAccount1001(t *testing.T) {
}
time.Sleep(time.Duration(70) * time.Second) // Allow calls to finish before start querying the results
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() == 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() == 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
} else if reply.Disabled == true {
t.Error("Account disabled")
}
@@ -535,7 +535,7 @@ func TestTutKamCallsAccountFraud1001(t *testing.T) {
return
}
var reply string
- attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Direction: "*out", Value: 101}
+ attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Value: 101}
if err := tutKamCallsRpc.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
@@ -549,7 +549,7 @@ func TestTutKamCallsAccountDisabled1001(t *testing.T) {
return
}
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
} else if reply.Disabled == false {
diff --git a/general_tests/tutorial_local_test.go b/general_tests/tutorial_local_test.go
index 255acc4cf..9f5e2dcb5 100644
--- a/general_tests/tutorial_local_test.go
+++ b/general_tests/tutorial_local_test.go
@@ -1085,7 +1085,7 @@ func TestTutLocalSetAccount(t *testing.T) {
return
}
var reply string
- attrs := &utils.AttrSetAccount{Tenant: "cgrates.org", Direction: "*out", Account: "tutacnt1", ActionPlanId: "PACKAGE_10", ActionTriggersId: "STANDARD_TRIGGERS"}
+ attrs := &utils.AttrSetAccount{Tenant: "cgrates.org", Account: "tutacnt1", ActionPlanId: "PACKAGE_10", ActionTriggersId: "STANDARD_TRIGGERS"}
if err := tutLocalRpc.Call("ApierV1.SetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.SetAccount: ", err.Error())
} else if reply != "OK" {
@@ -1099,17 +1099,17 @@ func TestTutLocalSetAccount(t *testing.T) {
Limit int // Limit number of items retrieved
}
var acnts []*engine.Account
- if err := tutLocalRpc.Call("ApierV1.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, Direction: attrs.Direction, AccountIds: []string{attrs.Account}}, &acnts); err != nil {
+ if err := tutLocalRpc.Call("ApierV1.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, AccountIds: []string{attrs.Account}}, &acnts); err != nil {
t.Error(err)
} else if len(acnts) != 1 {
t.Errorf("Accounts received: %+v", acnts)
} else {
acnt := acnts[0]
- dta, _ := utils.NewDTAFromAccountKey(acnt.Id)
- if dta.Direction != attrs.Direction || dta.Tenant != attrs.Tenant || dta.Account != attrs.Account {
+ dta, _ := utils.NewTAFromAccountKey(acnt.Id)
+ if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account {
t.Error("Unexpected account id received: ", acnt.Id)
}
- if balances := acnt.BalanceMap["*monetary*out"]; len(balances) != 1 {
+ if balances := acnt.BalanceMap["*monetary"]; len(balances) != 1 {
t.Errorf("Unexpected balances found: %+v", balances)
}
if len(acnt.ActionTriggers) != 4 {
@@ -1122,23 +1122,23 @@ func TestTutLocalSetAccount(t *testing.T) {
t.Error("Disabled should not be set")
}
}
- attrs = &utils.AttrSetAccount{Tenant: "cgrates.org", Direction: "*out", Account: "tutacnt1", AllowNegative: utils.BoolPointer(true), Disabled: utils.BoolPointer(true)}
+ attrs = &utils.AttrSetAccount{Tenant: "cgrates.org", Account: "tutacnt1", AllowNegative: utils.BoolPointer(true), Disabled: utils.BoolPointer(true)}
if err := tutLocalRpc.Call("ApierV1.SetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.SetAccount: ", err.Error())
} else if reply != "OK" {
t.Errorf("Calling ApierV1.SetAccount received: %s", reply)
}
- if err := tutLocalRpc.Call("ApierV1.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, Direction: attrs.Direction, AccountIds: []string{attrs.Account}}, &acnts); err != nil {
+ if err := tutLocalRpc.Call("ApierV1.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, AccountIds: []string{attrs.Account}}, &acnts); err != nil {
t.Error(err)
} else if len(acnts) != 1 {
t.Errorf("Accounts received: %+v", acnts)
} else {
acnt := acnts[0]
- dta, _ := utils.NewDTAFromAccountKey(acnt.Id)
- if dta.Direction != attrs.Direction || dta.Tenant != attrs.Tenant || dta.Account != attrs.Account {
+ dta, _ := utils.NewTAFromAccountKey(acnt.Id)
+ if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account {
t.Error("Unexpected account id received: ", acnt.Id)
}
- if balances := acnt.BalanceMap["*monetary*out"]; len(balances) != 1 {
+ if balances := acnt.BalanceMap["*monetary"]; len(balances) != 1 {
t.Errorf("Unexpected balances found: %+v", balances)
}
if len(acnt.ActionTriggers) != 4 {
diff --git a/general_tests/tutorial_osips_calls_test.go b/general_tests/tutorial_osips_calls_test.go
index 5f1bcafe3..2ee358950 100644
--- a/general_tests/tutorial_osips_calls_test.go
+++ b/general_tests/tutorial_osips_calls_test.go
@@ -137,37 +137,37 @@ func TestTutOsipsCallsAccountsBefore(t *testing.T) {
return
}
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002"}
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003"}
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004"}
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007"}
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() != 0.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 0.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
}
- attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005", Direction: "*out"}
+ attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005"}
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err == nil || !strings.HasSuffix(err.Error(), "does not exist") {
t.Error("Got error on ApierV1.GetAccount: %v", err)
}
@@ -315,11 +315,11 @@ func TestTutOsipsCallsAccount1001(t *testing.T) {
}
time.Sleep(time.Duration(70) * time.Second) // Allow calls to finish before start querying the results
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
- } else if reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue() == 10.0 { // Make sure we debitted
- t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY+attrs.Direction].GetTotalValue())
+ } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() == 10.0 { // Make sure we debitted
+ t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue())
} else if reply.Disabled == true {
t.Error("Account disabled")
}
@@ -535,7 +535,7 @@ func TestTutOsipsCallsAccountFraud1001(t *testing.T) {
return
}
var reply string
- attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Direction: "*out", Value: 101}
+ attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Value: 101}
if err := tutOsipsCallsRpc.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil {
t.Error("Got error on ApierV1.AddBalance: ", err.Error())
} else if reply != "OK" {
@@ -549,7 +549,7 @@ func TestTutOsipsCallsAccountDisabled1001(t *testing.T) {
return
}
var reply *engine.Account
- attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
if err := tutOsipsCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
} else if reply.Disabled == false {
diff --git a/utils/apitpdata.go b/utils/apitpdata.go
index 69442c171..8f1748464 100644
--- a/utils/apitpdata.go
+++ b/utils/apitpdata.go
@@ -276,14 +276,14 @@ type TPAction struct {
Identifier string // Identifier mapped in the code
BalanceId string // Balance identification string (account scope)
BalanceType string // Type of balance the action will operate on
- Direction string // Balance direction
+ Directions string // Balance direction
Units float64 // Number of units to add/deduct
ExpiryTime string // Time when the units will expire
TimingTags string // Timing when balance is active
DestinationIds string // Destination profile id
RatingSubject string // Reference a rate subject defined in RatingProfiles
- Category string // category filter for balances
- SharedGroup string // Reference to a shared group
+ Categories string // category filter for balances
+ SharedGroups string // Reference to a shared group
BalanceWeight float64 // Balance weight
ExtraParameters string
Weight float64 // Action's weight
@@ -476,14 +476,14 @@ type TPActionTrigger struct {
MinSleep string // Minimum duration between two executions in case of recurrent triggers
BalanceId string // The id of the balance in the account
BalanceType string // Type of balance this trigger monitors
- BalanceDirection string // Traffic direction
+ BalanceDirections string // Traffic direction
BalanceDestinationIds string // filter for balance
BalanceWeight float64 // filter for balance
BalanceExpirationDate string // filter for balance
BalanceTimingTags string // filter for balance
BalanceRatingSubject string // filter for balance
- BalanceCategory string // filter for balance
- BalanceSharedGroup string // filter for balance
+ BalanceCategories string // filter for balance
+ BalanceSharedGroups string // filter for balance
BalanceDisabled bool // filter for balance
MinQueuedItems int // Trigger actions only if this number is hit (stats only)
ActionsId string // Actions which will execute on threshold reached
@@ -496,10 +496,10 @@ func NewTPAccountActionsFromKeyId(tpid, loadId, keyId string) (*TPAccountActions
// *out:cgrates.org:1001
s := strings.Split(keyId, ":")
// [*out cgrates.org 1001]
- if len(s) != 3 {
+ if len(s) != 2 {
return nil, fmt.Errorf("Cannot parse key %s into AccountActions", keyId)
}
- return &TPAccountActions{TPid: tpid, LoadId: loadId, Direction: s[0], Tenant: s[1], Account: s[2]}, nil
+ return &TPAccountActions{TPid: tpid, LoadId: loadId, Tenant: s[0], Account: s[1]}, nil
}
type TPAccountActions struct {
@@ -507,7 +507,6 @@ type TPAccountActions struct {
LoadId string // LoadId, used to group actions on a load
Tenant string // Tenant's Id
Account string // Account name
- Direction string // Traffic direction
ActionPlanId string // Id of ActionPlan profile to use
ActionTriggersId string // Id of ActionTriggers profile to use
AllowNegative bool
@@ -516,13 +515,11 @@ type TPAccountActions struct {
// Returns the id used in some nosql dbs (eg: redis)
func (self *TPAccountActions) KeyId() string {
- return fmt.Sprintf("%s:%s:%s", self.Direction, self.Tenant, self.Account)
+ return fmt.Sprintf("%s:%s", self.Tenant, self.Account)
}
func (aa *TPAccountActions) GetAccountActionsId() string {
return aa.LoadId +
- CONCATENATED_KEY_SEP +
- aa.Direction +
CONCATENATED_KEY_SEP +
aa.Tenant +
CONCATENATED_KEY_SEP +
@@ -531,25 +528,22 @@ func (aa *TPAccountActions) GetAccountActionsId() string {
func (aa *TPAccountActions) SetAccountActionsId(id string) error {
ids := strings.Split(id, CONCATENATED_KEY_SEP)
- if len(ids) != 4 {
+ if len(ids) != 3 {
return fmt.Errorf("Wrong TP Account Action Id: %s", id)
}
aa.LoadId = ids[0]
- aa.Direction = ids[1]
- aa.Tenant = ids[2]
- aa.Account = ids[3]
+ aa.Tenant = ids[1]
+ aa.Account = ids[2]
return nil
}
type AttrGetAccount struct {
- Tenant string
- Account string
- Direction string
+ Tenant string
+ Account string
}
type AttrGetAccounts struct {
Tenant string
- Direction string
AccountIds []string
Offset int // Set the item offset
Limit int // Limit number of items retrieved
@@ -810,16 +804,16 @@ type AttrDerivedChargers struct {
Direction, Tenant, Category, Account, Subject string
}
-func NewDTAFromAccountKey(accountKey string) (*DirectionTenantAccount, error) {
+func NewTAFromAccountKey(accountKey string) (*TenantAccount, error) {
accountSplt := strings.Split(accountKey, CONCATENATED_KEY_SEP)
- if len(accountSplt) != 3 {
- return nil, fmt.Errorf("Unsupported format for DirectionTenantAccount: %s", accountKey)
+ if len(accountSplt) != 2 {
+ return nil, fmt.Errorf("Unsupported format for TenantAccount: %s", accountKey)
}
- return &DirectionTenantAccount{accountSplt[0], accountSplt[1], accountSplt[2]}, nil
+ return &TenantAccount{accountSplt[0], accountSplt[1]}, nil
}
-type DirectionTenantAccount struct {
- Direction, Tenant, Account string
+type TenantAccount struct {
+ Tenant, Account string
}
func NewDTCSFromRPKey(rpKey string) (*DirectionTenantCategorySubject, error) {
@@ -1104,7 +1098,6 @@ type AttrSetActions struct {
}
type AttrExecuteAction struct {
- Direction string
Tenant string
Account string
ActionsId string
@@ -1112,7 +1105,6 @@ type AttrExecuteAction struct {
type AttrSetAccount struct {
Tenant string
- Direction string
Account string
ActionPlanId string
ActionTriggersId string
@@ -1121,9 +1113,8 @@ type AttrSetAccount struct {
}
type AttrRemoveAccount struct {
- Tenant string
- Direction string
- Account string
+ Tenant string
+ Account string
}
type AttrGetSMASessions struct {
diff --git a/utils/consts.go b/utils/consts.go
index fe44cb630..ce4326b46 100644
--- a/utils/consts.go
+++ b/utils/consts.go
@@ -172,7 +172,7 @@ const (
RATING_PROFILE_PREFIX = "rpf_"
ACTION_PREFIX = "act_"
SHARED_GROUP_PREFIX = "shg_"
- ACCOUNT_PREFIX = "ubl_"
+ ACCOUNT_PREFIX = "acc_"
DESTINATION_PREFIX = "dst_"
LCR_PREFIX = "lcr_"
DERIVEDCHARGERS_PREFIX = "dcs_"
diff --git a/utils/coreutils.go b/utils/coreutils.go
index f8ef29531..630fbe139 100644
--- a/utils/coreutils.go
+++ b/utils/coreutils.go
@@ -238,8 +238,8 @@ func ParseDurationWithSecs(durStr string) (time.Duration, error) {
}
}
-func AccountKey(tenant, account, direction string) string {
- return fmt.Sprintf("%s:%s:%s", direction, tenant, account)
+func AccountKey(tenant, account string) string {
+ return fmt.Sprintf("%s:%s", tenant, account)
}
// returns the minimum duration between the two
diff --git a/utils/map.go b/utils/map.go
index 474225656..22a4fde6c 100644
--- a/utils/map.go
+++ b/utils/map.go
@@ -18,6 +18,8 @@ along with this program. If not, see
package utils
+import "strings"
+
// Converts map[string]string into map[string]interface{}
func ConvertMapValStrIf(inMap map[string]string) map[string]interface{} {
outMap := make(map[string]interface{})
@@ -57,3 +59,81 @@ func MapKeys(m map[string]string) []string {
}
return n
}
+
+type StringMap map[string]bool
+
+func NewStringMap(s ...string) StringMap {
+ result := make(StringMap)
+ for _, v := range s {
+ v = strings.TrimSpace(v)
+ if v != "" {
+ result[v] = true
+ }
+ }
+ return result
+}
+
+func ParseStringMap(s string) StringMap {
+ slice := strings.Split(s, INFIELD_SEP)
+ result := make(StringMap)
+ for _, v := range slice {
+ v = strings.TrimSpace(v)
+ if v != "" {
+ result[v] = true
+ }
+ }
+ return result
+}
+
+func (sm StringMap) Equal(om StringMap) bool {
+ if len(sm) != len(om) {
+ return false
+ }
+ for key := range sm {
+ if !om[key] {
+ return false
+ }
+ }
+ return true
+}
+
+func (sm StringMap) Includes(om StringMap) bool {
+ if len(sm) < len(om) {
+ return false
+ }
+ for key := range om {
+ if !sm[key] {
+ return false
+ }
+ }
+ return true
+}
+
+func (sm StringMap) Clone() StringMap {
+ result := make(StringMap, len(sm))
+ for k := range sm {
+ result[k] = true
+ }
+ return result
+}
+
+func (sm StringMap) Slice() []string {
+ result := make([]string, len(sm))
+ i := 0
+ for k := range sm {
+ result[i] = k
+ i++
+ }
+ return result
+}
+
+func (sm StringMap) String() string {
+ return strings.Join(sm.Slice(), INFIELD_SEP)
+}
+
+func (sm StringMap) GetOne() string {
+ for key := range sm{
+ return key
+ }
+ return ""
+}
diff --git a/utils/struct.go b/utils/struct.go
index a72652ba4..e56d63a29 100644
--- a/utils/struct.go
+++ b/utils/struct.go
@@ -20,6 +20,7 @@ package utils
import (
"reflect"
"strconv"
+ "strings"
)
// Detects missing field values based on mandatory field names, s should be a pointer to a struct
@@ -27,6 +28,10 @@ func MissingStructFields(s interface{}, mandatories []string) []string {
missing := []string{}
for _, fieldName := range mandatories {
fld := reflect.ValueOf(s).Elem().FieldByName(fieldName)
+ // sanitize the string fields before checking
+ if fld.Kind() == reflect.String || fld.CanSet() {
+ fld.SetString(strings.TrimSpace(fld.String()))
+ }
if (fld.Kind() == reflect.String && fld.String() == "") ||
((fld.Kind() == reflect.Slice || fld.Kind() == reflect.Map) && fld.Len() == 0) ||
(fld.Kind() == reflect.Int && fld.Int() == 0) {