From 6a990612d20019c366fc4f3b4a537ae4d2f0cbb2 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Tue, 20 Oct 2015 14:06:40 +0300 Subject: [PATCH 01/29] redo account prefix change --- utils/consts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/consts.go b/utils/consts.go index fe44cb630..1dc57e1ae 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 = "act_" DESTINATION_PREFIX = "dst_" LCR_PREFIX = "lcr_" DERIVEDCHARGERS_PREFIX = "dcs_" From af86bde715bfa1e798b6d8e222af6eb07c7315eb Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Tue, 20 Oct 2015 17:35:08 +0300 Subject: [PATCH 02/29] tests passing after account direction removal --- apier/v1/accounts.go | 19 ++++---- apier/v1/accounts_test.go | 10 ++--- apier/v1/apier.go | 6 +-- apier/v1/apier_local_test.go | 52 +++++++++++----------- apier/v1/tpaccountactions.go | 2 +- console/account_add.go | 2 +- console/account_remove.go | 2 +- console/accounts.go | 4 +- engine/actions_local_test.go | 6 +-- engine/actions_test.go | 28 ++++++------ engine/calldesc.go | 4 +- engine/calldesc_test.go | 22 ++++----- engine/loader_csv_test.go | 26 +++++------ engine/model_converters.go | 1 - engine/model_helpers.go | 1 - engine/model_helpers_test.go | 3 +- engine/models.go | 18 ++++---- engine/responder_test.go | 12 ++--- engine/storage_mongo_local_test.go | 8 ++-- engine/storage_mongo_tp.go | 12 ++--- engine/storage_mysql_local_test.go | 6 +-- engine/storage_psql_local_test.go | 6 +-- engine/storage_sql.go | 5 +-- engine/storage_test.go | 6 +-- general_tests/acntacts_test.go | 14 +++--- general_tests/auth_test.go | 4 +- general_tests/ddazmbl1_test.go | 8 ++-- general_tests/ddazmbl2_test.go | 8 ++-- general_tests/ddazmbl3_test.go | 8 ++-- general_tests/tutorial_fs_calls_test.go | 42 ++++++++--------- general_tests/tutorial_kam_calls_test.go | 40 ++++++++--------- general_tests/tutorial_local_test.go | 12 ++--- general_tests/tutorial_osips_calls_test.go | 40 ++++++++--------- utils/apitpdata.go | 28 +++++------- utils/consts.go | 2 +- utils/coreutils.go | 4 +- 36 files changed, 223 insertions(+), 248 deletions(-) diff --git a/apier/v1/accounts.go b/apier/v1/accounts.go index 2b18af8d0..f007f1537 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 @@ -246,13 +246,10 @@ func (self *ApierV1) GetAccounts(attr utils.AttrGetAccounts, reply *[]*engine.Ac 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 { diff --git a/apier/v1/accounts_test.go b/apier/v1/accounts_test.go index 474588c90..5c6a8604a 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 { diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 34b196e65..b4e84c69a 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 @@ -782,7 +782,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 { @@ -852,7 +852,7 @@ func (self *ApierV1) ResetTriggeredActions(attr AttrResetTriggeredAction, reply 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 { diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go index 19275a329..d30f24ab9 100644 --- a/apier/v1/apier_local_test.go +++ b/apier/v1/apier_local_test.go @@ -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 @@ -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" { @@ -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,7 +1193,7 @@ 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" { @@ -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/tpaccountactions.go b/apier/v1/tpaccountactions.go index ab8bf2799..17990eff7 100644 --- a/apier/v1/tpaccountactions.go +++ b/apier/v1/tpaccountactions.go @@ -157,7 +157,7 @@ func (self *ApierV1) RemTPAccountActions(attrs AttrGetTPAccountActions, reply *s 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/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..f1d760fc3 100644 --- a/console/accounts.go +++ b/console/accounts.go @@ -27,7 +27,7 @@ func init() { c := &CmdGetAccounts{ name: "accounts", rpcMethod: "ApierV1.GetAccounts", - rpcParams: &utils.AttrGetAccounts{Direction: "*out"}, + 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/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..4ce0667ce 100644 --- a/engine/actions_test.go +++ b/engine/actions_test.go @@ -1065,7 +1065,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,19 +1073,19 @@ 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, @@ -1094,12 +1094,12 @@ func TestTopupAction(t *testing.T) { } at := &ActionPlan{ - AccountIds: []string{"*out:vdf:minu"}, + AccountIds: []string{"vdf:minu"}, actions: Actions{a}, } at.Execute() - afterUb, _ := accountingStorage.GetAccount("*out:vdf:minu") + afterUb, _ := accountingStorage.GetAccount("vdf:minu") initialValue := initialUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() afterValue := afterUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() if initialValue != 50 || afterValue != 75 { @@ -1108,7 +1108,7 @@ func TestTopupAction(t *testing.T) { } func TestTopupActionLoaded(t *testing.T) { - initialUb, _ := accountingStorage.GetAccount("*out:vdf:minitsboy") + initialUb, _ := accountingStorage.GetAccount("vdf:minitsboy") a := &Action{ ActionType: TOPUP, BalanceType: utils.MONETARY, @@ -1117,12 +1117,12 @@ func TestTopupActionLoaded(t *testing.T) { } at := &ActionPlan{ - AccountIds: []string{"*out:vdf:minitsboy"}, + AccountIds: []string{"vdf:minitsboy"}, actions: Actions{a}, } at.Execute() - afterUb, _ := accountingStorage.GetAccount("*out:vdf:minitsboy") + afterUb, _ := accountingStorage.GetAccount("vdf:minitsboy") initialValue := initialUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() afterValue := afterUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() if initialValue != 100 || afterValue != 125 { @@ -1133,7 +1133,7 @@ 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, } @@ -1154,7 +1154,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/"}`, @@ -1181,7 +1181,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/"}`, @@ -1202,14 +1202,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/calldesc.go b/engine/calldesc.go index 0b69069bb..87609f7b2 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -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. @@ -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 { diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index 9c1aa542b..0e4fc746f 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -51,7 +51,7 @@ func populateDB() { } 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{ @@ -60,7 +60,7 @@ func populateDB() { }}, } 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"}, @@ -68,7 +68,7 @@ func populateDB() { }}, } luna := &Account{ - Id: "*out:vdf:luna", + Id: "vdf:luna", BalanceMap: map[string]BalanceChain{ utils.MONETARY + utils.OUT: BalanceChain{ &Balance{Value: 0, Weight: 20}, @@ -76,7 +76,7 @@ func populateDB() { } // 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"}, @@ -88,14 +88,14 @@ func populateDB() { }, } max := &Account{ - Id: "*out:cgrates.org:max", + Id: "cgrates.org:max", BalanceMap: map[string]BalanceChain{ utils.MONETARY + utils.OUT: 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{ &Balance{Value: 10000, Weight: 10}, @@ -725,7 +725,7 @@ func TestMaxDebitWithAccountShared(t *testing.T) { if len(balanceMap) != 1 || balanceMap[0].GetValue() != 0 { t.Errorf("Wrong shared balance debited: %+v", balanceMap[0]) } - other, err := accountingStorage.GetAccount("*out:vdf:empty10") + other, err := accountingStorage.GetAccount("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]) } @@ -856,7 +856,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) @@ -874,7 +874,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) @@ -891,7 +891,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) @@ -908,7 +908,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 { diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 794836b6c..7565a332f 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -190,16 +190,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 = ` @@ -970,7 +970,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}, @@ -1026,9 +1026,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..325e2ec68 100644 --- a/engine/model_converters.go +++ b/engine/model_converters.go @@ -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..d5b2cf15c 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -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..013dd3e5d 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -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..d54083baf 100644 --- a/engine/models.go +++ b/engine/models.go @@ -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..520320591 100644 --- a/engine/responder_test.go +++ b/engine/responder_test.go @@ -73,8 +73,8 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) { } 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}}} + rifsAccount := &Account{Id: utils.ConcatenatedKey(testTenant, "rif"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b10}}} + dansAccount := &Account{Id: utils.ConcatenatedKey(testTenant, "dan"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b20}}} if err := accountingStorage.SetAccount(rifsAccount); err != nil { t.Error(err) } @@ -94,14 +94,14 @@ 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()) } - 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()) @@ -430,8 +430,8 @@ func TestResponderGetLCR(t *testing.T) { } 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} + rif12sAccount := &Account{Id: utils.ConcatenatedKey("tenant12", "rif12"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{bRif12}}, AllowNegative: true} + ivo12sAccount := &Account{Id: utils.ConcatenatedKey("tenant12", "ivo12"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{bIvo12}}, AllowNegative: true} for _, acnt := range []*Account{rif12sAccount, ivo12sAccount} { if err := accountingStorage.SetAccount(acnt); err != nil { t.Error(err) diff --git a/engine/storage_mongo_local_test.go b/engine/storage_mongo_local_test.go index b097c3471..f67de9c90 100644 --- a/engine/storage_mongo_local_test.go +++ b/engine/storage_mongo_local_test.go @@ -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..f7b0d4893 100644 --- a/engine/storage_mysql_local_test.go +++ b/engine/storage_mysql_local_test.go @@ -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..d015763b8 100644 --- a/engine/storage_psql_local_test.go +++ b/engine/storage_psql_local_test.go @@ -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..30326f600 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,11 +258,11 @@ 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) } 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..fea2490bc 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,7 +131,7 @@ 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) @@ -158,7 +158,7 @@ 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) } diff --git a/general_tests/ddazmbl2_test.go b/general_tests/ddazmbl2_test.go index d07c72cc5..a37fbac4e 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,7 +130,7 @@ 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) @@ -157,7 +157,7 @@ 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) } diff --git a/general_tests/ddazmbl3_test.go b/general_tests/ddazmbl3_test.go index d1bd74029..70bf23a24 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,7 +128,7 @@ 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) @@ -153,7 +153,7 @@ 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) } 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..d8e1ac8a8 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") } @@ -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 d4e404915..2c72e35de 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,14 +1099,14 @@ 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 { + 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 { @@ -1122,20 +1122,20 @@ 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 { + 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 { diff --git a/general_tests/tutorial_osips_calls_test.go b/general_tests/tutorial_osips_calls_test.go index 5f1bcafe3..7de2b56df 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") } @@ -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..48a564e51 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -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 @@ -1112,7 +1106,6 @@ type AttrExecuteAction struct { type AttrSetAccount struct { Tenant string - Direction string Account string ActionPlanId string ActionTriggersId string @@ -1121,9 +1114,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 1dc57e1ae..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 = "act_" + 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 From 41c6a597aac50ffec0c8c5b51e93556e9b690f84 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 21 Oct 2015 19:26:45 +0300 Subject: [PATCH 03/29] direction as simple balance filter work in proggress --- engine/account.go | 105 ++++---- engine/account_test.go | 398 +++++++++++++++-------------- engine/action.go | 6 +- engine/action_trigger.go | 34 +-- engine/actions_test.go | 267 ++++++++++--------- engine/balances.go | 85 +++--- engine/balances_test.go | 63 ++--- engine/calldesc.go | 4 +- engine/calldesc_test.go | 52 ++-- engine/loader_csv_test.go | 22 +- engine/model_converters.go | 4 +- engine/model_helpers.go | 4 +- engine/model_helpers_test.go | 8 +- engine/models.go | 4 +- engine/responder_test.go | 8 +- engine/sharedgroup.go | 4 +- engine/storage_mongo_local_test.go | 4 +- engine/storage_mysql_local_test.go | 4 +- engine/storage_psql_local_test.go | 4 +- engine/storage_test.go | 9 +- engine/tp_reader.go | 29 +-- engine/units_counter.go | 12 +- engine/units_counter_test.go | 10 +- utils/apitpdata.go | 4 +- utils/map.go | 64 +++++ 25 files changed, 612 insertions(+), 596 deletions(-) diff --git a/engine/account.go b/engine/account.go index 6f8a6ef5b..de982653e 100644 --- a/engine/account.go +++ b/engine/account.go @@ -52,14 +52,14 @@ 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, ub.BalanceMap[utils.MONETARY], "") + unitBalances := ub.getBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, ub.BalanceMap[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.GetBalances(cd.Destination, cd.Category, cd.Direction, utils.MONETARY, ub) sgb = sharedGroup.SortBalancesByStrategy(cb, sgb) extendedCreditBalances = append(extendedCreditBalances, sgb...) } @@ -71,7 +71,7 @@ func (ub *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duratio 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.GetBalances(cd.Destination, cd.Category, cd.Direction, cd.TOR, ub) sgb = sharedGroup.SortBalancesByStrategy(mb, sgb) extendedMinuteBalances = append(extendedMinuteBalances, sgb...) } @@ -101,10 +101,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() { @@ -157,7 +154,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,7 +169,7 @@ 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 string, direction string, balances BalanceChain, sharedGroup string) BalanceChain { var usefulBalances BalanceChain for _, b := range balances { if b.Disabled { @@ -187,19 +184,20 @@ func (ub *Account) getBalancesForPrefix(prefix, category string, balances Balanc 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)] == false { + b.precision = len(p) + usefulBalances = append(usefulBalances, b) + break } if b.precision > 0 { break @@ -224,8 +222,8 @@ 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, account.BalanceMap[balanceType], "") for _, b := range balances { if b.SharedGroup != "" { sharedGroup, err := ratingStorage.GetSharedGroup(b.SharedGroup, false) @@ -233,7 +231,7 @@ func (account *Account) getAlldBalancesForPrefix(destination, category, balanceT utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", b.SharedGroup)) continue } - sharedBalances := sharedGroup.GetBalances(destination, category, balanceType, account) + sharedBalances := sharedGroup.GetBalances(destination, category, direction, balanceType, account) sharedBalances = sharedGroup.SortBalancesByStrategy(b, sharedBalances) bc = append(bc, sharedBalances...) } else { @@ -244,8 +242,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 +370,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.StringMap{leftCC.Destination: true}}}) } } } @@ -394,11 +392,8 @@ 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 } @@ -411,29 +406,29 @@ func (ub *Account) GetDefaultMoneyBalance(direction string) *Balance { 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 +469,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 +514,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 +527,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,9 +535,9 @@ func (ub *Account) countUnits(a *Action) { ub.executeActionTriggers(nil) } -// Create minute counters for all triggered actions that have actions opertating on balances +// Create counters for all triggered actions that have actions opertating on balances func (ub *Account) initCounters() { - ucTempMap := make(map[string]*UnitsCounter, 2) + ucTempMap := make(map[string]*UnitsCounter) for _, at := range ub.ActionTriggers { acs, err := ratingStorage.GetActions(at.ActionsId, false) if err != nil { @@ -558,14 +545,10 @@ func (ub *Account) initCounters() { } 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) } @@ -615,8 +598,8 @@ 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, account.BalanceMap[utils.MONETARY], "")...) + balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, account.BalanceMap[cd.TOR], "")...) // gather all shared group ids var sharedGroupIds []string for _, b := range balances { @@ -669,7 +652,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,10 +661,10 @@ 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}}}) } } } diff --git a/engine/account_test.go b/engine/account_test.go index 73b1826f8..18b3c2522 100644 --- a/engine/account_test.go +++ b/engine/account_test.go @@ -82,21 +82,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 +117,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 +146,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 +184,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{Category: "0", Value: 21}}}} var err error cc, err = rifsBalance.debitCreditBalance(cd, false, false, true) if err != nil { @@ -194,14 +194,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 +225,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 +238,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 +272,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 +284,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 +324,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 +335,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 +345,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 +375,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 +387,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 +398,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 +423,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 +435,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 +446,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 +476,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 +487,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 +525,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 +536,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 +575,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 +583,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 +619,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 +631,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 +643,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", Category: "0", Value: 250, Weight: 10, DestinationIds: utils.StringMap{"NAT": true}, RatingSubject: "minu"} cc := &CallCost{ Tenant: "vdf", Category: "0", @@ -672,8 +672,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 +685,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 +727,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 +738,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 +777,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 +790,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 +807,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 +821,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 +839,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 +853,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 +968,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 +988,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 +1001,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 +1016,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 +1053,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, SharedGroup: "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, SharedGroup: "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 +1068,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 +1123,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, SharedGroup: "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, SharedGroup: "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 +1169,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 +1180,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 +1212,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 +1223,10 @@ 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()) } } @@ -1258,8 +1262,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 +1278,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 +1316,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 +1341,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 +1353,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 +1367,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 +1377,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..291dacbfa 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, @@ -176,7 +174,7 @@ 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": @@ -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..74bf3993d 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 string // filter for balance + BalanceRatingSubject string // filter for balance + BalanceCategory string // filter for balance + BalanceSharedGroup string // 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,13 +110,13 @@ 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, category, sharedGroup, disabled := 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 @@ -127,7 +126,8 @@ func (at *ActionTrigger) Match(a *Action) 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)) weight = t.BalanceWeight == 0 || at.BalanceWeight == t.BalanceWeight ratingSubject = t.BalanceRatingSubject == "" || at.BalanceRatingSubject == t.BalanceRatingSubject category = t.BalanceCategory == "" || at.BalanceCategory == t.BalanceCategory @@ -137,12 +137,6 @@ func (at *ActionTrigger) Match(a *Action) bool { 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) -} - // makes a shallow copy of the receiver func (at *ActionTrigger) Clone() *ActionTrigger { clone := new(ActionTrigger) diff --git a/engine/actions_test.go b/engine/actions_test.go index 4ce0667ce..bb33035ee 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", } - 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,18 @@ 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]) } } @@ -768,18 +768,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 +787,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 +806,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 +904,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 +934,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 +949,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 +964,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 +983,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", } @@ -1089,8 +1090,7 @@ func TestTopupAction(t *testing.T) { 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{ @@ -1100,9 +1100,9 @@ func TestTopupAction(t *testing.T) { at.Execute() afterUb, _ := accountingStorage.GetAccount("vdf:minu") - initialValue := initialUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() - afterValue := afterUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() - if initialValue != 50 || afterValue != 75 { + 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) } } @@ -1112,8 +1112,7 @@ func TestTopupActionLoaded(t *testing.T) { 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{ @@ -1123,9 +1122,9 @@ func TestTopupActionLoaded(t *testing.T) { at.Execute() afterUb, _ := accountingStorage.GetAccount("vdf:minitsboy") - initialValue := initialUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() - afterValue := afterUb.BalanceMap[utils.MONETARY+utils.OUT].GetTotalValue() - if initialValue != 100 || afterValue != 125 { + 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) @@ -1140,7 +1139,7 @@ func TestActionCdrlogEmpty(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}, }, }) if err != nil { @@ -1162,11 +1161,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 { @@ -1189,11 +1188,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 { diff --git a/engine/balances.go b/engine/balances.go index 69ea789c5..4af0f26e7 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -35,9 +35,10 @@ 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 @@ -50,19 +51,18 @@ type Balance struct { } 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 && @@ -76,17 +76,16 @@ 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) && + (len(o.DestinationIds) == 0 || b.DestinationIds.Equal(o.DestinationIds)) && + (len(o.Directions) == 0 || b.Directions.Equal(o.Directions)) && (o.RatingSubject == "" || b.RatingSubject == o.RatingSubject) && (o.Category == "" || b.Category == o.Category) && (o.SharedGroup == "" || b.SharedGroup == o.SharedGroup) @@ -94,7 +93,8 @@ func (b *Balance) MatchFilter(o *Balance) bool { // the default balance has no destinationid, Expirationdate or ratesubject func (b *Balance) IsDefault() bool { - return (b.DestinationIds == "" || b.DestinationIds == utils.ANY) && + return (len(b.DestinationIds) == 0 || b.DestinationIds[utils.ANY] == true) && + len(b.Directions) == 0 && b.RatingSubject == "" && b.Category == "" && b.ExpirationDate.IsZero() && @@ -126,22 +126,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 } 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 +147,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() { @@ -173,6 +173,7 @@ func (b *Balance) MatchActionTrigger(at *ActionTrigger) bool { } return matchesDestination && + matchesDirection && matchesExpirationDate && matchesWeight && matchesRatingSubject && @@ -184,7 +185,8 @@ 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, @@ -198,18 +200,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) } - } } } @@ -323,7 +321,8 @@ func (b *Balance) SetValue(amount float64) { "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, @@ -391,7 +390,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 @@ -453,7 +452,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 @@ -477,9 +476,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: seconds, 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 { @@ -554,7 +553,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) @@ -569,7 +568,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 diff --git a/engine/balances_test.go b/engine/balances_test.go index eb8b2587e..7b79209e2 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) } @@ -240,27 +239,3 @@ func TestBalanceIsDefault(t *testing.T) { 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 87609f7b2..f6af50f7e 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -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() @@ -718,7 +718,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 0e4fc746f..b76e407fa 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -41,36 +41,36 @@ 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: "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: "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: "vdf:luna", BalanceMap: map[string]BalanceChain{ - utils.MONETARY + utils.OUT: BalanceChain{ + utils.MONETARY: BalanceChain{ &Balance{Value: 0, Weight: 20}, }}, } @@ -78,11 +78,11 @@ func populateDB() { minitsboy := &Account{ 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}, }, }, @@ -90,14 +90,14 @@ func populateDB() { max := &Account{ Id: "cgrates.org:max", BalanceMap: map[string]BalanceChain{ - utils.MONETARY + utils.OUT: BalanceChain{ + utils.MONETARY: BalanceChain{ &Balance{Value: 11, Weight: 20}, }}, } money := &Account{ Id: "cgrates.org:money", BalanceMap: map[string]BalanceChain{ - utils.MONETARY + utils.OUT: BalanceChain{ + utils.MONETARY: BalanceChain{ &Balance{Value: 10000, Weight: 10}, }}, } @@ -721,13 +721,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("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]) + if err != nil || other.BalanceMap[utils.MONETARY][0].GetValue() != 7.5 { + t.Errorf("Error debiting shared balance: %+v", other.BalanceMap[utils.MONETARY][0]) } } @@ -934,7 +934,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) } @@ -966,7 +966,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()) } @@ -995,13 +995,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) @@ -1084,8 +1084,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 7565a332f..151740810 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -809,30 +809,30 @@ 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, }, }, &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"), }, }, } @@ -845,10 +845,10 @@ func TestLoadActions(t *testing.T) { Id: "SHARED0", ActionType: TOPUP, BalanceType: utils.MONETARY, - Direction: utils.OUT, ExpirationString: UNLIMITED, Weight: 10, Balance: &Balance{ + Directions: utils.NewStringMap(utils.OUT), Uuid: as2[0].Balance.Uuid, Value: 100, Weight: 10, @@ -995,10 +995,10 @@ 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"), Weight: 10, ActionsId: "SOME_1", Executed: false, @@ -1009,10 +1009,10 @@ 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"), Weight: 10, ActionsId: "SOME_2", Executed: false, diff --git a/engine/model_converters.go b/engine/model_converters.go index 325e2ec68..28761830f 100644 --- a/engine/model_converters.go +++ b/engine/model_converters.go @@ -170,7 +170,7 @@ 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, @@ -223,7 +223,7 @@ 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, diff --git a/engine/model_helpers.go b/engine/model_helpers.go index d5b2cf15c..00fba52c5 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -387,7 +387,7 @@ 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, @@ -428,7 +428,7 @@ 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, diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index 013dd3e5d..f856358d7 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -239,7 +239,7 @@ 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", @@ -252,7 +252,7 @@ func TestTPActionsAsExportSlice(t *testing.T) { &utils.TPAction{ Identifier: "*http_post", BalanceType: "", - Direction: "", + Directions: "", Units: 0.0, ExpiryTime: "", DestinationIds: "", @@ -557,7 +557,7 @@ func TestTPActionPlanAsExportSlice(t *testing.T) { MinSleep: "0", BalanceId: "b1", BalanceType: "*monetary", - BalanceDirection: "*out", + BalanceDirections: "*out", BalanceDestinationIds: "", BalanceWeight: 0.0, BalanceExpirationDate: "*never", @@ -576,7 +576,7 @@ func TestTPActionPlanAsExportSlice(t *testing.T) { MinSleep: "0", BalanceId: "b2", BalanceType: "*monetary", - BalanceDirection: "*out", + BalanceDirections: "*out", BalanceDestinationIds: "FS_USERS", BalanceWeight: 0.0, BalanceExpirationDate: "*never", diff --git a/engine/models.go b/engine/models.go index d54083baf..a52e8fd3e 100644 --- a/engine/models.go +++ b/engine/models.go @@ -158,7 +158,7 @@ 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*"` + Directions string `index:"5" re:""` Category string `index:"6" re:"\*?\w+\s*"` DestinationTags string `index:"7" re:"\*any|\w+\s*"` RatingSubject string `index:"8" re:"\w+\s*"` @@ -193,7 +193,7 @@ 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"` + BalanceDirections string `index:"8" re:"\*out"` BalanceCategory string `index:"9" re:"\w+|\*any"` BalanceDestinationTags string `index:"10" re:"\w+|\*any"` BalanceRatingSubject string `index:"11" re:"\w+|\*any"` diff --git a/engine/responder_test.go b/engine/responder_test.go index 520320591..aea4a98b3 100644 --- a/engine/responder_test.go +++ b/engine/responder_test.go @@ -71,8 +71,8 @@ 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"} + 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 + utils.OUT: BalanceChain{b10}}} dansAccount := &Account{Id: utils.ConcatenatedKey(testTenant, "dan"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b20}}} if err := accountingStorage.SetAccount(rifsAccount); err != nil { @@ -428,8 +428,8 @@ 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} + 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 + utils.OUT: BalanceChain{bRif12}}, AllowNegative: true} ivo12sAccount := &Account{Id: utils.ConcatenatedKey("tenant12", "ivo12"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{bIvo12}}, AllowNegative: true} for _, acnt := range []*Account{rif12sAccount, ivo12sAccount} { diff --git a/engine/sharedgroup.go b/engine/sharedgroup.go index 4f7ef3d9f..e3f08ad34 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, nUb.BalanceMap[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 f67de9c90..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, diff --git a/engine/storage_mysql_local_test.go b/engine/storage_mysql_local_test.go index f7b0d4893..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, diff --git a/engine/storage_psql_local_test.go b/engine/storage_psql_local_test.go index d015763b8..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, diff --git a/engine/storage_test.go b/engine/storage_test.go index 30326f600..ba9be2beb 100644 --- a/engine/storage_test.go +++ b/engine/storage_test.go @@ -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/tp_reader.go b/engine/tp_reader.go index e2596003b..4ef2d98ed 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,16 @@ 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, + Directions: utils.ParseStringMap(tpact.Directions), + DestinationIds: utils.ParseStringMap(tpact.DestinationIds), SharedGroup: tpact.SharedGroup, }, } // 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,8 +616,8 @@ 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, @@ -756,8 +755,8 @@ 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, @@ -799,7 +798,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,7 +805,8 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error Value: tpact.Units, Weight: tpact.BalanceWeight, RatingSubject: tpact.RatingSubject, - DestinationIds: tpact.DestinationIds, + Directions: utils.ParseStringMap(tpact.Directions), + DestinationIds: utils.ParseStringMap(tpact.DestinationIds), SharedGroup: tpact.SharedGroup, }, } @@ -959,8 +958,8 @@ 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, @@ -1011,7 +1010,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,7 +1017,8 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) { Value: tpact.Units, Weight: tpact.BalanceWeight, RatingSubject: tpact.RatingSubject, - DestinationIds: tpact.DestinationIds, + Directions: utils.ParseStringMap(tpact.Directions), + DestinationIds: utils.ParseStringMap(tpact.DestinationIds), SharedGroup: tpact.SharedGroup, }, } diff --git a/engine/units_counter.go b/engine/units_counter.go index d74364f8c..e7bd22c44 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,7 +55,7 @@ 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 @@ -69,8 +68,13 @@ 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 := "" + for key := range prefixMap { // get the first value + prefix = key + break + } if prefix != "" { for _, mb := range uc.Balances { if !mb.HasDestination() { 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/utils/apitpdata.go b/utils/apitpdata.go index 48a564e51..44a544c7c 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -276,7 +276,7 @@ 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 @@ -476,7 +476,7 @@ 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 diff --git a/utils/map.go b/utils/map.go index 474225656..62de1e3d9 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,65 @@ 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) == 0 { + return len(om) == 0 + } + if len(sm) != len(om) { + return false + } + for key := range sm { + if !om[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) Keys() []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.Keys(), INFIELD_SEP) +} From 0745cee15852ea6b1e0057ecb0e386ec951fcbca Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 21 Oct 2015 22:28:16 +0300 Subject: [PATCH 04/29] engine tests passing --- engine/account.go | 3 +-- engine/calldesc_test.go | 2 ++ engine/loader_csv_test.go | 19 +++++++++++-------- engine/responder_test.go | 20 ++++++++++---------- engine/storage_test.go | 6 +++--- engine/units_counter.go | 13 +++++++++---- utils/map.go | 3 --- 7 files changed, 36 insertions(+), 30 deletions(-) diff --git a/engine/account.go b/engine/account.go index de982653e..a2aef7b33 100644 --- a/engine/account.go +++ b/engine/account.go @@ -187,14 +187,13 @@ func (ub *Account) getBalancesForPrefix(prefix, category string, direction strin if b.HasDirection() && b.Directions[direction] == false { continue } - b.account = ub 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 { - if b.DestinationIds[dId.(string)] == false { + if b.DestinationIds[dId.(string)] == true { b.precision = len(p) usefulBalances = append(usefulBalances, b) break diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index b76e407fa..21827f091 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -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", diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 151740810..0b9452da1 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -848,15 +848,16 @@ func TestLoadActions(t *testing.T) { ExpirationString: UNLIMITED, Weight: 10, Balance: &Balance{ - Directions: utils.NewStringMap(utils.OUT), - 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, + SharedGroup: "SG1", }, }, } - 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"] @@ -867,12 +868,14 @@ 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{}, }, }, } if !reflect.DeepEqual(as3, expected) { - t.Errorf("Error loading action: %+v", as3[0]) + t.Errorf("Error loading action: %+v", as3[0].Balance) } } diff --git a/engine/responder_test.go b/engine/responder_test.go index aea4a98b3..29b1ee2c6 100644 --- a/engine/responder_test.go +++ b/engine/responder_test.go @@ -73,8 +73,8 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) { } 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 + utils.OUT: BalanceChain{b10}}} - dansAccount := &Account{Id: utils.ConcatenatedKey(testTenant, "dan"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{b20}}} + 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) } @@ -96,15 +96,15 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) { ratingStorage.CacheRatingAll() 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(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"} @@ -430,8 +430,8 @@ func TestResponderGetLCR(t *testing.T) { } 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 + utils.OUT: BalanceChain{bRif12}}, AllowNegative: true} - ivo12sAccount := &Account{Id: utils.ConcatenatedKey("tenant12", "ivo12"), BalanceMap: map[string]BalanceChain{utils.VOICE + utils.OUT: BalanceChain{bIvo12}}, AllowNegative: true} + 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/storage_test.go b/engine/storage_test.go index ba9be2beb..3332cec8b 100644 --- a/engine/storage_test.go +++ b/engine/storage_test.go @@ -266,9 +266,9 @@ func TestDifferentUuid(t *testing.T) { 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]) } } diff --git a/engine/units_counter.go b/engine/units_counter.go index e7bd22c44..39c5f5c74 100644 --- a/engine/units_counter.go +++ b/engine/units_counter.go @@ -83,10 +83,15 @@ func (uc *UnitsCounter) addUnits(amount float64, prefixMap utils.StringMap) { 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/utils/map.go b/utils/map.go index 62de1e3d9..caea125bd 100644 --- a/utils/map.go +++ b/utils/map.go @@ -86,9 +86,6 @@ func ParseStringMap(s string) StringMap { } func (sm StringMap) Equal(om StringMap) bool { - if len(sm) == 0 { - return len(om) == 0 - } if len(sm) != len(om) { return false } From f237e096a9c08394787f542bbe690091dfdbc2ac Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 22 Oct 2015 09:45:41 +0300 Subject: [PATCH 05/29] all unit tests passing --- apier/v1/apier.go | 28 +++++++++++++--------------- apier/v1/apier_local_test.go | 8 ++++---- general_tests/ddazmbl1_test.go | 16 ++++++++-------- general_tests/ddazmbl2_test.go | 14 +++++++------- general_tests/ddazmbl3_test.go | 12 ++++++------ 5 files changed, 38 insertions(+), 40 deletions(-) diff --git a/apier/v1/apier.go b/apier/v1/apier.go index b4e84c69a..1e5ef7fe6 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -165,14 +165,14 @@ 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.Direction), + DestinationIds: utils.ParseStringMap(attr.DestinationId), Weight: attr.Weight, SharedGroup: attr.SharedGroup, Disabled: attr.Disabled, @@ -207,14 +207,14 @@ func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) e &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.Direction), + DestinationIds: utils.ParseStringMap(attr.DestinationId), Weight: attr.Weight, SharedGroup: attr.SharedGroup, Disabled: attr.Disabled, @@ -616,7 +616,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,7 +624,8 @@ 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, }, @@ -653,14 +653,14 @@ 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.BalanceWeight = engAct.Balance.Weight @@ -773,8 +773,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, @@ -808,7 +808,7 @@ type AttrResetTriggeredAction struct { Id string Tenant string Account string - Direction string + Directions string BalanceType string ThresholdType string ThresholdValue float64 @@ -824,21 +824,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,7 +847,6 @@ func (self *ApierV1) ResetTriggeredActions(attr AttrResetTriggeredAction, reply } a = &engine.Action{ BalanceType: attr.BalanceType, - Direction: attr.Direction, ExtraParameters: string(extraParameters), } } diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go index d30f24ab9..e6b39aefe 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 @@ -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 { diff --git a/general_tests/ddazmbl1_test.go b/general_tests/ddazmbl1_test.go index fea2490bc..34c8a2988 100644 --- a/general_tests/ddazmbl1_test.go +++ b/general_tests/ddazmbl1_test.go @@ -135,10 +135,10 @@ func TestExecuteActions(t *testing.T) { 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) } } @@ -162,10 +162,10 @@ func TestDebit(t *testing.T) { 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 a37fbac4e..1a0004d1a 100644 --- a/general_tests/ddazmbl2_test.go +++ b/general_tests/ddazmbl2_test.go @@ -134,10 +134,10 @@ func TestExecuteActions2(t *testing.T) { 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) } } @@ -164,10 +164,10 @@ func TestDebit2(t *testing.T) { 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 70bf23a24..0b49f8ea7 100644 --- a/general_tests/ddazmbl3_test.go +++ b/general_tests/ddazmbl3_test.go @@ -132,8 +132,8 @@ func TestExecuteActions3(t *testing.T) { 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) } } @@ -160,10 +160,10 @@ func TestDebit3(t *testing.T) { 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) } } From 332bb5e26c777108820490012925abe7c8001f42 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 22 Oct 2015 16:01:02 +0300 Subject: [PATCH 06/29] add *default Id to default balance reference to #251 --- engine/account.go | 17 +++++++++++++---- engine/balances.go | 11 ++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/engine/account.go b/engine/account.go index a2aef7b33..8f2ea9182 100644 --- a/engine/account.go +++ b/engine/account.go @@ -118,8 +118,17 @@ 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 == "" { @@ -399,8 +408,8 @@ func (ub *Account) GetDefaultMoneyBalance() *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) diff --git a/engine/balances.go b/engine/balances.go index 4af0f26e7..b38d7fe7f 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -91,16 +91,9 @@ func (b *Balance) MatchFilter(o *Balance) bool { (o.SharedGroup == "" || b.SharedGroup == o.SharedGroup) } -// the default balance has no destinationid, Expirationdate or ratesubject +// the default balance has standard Id func (b *Balance) IsDefault() bool { - return (len(b.DestinationIds) == 0 || b.DestinationIds[utils.ANY] == true) && - len(b.Directions) == 0 && - 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 { From 9782769d9b3aa2f598197c3649ca4ff1fa7e3e51 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 22 Oct 2015 16:05:32 +0300 Subject: [PATCH 07/29] fix for default balance test --- engine/balances_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/engine/balances_test.go b/engine/balances_test.go index 7b79209e2..ce409924f 100644 --- a/engine/balances_test.go +++ b/engine/balances_test.go @@ -235,6 +235,10 @@ 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) } From 07647f765b984ca1515fe34424aaf558c1cfef49 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 22 Oct 2015 17:01:42 +0300 Subject: [PATCH 08/29] multiple categories in one balance fixes #204 --- engine/account_test.go | 7 ++++--- engine/action.go | 2 +- engine/action_trigger.go | 10 +++++----- engine/balances.go | 12 ++++++------ engine/loader_csv_test.go | 2 ++ engine/model_converters.go | 4 ++-- engine/model_helpers.go | 4 ++-- engine/model_helpers_test.go | 8 ++++---- engine/models.go | 4 ++-- engine/tp_reader.go | 8 ++++---- utils/apitpdata.go | 4 ++-- utils/map.go | 4 ++-- 12 files changed, 36 insertions(+), 33 deletions(-) diff --git a/engine/account_test.go b/engine/account_test.go index 18b3c2522..40669f151 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) } } @@ -184,7 +185,7 @@ func TestDebitCreditZeroSecond(t *testing.T) { TOR: utils.VOICE, testCallcost: cc, } - rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{utils.VOICE: BalanceChain{b1}, utils.MONETARY: 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 { @@ -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: utils.StringMap{"NAT": true}, 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", diff --git a/engine/action.go b/engine/action.go index 291dacbfa..861788953 100644 --- a/engine/action.go +++ b/engine/action.go @@ -180,7 +180,7 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action) 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) default: diff --git a/engine/action_trigger.go b/engine/action_trigger.go index 74bf3993d..32ce9ab54 100644 --- a/engine/action_trigger.go +++ b/engine/action_trigger.go @@ -43,7 +43,7 @@ type ActionTrigger struct { BalanceExpirationDate time.Time // filter for balance BalanceTimingTags string // filter for balance BalanceRatingSubject string // filter for balance - BalanceCategory string // filter for balance + BalanceCategories utils.StringMap // filter for balance BalanceSharedGroup string // filter for balance BalanceDisabled bool // filter for balance Weight float64 @@ -110,7 +110,7 @@ func (at *ActionTrigger) Match(a *Action) bool { return match } id := a.BalanceType == "" || at.BalanceType == a.BalanceType - thresholdType, thresholdValue, direction, destinationId, weight, ratingSubject, category, sharedGroup, disabled := true, true, true, true, true, true, true, true, true + thresholdType, thresholdValue, direction, destinationId, weight, ratingSubject, categories, sharedGroup, disabled := true, true, true, true, true, true, true, true, true if a.ExtraParameters != "" { t := struct { ThresholdType string @@ -119,7 +119,7 @@ func (at *ActionTrigger) Match(a *Action) bool { BalanceDirections string BalanceWeight float64 BalanceRatingSubject string - BalanceCategory string + BalanceCategories string BalanceSharedGroup string BalanceDisabled bool }{} @@ -128,13 +128,13 @@ func (at *ActionTrigger) Match(a *Action) bool { thresholdValue = t.ThresholdValue == 0 || at.ThresholdValue == t.ThresholdValue 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)) 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 + return id && direction && thresholdType && thresholdValue && destinationId && weight && ratingSubject && categories && sharedGroup && disabled } // makes a shallow copy of the receiver diff --git a/engine/balances.go b/engine/balances.go index b38d7fe7f..c59770f1e 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -40,7 +40,7 @@ type Balance struct { Weight float64 DestinationIds utils.StringMap RatingSubject string - Category string + Categories utils.StringMap SharedGroup string Timings []*RITiming TimingIDs string @@ -64,7 +64,7 @@ func (b *Balance) Equal(o *Balance) bool { b.DestinationIds.Equal(o.DestinationIds) && b.Directions.Equal(o.Directions) && b.RatingSubject == o.RatingSubject && - b.Category == o.Category && + b.Categories.Equal(o.Categories) && b.SharedGroup == o.SharedGroup && b.Disabled == o.Disabled } @@ -86,8 +86,8 @@ func (b *Balance) MatchFilter(o *Balance) bool { (o.Weight == 0 || b.Weight == o.Weight) && (len(o.DestinationIds) == 0 || b.DestinationIds.Equal(o.DestinationIds)) && (len(o.Directions) == 0 || b.Directions.Equal(o.Directions)) && + (len(o.Categories) == 0 || b.Categories.Equal(o.Categories)) && (o.RatingSubject == "" || b.RatingSubject == o.RatingSubject) && - (o.Category == "" || b.Category == o.Category) && (o.SharedGroup == "" || b.SharedGroup == o.SharedGroup) } @@ -120,7 +120,7 @@ func (b *Balance) IsActiveAt(t time.Time) bool { } 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 { @@ -183,7 +183,7 @@ func (b *Balance) Clone() *Balance { ExpirationDate: b.ExpirationDate, Weight: b.Weight, RatingSubject: b.RatingSubject, - Category: b.Category, + Categories: b.Categories, SharedGroup: b.SharedGroup, TimingIDs: b.TimingIDs, Timings: b.Timings, // should not be a problem with aliasing @@ -317,7 +317,7 @@ func (b *Balance) SetValue(amount float64) { "DestinationIds": b.DestinationIds.String(), "Directions": b.Directions.String(), "RatingSubject": b.RatingSubject, - "Category": b.Category, + "Categories": b.Categories.String(), "SharedGroup": b.SharedGroup, "TimingIDs": b.TimingIDs, "Account": accountId, diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 0b9452da1..9d4fe2b1c 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -1002,6 +1002,7 @@ func TestLoadActionTriggers(t *testing.T) { ThresholdType: TRIGGER_MIN_COUNTER, ThresholdValue: 10, BalanceDestinationIds: utils.NewStringMap("GERMANY_O2"), + BalanceCategories: utils.StringMap{}, Weight: 10, ActionsId: "SOME_1", Executed: false, @@ -1016,6 +1017,7 @@ func TestLoadActionTriggers(t *testing.T) { ThresholdType: TRIGGER_MAX_BALANCE, ThresholdValue: 200, BalanceDestinationIds: utils.NewStringMap("GERMANY"), + BalanceCategories: utils.StringMap{}, Weight: 10, ActionsId: "SOME_2", Executed: false, diff --git a/engine/model_converters.go b/engine/model_converters.go index 28761830f..373d01ba7 100644 --- a/engine/model_converters.go +++ b/engine/model_converters.go @@ -176,7 +176,7 @@ func APItoModelAction(as *utils.TPActions) (result []TpAction) { TimingTags: a.TimingTags, DestinationTags: a.DestinationIds, RatingSubject: a.RatingSubject, - Category: a.Category, + Categories: a.Categories, SharedGroup: a.SharedGroup, BalanceWeight: a.BalanceWeight, ExtraParameters: a.ExtraParameters, @@ -229,7 +229,7 @@ func APItoModelActionTrigger(ats *utils.TPActionTriggers) (result []TpActionTrig BalanceExpiryTime: at.BalanceExpirationDate, BalanceTimingTags: at.BalanceTimingTags, BalanceRatingSubject: at.BalanceRatingSubject, - BalanceCategory: at.BalanceCategory, + BalanceCategories: at.BalanceCategories, BalanceSharedGroup: at.BalanceSharedGroup, BalanceDisabled: at.BalanceDisabled, MinQueuedItems: at.MinQueuedItems, diff --git a/engine/model_helpers.go b/engine/model_helpers.go index 00fba52c5..c33e6c9c1 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -393,7 +393,7 @@ func (tps TpActions) GetActions() (map[string][]*utils.TPAction, error) { TimingTags: tpAc.TimingTags, DestinationIds: tpAc.DestinationTags, RatingSubject: tpAc.RatingSubject, - Category: tpAc.Category, + Categories: tpAc.Categories, SharedGroup: tpAc.SharedGroup, BalanceWeight: tpAc.BalanceWeight, ExtraParameters: tpAc.ExtraParameters, @@ -434,7 +434,7 @@ func (tps TpActionTriggers) GetActionTriggers() (map[string][]*utils.TPActionTri BalanceExpirationDate: tpAt.BalanceExpiryTime, BalanceTimingTags: tpAt.BalanceTimingTags, BalanceRatingSubject: tpAt.BalanceRatingSubject, - BalanceCategory: tpAt.BalanceCategory, + BalanceCategories: tpAt.BalanceCategories, BalanceSharedGroup: tpAt.BalanceSharedGroup, BalanceDisabled: tpAt.BalanceDisabled, Weight: tpAt.Weight, diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index f856358d7..207506f97 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -244,7 +244,7 @@ func TestTPActionsAsExportSlice(t *testing.T) { ExpiryTime: "*never", DestinationIds: "*any", RatingSubject: "special1", - Category: "call", + Categories: "call", SharedGroup: "GROUP1", BalanceWeight: 10.0, ExtraParameters: "", @@ -257,7 +257,7 @@ func TestTPActionsAsExportSlice(t *testing.T) { ExpiryTime: "", DestinationIds: "", RatingSubject: "", - Category: "", + Categories: "", SharedGroup: "", BalanceWeight: 0.0, ExtraParameters: "http://localhost/¶m1=value1", @@ -563,7 +563,7 @@ func TestTPActionPlanAsExportSlice(t *testing.T) { BalanceExpirationDate: "*never", BalanceTimingTags: "T1", BalanceRatingSubject: "special1", - BalanceCategory: "call", + BalanceCategories: "call", BalanceSharedGroup: "SHARED_1", BalanceDisabled: false, MinQueuedItems: 0, @@ -582,7 +582,7 @@ func TestTPActionPlanAsExportSlice(t *testing.T) { BalanceExpirationDate: "*never", BalanceTimingTags: "T1", BalanceRatingSubject: "special1", - BalanceCategory: "call", + BalanceCategories: "call", BalanceSharedGroup: "SHARED_1", BalanceDisabled: false, MinQueuedItems: 0, diff --git a/engine/models.go b/engine/models.go index a52e8fd3e..9b1ff16de 100644 --- a/engine/models.go +++ b/engine/models.go @@ -159,7 +159,7 @@ type TpAction struct { BalanceTag string `index:"3" re:"\w+\s*"` BalanceType string `index:"4" re:"\*\w+\s*"` Directions string `index:"5" re:""` - Category string `index:"6" re:"\*?\w+\s*"` + 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_;]*"` @@ -194,7 +194,7 @@ type TpActionTrigger struct { BalanceTag string `index:"6" re:"\w+\s*"` BalanceType string `index:"7" re:"\*\w+"` BalanceDirections string `index:"8" re:"\*out"` - BalanceCategory string `index:"9" re:"\w+|\*any"` + 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"` diff --git a/engine/tp_reader.go b/engine/tp_reader.go index 4ef2d98ed..57a1a2698 100644 --- a/engine/tp_reader.go +++ b/engine/tp_reader.go @@ -514,7 +514,7 @@ func (tpr *TpReader) LoadActions() (err error) { Value: tpact.Units, Weight: tpact.BalanceWeight, RatingSubject: tpact.RatingSubject, - Category: tpact.Category, + Categories: utils.ParseStringMap(tpact.Categories), Directions: utils.ParseStringMap(tpact.Directions), DestinationIds: utils.ParseStringMap(tpact.DestinationIds), SharedGroup: tpact.SharedGroup, @@ -622,7 +622,7 @@ func (tpr *TpReader) LoadActionTriggers() (err error) { BalanceExpirationDate: balanceExpirationDate, BalanceTimingTags: atr.BalanceTimingTags, BalanceRatingSubject: atr.BalanceRatingSubject, - BalanceCategory: atr.BalanceCategory, + BalanceCategories: utils.ParseStringMap(atr.BalanceCategories), BalanceSharedGroup: atr.BalanceSharedGroup, Weight: atr.Weight, ActionsId: atr.ActionsId, @@ -760,7 +760,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error BalanceWeight: apiAtr.BalanceWeight, BalanceExpirationDate: expTime, BalanceRatingSubject: apiAtr.BalanceRatingSubject, - BalanceCategory: apiAtr.BalanceCategory, + BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories), BalanceSharedGroup: apiAtr.BalanceSharedGroup, Weight: apiAtr.Weight, ActionsId: apiAtr.ActionsId, @@ -963,7 +963,7 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) { BalanceWeight: apiAtr.BalanceWeight, BalanceExpirationDate: expTime, BalanceRatingSubject: apiAtr.BalanceRatingSubject, - BalanceCategory: apiAtr.BalanceCategory, + BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories), BalanceSharedGroup: apiAtr.BalanceSharedGroup, Weight: apiAtr.Weight, ActionsId: apiAtr.ActionsId, diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 44a544c7c..c66cae6c4 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -282,7 +282,7 @@ type TPAction struct { 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 + Categories string // category filter for balances SharedGroup string // Reference to a shared group BalanceWeight float64 // Balance weight ExtraParameters string @@ -482,7 +482,7 @@ type TPActionTrigger struct { BalanceExpirationDate string // filter for balance BalanceTimingTags string // filter for balance BalanceRatingSubject string // filter for balance - BalanceCategory string // filter for balance + BalanceCategories string // filter for balance BalanceSharedGroup string // filter for balance BalanceDisabled bool // filter for balance MinQueuedItems int // Trigger actions only if this number is hit (stats only) diff --git a/utils/map.go b/utils/map.go index caea125bd..caf5d563d 100644 --- a/utils/map.go +++ b/utils/map.go @@ -105,7 +105,7 @@ func (sm StringMap) Clone() StringMap { return result } -func (sm StringMap) Keys() []string { +func (sm StringMap) Slice() []string { result := make([]string, len(sm)) i := 0 for k := range sm { @@ -116,5 +116,5 @@ func (sm StringMap) Keys() []string { } func (sm StringMap) String() string { - return strings.Join(sm.Keys(), INFIELD_SEP) + return strings.Join(sm.Slice(), INFIELD_SEP) } From ec57a3e80c4d20e8d69ce09240a2a636b7ba80a2 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 22 Oct 2015 17:03:46 +0300 Subject: [PATCH 09/29] better match filter --- engine/balances.go | 6 +++--- utils/map.go | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/engine/balances.go b/engine/balances.go index c59770f1e..ba15e736f 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -84,9 +84,9 @@ func (b *Balance) MatchFilter(o *Balance) bool { } return (o.ExpirationDate.IsZero() || b.ExpirationDate.Equal(o.ExpirationDate)) && (o.Weight == 0 || b.Weight == o.Weight) && - (len(o.DestinationIds) == 0 || b.DestinationIds.Equal(o.DestinationIds)) && - (len(o.Directions) == 0 || b.Directions.Equal(o.Directions)) && - (len(o.Categories) == 0 || b.Categories.Equal(o.Categories)) && + (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)) && (o.RatingSubject == "" || b.RatingSubject == o.RatingSubject) && (o.SharedGroup == "" || b.SharedGroup == o.SharedGroup) } diff --git a/utils/map.go b/utils/map.go index caf5d563d..8be47180f 100644 --- a/utils/map.go +++ b/utils/map.go @@ -97,6 +97,18 @@ func (sm StringMap) Equal(om StringMap) bool { 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 { From 7c74e67bf240c7fdbec7330b81d6a38ce94b6577 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 13:25:11 +0300 Subject: [PATCH 10/29] updated csv and sql --- data/storage/mysql/create_tariffplan_tables.sql | 15 +++++++-------- .../postgres/create_tariffplan_tables.sql | 17 ++++++++--------- data/tariffplans/cdrstats/ActionTriggers.csv | 2 +- data/tariffplans/cdrstats/Actions.csv | 2 +- .../prepaid1centpsec/AccountActions.csv | 12 ++++++------ .../prepaid1centpsec/ActionTriggers.csv | 2 +- data/tariffplans/prepaid1centpsec/Actions.csv | 2 +- data/tariffplans/tutorial/AccountActions.csv | 12 ++++++------ data/tariffplans/tutorial/ActionTriggers.csv | 2 +- data/tariffplans/tutorial/Actions.csv | 2 +- 10 files changed, 33 insertions(+), 35 deletions(-) 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 From ad5e6ddace17e2561331c685930e4d5efb93c959 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 13:34:06 +0300 Subject: [PATCH 11/29] fixes for the apis --- apier/v1/tpaccountactions.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apier/v1/tpaccountactions.go b/apier/v1/tpaccountactions.go index 17990eff7..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,7 +150,7 @@ 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} From 95fec8c4d1ff3f22b7a33ba9f30c89a811b209aa Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 14:33:56 +0300 Subject: [PATCH 12/29] fixed add balance api --- apier/v1/apier.go | 43 +++++++++++++++++------------------- apier/v1/apier_local_test.go | 2 +- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 1e5ef7fe6..5b1ab2058 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -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 + SharedGroup 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{ @@ -171,8 +171,8 @@ func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error { Value: attr.Value, ExpirationDate: expTime, RatingSubject: attr.RatingSubject, - Directions: utils.ParseStringMap(attr.Direction), - DestinationIds: utils.ParseStringMap(attr.DestinationId), + Directions: utils.ParseStringMap(attr.Directions), + DestinationIds: utils.ParseStringMap(attr.DestinationIds), Weight: attr.Weight, SharedGroup: attr.SharedGroup, Disabled: attr.Disabled, @@ -193,16 +193,13 @@ 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, @@ -213,8 +210,8 @@ func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) e Value: attr.Value, ExpirationDate: expTime, RatingSubject: attr.RatingSubject, - Directions: utils.ParseStringMap(attr.Direction), - DestinationIds: utils.ParseStringMap(attr.DestinationId), + Directions: utils.ParseStringMap(attr.Directions), + DestinationIds: utils.ParseStringMap(attr.DestinationIds), Weight: attr.Weight, SharedGroup: attr.SharedGroup, Disabled: attr.Disabled, diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go index e6b39aefe..c4b7f064c 100644 --- a/apier/v1/apier_local_test.go +++ b/apier/v1/apier_local_test.go @@ -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 From c86825792b1fd318ec2ad90b3202085f84c57f73 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 14:45:11 +0300 Subject: [PATCH 13/29] fixes for local tests --- apier/v1/apier.go | 6 +----- apier/v1/apier_local_test.go | 20 ++++++++++---------- utils/apitpdata.go | 1 - 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 5b1ab2058..6b6622f48 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -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 @@ -227,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, @@ -905,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 c4b7f064c..2c9cc9db1 100644 --- a/apier/v1/apier_local_test.go +++ b/apier/v1/apier_local_test.go @@ -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) } @@ -1199,7 +1199,7 @@ func TestApierTriggersExecute(t *testing.T) { } 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" { diff --git a/utils/apitpdata.go b/utils/apitpdata.go index c66cae6c4..b73c5eb27 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -1098,7 +1098,6 @@ type AttrSetActions struct { } type AttrExecuteAction struct { - Direction string Tenant string Account string ActionsId string From 53df1dcdd168597cf1ac5e1cb30a45672482c2ec Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 14:47:46 +0300 Subject: [PATCH 14/29] general tests fixes --- general_tests/tutorial_kam_calls_test.go | 2 +- general_tests/tutorial_osips_calls_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/general_tests/tutorial_kam_calls_test.go b/general_tests/tutorial_kam_calls_test.go index d8e1ac8a8..c9f90885d 100644 --- a/general_tests/tutorial_kam_calls_test.go +++ b/general_tests/tutorial_kam_calls_test.go @@ -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" { diff --git a/general_tests/tutorial_osips_calls_test.go b/general_tests/tutorial_osips_calls_test.go index 7de2b56df..2ee358950 100644 --- a/general_tests/tutorial_osips_calls_test.go +++ b/general_tests/tutorial_osips_calls_test.go @@ -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" { From bf8e6c6c5a22895971081c1656734c2f93e59fb7 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 15:43:52 +0300 Subject: [PATCH 15/29] more test fixes --- apier/v1/scheduler.go | 14 +++++--------- console/action_execute.go | 4 ++-- engine/action.go | 6 +++--- general_tests/tutorial_local_test.go | 4 ++-- utils/apitpdata.go | 12 ++++++------ 5 files changed, 18 insertions(+), 22 deletions(-) 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/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/engine/action.go b/engine/action.go index 861788953..8eae10d38 100644 --- a/engine/action.go +++ b/engine/action.go @@ -146,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 { @@ -156,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": diff --git a/general_tests/tutorial_local_test.go b/general_tests/tutorial_local_test.go index 2c72e35de..a3ef716fc 100644 --- a/general_tests/tutorial_local_test.go +++ b/general_tests/tutorial_local_test.go @@ -1105,7 +1105,7 @@ func TestTutLocalSetAccount(t *testing.T) { t.Errorf("Accounts received: %+v", acnts) } else { acnt := acnts[0] - dta, _ := utils.NewDTAFromAccountKey(acnt.Id) + dta, _ := utils.NewTAFromAccountKey(acnt.Id) if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account { t.Error("Unexpected account id received: ", acnt.Id) } @@ -1134,7 +1134,7 @@ func TestTutLocalSetAccount(t *testing.T) { t.Errorf("Accounts received: %+v", acnts) } else { acnt := acnts[0] - dta, _ := utils.NewDTAFromAccountKey(acnt.Id) + dta, _ := utils.NewTAFromAccountKey(acnt.Id) if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account { t.Error("Unexpected account id received: ", acnt.Id) } diff --git a/utils/apitpdata.go b/utils/apitpdata.go index b73c5eb27..b6dbe0b4f 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -804,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) { From 2fd914bb24eb2fd6cd2bb64cc0b4501d4ae24e7d Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 15:50:16 +0300 Subject: [PATCH 16/29] fixed local tests --- general_tests/tutorial_local_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/general_tests/tutorial_local_test.go b/general_tests/tutorial_local_test.go index a3ef716fc..01052bcff 100644 --- a/general_tests/tutorial_local_test.go +++ b/general_tests/tutorial_local_test.go @@ -1109,7 +1109,7 @@ func TestTutLocalSetAccount(t *testing.T) { 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 { @@ -1138,7 +1138,7 @@ func TestTutLocalSetAccount(t *testing.T) { 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 { From 3937e4f33bde6cf46f3b7c89514dd539a295c2b7 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 18:49:59 +0300 Subject: [PATCH 17/29] added account migrator --- cmd/cgr-loader/cgr-loader.go | 44 ++++++ cmd/cgr-loader/migrator_rc8.go | 266 +++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 cmd/cgr-loader/migrator_rc8.go diff --git a/cmd/cgr-loader/cgr-loader.go b/cmd/cgr-loader/cgr-loader.go index d958881a6..d23a26441 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 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,48 @@ 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 { + utils.Logger.Crit("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 { + utils.Logger.Crit(err.Error()) + return + } + if err := migratorRC8acc.migrateAccounts(); err != nil { + utils.Logger.Crit(err.Error()) + return + } + + db_nb, err = strconv.Atoi(*tpdb_name) + if err != nil { + utils.Logger.Crit("Redis db name must be an integer!") + return + } + host = *tpdb_host + if *tpdb_port != "" { + host += ":" + *tpdb_port + } + migratorRC8atr, err := NewMigratorRC8(host, db_nb, *tpdb_pass, *dbdata_encoding) + if err != nil { + utils.Logger.Crit(err.Error()) + return + } + if err := migratorRC8atr.migrateActionTriggers(); err != nil { + utils.Logger.Crit(err.Error()) + return + } + + 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..79b560e24 --- /dev/null +++ b/cmd/cgr-loader/migrator_rc8.go @@ -0,0 +1,266 @@ +package main + +import ( + "fmt" + "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 +} + +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 +} + +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 { + 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, + } + // balances + for oldBalKey, oldBalChain := range oldAcc.BalanceMap { + keyElements := strings.Split(oldBalKey, "*") + if len(key) != 4 { + return fmt.Errorf("Malformed balance key in %s: %s", oldAcc.Id, oldBalKey) + } + newBalKey := "*" + keyElements[1] + newBalDirection := "*" + keyElements[3] + newAcc.BalanceMap[newBalKey] = make(engine.BalanceChain, len(oldBalChain)) + for index, oldBal := range oldBalChain { + 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), + SharedGroup: oldBal.SharedGroup, + Timings: oldBal.Timings, + TimingIDs: 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), + SharedGroup: oldUcBal.SharedGroup, + Timings: oldUcBal.Timings, + TimingIDs: 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: oldAtr.BalanceTimingTags, + BalanceRatingSubject: oldAtr.BalanceRatingSubject, + BalanceCategories: utils.ParseStringMap(oldAtr.BalanceCategory), + BalanceSharedGroup: 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 + _, err = mig.db.Del(OLD_ACCOUNT_PREFIX + "*") + 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 { + 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: oldAtr.BalanceTimingTags, + BalanceRatingSubject: oldAtr.BalanceRatingSubject, + BalanceCategories: utils.ParseStringMap(oldAtr.BalanceCategory), + BalanceSharedGroup: 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 +} From d131b90d4fc72ddaaa13fa63ae3d8545cf525897 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 19:21:16 +0300 Subject: [PATCH 18/29] added action migration --- cmd/cgr-loader/cgr-loader.go | 12 +++-- cmd/cgr-loader/migrator_rc8.go | 82 ++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/cmd/cgr-loader/cgr-loader.go b/cmd/cgr-loader/cgr-loader.go index d23a26441..1c1603e28 100644 --- a/cmd/cgr-loader/cgr-loader.go +++ b/cmd/cgr-loader/cgr-loader.go @@ -35,7 +35,7 @@ import ( var ( //separator = flag.String("separator", ",", "Default field separator") cgrConfig, _ = config.NewDefaultCGRConfig() - migrateRC8 = flag.Bool("migrate_rc8", false, "Migrate Accounts and ActionTriggers to RC8 structures") + 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.") @@ -120,16 +120,20 @@ func main() { if *tpdb_port != "" { host += ":" + *tpdb_port } - migratorRC8atr, err := NewMigratorRC8(host, db_nb, *tpdb_pass, *dbdata_encoding) + migratorRC8rat, err := NewMigratorRC8(host, db_nb, *tpdb_pass, *dbdata_encoding) if err != nil { utils.Logger.Crit(err.Error()) return } - if err := migratorRC8atr.migrateActionTriggers(); err != nil { + if err := migratorRC8rat.migrateActionTriggers(); err != nil { utils.Logger.Crit(err.Error()) return } - + if err := migratorRC8rat.migrateActions(); err != nil { + utils.Logger.Crit(err.Error()) + return + } + utils.Logger.Info("Done!") return } // Init necessary db connections, only if not already diff --git a/cmd/cgr-loader/migrator_rc8.go b/cmd/cgr-loader/migrator_rc8.go index 79b560e24..45a29a7a5 100644 --- a/cmd/cgr-loader/migrator_rc8.go +++ b/cmd/cgr-loader/migrator_rc8.go @@ -91,6 +91,18 @@ type ActionTrigger struct { 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 + "*") @@ -100,6 +112,7 @@ func (mig MigratorRC8) migrateAccounts() error { newAccounts := make([]*engine.Account, len(keys)) // get existing accounts for keyIndex, key := range keys { + utils.Logger.Info(fmt.Sprintf("Migrating account: %s...", key)) values, err := mig.db.Get(key) if err != nil { continue @@ -117,14 +130,20 @@ func (mig MigratorRC8) migrateAccounts() error { 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(key) != 4 { + if len(keyElements) != 3 { return fmt.Errorf("Malformed balance key in %s: %s", oldAcc.Id, oldBalKey) } newBalKey := "*" + keyElements[1] - newBalDirection := "*" + keyElements[3] + newBalDirection := "*" + keyElements[2] newAcc.BalanceMap[newBalKey] = make(engine.BalanceChain, len(oldBalChain)) for index, oldBal := range oldBalChain { newAcc.BalanceMap[newBalKey][index] = &engine.Balance{ @@ -169,7 +188,6 @@ func (mig MigratorRC8) migrateAccounts() error { } } // action triggers - for index, oldAtr := range oldAcc.ActionTriggers { newAcc.ActionTriggers[index] = &engine.ActionTrigger{ Id: oldAtr.Id, @@ -207,6 +225,7 @@ func (mig MigratorRC8) migrateAccounts() error { } } // delete old data + utils.Logger.Info(fmt.Sprintf("Deleting old accounts: %s...", OLD_ACCOUNT_PREFIX+"*")) _, err = mig.db.Del(OLD_ACCOUNT_PREFIX + "*") return err } @@ -218,6 +237,7 @@ func (mig MigratorRC8) migrateActionTriggers() error { } newAtrsMap := make(map[string]engine.ActionTriggers, len(keys)) for _, key := range keys { + utils.Logger.Info(fmt.Sprintf("Migrating action trigger: %s...", key)) var oldAtrs ActionTriggers var values []byte if values, err = mig.db.Get(key); err == nil { @@ -264,3 +284,59 @@ func (mig MigratorRC8) migrateActionTriggers() error { } 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 { + utils.Logger.Info(fmt.Sprintf("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), + SharedGroup: oldAc.Balance.SharedGroup, + Timings: oldAc.Balance.Timings, + TimingIDs: 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 +} From 6149cdb5f863c270b6e7052f5da2b47e0b0e26e0 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Oct 2015 19:28:15 +0300 Subject: [PATCH 19/29] set *default Id for default balances --- cmd/cgr-loader/migrator_rc8.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/cmd/cgr-loader/migrator_rc8.go b/cmd/cgr-loader/migrator_rc8.go index 45a29a7a5..0ba41f568 100644 --- a/cmd/cgr-loader/migrator_rc8.go +++ b/cmd/cgr-loader/migrator_rc8.go @@ -60,6 +60,16 @@ type Balance struct { 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 @@ -146,6 +156,10 @@ func (mig MigratorRC8) migrateAccounts() error { 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, @@ -226,7 +240,9 @@ func (mig MigratorRC8) migrateAccounts() error { } // delete old data utils.Logger.Info(fmt.Sprintf("Deleting old accounts: %s...", OLD_ACCOUNT_PREFIX+"*")) - _, err = mig.db.Del(OLD_ACCOUNT_PREFIX + "*") + for _, key := range keys { + _, err = mig.db.Del(key) + } return err } From 23d85af43982810d6fdae0c588fd118453394d6a Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 28 Oct 2015 16:46:12 +0200 Subject: [PATCH 20/29] timing ids and sharedgroup are now maps --- apier/v1/apier.go | 10 +++--- engine/account.go | 60 ++++++++++++++++++++---------------- engine/account_test.go | 8 ++--- engine/action.go | 2 +- engine/action_trigger.go | 14 +++++---- engine/actions_test.go | 2 +- engine/balances.go | 29 ++++++++++------- engine/balances_test.go | 12 ++++---- engine/loader_csv_test.go | 13 +++++++- engine/model_converters.go | 4 +-- engine/model_helpers.go | 4 +-- engine/model_helpers_test.go | 8 ++--- engine/models.go | 4 +-- engine/tp_reader.go | 18 ++++++----- utils/apitpdata.go | 4 +-- utils/map.go | 7 +++++ 16 files changed, 118 insertions(+), 81 deletions(-) diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 6b6622f48..123f24b57 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -126,7 +126,7 @@ type AttrAddBalance struct { RatingSubject string DestinationIds string Weight float64 - SharedGroup string + SharedGroups string Overwrite bool // When true it will reset if the balance is already there Disabled bool } @@ -171,7 +171,7 @@ func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error { Directions: utils.ParseStringMap(attr.Directions), DestinationIds: utils.ParseStringMap(attr.DestinationIds), Weight: attr.Weight, - SharedGroup: attr.SharedGroup, + SharedGroups: utils.ParseStringMap(attr.SharedGroups), Disabled: attr.Disabled, }, }, @@ -210,7 +210,7 @@ func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) e Directions: utils.ParseStringMap(attr.Directions), DestinationIds: utils.ParseStringMap(attr.DestinationIds), Weight: attr.Weight, - SharedGroup: attr.SharedGroup, + SharedGroups: utils.ParseStringMap(attr.SharedGroups), Disabled: attr.Disabled, }, }, @@ -621,7 +621,7 @@ func (self *ApierV1) SetActions(attrs utils.AttrSetActions, reply *string) error Directions: utils.ParseStringMap(apiAct.Directions), DestinationIds: utils.ParseStringMap(apiAct.DestinationIds), RatingSubject: apiAct.RatingSubject, - SharedGroup: apiAct.SharedGroup, + SharedGroups: utils.ParseStringMap(apiAct.SharedGroups), }, } storeActions[idx] = a @@ -656,7 +656,7 @@ func (self *ApierV1) GetActions(actsId string, reply *[]*utils.TPAction) error { 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) diff --git a/engine/account.go b/engine/account.go index 8f2ea9182..e984ec0f1 100644 --- a/engine/account.go +++ b/engine/account.go @@ -57,11 +57,13 @@ func (ub *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duratio // 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, cd.Direction, utils.MONETARY, 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 +71,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.Direction, cd.TOR, 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) @@ -136,12 +140,12 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error { } 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 @@ -184,10 +188,10 @@ func (ub *Account) getBalancesForPrefix(prefix, category string, direction strin 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) { @@ -233,15 +237,17 @@ func (ub *Account) getBalancesForPrefix(prefix, category string, direction strin func (account *Account) getAlldBalancesForPrefix(destination, category, direction, balanceType string) (bc BalanceChain) { balances := account.getBalancesForPrefix(destination, category, direction, account.BalanceMap[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, direction, balanceType, account) - sharedBalances = sharedGroup.SortBalancesByStrategy(b, sharedBalances) - bc = append(bc, sharedBalances...) } else { bc = append(bc, b) } @@ -596,8 +602,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) } } } @@ -611,8 +617,8 @@ func (account *Account) GetUniqueSharedGroupMembers(cd *CallDescriptor) ([]strin // 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 diff --git a/engine/account_test.go b/engine/account_test.go index 40669f151..fbeddfb73 100644 --- a/engine/account_test.go +++ b/engine/account_test.go @@ -1054,10 +1054,10 @@ func TestDebitShared(t *testing.T) { testCallcost: cc, } rif := &Account{Id: "rif", BalanceMap: map[string]BalanceChain{ - utils.MONETARY: 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: 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}}} @@ -1124,10 +1124,10 @@ func TestMaxDurationShared(t *testing.T) { testCallcost: cc, } rif := &Account{Id: "rif", BalanceMap: map[string]BalanceChain{ - utils.MONETARY: 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: 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}}} diff --git a/engine/action.go b/engine/action.go index 8eae10d38..0a2e9d592 100644 --- a/engine/action.go +++ b/engine/action.go @@ -182,7 +182,7 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action) case "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 } diff --git a/engine/action_trigger.go b/engine/action_trigger.go index 32ce9ab54..615ddc2f8 100644 --- a/engine/action_trigger.go +++ b/engine/action_trigger.go @@ -41,10 +41,10 @@ type ActionTrigger struct { BalanceDestinationIds utils.StringMap // filter for balance BalanceWeight float64 // filter for balance BalanceExpirationDate time.Time // filter for balance - BalanceTimingTags string // filter for balance + BalanceTimingTags utils.StringMap // filter for balance BalanceRatingSubject string // filter for balance BalanceCategories utils.StringMap // filter for balance - BalanceSharedGroup string // filter for balance + BalanceSharedGroups utils.StringMap // filter for balance BalanceDisabled bool // filter for balance Weight float64 ActionsId string @@ -110,7 +110,7 @@ func (at *ActionTrigger) Match(a *Action) bool { return match } id := a.BalanceType == "" || at.BalanceType == a.BalanceType - thresholdType, thresholdValue, direction, destinationId, weight, ratingSubject, categories, sharedGroup, disabled := true, 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 @@ -120,7 +120,8 @@ func (at *ActionTrigger) Match(a *Action) bool { BalanceWeight float64 BalanceRatingSubject string BalanceCategories string - BalanceSharedGroup string + BalanceSharedGroups string + BalanceTimingTags string BalanceDisabled bool }{} json.Unmarshal([]byte(a.ExtraParameters), &t) @@ -129,12 +130,13 @@ func (at *ActionTrigger) Match(a *Action) bool { 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 - sharedGroup = t.BalanceSharedGroup == "" || at.BalanceSharedGroup == t.BalanceSharedGroup disabled = at.BalanceDisabled == t.BalanceDisabled } - return id && direction && thresholdType && thresholdValue && destinationId && weight && ratingSubject && categories && sharedGroup && disabled + return id && direction && thresholdType && thresholdValue && destinationId && weight && ratingSubject && categories && sharedGroup && timings && disabled } // makes a shallow copy of the receiver diff --git a/engine/actions_test.go b/engine/actions_test.go index bb33035ee..4e4aa80d2 100644 --- a/engine/actions_test.go +++ b/engine/actions_test.go @@ -625,7 +625,7 @@ func TestActionTriggerMatchAll(t *testing.T) { BalanceDestinationIds: utils.NewStringMap("NAT"), BalanceWeight: 1.0, BalanceRatingSubject: "test1", - BalanceSharedGroup: "test2", + BalanceSharedGroups: utils.NewStringMap("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) { diff --git a/engine/balances.go b/engine/balances.go index d51f4e299..55378fa78 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -41,9 +41,9 @@ type Balance struct { DestinationIds utils.StringMap RatingSubject string Categories utils.StringMap - SharedGroup string + SharedGroups utils.StringMap Timings []*RITiming - TimingIDs string + TimingIDs utils.StringMap Disabled bool precision int account *Account // used to store ub reference for shared balances @@ -65,7 +65,7 @@ func (b *Balance) Equal(o *Balance) bool { b.Directions.Equal(o.Directions) && b.RatingSubject == o.RatingSubject && b.Categories.Equal(o.Categories) && - b.SharedGroup == o.SharedGroup && + b.SharedGroups.Equal(o.SharedGroups) && b.Disabled == o.Disabled } @@ -87,8 +87,9 @@ func (b *Balance) MatchFilter(o *Balance) bool { (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)) && - (o.RatingSubject == "" || b.RatingSubject == o.RatingSubject) && - (o.SharedGroup == "" || b.SharedGroup == o.SharedGroup) + (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 standard Id @@ -161,8 +162,13 @@ 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 && @@ -170,7 +176,8 @@ func (b *Balance) MatchActionTrigger(at *ActionTrigger) bool { matchesExpirationDate && matchesWeight && matchesRatingSubject && - matchesSharedGroup + matchesSharedGroup && + matchesTiming } func (b *Balance) Clone() *Balance { @@ -184,7 +191,7 @@ func (b *Balance) Clone() *Balance { Weight: b.Weight, RatingSubject: b.RatingSubject, Categories: b.Categories, - SharedGroup: b.SharedGroup, + SharedGroups: b.SharedGroups, TimingIDs: b.TimingIDs, Timings: b.Timings, // should not be a problem with aliasing Disabled: b.Disabled, @@ -657,8 +664,8 @@ func (bc BalanceChain) SaveDirtyBalances(acc *Account) { "Directions": b.Directions.String(), "RatingSubject": b.RatingSubject, "Categories": b.Categories.String(), - "SharedGroup": b.SharedGroup, - "TimingIDs": b.TimingIDs, + "SharedGroups": b.SharedGroups.String(), + "TimingIDs": b.TimingIDs.String(), "Account": accountId, "AccountAllowNegative": allowNegative, "AccountDisabled": disabled, diff --git a/engine/balances_test.go b/engine/balances_test.go index ce409924f..608db65ba 100644 --- a/engine/balances_test.go +++ b/engine/balances_test.go @@ -213,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) } diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 8ff6e154d..9e7ca337b 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -821,6 +821,8 @@ func TestLoadActions(t *testing.T) { Directions: utils.NewStringMap(utils.OUT), Value: 10, Weight: 10, + TimingIDs: utils.StringMap{}, + SharedGroups: utils.StringMap{}, }, }, &Action{ @@ -837,6 +839,8 @@ func TestLoadActions(t *testing.T) { Weight: 10, RatingSubject: "test", DestinationIds: utils.NewStringMap("NAT"), + TimingIDs: utils.StringMap{}, + SharedGroups: utils.StringMap{}, }, }, } @@ -857,7 +861,8 @@ func TestLoadActions(t *testing.T) { Uuid: as2[0].Balance.Uuid, Value: 100, Weight: 10, - SharedGroup: "SG1", + SharedGroups: utils.NewStringMap("SG1"), + TimingIDs: utils.StringMap{}, }, }, } @@ -875,6 +880,8 @@ func TestLoadActions(t *testing.T) { Uuid: as3[0].Balance.Uuid, Directions: utils.StringMap{}, DestinationIds: utils.StringMap{}, + TimingIDs: utils.StringMap{}, + SharedGroups: utils.StringMap{}, }, }, } @@ -1007,6 +1014,8 @@ func TestLoadActionTriggers(t *testing.T) { ThresholdValue: 10, BalanceDestinationIds: utils.NewStringMap("GERMANY_O2"), BalanceCategories: utils.StringMap{}, + BalanceTimingTags: utils.StringMap{}, + BalanceSharedGroups: utils.StringMap{}, Weight: 10, ActionsId: "SOME_1", Executed: false, @@ -1022,6 +1031,8 @@ func TestLoadActionTriggers(t *testing.T) { ThresholdValue: 200, BalanceDestinationIds: utils.NewStringMap("GERMANY"), BalanceCategories: utils.StringMap{}, + BalanceTimingTags: utils.StringMap{}, + BalanceSharedGroups: utils.StringMap{}, Weight: 10, ActionsId: "SOME_2", Executed: false, diff --git a/engine/model_converters.go b/engine/model_converters.go index 373d01ba7..5dace97df 100644 --- a/engine/model_converters.go +++ b/engine/model_converters.go @@ -177,7 +177,7 @@ func APItoModelAction(as *utils.TPActions) (result []TpAction) { DestinationTags: a.DestinationIds, RatingSubject: a.RatingSubject, Categories: a.Categories, - SharedGroup: a.SharedGroup, + SharedGroups: a.SharedGroups, BalanceWeight: a.BalanceWeight, ExtraParameters: a.ExtraParameters, Weight: a.Weight, @@ -230,7 +230,7 @@ func APItoModelActionTrigger(ats *utils.TPActionTriggers) (result []TpActionTrig BalanceTimingTags: at.BalanceTimingTags, BalanceRatingSubject: at.BalanceRatingSubject, BalanceCategories: at.BalanceCategories, - BalanceSharedGroup: at.BalanceSharedGroup, + BalanceSharedGroups: at.BalanceSharedGroups, BalanceDisabled: at.BalanceDisabled, MinQueuedItems: at.MinQueuedItems, ActionsTag: at.ActionsId, diff --git a/engine/model_helpers.go b/engine/model_helpers.go index c33e6c9c1..a8254e066 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -394,7 +394,7 @@ func (tps TpActions) GetActions() (map[string][]*utils.TPAction, error) { DestinationIds: tpAc.DestinationTags, RatingSubject: tpAc.RatingSubject, Categories: tpAc.Categories, - SharedGroup: tpAc.SharedGroup, + SharedGroups: tpAc.SharedGroups, BalanceWeight: tpAc.BalanceWeight, ExtraParameters: tpAc.ExtraParameters, Weight: tpAc.Weight, @@ -435,7 +435,7 @@ func (tps TpActionTriggers) GetActionTriggers() (map[string][]*utils.TPActionTri BalanceTimingTags: tpAt.BalanceTimingTags, BalanceRatingSubject: tpAt.BalanceRatingSubject, BalanceCategories: tpAt.BalanceCategories, - BalanceSharedGroup: tpAt.BalanceSharedGroup, + BalanceSharedGroups: tpAt.BalanceSharedGroups, BalanceDisabled: tpAt.BalanceDisabled, Weight: tpAt.Weight, ActionsId: tpAt.ActionsTag, diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index 207506f97..58ac02b6e 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -245,7 +245,7 @@ func TestTPActionsAsExportSlice(t *testing.T) { DestinationIds: "*any", RatingSubject: "special1", Categories: "call", - SharedGroup: "GROUP1", + SharedGroups: "GROUP1", BalanceWeight: 10.0, ExtraParameters: "", Weight: 10.0}, @@ -258,7 +258,7 @@ func TestTPActionsAsExportSlice(t *testing.T) { DestinationIds: "", RatingSubject: "", Categories: "", - SharedGroup: "", + SharedGroups: "", BalanceWeight: 0.0, ExtraParameters: "http://localhost/¶m1=value1", Weight: 20.0}, @@ -564,7 +564,7 @@ func TestTPActionPlanAsExportSlice(t *testing.T) { BalanceTimingTags: "T1", BalanceRatingSubject: "special1", BalanceCategories: "call", - BalanceSharedGroup: "SHARED_1", + BalanceSharedGroups: "SHARED_1", BalanceDisabled: false, MinQueuedItems: 0, ActionsId: "LOG_WARNING", @@ -583,7 +583,7 @@ func TestTPActionPlanAsExportSlice(t *testing.T) { BalanceTimingTags: "T1", BalanceRatingSubject: "special1", BalanceCategories: "call", - BalanceSharedGroup: "SHARED_1", + BalanceSharedGroups: "SHARED_1", BalanceDisabled: false, MinQueuedItems: 0, ActionsId: "LOG_WARNING", diff --git a/engine/models.go b/engine/models.go index 9b1ff16de..59aff1737 100644 --- a/engine/models.go +++ b/engine/models.go @@ -162,7 +162,7 @@ type TpAction struct { 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*"` @@ -197,7 +197,7 @@ type TpActionTrigger struct { 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*"` diff --git a/engine/tp_reader.go b/engine/tp_reader.go index 57a1a2698..75165cd84 100644 --- a/engine/tp_reader.go +++ b/engine/tp_reader.go @@ -517,7 +517,8 @@ func (tpr *TpReader) LoadActions() (err error) { Categories: utils.ParseStringMap(tpact.Categories), Directions: utils.ParseStringMap(tpact.Directions), DestinationIds: utils.ParseStringMap(tpact.DestinationIds), - SharedGroup: tpact.SharedGroup, + SharedGroups: utils.ParseStringMap(tpact.SharedGroups), + TimingIDs: utils.ParseStringMap(tpact.TimingTags), }, } // load action timings from tags @@ -620,10 +621,10 @@ func (tpr *TpReader) LoadActionTriggers() (err error) { BalanceDestinationIds: utils.ParseStringMap(atr.BalanceDestinationIds), BalanceWeight: atr.BalanceWeight, BalanceExpirationDate: balanceExpirationDate, - BalanceTimingTags: atr.BalanceTimingTags, + BalanceTimingTags: utils.ParseStringMap(atr.BalanceTimingTags), BalanceRatingSubject: atr.BalanceRatingSubject, BalanceCategories: utils.ParseStringMap(atr.BalanceCategories), - BalanceSharedGroup: atr.BalanceSharedGroup, + BalanceSharedGroups: utils.ParseStringMap(atr.BalanceSharedGroups), Weight: atr.Weight, ActionsId: atr.ActionsId, MinQueuedItems: atr.MinQueuedItems, @@ -761,7 +762,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error BalanceExpirationDate: expTime, BalanceRatingSubject: apiAtr.BalanceRatingSubject, BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories), - BalanceSharedGroup: apiAtr.BalanceSharedGroup, + BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups), Weight: apiAtr.Weight, ActionsId: apiAtr.ActionsId, } @@ -807,7 +808,8 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error RatingSubject: tpact.RatingSubject, Directions: utils.ParseStringMap(tpact.Directions), DestinationIds: utils.ParseStringMap(tpact.DestinationIds), - SharedGroup: tpact.SharedGroup, + SharedGroups: utils.ParseStringMap(tpact.SharedGroups), + TimingIDs: utils.ParseStringMap(tpact.TimingTags), }, } } @@ -964,7 +966,8 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) { BalanceExpirationDate: expTime, BalanceRatingSubject: apiAtr.BalanceRatingSubject, BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories), - BalanceSharedGroup: apiAtr.BalanceSharedGroup, + BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups), + BalanceTimingTags: utils.ParseStringMap(apiAtr.BalanceTimingTags), Weight: apiAtr.Weight, ActionsId: apiAtr.ActionsId, } @@ -1019,7 +1022,8 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) { RatingSubject: tpact.RatingSubject, Directions: utils.ParseStringMap(tpact.Directions), DestinationIds: utils.ParseStringMap(tpact.DestinationIds), - SharedGroup: tpact.SharedGroup, + SharedGroups: utils.ParseStringMap(tpact.SharedGroups), + TimingIDs: utils.ParseStringMap(tpact.TimingTags), }, } } diff --git a/utils/apitpdata.go b/utils/apitpdata.go index b6dbe0b4f..8f1748464 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -283,7 +283,7 @@ type TPAction struct { DestinationIds string // Destination profile id RatingSubject string // Reference a rate subject defined in RatingProfiles Categories string // category filter for balances - SharedGroup string // Reference to a shared group + SharedGroups string // Reference to a shared group BalanceWeight float64 // Balance weight ExtraParameters string Weight float64 // Action's weight @@ -483,7 +483,7 @@ type TPActionTrigger struct { BalanceTimingTags string // filter for balance BalanceRatingSubject string // filter for balance BalanceCategories string // filter for balance - BalanceSharedGroup 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 diff --git a/utils/map.go b/utils/map.go index 8be47180f..22a4fde6c 100644 --- a/utils/map.go +++ b/utils/map.go @@ -130,3 +130,10 @@ func (sm StringMap) Slice() []string { func (sm StringMap) String() string { return strings.Join(sm.Slice(), INFIELD_SEP) } + +func (sm StringMap) GetOne() string { + for key := range sm{ + return key + } + return "" +} From c8ebf0a75676e9ce89e7332bd449f7ff5064a94d Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 28 Oct 2015 21:00:17 +0200 Subject: [PATCH 21/29] added timings and shared groups to migrator --- cmd/cgr-loader/migrator_rc8.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cmd/cgr-loader/migrator_rc8.go b/cmd/cgr-loader/migrator_rc8.go index 0ba41f568..0008f66f1 100644 --- a/cmd/cgr-loader/migrator_rc8.go +++ b/cmd/cgr-loader/migrator_rc8.go @@ -170,9 +170,9 @@ func (mig MigratorRC8) migrateAccounts() error { DestinationIds: utils.ParseStringMap(oldBal.DestinationIds), RatingSubject: oldBal.RatingSubject, Categories: utils.ParseStringMap(oldBal.Category), - SharedGroup: oldBal.SharedGroup, + SharedGroups: utils.ParseStringMap(oldBal.SharedGroup), Timings: oldBal.Timings, - TimingIDs: oldBal.TimingIDs, + TimingIDs: utils.ParseStringMap(oldBal.TimingIDs), Disabled: oldBal.Disabled, } } @@ -194,9 +194,9 @@ func (mig MigratorRC8) migrateAccounts() error { DestinationIds: utils.ParseStringMap(oldUcBal.DestinationIds), RatingSubject: oldUcBal.RatingSubject, Categories: utils.ParseStringMap(oldUcBal.Category), - SharedGroup: oldUcBal.SharedGroup, + SharedGroups: utils.ParseStringMap(oldUcBal.SharedGroup), Timings: oldUcBal.Timings, - TimingIDs: oldUcBal.TimingIDs, + TimingIDs: utils.ParseStringMap(oldUcBal.TimingIDs), Disabled: oldUcBal.Disabled, } } @@ -215,10 +215,10 @@ func (mig MigratorRC8) migrateAccounts() error { BalanceDestinationIds: utils.ParseStringMap(oldAtr.BalanceDestinationIds), BalanceWeight: oldAtr.BalanceWeight, BalanceExpirationDate: oldAtr.BalanceExpirationDate, - BalanceTimingTags: oldAtr.BalanceTimingTags, + BalanceTimingTags: utils.ParseStringMap(oldAtr.BalanceTimingTags), BalanceRatingSubject: oldAtr.BalanceRatingSubject, BalanceCategories: utils.ParseStringMap(oldAtr.BalanceCategory), - BalanceSharedGroup: oldAtr.BalanceSharedGroup, + BalanceSharedGroups: utils.ParseStringMap(oldAtr.BalanceSharedGroup), BalanceDisabled: oldAtr.BalanceDisabled, Weight: oldAtr.Weight, ActionsId: oldAtr.ActionsId, @@ -275,10 +275,10 @@ func (mig MigratorRC8) migrateActionTriggers() error { BalanceDestinationIds: utils.ParseStringMap(oldAtr.BalanceDestinationIds), BalanceWeight: oldAtr.BalanceWeight, BalanceExpirationDate: oldAtr.BalanceExpirationDate, - BalanceTimingTags: oldAtr.BalanceTimingTags, + BalanceTimingTags: utils.ParseStringMap(oldAtr.BalanceTimingTags), BalanceRatingSubject: oldAtr.BalanceRatingSubject, BalanceCategories: utils.ParseStringMap(oldAtr.BalanceCategory), - BalanceSharedGroup: oldAtr.BalanceSharedGroup, + BalanceSharedGroups: utils.ParseStringMap(oldAtr.BalanceSharedGroup), BalanceDisabled: oldAtr.BalanceDisabled, Weight: oldAtr.Weight, ActionsId: oldAtr.ActionsId, @@ -335,9 +335,9 @@ func (mig MigratorRC8) migrateActions() error { DestinationIds: utils.ParseStringMap(oldAc.Balance.DestinationIds), RatingSubject: oldAc.Balance.RatingSubject, Categories: utils.ParseStringMap(oldAc.Balance.Category), - SharedGroup: oldAc.Balance.SharedGroup, + SharedGroups: utils.ParseStringMap(oldAc.Balance.SharedGroup), Timings: oldAc.Balance.Timings, - TimingIDs: oldAc.Balance.TimingIDs, + TimingIDs: utils.ParseStringMap(oldAc.Balance.TimingIDs), Disabled: oldAc.Balance.Disabled, }, } From 3d3cdb0252850ef41d6bceb6401edec7ce35a596 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 28 Oct 2015 22:25:18 +0200 Subject: [PATCH 22/29] implemented AsOldStructure for accounts --- engine/account.go | 140 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/engine/account.go b/engine/account.go index e984ec0f1..c5ec13f00 100644 --- a/engine/account.go +++ b/engine/account.go @@ -683,3 +683,143 @@ func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balance } } } + +// 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 +} From b81b9e5c566c4419af3df3ee7e5edcc77a86067a Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 29 Oct 2015 09:51:18 +0200 Subject: [PATCH 23/29] old account format for apier v1 --- apier/v1/accounts.go | 6 ++-- apier/v1/accounts_test.go | 2 +- apier/v2/accounts.go | 66 +++++++++++++++++++++++++++++++++++++++ console/accounts.go | 2 +- 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 apier/v2/accounts.go diff --git a/apier/v1/accounts.go b/apier/v1/accounts.go index f007f1537..4331f4c24 100644 --- a/apier/v1/accounts.go +++ b/apier/v1/accounts.go @@ -242,7 +242,7 @@ 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") } @@ -270,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 5c6a8604a..51a5ce573 100644 --- a/apier/v1/accounts_test.go +++ b/apier/v1/accounts_test.go @@ -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/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/console/accounts.go b/console/accounts.go index f1d760fc3..c9030290e 100644 --- a/console/accounts.go +++ b/console/accounts.go @@ -26,7 +26,7 @@ import ( func init() { c := &CmdGetAccounts{ name: "accounts", - rpcMethod: "ApierV1.GetAccounts", + rpcMethod: "ApierV2.GetAccounts", rpcParams: &utils.AttrGetAccounts{}, } commands[c.Name()] = c From f9c532c42f82ec7477f07ad2819be26ae6eb86d1 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 29 Oct 2015 10:57:11 +0200 Subject: [PATCH 24/29] logging to console --- cmd/cgr-loader/cgr-loader.go | 16 ++++++++-------- cmd/cgr-loader/migrator_rc8.go | 11 ++++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cmd/cgr-loader/cgr-loader.go b/cmd/cgr-loader/cgr-loader.go index 1c1603e28..17c368cd8 100644 --- a/cmd/cgr-loader/cgr-loader.go +++ b/cmd/cgr-loader/cgr-loader.go @@ -94,7 +94,7 @@ func main() { var db_nb int db_nb, err = strconv.Atoi(*datadb_name) if err != nil { - utils.Logger.Crit("Redis db name must be an integer!") + log.Print("Redis db name must be an integer!") return } host := *datadb_host @@ -103,17 +103,17 @@ func main() { } migratorRC8acc, err := NewMigratorRC8(host, db_nb, *datadb_pass, *dbdata_encoding) if err != nil { - utils.Logger.Crit(err.Error()) + log.Print(err.Error()) return } if err := migratorRC8acc.migrateAccounts(); err != nil { - utils.Logger.Crit(err.Error()) + log.Print(err.Error()) return } db_nb, err = strconv.Atoi(*tpdb_name) if err != nil { - utils.Logger.Crit("Redis db name must be an integer!") + log.Print("Redis db name must be an integer!") return } host = *tpdb_host @@ -122,18 +122,18 @@ func main() { } migratorRC8rat, err := NewMigratorRC8(host, db_nb, *tpdb_pass, *dbdata_encoding) if err != nil { - utils.Logger.Crit(err.Error()) + log.Print(err.Error()) return } if err := migratorRC8rat.migrateActionTriggers(); err != nil { - utils.Logger.Crit(err.Error()) + log.Print(err.Error()) return } if err := migratorRC8rat.migrateActions(); err != nil { - utils.Logger.Crit(err.Error()) + log.Print(err.Error()) return } - utils.Logger.Info("Done!") + log.Print("Done!") return } // Init necessary db connections, only if not already diff --git a/cmd/cgr-loader/migrator_rc8.go b/cmd/cgr-loader/migrator_rc8.go index 0008f66f1..3fc97d2bd 100644 --- a/cmd/cgr-loader/migrator_rc8.go +++ b/cmd/cgr-loader/migrator_rc8.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "log" "strings" "time" @@ -122,7 +123,7 @@ func (mig MigratorRC8) migrateAccounts() error { newAccounts := make([]*engine.Account, len(keys)) // get existing accounts for keyIndex, key := range keys { - utils.Logger.Info(fmt.Sprintf("Migrating account: %s...", key)) + log.Printf("Migrating account: %s...", key) values, err := mig.db.Get(key) if err != nil { continue @@ -239,7 +240,7 @@ func (mig MigratorRC8) migrateAccounts() error { } } // delete old data - utils.Logger.Info(fmt.Sprintf("Deleting old accounts: %s...", OLD_ACCOUNT_PREFIX+"*")) + log.Printf("Deleting old accounts: %s...", OLD_ACCOUNT_PREFIX+"*") for _, key := range keys { _, err = mig.db.Del(key) } @@ -253,7 +254,7 @@ func (mig MigratorRC8) migrateActionTriggers() error { } newAtrsMap := make(map[string]engine.ActionTriggers, len(keys)) for _, key := range keys { - utils.Logger.Info(fmt.Sprintf("Migrating action trigger: %s...", key)) + log.Printf("Migrating action trigger: %s...", key) var oldAtrs ActionTriggers var values []byte if values, err = mig.db.Get(key); err == nil { @@ -308,7 +309,7 @@ func (mig MigratorRC8) migrateActions() error { } newAcsMap := make(map[string]engine.Actions, len(keys)) for _, key := range keys { - utils.Logger.Info(fmt.Sprintf("Migrating action: %s...", key)) + log.Printf("Migrating action: %s...", key) var oldAcs Actions var values []byte if values, err = mig.db.Get(key); err == nil { @@ -335,7 +336,7 @@ func (mig MigratorRC8) migrateActions() error { DestinationIds: utils.ParseStringMap(oldAc.Balance.DestinationIds), RatingSubject: oldAc.Balance.RatingSubject, Categories: utils.ParseStringMap(oldAc.Balance.Category), - SharedGroups: utils.ParseStringMap(oldAc.Balance.SharedGroup), + SharedGroups: utils.ParseStringMap(oldAc.Balance.SharedGroup), Timings: oldAc.Balance.Timings, TimingIDs: utils.ParseStringMap(oldAc.Balance.TimingIDs), Disabled: oldAc.Balance.Disabled, From 7b89af8b6a8ee82e98d42bc48ebdcd399c7d92f5 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 29 Oct 2015 12:48:13 +0200 Subject: [PATCH 25/29] snitize apier string struct fields --- utils/struct.go | 5 +++++ 1 file changed, 5 insertions(+) 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) { From 1e1c115ed426f67c87aea4d8672546fb0336dcfb Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 30 Oct 2015 11:26:49 +0200 Subject: [PATCH 26/29] unit counters revision --- engine/account.go | 93 +++++++++++++++++++++------------------- engine/action_trigger.go | 24 ++++++++--- engine/balances.go | 6 +-- engine/units_counter.go | 8 +--- 4 files changed, 72 insertions(+), 59 deletions(-) diff --git a/engine/account.go b/engine/account.go index c5ec13f00..73b4dbbed 100644 --- a/engine/account.go +++ b/engine/account.go @@ -390,7 +390,7 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo increment.BalanceInfo.AccountId = ub.Id increment.paid = true if count { - ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{leftCC.Direction: true}, Value: cost, DestinationIds: utils.StringMap{leftCC.Destination: true}}}) + ub.countUnits(&Action{BalanceType: utils.MONETARY, Balance: &Balance{Directions: utils.StringMap{leftCC.Direction: true}, Value: cost, DestinationIds: utils.NewStringMap(leftCC.Destination)}}) } } } @@ -550,9 +550,10 @@ func (ub *Account) countUnits(a *Action) { } // Create counters for all triggered actions that have actions opertating on balances -func (ub *Account) initCounters() { +func (acc *Account) initCounters() { ucTempMap := make(map[string]*UnitsCounter) - for _, at := range ub.ActionTriggers { + // add default balance + for _, at := range acc.ActionTriggers { acs, err := ratingStorage.GetActions(at.ActionsId, false) if err != nil { continue @@ -564,12 +565,14 @@ func (ub *Account) initCounters() { 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 } } } @@ -775,48 +778,48 @@ func (acc *Account) AsOldStructure() interface{} { } } } - 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 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{ + 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, + 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, } } } diff --git a/engine/action_trigger.go b/engine/action_trigger.go index 615ddc2f8..57177b2cc 100644 --- a/engine/action_trigger.go +++ b/engine/action_trigger.go @@ -41,7 +41,7 @@ type ActionTrigger struct { BalanceDestinationIds utils.StringMap // filter for balance BalanceWeight float64 // filter for balance BalanceExpirationDate time.Time // filter for balance - BalanceTimingTags utils.StringMap // 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 @@ -110,7 +110,7 @@ func (at *ActionTrigger) Match(a *Action) bool { return match } id := a.BalanceType == "" || at.BalanceType == a.BalanceType - thresholdType, thresholdValue, direction, destinationId, weight, ratingSubject, categories, sharedGroup,timings, disabled := true, true, 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 @@ -120,8 +120,8 @@ func (at *ActionTrigger) Match(a *Action) bool { BalanceWeight float64 BalanceRatingSubject string BalanceCategories string - BalanceSharedGroups string - BalanceTimingTags string + BalanceSharedGroups string + BalanceTimingTags string BalanceDisabled bool }{} json.Unmarshal([]byte(a.ExtraParameters), &t) @@ -131,7 +131,7 @@ func (at *ActionTrigger) Match(a *Action) bool { 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)) + 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 disabled = at.BalanceDisabled == t.BalanceDisabled @@ -146,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/balances.go b/engine/balances.go index 55378fa78..7f7c49a14 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -41,7 +41,7 @@ type Balance struct { DestinationIds utils.StringMap RatingSubject string Categories utils.StringMap - SharedGroups utils.StringMap + SharedGroups utils.StringMap Timings []*RITiming TimingIDs utils.StringMap Disabled bool @@ -191,7 +191,7 @@ func (b *Balance) Clone() *Balance { Weight: b.Weight, RatingSubject: b.RatingSubject, Categories: b.Categories, - SharedGroups: b.SharedGroups, + SharedGroups: b.SharedGroups, TimingIDs: b.TimingIDs, Timings: b.Timings, // should not be a problem with aliasing Disabled: b.Disabled, @@ -664,7 +664,7 @@ func (bc BalanceChain) SaveDirtyBalances(acc *Account) { "Directions": b.Directions.String(), "RatingSubject": b.RatingSubject, "Categories": b.Categories.String(), - "SharedGroups": b.SharedGroups.String(), + "SharedGroups": b.SharedGroups.String(), "TimingIDs": b.TimingIDs.String(), "Account": accountId, "AccountAllowNegative": allowNegative, diff --git a/engine/units_counter.go b/engine/units_counter.go index 39c5f5c74..1bf97eed0 100644 --- a/engine/units_counter.go +++ b/engine/units_counter.go @@ -60,7 +60,7 @@ func (uc *UnitsCounter) initBalances(ats []*ActionTrigger) { // 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] @@ -70,11 +70,7 @@ func (uc *UnitsCounter) GetGeneralBalance() *Balance { // is the same or ads the balance to the list if none matches. func (uc *UnitsCounter) addUnits(amount float64, prefixMap utils.StringMap) { counted := false - prefix := "" - for key := range prefixMap { // get the first value - prefix = key - break - } + prefix := prefixMap.String() if prefix != "" { for _, mb := range uc.Balances { if !mb.HasDestination() { From 362c6fa7c66ad46f46e847067657cf8970928c02 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 30 Oct 2015 12:34:30 +0200 Subject: [PATCH 27/29] global rounding default set to 5 --- config/config_defaults.go | 2 +- engine/calldesc.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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/engine/calldesc.go b/engine/calldesc.go index 4b93208cc..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) { From 88137b75dbe04cd72793af0906f15e7ef0fb3698 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 30 Oct 2015 17:03:54 +0200 Subject: [PATCH 28/29] *generic balance used by all tors fixes #250 --- config/config_json_test.go | 2 +- engine/account.go | 18 +++++--- engine/account_test.go | 86 ++++++++++++++++++++++++++++++++++++++ engine/balances.go | 32 +++++++++----- engine/loader_csv_test.go | 26 ++++++------ engine/sharedgroup.go | 2 +- engine/timespans_test.go | 2 +- 7 files changed, 136 insertions(+), 32 deletions(-) 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/engine/account.go b/engine/account.go index 73b4dbbed..1c1954c53 100644 --- a/engine/account.go +++ b/engine/account.go @@ -52,8 +52,9 @@ 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, cd.Direction, ub.BalanceMap[utils.MONETARY], "") - unitBalances := ub.getBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, ub.BalanceMap[cd.TOR], "") + 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 { @@ -182,7 +183,12 @@ func (ub *Account) enableDisableBalanceAction(a *Action) error { return nil } -func (ub *Account) getBalancesForPrefix(prefix, category string, direction 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 { @@ -235,7 +241,7 @@ func (ub *Account) getBalancesForPrefix(prefix, category string, direction strin // like getBalancesForPrefix but expanding shared balances func (account *Account) getAlldBalancesForPrefix(destination, category, direction, balanceType string) (bc BalanceChain) { - balances := account.getBalancesForPrefix(destination, category, direction, account.BalanceMap[balanceType], "") + balances := account.getBalancesForPrefix(destination, category, direction, balanceType, "") for _, b := range balances { if len(b.SharedGroups) > 0 { for sgId := range b.SharedGroups { @@ -615,8 +621,8 @@ 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, cd.Direction, account.BalanceMap[utils.MONETARY], "")...) - balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, cd.Direction, account.BalanceMap[cd.TOR], "")...) + 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 { diff --git a/engine/account_test.go b/engine/account_test.go index fbeddfb73..799177a78 100644 --- a/engine/account_test.go +++ b/engine/account_test.go @@ -1231,6 +1231,92 @@ func TestDebitGeneric(t *testing.T) { } } +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()) + } +} + func TestDebitDataUnits(t *testing.T) { cc := &CallCost{ Direction: utils.OUT, diff --git a/engine/balances.go b/engine/balances.go index 7f7c49a14..f5a565656 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -45,6 +45,7 @@ type Balance struct { Timings []*RITiming TimingIDs utils.StringMap Disabled bool + Factor ValueFactor precision int account *Account // used to store ub reference for shared balances dirty bool @@ -319,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{ @@ -352,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) @@ -401,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 @@ -437,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) @@ -449,7 +452,7 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala } inc.paid = true if count { - ub.countUnits(&Action{BalanceType: cc.TOR, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: seconds, DestinationIds: utils.StringMap{cc.Destination: true}}}) + 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, Balance: &Balance{Directions: utils.StringMap{cc.Direction: true}, Value: cost, DestinationIds: utils.StringMap{cc.Destination: true}}}) } @@ -678,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/loader_csv_test.go b/engine/loader_csv_test.go index 9e7ca337b..84b6069f4 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -817,12 +817,12 @@ func TestLoadActions(t *testing.T) { ExtraParameters: "", Weight: 10, Balance: &Balance{ - Uuid: as1[0].Balance.Uuid, - Directions: utils.NewStringMap(utils.OUT), - Value: 10, - Weight: 10, - TimingIDs: utils.StringMap{}, - SharedGroups: utils.StringMap{}, + Uuid: as1[0].Balance.Uuid, + Directions: utils.NewStringMap(utils.OUT), + Value: 10, + Weight: 10, + TimingIDs: utils.StringMap{}, + SharedGroups: utils.StringMap{}, }, }, &Action{ @@ -840,7 +840,7 @@ func TestLoadActions(t *testing.T) { RatingSubject: "test", DestinationIds: utils.NewStringMap("NAT"), TimingIDs: utils.StringMap{}, - SharedGroups: utils.StringMap{}, + SharedGroups: utils.StringMap{}, }, }, } @@ -861,7 +861,7 @@ func TestLoadActions(t *testing.T) { Uuid: as2[0].Balance.Uuid, Value: 100, Weight: 10, - SharedGroups: utils.NewStringMap("SG1"), + SharedGroups: utils.NewStringMap("SG1"), TimingIDs: utils.StringMap{}, }, }, @@ -881,7 +881,7 @@ func TestLoadActions(t *testing.T) { Directions: utils.StringMap{}, DestinationIds: utils.StringMap{}, TimingIDs: utils.StringMap{}, - SharedGroups: utils.StringMap{}, + SharedGroups: utils.StringMap{}, }, }, } @@ -1014,8 +1014,8 @@ func TestLoadActionTriggers(t *testing.T) { ThresholdValue: 10, BalanceDestinationIds: utils.NewStringMap("GERMANY_O2"), BalanceCategories: utils.StringMap{}, - BalanceTimingTags: utils.StringMap{}, - BalanceSharedGroups: utils.StringMap{}, + BalanceTimingTags: utils.StringMap{}, + BalanceSharedGroups: utils.StringMap{}, Weight: 10, ActionsId: "SOME_1", Executed: false, @@ -1031,8 +1031,8 @@ func TestLoadActionTriggers(t *testing.T) { ThresholdValue: 200, BalanceDestinationIds: utils.NewStringMap("GERMANY"), BalanceCategories: utils.StringMap{}, - BalanceTimingTags: utils.StringMap{}, - BalanceSharedGroups: utils.StringMap{}, + BalanceTimingTags: utils.StringMap{}, + BalanceSharedGroups: utils.StringMap{}, Weight: 10, ActionsId: "SOME_2", Executed: false, diff --git a/engine/sharedgroup.go b/engine/sharedgroup.go index e3f08ad34..4ec1bde23 100644 --- a/engine/sharedgroup.go +++ b/engine/sharedgroup.go @@ -103,7 +103,7 @@ func (sg *SharedGroup) GetBalances(destination, category, direction, balanceType } } //sg.members = append(sg.members, nUb) - sb := nUb.getBalancesForPrefix(destination, category, direction, nUb.BalanceMap[balanceType], sg.Id) + sb := nUb.getBalancesForPrefix(destination, category, direction, balanceType, sg.Id) bc = append(bc, sb...) } /* } else { 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) } } From c81db1afcca70a9447d9c5aae74f0fffe7c3f2bd Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 30 Oct 2015 18:15:23 +0200 Subject: [PATCH 29/29] Factor value parsing --- engine/account.go | 11 +++++++++++ engine/actions_test.go | 21 ++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/engine/account.go b/engine/account.go index 1c1954c53..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" @@ -139,6 +140,16 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error { 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) } for sgId := range a.Balance.SharedGroups { diff --git a/engine/actions_test.go b/engine/actions_test.go index 4e4aa80d2..7896008bb 100644 --- a/engine/actions_test.go +++ b/engine/actions_test.go @@ -625,7 +625,7 @@ func TestActionTriggerMatchAll(t *testing.T) { BalanceDestinationIds: utils.NewStringMap("NAT"), BalanceWeight: 1.0, BalanceRatingSubject: "test1", - BalanceSharedGroups: utils.NewStringMap("test2"), + BalanceSharedGroups: utils.NewStringMap("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) { @@ -764,6 +764,25 @@ func TestActionTopupResetCredit(t *testing.T) { } } +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) + } +} + func TestActionTopupResetCreditId(t *testing.T) { ub := &Account{ Id: "TEST_UB",