mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Merge branch 'master' into shared_balances
Conflicts: engine/account.go engine/loader_csv_test.go engine/storage_interface.go engine/storage_map.go engine/storage_redis.go
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ docs/_*
|
||||
bin
|
||||
.idea
|
||||
dean*
|
||||
data/vagrant/.vagrant
|
||||
|
||||
@@ -51,7 +51,7 @@ func (self *ApierV1) GetAccountActionPlan(attrs AttrAcntAction, reply *[]*Accoun
|
||||
}
|
||||
for _, ats := range allATs {
|
||||
for _, at := range ats {
|
||||
if utils.IsSliceMember(at.UserBalanceIds, utils.BalanceKey(attrs.Tenant, attrs.Account, attrs.Direction)) {
|
||||
if utils.IsSliceMember(at.AccountIds, utils.BalanceKey(attrs.Tenant, attrs.Account, attrs.Direction)) {
|
||||
accountATs = append(accountATs, &AccountActionTiming{Id: at.Id, ActionPlanId: at.Tag, ActionsId: at.ActionsId, NextExecTime: at.GetNextStartTime(time.Now())})
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func (self *ApierV1) GetAccountActionTriggers(attrs AttrAcntAction, reply *engin
|
||||
if missing := utils.MissingStructFields(&attrs, []string{"Tenant", "Account", "Direction"}); len(missing) != 0 {
|
||||
return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing)
|
||||
}
|
||||
if balance, err := self.AccountDb.GetUserBalance(utils.BalanceKey(attrs.Tenant, attrs.Account, attrs.Direction)); err != nil {
|
||||
if balance, err := self.AccountDb.GetAccount(utils.BalanceKey(attrs.Tenant, attrs.Account, attrs.Direction)); err != nil {
|
||||
return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
|
||||
} else {
|
||||
*reply = balance.ActionTriggers
|
||||
@@ -130,7 +130,7 @@ func (self *ApierV1) RemAccountActionTriggers(attrs AttrRemAcntActionTriggers, r
|
||||
}
|
||||
balanceId := utils.BalanceKey(attrs.Tenant, attrs.Account, attrs.Direction)
|
||||
_, err := engine.AccLock.Guard(balanceId, func() (float64, error) {
|
||||
ub, err := self.AccountDb.GetUserBalance(balanceId)
|
||||
ub, err := self.AccountDb.GetAccount(balanceId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -144,7 +144,7 @@ func (self *ApierV1) RemAccountActionTriggers(attrs AttrRemAcntActionTriggers, r
|
||||
ub.ActionTriggers = make(engine.ActionTriggerPriotityList, 0)
|
||||
}
|
||||
}
|
||||
if err := self.AccountDb.SetUserBalance(ub); err != nil {
|
||||
if err := self.AccountDb.SetAccount(ub); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return 0, nil
|
||||
@@ -157,11 +157,11 @@ func (self *ApierV1) RemAccountActionTriggers(attrs AttrRemAcntActionTriggers, r
|
||||
}
|
||||
|
||||
type AttrSetAccount struct {
|
||||
Tenant string
|
||||
Direction string
|
||||
Account string
|
||||
Type string // <*prepaid|*postpaid>
|
||||
ActionPlanId string
|
||||
Tenant string
|
||||
Direction string
|
||||
Account string
|
||||
ActionPlanId string
|
||||
AllowNegative bool
|
||||
}
|
||||
|
||||
// Ads a new account into dataDb. If already defined, returns success.
|
||||
@@ -170,20 +170,15 @@ func (self *ApierV1) SetAccount(attr AttrSetAccount, reply *string) error {
|
||||
return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing)
|
||||
}
|
||||
balanceId := utils.BalanceKey(attr.Tenant, attr.Account, attr.Direction)
|
||||
var ub *engine.UserBalance
|
||||
var ub *engine.Account
|
||||
var ats engine.ActionPlan
|
||||
_, err := engine.AccLock.Guard(balanceId, func() (float64, error) {
|
||||
if bal, _ := self.AccountDb.GetUserBalance(balanceId); bal != nil {
|
||||
if bal, _ := self.AccountDb.GetAccount(balanceId); bal != nil {
|
||||
ub = bal
|
||||
} else { // Not found in db, create it here
|
||||
if len(attr.Type) == 0 {
|
||||
attr.Type = engine.UB_TYPE_PREPAID
|
||||
} else if !utils.IsSliceMember([]string{engine.UB_TYPE_POSTPAID, engine.UB_TYPE_PREPAID}, attr.Type) {
|
||||
return 0, fmt.Errorf("%s:%s", utils.ERR_MANDATORY_IE_MISSING, "Type")
|
||||
}
|
||||
ub = &engine.UserBalance{
|
||||
Id: balanceId,
|
||||
Type: attr.Type,
|
||||
ub = &engine.Account{
|
||||
Id: balanceId,
|
||||
AllowNegative: attr.AllowNegative,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,11 +189,11 @@ func (self *ApierV1) SetAccount(attr AttrSetAccount, reply *string) error {
|
||||
return 0, err
|
||||
}
|
||||
for _, at := range ats {
|
||||
at.UserBalanceIds = append(at.UserBalanceIds, balanceId)
|
||||
at.AccountIds = append(at.AccountIds, balanceId)
|
||||
}
|
||||
}
|
||||
// All prepared, save account
|
||||
if err := self.AccountDb.SetUserBalance(ub); err != nil {
|
||||
if err := self.AccountDb.SetAccount(ub); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return 0, nil
|
||||
|
||||
@@ -62,17 +62,17 @@ func (self *ApierV1) GetRatingPlan(rplnId string, reply *engine.RatingPlan) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrGetUserBalance struct {
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceId string
|
||||
Direction string
|
||||
type AttrGetAccount struct {
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceType string
|
||||
Direction string
|
||||
}
|
||||
|
||||
// Get balance
|
||||
func (self *ApierV1) GetUserBalance(attr *AttrGetUserBalance, reply *engine.UserBalance) error {
|
||||
func (self *ApierV1) GetAccount(attr *AttrGetAccount, reply *engine.Account) error {
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
userBalance, err := self.AccountDb.GetUserBalance(tag)
|
||||
userBalance, err := self.AccountDb.GetAccount(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (self *ApierV1) GetUserBalance(attr *AttrGetUserBalance, reply *engine.User
|
||||
type AttrAddBalance struct {
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceId string
|
||||
BalanceType string
|
||||
Direction string
|
||||
Value float64
|
||||
ExpirationDate time.Time
|
||||
@@ -96,18 +96,18 @@ type AttrAddBalance struct {
|
||||
|
||||
func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error {
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
if _, err := self.AccountDb.GetUserBalance(tag); err != nil {
|
||||
if _, err := self.AccountDb.GetAccount(tag); err != nil {
|
||||
// create user balance if not exists
|
||||
ub := &engine.UserBalance{
|
||||
ub := &engine.Account{
|
||||
Id: tag,
|
||||
}
|
||||
if err := self.AccountDb.SetUserBalance(ub); err != nil {
|
||||
if err := self.AccountDb.SetAccount(ub); err != nil {
|
||||
*reply = err.Error()
|
||||
return err
|
||||
}
|
||||
}
|
||||
at := &engine.ActionTiming{
|
||||
UserBalanceIds: []string{tag},
|
||||
AccountIds: []string{tag},
|
||||
}
|
||||
|
||||
if attr.Direction == "" {
|
||||
@@ -119,9 +119,9 @@ func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error {
|
||||
}
|
||||
at.SetActions(engine.Actions{
|
||||
&engine.Action{
|
||||
ActionType: aType,
|
||||
BalanceId: attr.BalanceId,
|
||||
Direction: attr.Direction,
|
||||
ActionType: aType,
|
||||
BalanceType: attr.BalanceType,
|
||||
Direction: attr.Direction,
|
||||
Balance: &engine.Balance{
|
||||
Value: attr.Value,
|
||||
ExpirationDate: attr.ExpirationDate,
|
||||
@@ -149,8 +149,8 @@ type AttrExecuteAction struct {
|
||||
func (self *ApierV1) ExecuteAction(attr *AttrExecuteAction, reply *string) error {
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
at := &engine.ActionTiming{
|
||||
UserBalanceIds: []string{tag},
|
||||
ActionsId: attr.ActionsId,
|
||||
AccountIds: []string{tag},
|
||||
ActionsId: attr.ActionsId,
|
||||
}
|
||||
|
||||
if err := at.Execute(); err != nil {
|
||||
@@ -274,7 +274,7 @@ func (self *ApierV1) SetActions(attrs AttrSetActions, reply *string) error {
|
||||
a := &engine.Action{
|
||||
Id: utils.GenUUID(),
|
||||
ActionType: apiAct.Identifier,
|
||||
BalanceId: apiAct.BalanceType,
|
||||
BalanceType: apiAct.BalanceType,
|
||||
Direction: apiAct.Direction,
|
||||
Weight: apiAct.Weight,
|
||||
ExpirationString: apiAct.ExpiryTime,
|
||||
@@ -370,7 +370,7 @@ type AttrAddActionTrigger struct {
|
||||
Tenant string
|
||||
Account string
|
||||
Direction string
|
||||
BalanceId string
|
||||
BalanceType string
|
||||
ThresholdType string
|
||||
ThresholdValue float64
|
||||
DestinationId string
|
||||
@@ -385,7 +385,7 @@ func (self *ApierV1) AddTriggeredAction(attr AttrAddActionTrigger, reply *string
|
||||
|
||||
at := &engine.ActionTrigger{
|
||||
Id: utils.GenUUID(),
|
||||
BalanceId: attr.BalanceId,
|
||||
BalanceType: attr.BalanceType,
|
||||
Direction: attr.Direction,
|
||||
ThresholdType: attr.ThresholdType,
|
||||
ThresholdValue: attr.ThresholdValue,
|
||||
@@ -397,14 +397,14 @@ func (self *ApierV1) AddTriggeredAction(attr AttrAddActionTrigger, reply *string
|
||||
|
||||
tag := utils.BalanceKey(attr.Tenant, attr.Account, attr.Direction)
|
||||
_, err := engine.AccLock.Guard(tag, func() (float64, error) {
|
||||
userBalance, err := self.AccountDb.GetUserBalance(tag)
|
||||
userBalance, err := self.AccountDb.GetAccount(tag)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
userBalance.ActionTriggers = append(userBalance.ActionTriggers, at)
|
||||
|
||||
if err = self.AccountDb.SetUserBalance(userBalance); err != nil {
|
||||
if err = self.AccountDb.SetAccount(userBalance); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return 0, nil
|
||||
|
||||
@@ -887,43 +887,43 @@ func TestApierAddBalance(t *testing.T) {
|
||||
return
|
||||
}
|
||||
reply := ""
|
||||
attrs := &AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceId: "*monetary", Direction: "*out", Value: 1.5}
|
||||
attrs := &AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Direction: "*out", 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", BalanceId: "*monetary", Direction: "*out", Value: 1.5}
|
||||
attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan", BalanceType: "*monetary", Direction: "*out", 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", BalanceId: "*monetary", Direction: "*out", Value: 1.5}
|
||||
attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan2", BalanceType: "*monetary", Direction: "*out", 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", BalanceId: "*monetary", Direction: "*out", Value: 1.5}
|
||||
attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan3", BalanceType: "*monetary", Direction: "*out", 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", BalanceId: "*monetary", Direction: "*out", Value: 2.1}
|
||||
attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan3", BalanceType: "*monetary", Direction: "*out", 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", BalanceId: "*monetary", Direction: "*out", Value: 2.1}
|
||||
attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan6", BalanceType: "*monetary", Direction: "*out", 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", BalanceId: "*monetary", Direction: "*out", Value: 1, Overwrite: true}
|
||||
attrs = &AttrAddBalance{Tenant: "cgrates.org", Account: "dan6", BalanceType: "*monetary", Direction: "*out", 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" {
|
||||
@@ -996,7 +996,7 @@ func TestApierAddTriggeredAction(t *testing.T) {
|
||||
}
|
||||
reply := ""
|
||||
// Add balance to a previously known account
|
||||
attrs := &AttrAddActionTrigger{Tenant: "cgrates.org", Account: "dan2", Direction: "*out", BalanceId: "*monetary",
|
||||
attrs := &AttrAddActionTrigger{Tenant: "cgrates.org", Account: "dan2", Direction: "*out", BalanceType: "*monetary",
|
||||
ThresholdType: "*min_balance", ThresholdValue: 2, DestinationId: "*any", Weight: 10, ActionsId: "WARN_VIA_HTTP"}
|
||||
if err := rater.Call("ApierV1.AddTriggeredAction", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.AddTriggeredAction: ", err.Error())
|
||||
@@ -1060,7 +1060,7 @@ func TestApierSetAccount(t *testing.T) {
|
||||
return
|
||||
}
|
||||
reply := ""
|
||||
attrs := &AttrSetAccount{Tenant: "cgrates.org", Direction: "*out", Account: "dan7", Type: "*prepaid", ActionPlanId: "ATMS_1"}
|
||||
attrs := &AttrSetAccount{Tenant: "cgrates.org", Direction: "*out", 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" {
|
||||
@@ -1115,42 +1115,42 @@ func TestApierRemActionTiming(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test here GetUserBalance
|
||||
func TestApierGetUserBalance(t *testing.T) {
|
||||
// Test here GetAccount
|
||||
func TestApierGetAccount(t *testing.T) {
|
||||
if !*testLocal {
|
||||
return
|
||||
}
|
||||
var reply *engine.UserBalance
|
||||
attrs := &AttrGetUserBalance{Tenant: "cgrates.org", Account: "1001", BalanceId: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetUserBalance", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetUserBalance: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceId+attrs.Direction].GetTotalValue() != 11.5 { // We expect 11.5 since we have added in the previous test 1.5
|
||||
var reply *engine.Account
|
||||
attrs := &AttrGetAccount{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceType+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)
|
||||
}
|
||||
attrs = &AttrGetUserBalance{Tenant: "cgrates.org", Account: "dan", BalanceId: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetUserBalance", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetUserBalance: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceId+attrs.Direction].GetTotalValue() != 1.5 {
|
||||
t.Errorf("Calling ApierV1.GetUserBalance expected: 1.5, received: %f", reply)
|
||||
attrs = &AttrGetAccount{Tenant: "cgrates.org", Account: "dan", BalanceType: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceType+attrs.Direction].GetTotalValue() != 1.5 {
|
||||
t.Errorf("Calling ApierV1.GetAccount expected: 1.5, received: %f", reply)
|
||||
}
|
||||
// The one we have topped up though executeAction
|
||||
attrs = &AttrGetUserBalance{Tenant: "cgrates.org", Account: "dan2", BalanceId: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetUserBalance", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetUserBalance: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceId+attrs.Direction].GetTotalValue() != 10 {
|
||||
t.Errorf("Calling ApierV1.GetUserBalance expected: 10, received: %f", reply)
|
||||
attrs = &AttrGetAccount{Tenant: "cgrates.org", Account: "dan2", BalanceType: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceType+attrs.Direction].GetTotalValue() != 10 {
|
||||
t.Errorf("Calling ApierV1.GetAccount expected: 10, received: %f", reply)
|
||||
}
|
||||
attrs = &AttrGetUserBalance{Tenant: "cgrates.org", Account: "dan3", BalanceId: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetUserBalance", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetUserBalance: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceId+attrs.Direction].GetTotalValue() != 3.6 {
|
||||
t.Errorf("Calling ApierV1.GetUserBalance expected: 3.6, received: %f", reply)
|
||||
attrs = &AttrGetAccount{Tenant: "cgrates.org", Account: "dan3", BalanceType: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceType+attrs.Direction].GetTotalValue() != 3.6 {
|
||||
t.Errorf("Calling ApierV1.GetAccount expected: 3.6, received: %f", reply)
|
||||
}
|
||||
attrs = &AttrGetUserBalance{Tenant: "cgrates.org", Account: "dan6", BalanceId: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetUserBalance", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetUserBalance: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceId+attrs.Direction].GetTotalValue() != 1 {
|
||||
t.Errorf("Calling ApierV1.GetUserBalance expected: 1, received: %f", reply)
|
||||
attrs = &AttrGetAccount{Tenant: "cgrates.org", Account: "dan6", BalanceType: "*monetary", Direction: "*out"}
|
||||
if err := rater.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.GetAccount: ", err.Error())
|
||||
} else if reply.BalanceMap[attrs.BalanceType+attrs.Direction].GetTotalValue() != 1 {
|
||||
t.Errorf("Calling ApierV1.GetAccount expected: 1, received: %f", reply)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1160,13 +1160,13 @@ func TestTriggersExecute(t *testing.T) {
|
||||
return
|
||||
}
|
||||
reply := ""
|
||||
attrs := &AttrSetAccount{Tenant: "cgrates.org", Direction: "*out", Account: "dan8", Type: "*prepaid"}
|
||||
attrs := &AttrSetAccount{Tenant: "cgrates.org", Direction: "*out", Account: "dan8"}
|
||||
if err := rater.Call("ApierV1.SetAccount", attrs, &reply); err != nil {
|
||||
t.Error("Got error on ApierV1.SetAccount: ", err.Error())
|
||||
} else if reply != "OK" {
|
||||
t.Errorf("Calling ApierV1.SetAccount received: %s", reply)
|
||||
}
|
||||
attrAddBlnc := &AttrAddBalance{Tenant: "cgrates.org", Account: "1008", BalanceId: "*monetary", Direction: "*out", Value: 2}
|
||||
attrAddBlnc := &AttrAddBalance{Tenant: "cgrates.org", Account: "1008", BalanceType: "*monetary", Direction: "*out", 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" {
|
||||
|
||||
@@ -20,6 +20,8 @@ package console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/cgrates/cgrates/apier"
|
||||
)
|
||||
|
||||
@@ -36,7 +38,7 @@ type CmdAddAccount struct {
|
||||
|
||||
// name should be exec's name
|
||||
func (self *CmdAddAccount) Usage(name string) string {
|
||||
return fmt.Sprintf("\n\tUsage: cgr-console [cfg_opts...{-h}] add_account <tenant> <account> <type=prepaid|postpaid> <actiontimingsid> [<direction>]")
|
||||
return fmt.Sprintf("\n\tUsage: cgr-console [cfg_opts...{-h}] add_account <tenant> <account> <allownegative> <actiontimingsid> [<direction>]")
|
||||
}
|
||||
|
||||
// set param defaults
|
||||
@@ -55,7 +57,11 @@ func (self *CmdAddAccount) FromArgs(args []string) error {
|
||||
self.defaults()
|
||||
self.rpcParams.Tenant = args[2]
|
||||
self.rpcParams.Account = args[3]
|
||||
self.rpcParams.Type = args[4]
|
||||
if an, err := strconv.ParseBool(args[4]); err != nil {
|
||||
return fmt.Errorf("Error parsing allownegative boolean: ", args[4])
|
||||
} else {
|
||||
self.rpcParams.AllowNegative = an
|
||||
}
|
||||
self.rpcParams.ActionPlanId = args[5]
|
||||
if len(args) > 6 {
|
||||
self.rpcParams.Direction = args[6]
|
||||
|
||||
@@ -45,7 +45,7 @@ func (self *CmdAddBalance) Usage(name string) string {
|
||||
// set param defaults
|
||||
func (self *CmdAddBalance) defaults() error {
|
||||
self.rpcMethod = "ApierV1.AddBalance"
|
||||
self.rpcParams = &apier.AttrAddBalance{BalanceId: engine.CREDIT}
|
||||
self.rpcParams = &apier.AttrAddBalance{BalanceType: engine.CREDIT}
|
||||
self.rpcParams.Direction = "*out"
|
||||
return nil
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func (self *CmdAddBalance) FromArgs(args []string) error {
|
||||
}
|
||||
self.rpcParams.Value = value
|
||||
if len(args) > 5 {
|
||||
self.rpcParams.BalanceId = args[5]
|
||||
self.rpcParams.BalanceType = args[5]
|
||||
}
|
||||
if len(args) > 6 {
|
||||
self.rpcParams.DestinationId = args[6]
|
||||
|
||||
@@ -20,8 +20,9 @@ package console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cgrates/cgrates/apier"
|
||||
"strconv"
|
||||
|
||||
"github.com/cgrates/cgrates/apier"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -56,7 +57,7 @@ func (self *CmdAddTriggeredAction) FromArgs(args []string) error {
|
||||
self.defaults()
|
||||
self.rpcParams.Tenant = args[2]
|
||||
self.rpcParams.Account = args[3]
|
||||
self.rpcParams.BalanceId = args[4]
|
||||
self.rpcParams.BalanceType = args[4]
|
||||
thresholdvalue, err := strconv.ParseFloat(args[5], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -26,14 +26,14 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
commands["get_balances"] = &CmdGetBalances{}
|
||||
commands["get_account"] = &CmdGetBalances{}
|
||||
}
|
||||
|
||||
// Commander implementation
|
||||
type CmdGetBalances struct {
|
||||
rpcMethod string
|
||||
rpcParams *apier.AttrGetUserBalance
|
||||
rpcResult *engine.UserBalance
|
||||
rpcParams *apier.AttrGetAccount
|
||||
rpcResult *engine.Account
|
||||
}
|
||||
|
||||
// name should be exec's name
|
||||
@@ -43,8 +43,8 @@ func (self *CmdGetBalances) Usage(name string) string {
|
||||
|
||||
// set param defaults
|
||||
func (self *CmdGetBalances) defaults() error {
|
||||
self.rpcMethod = "ApierV1.GetUserBalance"
|
||||
self.rpcParams = &apier.AttrGetUserBalance{BalanceId: engine.CREDIT}
|
||||
self.rpcMethod = "ApierV1.GetAccount"
|
||||
self.rpcParams = &apier.AttrGetAccount{BalanceType: engine.CREDIT}
|
||||
self.rpcParams.Direction = "*out"
|
||||
return nil
|
||||
}
|
||||
60
data/vagrant/Vagrantfile
vendored
Normal file
60
data/vagrant/Vagrantfile
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
||||
VAGRANTFILE_API_VERSION = "2"
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
# All Vagrant configuration is done here. The most common configuration
|
||||
# options are documented and commented below. For a complete reference,
|
||||
# please see the online documentation at vagrantup.com.
|
||||
|
||||
# Every Vagrant virtual environment requires a box to build off of.
|
||||
config.vm.box = "debian74_64"
|
||||
config.vm.box_url = "https://s3-eu-west-1.amazonaws.com/ffuenf-vagrant-boxes/debian/debian-7.4.0-amd64_virtualbox.box"
|
||||
config.vm.network :public_network
|
||||
|
||||
|
||||
# Create a forwarded port mapping which allows access to a specific port
|
||||
# within the machine from a port on the host machine. In the example below,
|
||||
# accessing "localhost:8080" will access port 80 on the guest machine.
|
||||
# config.vm.network :forwarded_port, guest: 80, host: 8080
|
||||
|
||||
# Create a private network, which allows host-only access to the machine
|
||||
# using a specific IP.
|
||||
# config.vm.network :private_network, ip: "192.168.33.10"
|
||||
|
||||
# Create a public network, which generally matched to bridged network.
|
||||
# Bridged networks make the machine appear as another physical device on
|
||||
# your network.
|
||||
# config.vm.network :public_network
|
||||
|
||||
# If true, then any SSH connections made will enable agent forwarding.
|
||||
# Default value: false
|
||||
# config.ssh.forward_agent = true
|
||||
|
||||
# Share an additional folder to the guest VM. The first argument is
|
||||
# the path on the host to the actual folder. The second argument is
|
||||
# the path on the guest to mount the folder. And the optional third
|
||||
# argument is a set of non-required options.
|
||||
# config.vm.synced_folder "../data", "/vagrant_data"
|
||||
|
||||
# Provider-specific configuration so you can fine-tune various
|
||||
# backing providers for Vagrant. These expose provider-specific options.
|
||||
# Example for VirtualBox:
|
||||
#
|
||||
# config.vm.provider :virtualbox do |vb|
|
||||
# # Don't boot with headless mode
|
||||
# vb.gui = true
|
||||
#
|
||||
# # Use VBoxManage to customize the VM. For example to change memory:
|
||||
# vb.customize ["modifyvm", :id, "--memory", "1024"]
|
||||
# end
|
||||
#
|
||||
# View the documentation for the provider you're using for more
|
||||
# information on available options.
|
||||
config.vm.provision "ansible" do |ansible|
|
||||
ansible.playbook = "ansible_golang_release.yml"
|
||||
#ansible.verbose = "vvvv"
|
||||
end
|
||||
end
|
||||
71
data/vagrant/ansible_golang_release.yml
Normal file
71
data/vagrant/ansible_golang_release.yml
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
|
||||
- hosts: all
|
||||
user: vagrant
|
||||
sudo: yes
|
||||
vars:
|
||||
root_db_password: CGRateS.org
|
||||
|
||||
tasks:
|
||||
- name: install dependency
|
||||
apt: pkg={{ item }} state=latest
|
||||
with_items:
|
||||
- git
|
||||
- bzr
|
||||
- redis-server
|
||||
- mysql-server
|
||||
- python-pycurl
|
||||
- python-mysqldb
|
||||
- mercurial
|
||||
|
||||
- name: add freeswitch gpg key
|
||||
command: gpg --keyserver pool.sks-keyservers.net --recv-key D76EDC7725E010CF
|
||||
|
||||
- name: add freeswitch apt key
|
||||
shell: gpg -a --export D76EDC7725E010CF | sudo apt-key add -
|
||||
|
||||
- name: add freeswitch apt repo
|
||||
apt_repository: repo='deb http://files.freeswitch.org/repo/deb/debian/ wheezy main' state=present
|
||||
|
||||
- name: install freeswitch
|
||||
apt: pkg={{ item }} update_cache=yes state=latest
|
||||
with_items:
|
||||
- freeswitch-meta-vanilla
|
||||
- freeswitch-mod-json-cdr
|
||||
|
||||
- name: add cgrates apt-key
|
||||
apt_key: url=http://apt.itsyscom.com/conf/cgrates.gpg.key state=present
|
||||
|
||||
- name: add cgrates repo
|
||||
apt_repository: repo='deb http://apt.itsyscom.com/debian wheezy main' state=present
|
||||
|
||||
- name: install cgrates
|
||||
apt: pkg=cgrates update_cache=yes state=latest
|
||||
|
||||
- name: update mysql root password for root account
|
||||
mysql_user: name=root host=localhost password={{ root_db_password }}
|
||||
|
||||
- name: copy .my.cnf
|
||||
template: src=my.cnf dest=/root/.my.cnf mode=0600
|
||||
|
||||
- name: setup database tables
|
||||
shell: chdir=/usr/share/cgrates/storage/mysql ./setup_cgr_db.sh root {{ root_db_password }} localhost
|
||||
|
||||
- hosts: all
|
||||
user: vagrant
|
||||
|
||||
tasks:
|
||||
- name: get golang
|
||||
get_url: url=http://go.googlecode.com/files/go1.2.linux-amd64.tar.gz dest=~/go1.2.linux-amd64.tar.gz
|
||||
|
||||
- name: unpack go
|
||||
command: chdir=~/ tar xvf go1.2.linux-amd64.tar.gz
|
||||
|
||||
- name: delete golang archive
|
||||
file: path=~/go1.2.linux-amd64.tar.gz state=absent
|
||||
|
||||
- name: copy bashrc
|
||||
copy: src=bashrc dest=~/.bashrc
|
||||
|
||||
- name: get cgrates
|
||||
shell: GOROOT=~/go GOPATH=~/go_home ~/go/bin/go get -u -v github.com/cgrates/cgrates
|
||||
115
data/vagrant/bashrc
Normal file
115
data/vagrant/bashrc
Normal file
@@ -0,0 +1,115 @@
|
||||
# ~/.bashrc: executed by bash(1) for non-login shells.
|
||||
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
|
||||
# for examples
|
||||
|
||||
# If not running interactively, don't do anything
|
||||
case $- in
|
||||
*i*) ;;
|
||||
*) return;;
|
||||
esac
|
||||
|
||||
# don't put duplicate lines or lines starting with space in the history.
|
||||
# See bash(1) for more options
|
||||
HISTCONTROL=ignoreboth
|
||||
|
||||
# append to the history file, don't overwrite it
|
||||
shopt -s histappend
|
||||
|
||||
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
|
||||
HISTSIZE=1000
|
||||
HISTFILESIZE=2000
|
||||
|
||||
# check the window size after each command and, if necessary,
|
||||
# update the values of LINES and COLUMNS.
|
||||
shopt -s checkwinsize
|
||||
|
||||
# If set, the pattern "**" used in a pathname expansion context will
|
||||
# match all files and zero or more directories and subdirectories.
|
||||
#shopt -s globstar
|
||||
|
||||
# make less more friendly for non-text input files, see lesspipe(1)
|
||||
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
|
||||
|
||||
# set variable identifying the chroot you work in (used in the prompt below)
|
||||
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
|
||||
debian_chroot=$(cat /etc/debian_chroot)
|
||||
fi
|
||||
|
||||
# set a fancy prompt (non-color, unless we know we "want" color)
|
||||
case "$TERM" in
|
||||
xterm-color) color_prompt=yes;;
|
||||
esac
|
||||
|
||||
# uncomment for a colored prompt, if the terminal has the capability; turned
|
||||
# off by default to not distract the user: the focus in a terminal window
|
||||
# should be on the output of commands, not on the prompt
|
||||
#force_color_prompt=yes
|
||||
|
||||
if [ -n "$force_color_prompt" ]; then
|
||||
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
|
||||
# We have color support; assume it's compliant with Ecma-48
|
||||
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
|
||||
# a case would tend to support setf rather than setaf.)
|
||||
color_prompt=yes
|
||||
else
|
||||
color_prompt=
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$color_prompt" = yes ]; then
|
||||
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
|
||||
else
|
||||
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
||||
fi
|
||||
unset color_prompt force_color_prompt
|
||||
|
||||
# If this is an xterm set the title to user@host:dir
|
||||
case "$TERM" in
|
||||
xterm*|rxvt*)
|
||||
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# enable color support of ls and also add handy aliases
|
||||
if [ -x /usr/bin/dircolors ]; then
|
||||
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
|
||||
alias ls='ls --color=auto'
|
||||
#alias dir='dir --color=auto'
|
||||
#alias vdir='vdir --color=auto'
|
||||
|
||||
#alias grep='grep --color=auto'
|
||||
#alias fgrep='fgrep --color=auto'
|
||||
#alias egrep='egrep --color=auto'
|
||||
fi
|
||||
|
||||
# some more ls aliases
|
||||
#alias ll='ls -l'
|
||||
#alias la='ls -A'
|
||||
#alias l='ls -CF'
|
||||
|
||||
# Alias definitions.
|
||||
# You may want to put all your additions into a separate file like
|
||||
# ~/.bash_aliases, instead of adding them here directly.
|
||||
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
|
||||
|
||||
if [ -f ~/.bash_aliases ]; then
|
||||
. ~/.bash_aliases
|
||||
fi
|
||||
|
||||
# enable programmable completion features (you don't need to enable
|
||||
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
|
||||
# sources /etc/bash.bashrc).
|
||||
if ! shopt -oq posix; then
|
||||
if [ -f /usr/share/bash-completion/bash_completion ]; then
|
||||
. /usr/share/bash-completion/bash_completion
|
||||
elif [ -f /etc/bash_completion ]; then
|
||||
. /etc/bash_completion
|
||||
fi
|
||||
fi
|
||||
|
||||
export GOROOT=$HOME/go
|
||||
export GOPATH=$HOME/go_home
|
||||
|
||||
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
|
||||
3
data/vagrant/my.cnf
Normal file
3
data/vagrant/my.cnf
Normal file
@@ -0,0 +1,3 @@
|
||||
[client]
|
||||
user=root
|
||||
password={{ root_db_password }}
|
||||
3
data/vagrant/vagrant_ansible_inventory_default
Normal file
3
data/vagrant/vagrant_ansible_inventory_default
Normal file
@@ -0,0 +1,3 @@
|
||||
# Generated by Vagrant
|
||||
|
||||
default ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222
|
||||
@@ -30,8 +30,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
UB_TYPE_POSTPAID = "*postpaid"
|
||||
UB_TYPE_PREPAID = "*prepaid"
|
||||
// Direction type
|
||||
INBOUND = "*in"
|
||||
OUTBOUND = "*out"
|
||||
@@ -59,23 +57,23 @@ var (
|
||||
Structure containing information about user's credit (minutes, cents, sms...).'
|
||||
This can represent a user or a shared group.
|
||||
*/
|
||||
type UserBalance struct {
|
||||
type Account struct {
|
||||
Id string
|
||||
Type string // prepaid-postpaid
|
||||
BalanceMap map[string]BalanceChain
|
||||
UnitCounters []*UnitsCounter
|
||||
ActionTriggers ActionTriggerPriotityList
|
||||
Groups GroupLinks // user info about groups
|
||||
// group information
|
||||
UserIds []string // group info about users
|
||||
Disabled bool
|
||||
UserIds []string // group info about users
|
||||
AllowNegative bool
|
||||
Disabled bool
|
||||
}
|
||||
|
||||
// Returns user's available minutes for the specified destination
|
||||
func (ub *UserBalance) getCreditForPrefix(cd *CallDescriptor) (duration time.Duration, credit float64, balances BalanceChain) {
|
||||
|
||||
func (ub *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duration, credit float64, balances BalanceChain) {
|
||||
credit = ub.getBalancesForPrefix(cd.Destination, ub.BalanceMap[CREDIT+cd.Direction], "").GetTotalValue()
|
||||
balances = ub.getBalancesForPrefix(cd.Destination, ub.BalanceMap[MINUTES+cd.Direction], "")
|
||||
|
||||
for _, b := range balances {
|
||||
d, c := b.GetMinutesForCredit(cd, credit)
|
||||
credit = c
|
||||
@@ -86,7 +84,7 @@ func (ub *UserBalance) getCreditForPrefix(cd *CallDescriptor) (duration time.Dur
|
||||
|
||||
// Debits some amount of user's specified balance adding the balance if it does not exists.
|
||||
// Returns the remaining credit in user's balance.
|
||||
func (ub *UserBalance) debitBalanceAction(a *Action) error {
|
||||
func (ub *Account) debitBalanceAction(a *Action) error {
|
||||
if a == nil {
|
||||
return errors.New("nil minute action!")
|
||||
}
|
||||
@@ -94,10 +92,10 @@ func (ub *UserBalance) debitBalanceAction(a *Action) error {
|
||||
a.Balance.Uuid = utils.GenUUID()
|
||||
}
|
||||
if ub.BalanceMap == nil {
|
||||
ub.BalanceMap = make(map[string]BalanceChain, 0)
|
||||
ub.BalanceMap = make(map[string]BalanceChain, 1)
|
||||
}
|
||||
found := false
|
||||
id := a.BalanceId + a.Direction
|
||||
id := a.BalanceType + a.Direction
|
||||
for _, b := range ub.BalanceMap[id] {
|
||||
if b.IsExpired() {
|
||||
continue // we can clean expired balances balances here
|
||||
@@ -108,9 +106,8 @@ func (ub *UserBalance) debitBalanceAction(a *Action) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
// if it is not found and the Seconds are negative (topup)
|
||||
// then we add it to the list
|
||||
if !found && a.Balance.Value <= 0 {
|
||||
// if it is not found then we add it to the list
|
||||
if !found {
|
||||
a.Balance.Value = -a.Balance.Value
|
||||
ub.BalanceMap[id] = append(ub.BalanceMap[id], a.Balance)
|
||||
if a.Balance.SharedGroup != "" {
|
||||
@@ -130,10 +127,10 @@ func (ub *UserBalance) debitBalanceAction(a *Action) error {
|
||||
return nil //ub.BalanceMap[id].GetTotalValue()
|
||||
}
|
||||
|
||||
func (ub *UserBalance) getBalancesForPrefix(prefix string, balances BalanceChain, sharedGroup string) BalanceChain {
|
||||
func (ub *Account) getBalancesForPrefix(prefix string, balances BalanceChain, sharedGroup string) BalanceChain {
|
||||
var usefulBalances BalanceChain
|
||||
for _, b := range balances {
|
||||
if b.IsExpired() || (ub.Type != UB_TYPE_POSTPAID && b.Value <= 0) {
|
||||
if b.IsExpired() || (ub.AllowNegative == false && b.Value <= 0) {
|
||||
continue
|
||||
}
|
||||
if b.SharedGroup != sharedGroup {
|
||||
@@ -142,7 +139,7 @@ func (ub *UserBalance) getBalancesForPrefix(prefix string, balances BalanceChain
|
||||
if b.SharedGroup != "" {
|
||||
// we are asking for balances from a sharing user so
|
||||
// attach ub info to the balance
|
||||
b.userBalance = ub
|
||||
b.account = ub
|
||||
}
|
||||
if b.DestinationId != "" && b.DestinationId != utils.ANY {
|
||||
for _, p := range utils.SplitPrefix(prefix, MIN_PREFIX_MATCH) {
|
||||
@@ -169,11 +166,10 @@ func (ub *UserBalance) getBalancesForPrefix(prefix string, balances BalanceChain
|
||||
return usefulBalances
|
||||
}
|
||||
|
||||
func (ub *UserBalance) debitCreditBalance(cc *CallCost, count bool) (err error) {
|
||||
func (ub *Account) debitCreditBalance(cc *CallCost, count bool) (err error) {
|
||||
usefulMinuteBalances := ub.getBalancesForPrefix(cc.Destination, ub.BalanceMap[MINUTES+cc.Direction], "")
|
||||
usefulMoneyBalances := ub.getBalancesForPrefix(cc.Destination, ub.BalanceMap[CREDIT+cc.Direction], "")
|
||||
defaultMoneyBalance := ub.GetDefaultMoneyBalance(cc.Direction)
|
||||
|
||||
// debit minutes
|
||||
for _, balance := range usefulMinuteBalances {
|
||||
balance.DebitMinutes(cc, count, ub, usefulMoneyBalances)
|
||||
@@ -231,7 +227,7 @@ func (ub *UserBalance) debitCreditBalance(cc *CallCost, count bool) (err error)
|
||||
cost := increment.Cost
|
||||
defaultMoneyBalance.Value -= cost
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: cost, DestinationId: cc.Destination}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: cost, DestinationId: cc.Destination}})
|
||||
}
|
||||
err = errors.New("not enough credit")
|
||||
}
|
||||
@@ -246,7 +242,7 @@ CONNECT_FEE:
|
||||
b.Value -= amount
|
||||
// the conect fee is not refundable!
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationId: cc.Destination}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationId: cc.Destination}})
|
||||
}
|
||||
connectFeePaid = true
|
||||
break
|
||||
@@ -258,14 +254,14 @@ CONNECT_FEE:
|
||||
defaultMoneyBalance.Value -= amount
|
||||
// the conect fee is not refundable!
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationId: cc.Destination}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationId: cc.Destination}})
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (ub *UserBalance) debitMinutesFromSharedBalances(sharedGroupName string, cc *CallCost, moneyBalances BalanceChain, count bool) {
|
||||
func (ub *Account) debitMinutesFromSharedBalances(sharedGroupName string, cc *CallCost, moneyBalances BalanceChain, count bool) {
|
||||
sharedGroup, err := accountingStorage.GetSharedGroup(sharedGroupName, false)
|
||||
if err != nil {
|
||||
Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sharedGroupName))
|
||||
@@ -279,7 +275,7 @@ func (ub *UserBalance) debitMinutesFromSharedBalances(sharedGroupName string, cc
|
||||
continue
|
||||
}
|
||||
|
||||
nUb, err := accountingStorage.GetUserBalance(ubId)
|
||||
nUb, err := accountingStorage.GetAccount(ubId)
|
||||
if err != nil {
|
||||
Logger.Warning(fmt.Sprintf("Could not get user balance: %s", ubId))
|
||||
}
|
||||
@@ -293,9 +289,9 @@ func (ub *UserBalance) debitMinutesFromSharedBalances(sharedGroupName string, cc
|
||||
for sharedBalance := sharedGroup.PopBalanceByStrategy(ub.Id, &allMinuteSharedBalances); sharedBalance != nil; sharedBalance = sharedGroup.PopBalanceByStrategy(ub.Id,
|
||||
&allMinuteSharedBalances) {
|
||||
initialValue := sharedBalance.Value
|
||||
sharedBalance.DebitMinutes(cc, count, sharedBalance.userBalance, moneyBalances)
|
||||
sharedBalance.DebitMinutes(cc, count, sharedBalance.account, moneyBalances)
|
||||
if sharedBalance.Value != initialValue {
|
||||
accountingStorage.SetUserBalance(sharedBalance.userBalance)
|
||||
accountingStorage.SetAccount(sharedBalance.account)
|
||||
}
|
||||
if cc.IsPaid() {
|
||||
return 0, nil
|
||||
@@ -305,7 +301,7 @@ func (ub *UserBalance) debitMinutesFromSharedBalances(sharedGroupName string, cc
|
||||
})
|
||||
}
|
||||
|
||||
func (ub *UserBalance) debitMoneyFromSharedBalances(sharedGroupName string, cc *CallCost, count bool) {
|
||||
func (ub *Account) debitMoneyFromSharedBalances(sharedGroupName string, cc *CallCost, count bool) {
|
||||
sharedGroup, err := accountingStorage.GetSharedGroup(sharedGroupName, false)
|
||||
if err != nil {
|
||||
Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sharedGroup))
|
||||
@@ -319,7 +315,7 @@ func (ub *UserBalance) debitMoneyFromSharedBalances(sharedGroupName string, cc *
|
||||
continue
|
||||
}
|
||||
|
||||
nUb, err := accountingStorage.GetUserBalance(ubId)
|
||||
nUb, err := accountingStorage.GetAccount(ubId)
|
||||
if err != nil {
|
||||
Logger.Warning(fmt.Sprintf("Could not get user balance: %s", ubId))
|
||||
}
|
||||
@@ -332,9 +328,9 @@ func (ub *UserBalance) debitMoneyFromSharedBalances(sharedGroupName string, cc *
|
||||
}
|
||||
for sharedBalance := sharedGroup.PopBalanceByStrategy(ub.Id, &allMoneySharedBalances); sharedBalance != nil; sharedBalance = sharedGroup.PopBalanceByStrategy(ub.Id, &allMoneySharedBalances) {
|
||||
initialValue := sharedBalance.Value
|
||||
sharedBalance.DebitMoney(cc, count, sharedBalance.userBalance)
|
||||
sharedBalance.DebitMoney(cc, count, sharedBalance.account)
|
||||
if sharedBalance.Value != initialValue {
|
||||
accountingStorage.SetUserBalance(sharedBalance.userBalance)
|
||||
accountingStorage.SetAccount(sharedBalance.account)
|
||||
}
|
||||
if cc.IsPaid() {
|
||||
return 0, nil
|
||||
@@ -344,7 +340,7 @@ func (ub *UserBalance) debitMoneyFromSharedBalances(sharedGroupName string, cc *
|
||||
})
|
||||
}
|
||||
|
||||
func (ub *UserBalance) GetDefaultMoneyBalance(direction string) *Balance {
|
||||
func (ub *Account) GetDefaultMoneyBalance(direction string) *Balance {
|
||||
for _, balance := range ub.BalanceMap[CREDIT+direction] {
|
||||
if balance.IsDefault() {
|
||||
return balance
|
||||
@@ -357,7 +353,7 @@ func (ub *UserBalance) GetDefaultMoneyBalance(direction string) *Balance {
|
||||
return defaultBalance
|
||||
}
|
||||
|
||||
func (ub *UserBalance) refundIncrements(increments Increments, direction string, count bool) {
|
||||
func (ub *Account) refundIncrements(increments Increments, direction string, count bool) {
|
||||
for _, increment := range increments {
|
||||
var balance *Balance
|
||||
if increment.BalanceInfo.MinuteBalanceUuid != "" {
|
||||
@@ -366,7 +362,7 @@ func (ub *UserBalance) refundIncrements(increments Increments, direction string,
|
||||
}
|
||||
balance.Value += increment.Duration.Seconds()
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: MINUTES, Direction: direction, Balance: &Balance{Value: -increment.Duration.Seconds()}})
|
||||
ub.countUnits(&Action{BalanceType: MINUTES, Direction: direction, Balance: &Balance{Value: -increment.Duration.Seconds()}})
|
||||
}
|
||||
}
|
||||
// check money too
|
||||
@@ -376,7 +372,7 @@ func (ub *UserBalance) refundIncrements(increments Increments, direction string,
|
||||
}
|
||||
balance.Value += increment.Cost
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: direction, Balance: &Balance{Value: -increment.Cost}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: direction, Balance: &Balance{Value: -increment.Cost}})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,16 +381,16 @@ func (ub *UserBalance) refundIncrements(increments Increments, direction string,
|
||||
/*
|
||||
Debits some amount of user's specified balance. Returns the remaining credit in user's balance.
|
||||
*/
|
||||
func (ub *UserBalance) debitGenericBalance(balanceId string, direction string, amount float64, count bool) float64 {
|
||||
func (ub *Account) debitGenericBalance(balanceId string, direction string, amount float64, count bool) float64 {
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: balanceId, Direction: direction, Balance: &Balance{Value: amount}})
|
||||
ub.countUnits(&Action{BalanceType: balanceId, Direction: direction, Balance: &Balance{Value: amount}})
|
||||
}
|
||||
ub.BalanceMap[balanceId+direction].Debit(amount)
|
||||
return ub.BalanceMap[balanceId+direction].GetTotalValue()
|
||||
}
|
||||
|
||||
// Scans the action trigers and execute the actions for which trigger is met
|
||||
func (ub *UserBalance) executeActionTriggers(a *Action) {
|
||||
func (ub *Account) executeActionTriggers(a *Action) {
|
||||
ub.ActionTriggers.Sort()
|
||||
for _, at := range ub.ActionTriggers {
|
||||
if at.Executed {
|
||||
@@ -407,7 +403,7 @@ func (ub *UserBalance) executeActionTriggers(a *Action) {
|
||||
}
|
||||
if strings.Contains(at.ThresholdType, "counter") {
|
||||
for _, uc := range ub.UnitCounters {
|
||||
if uc.BalanceId == at.BalanceId {
|
||||
if uc.BalanceType == at.BalanceType {
|
||||
for _, mb := range uc.Balances {
|
||||
if strings.Contains(at.ThresholdType, "*max") {
|
||||
if mb.MatchDestination(at.DestinationId) && mb.Value >= at.ThresholdValue {
|
||||
@@ -424,7 +420,7 @@ func (ub *UserBalance) executeActionTriggers(a *Action) {
|
||||
}
|
||||
}
|
||||
} else { // BALANCE
|
||||
for _, b := range ub.BalanceMap[at.BalanceId+at.Direction] {
|
||||
for _, b := range ub.BalanceMap[at.BalanceType+at.Direction] {
|
||||
if strings.Contains(at.ThresholdType, "*max") {
|
||||
if b.MatchDestination(at.DestinationId) && b.Value >= at.ThresholdValue {
|
||||
// run the actions
|
||||
@@ -443,7 +439,7 @@ func (ub *UserBalance) executeActionTriggers(a *Action) {
|
||||
|
||||
// Mark all action trigers as ready for execution
|
||||
// If the action is not nil it acts like a filter
|
||||
func (ub *UserBalance) resetActionTriggers(a *Action) {
|
||||
func (ub *Account) resetActionTriggers(a *Action) {
|
||||
for _, at := range ub.ActionTriggers {
|
||||
if !at.Match(a) {
|
||||
continue
|
||||
@@ -454,13 +450,13 @@ func (ub *UserBalance) resetActionTriggers(a *Action) {
|
||||
}
|
||||
|
||||
// Returns the unit counter that matches the specified action type
|
||||
func (ub *UserBalance) getUnitCounter(a *Action) *UnitsCounter {
|
||||
func (ub *Account) getUnitCounter(a *Action) *UnitsCounter {
|
||||
for _, uc := range ub.UnitCounters {
|
||||
direction := a.Direction
|
||||
if direction == "" {
|
||||
direction = OUTBOUND
|
||||
}
|
||||
if uc.BalanceId == a.BalanceId && uc.Direction == direction {
|
||||
if uc.BalanceType == a.BalanceType && uc.Direction == direction {
|
||||
return uc
|
||||
}
|
||||
}
|
||||
@@ -469,7 +465,7 @@ func (ub *UserBalance) getUnitCounter(a *Action) *UnitsCounter {
|
||||
|
||||
// Increments the counter for the type specified in the received Action
|
||||
// with the actions values
|
||||
func (ub *UserBalance) countUnits(a *Action) {
|
||||
func (ub *Account) countUnits(a *Action) {
|
||||
unitsCounter := ub.getUnitCounter(a)
|
||||
// if not found add the counter
|
||||
if unitsCounter == nil {
|
||||
@@ -477,7 +473,7 @@ func (ub *UserBalance) countUnits(a *Action) {
|
||||
if direction == "" {
|
||||
direction = OUTBOUND
|
||||
}
|
||||
unitsCounter = &UnitsCounter{BalanceId: a.BalanceId, Direction: direction}
|
||||
unitsCounter = &UnitsCounter{BalanceType: a.BalanceType, Direction: direction}
|
||||
ub.UnitCounters = append(ub.UnitCounters, unitsCounter)
|
||||
}
|
||||
|
||||
@@ -485,8 +481,8 @@ func (ub *UserBalance) countUnits(a *Action) {
|
||||
ub.executeActionTriggers(nil)
|
||||
}
|
||||
|
||||
// Create minute counters for all triggered actions that have actions operating on minute buckets
|
||||
func (ub *UserBalance) initCounters() {
|
||||
// Create minute counters for all triggered actions that have actions opertating on balances
|
||||
func (ub *Account) initCounters() {
|
||||
ucTempMap := make(map[string]*UnitsCounter, 2)
|
||||
for _, at := range ub.ActionTriggers {
|
||||
acs, err := accountingStorage.GetActions(at.ActionsId, false)
|
||||
@@ -501,7 +497,7 @@ func (ub *UserBalance) initCounters() {
|
||||
}
|
||||
uc, exists := ucTempMap[direction]
|
||||
if !exists {
|
||||
uc = &UnitsCounter{BalanceId: a.BalanceId, Direction: direction}
|
||||
uc = &UnitsCounter{BalanceType: a.BalanceType, Direction: direction}
|
||||
ucTempMap[direction] = uc
|
||||
uc.Balances = BalanceChain{}
|
||||
ub.UnitCounters = append(ub.UnitCounters, uc)
|
||||
@@ -515,7 +511,7 @@ func (ub *UserBalance) initCounters() {
|
||||
}
|
||||
}
|
||||
|
||||
func (ub *UserBalance) CleanExpiredBalancesAndBuckets() {
|
||||
func (ub *Account) CleanExpiredBalancesAndBuckets() {
|
||||
for key, bm := range ub.BalanceMap {
|
||||
for i := 0; i < len(bm); i++ {
|
||||
if bm[i].IsExpired() {
|
||||
@@ -528,7 +524,7 @@ func (ub *UserBalance) CleanExpiredBalancesAndBuckets() {
|
||||
}
|
||||
|
||||
// returns the shared groups that this user balance belnongs to
|
||||
func (ub *UserBalance) GetSharedGroups() (groups []string) {
|
||||
func (ub *Account) GetSharedGroups() (groups []string) {
|
||||
for _, balanceChain := range ub.BalanceMap {
|
||||
for _, b := range balanceChain {
|
||||
if b.SharedGroup != "" {
|
||||
@@ -28,23 +28,6 @@ var (
|
||||
RET = &Destination{Id: "RET", Prefixes: []string{"0723", "0724"}}
|
||||
)
|
||||
|
||||
func init() {
|
||||
populateTestActionsForTriggers()
|
||||
}
|
||||
|
||||
func populateTestActionsForTriggers() {
|
||||
ats := []*Action{
|
||||
&Action{ActionType: "*topup", BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}},
|
||||
&Action{ActionType: "*topup", BalanceId: MINUTES, Direction: OUTBOUND, Balance: &Balance{Weight: 20, Value: 10, DestinationId: "NAT"}},
|
||||
}
|
||||
accountingStorage.SetActions("TEST_ACTIONS", ats)
|
||||
ats1 := []*Action{
|
||||
&Action{ActionType: "*topup", BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}, Weight: 20},
|
||||
&Action{ActionType: "*reset_prepaid", Weight: 10},
|
||||
}
|
||||
accountingStorage.SetActions("TEST_ACTIONS_ORDER", ats1)
|
||||
}
|
||||
|
||||
func TestBalanceStoreRestore(t *testing.T) {
|
||||
b := &Balance{Value: 14, Weight: 1, Uuid: "test", ExpirationDate: time.Date(2013, time.July, 15, 17, 48, 0, 0, time.UTC)}
|
||||
marsh := NewCodecMsgpackMarshaler()
|
||||
@@ -95,12 +78,12 @@ func TestBalanceChainStoreRestore(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceStorageStoreRestore(t *testing.T) {
|
||||
func TestAccountStorageStoreRestore(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
accountingStorage.SetUserBalance(rifsBalance)
|
||||
ub1, err := accountingStorage.GetUserBalance("other")
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
accountingStorage.SetAccount(rifsBalance)
|
||||
ub1, err := accountingStorage.GetAccount("other")
|
||||
if err != nil || !ub1.BalanceMap[CREDIT+OUTBOUND].Equal(rifsBalance.BalanceMap[CREDIT+OUTBOUND]) {
|
||||
t.Log("UB: ", ub1)
|
||||
t.Errorf("Expected %v was %v", rifsBalance.BalanceMap[CREDIT+OUTBOUND], ub1.BalanceMap[CREDIT+OUTBOUND])
|
||||
@@ -110,7 +93,7 @@ func TestUserBalanceStorageStoreRestore(t *testing.T) {
|
||||
func TestGetSecondsForPrefix(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 200}}}}
|
||||
ub1 := &Account{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 200}}}}
|
||||
cd := &CallDescriptor{
|
||||
TOR: "0",
|
||||
Tenant: "vdf",
|
||||
@@ -133,7 +116,7 @@ func TestGetSpecialPricedSeconds(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT", RateSubject: "minu"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET", RateSubject: "minu"}
|
||||
|
||||
ub1 := &UserBalance{
|
||||
ub1 := &Account{
|
||||
Id: "OUT:CUSTOMER_1:rif",
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1, b2},
|
||||
@@ -157,12 +140,12 @@ func TestGetSpecialPricedSeconds(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceStorageStore(t *testing.T) {
|
||||
func TestAccountStorageStore(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
accountingStorage.SetUserBalance(rifsBalance)
|
||||
result, err := accountingStorage.GetUserBalance(rifsBalance.Id)
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
accountingStorage.SetAccount(rifsBalance)
|
||||
result, err := accountingStorage.GetAccount(rifsBalance.Id)
|
||||
if err != nil || rifsBalance.Id != result.Id ||
|
||||
len(rifsBalance.BalanceMap[MINUTES+OUTBOUND]) < 2 || len(result.BalanceMap[MINUTES+OUTBOUND]) < 2 ||
|
||||
!(rifsBalance.BalanceMap[MINUTES+OUTBOUND][0].Equal(result.BalanceMap[MINUTES+OUTBOUND][0])) ||
|
||||
@@ -175,7 +158,7 @@ func TestUserBalanceStorageStore(t *testing.T) {
|
||||
func TestDebitMoneyBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
result := rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, 6, false)
|
||||
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 15 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 15, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
@@ -185,7 +168,7 @@ func TestDebitMoneyBalance(t *testing.T) {
|
||||
func TestDebitAllMoneyBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, 21, false)
|
||||
result := rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, 0, false)
|
||||
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 0 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
|
||||
@@ -196,7 +179,7 @@ func TestDebitAllMoneyBalance(t *testing.T) {
|
||||
func TestDebitMoreMoneyBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
result := rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, 22, false)
|
||||
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != -1 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", -1, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
@@ -206,7 +189,7 @@ func TestDebitMoreMoneyBalance(t *testing.T) {
|
||||
func TestDebitNegativeMoneyBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
result := rifsBalance.debitGenericBalance(CREDIT, OUTBOUND, -15, false)
|
||||
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 36 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 36, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
@@ -227,7 +210,7 @@ func TestDebitCreditZeroSecond(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitCreditBalance(cc, false)
|
||||
if err != nil {
|
||||
t.Error("Error debiting balance: ", err)
|
||||
@@ -256,7 +239,7 @@ func TestDebitCreditZeroMinute(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}},
|
||||
}}
|
||||
@@ -291,7 +274,7 @@ func TestDebitCreditZeroMixedMinute(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1, b2},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}},
|
||||
}}
|
||||
@@ -330,7 +313,7 @@ func TestDebitCreditNoCredit(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
}}
|
||||
err := rifsBalance.debitCreditBalance(cc, false)
|
||||
@@ -370,7 +353,7 @@ func TestDebitCreditHasCredit(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 50}},
|
||||
}}
|
||||
@@ -407,7 +390,7 @@ func TestDebitCreditSplitMinutesMoney(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 50}},
|
||||
}}
|
||||
@@ -449,7 +432,7 @@ func TestDebitCreditMoreTimespans(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
}}
|
||||
err := rifsBalance.debitCreditBalance(cc, false)
|
||||
@@ -487,7 +470,7 @@ func TestDebitCreditMoreTimespansMixed(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1, b2},
|
||||
}}
|
||||
err := rifsBalance.debitCreditBalance(cc, false)
|
||||
@@ -525,7 +508,7 @@ func TestDebitCreditNoConectFeeCredit(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
}}
|
||||
err := rifsBalance.debitCreditBalance(cc, false)
|
||||
@@ -558,7 +541,7 @@ func TestDebitCreditMoneyOnly(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Uuid: "money", Value: 50}},
|
||||
}}
|
||||
err := rifsBalance.debitCreditBalance(cc, false)
|
||||
@@ -599,7 +582,7 @@ func TestDebitCreditSubjectMinutes(t *testing.T) {
|
||||
},
|
||||
deductConnectFee: true,
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 350}},
|
||||
}}
|
||||
@@ -641,7 +624,7 @@ func TestDebitCreditSubjectMoney(t *testing.T) {
|
||||
},
|
||||
deductConnectFee: true,
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 75, DestinationId: "NAT", RateSubject: "minu"}},
|
||||
}}
|
||||
err := rifsBalance.debitCreditBalance(cc, false)
|
||||
@@ -678,7 +661,7 @@ func TestDebitCreditSubjectMixed(t *testing.T) {
|
||||
},
|
||||
deductConnectFee: true,
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 150, RateSubject: "minu"}},
|
||||
}}
|
||||
@@ -727,7 +710,7 @@ func TestDebitCreditSubjectMixedMoreTS(t *testing.T) {
|
||||
},
|
||||
deductConnectFee: true,
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 50, RateSubject: "minu"}},
|
||||
}}
|
||||
@@ -778,7 +761,7 @@ func TestDebitCreditSubjectMixedPartPay(t *testing.T) {
|
||||
},
|
||||
deductConnectFee: true,
|
||||
}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{b1},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 75, RateSubject: "minu"}},
|
||||
}}
|
||||
@@ -809,7 +792,7 @@ func TestDebitCreditSubjectMixedPartPay(t *testing.T) {
|
||||
func TestDebitSMSBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
result := rifsBalance.debitGenericBalance(SMS, OUTBOUND, 12, false)
|
||||
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 88 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 88, rifsBalance.BalanceMap[SMS+OUTBOUND])
|
||||
@@ -819,7 +802,7 @@ func TestDebitSMSBalance(t *testing.T) {
|
||||
func TestDebitAllSMSBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
result := rifsBalance.debitGenericBalance(SMS, OUTBOUND, 100, false)
|
||||
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 0 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 0, rifsBalance.BalanceMap[SMS+OUTBOUND])
|
||||
@@ -829,7 +812,7 @@ func TestDebitAllSMSBalance(t *testing.T) {
|
||||
func TestDebitMoreSMSBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
result := rifsBalance.debitGenericBalance(SMS, OUTBOUND, 110, false)
|
||||
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != -10 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", -10, rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value)
|
||||
@@ -839,47 +822,47 @@ func TestDebitMoreSMSBalance(t *testing.T) {
|
||||
func TestDebitNegativeSMSBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
result := rifsBalance.debitGenericBalance(SMS, OUTBOUND, -15, false)
|
||||
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 115 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 115, rifsBalance.BalanceMap[SMS+OUTBOUND])
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalancedebitBalance(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS: BalanceChain{&Balance{Value: 14}}, TRAFFIC: BalanceChain{&Balance{Value: 1204}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
func TestAccountdebitBalance(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "rif",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{SMS: BalanceChain{&Balance{Value: 14}}, TRAFFIC: BalanceChain{&Balance{Value: 1204}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
}
|
||||
newMb := &Balance{Weight: 20, DestinationId: "NEW"}
|
||||
a := &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: newMb}
|
||||
a := &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: newMb}
|
||||
ub.debitBalanceAction(a)
|
||||
if len(ub.BalanceMap[MINUTES+OUTBOUND]) != 3 || ub.BalanceMap[MINUTES+OUTBOUND][2] != newMb {
|
||||
t.Error("Error adding minute bucket!", len(ub.BalanceMap[MINUTES+OUTBOUND]), ub.BalanceMap[MINUTES+OUTBOUND])
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalancedebitBalanceExists(t *testing.T) {
|
||||
func TestAccountdebitBalanceExists(t *testing.T) {
|
||||
|
||||
ub := &UserBalance{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 15, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
ub := &Account{
|
||||
Id: "rif",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 15, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
}
|
||||
newMb := &Balance{Value: -10, Weight: 20, DestinationId: "NAT"}
|
||||
a := &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: newMb}
|
||||
a := &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: newMb}
|
||||
ub.debitBalanceAction(a)
|
||||
if len(ub.BalanceMap[MINUTES+OUTBOUND]) != 2 || ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 25 {
|
||||
t.Error("Error adding minute bucket!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceAddMinuteNil(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
func TestAccountAddMinuteNil(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "rif",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
}
|
||||
ub.debitBalanceAction(nil)
|
||||
if len(ub.BalanceMap[MINUTES+OUTBOUND]) != 2 {
|
||||
@@ -887,80 +870,80 @@ func TestUserBalanceAddMinuteNil(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceAddMinutBucketEmpty(t *testing.T) {
|
||||
func TestAccountAddMinutBucketEmpty(t *testing.T) {
|
||||
mb1 := &Balance{Value: -10, DestinationId: "NAT"}
|
||||
mb2 := &Balance{Value: -10, DestinationId: "NAT"}
|
||||
mb3 := &Balance{Value: -10, DestinationId: "OTHER"}
|
||||
ub := &UserBalance{}
|
||||
a := &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: mb1}
|
||||
ub := &Account{}
|
||||
a := &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: mb1}
|
||||
ub.debitBalanceAction(a)
|
||||
if len(ub.BalanceMap[MINUTES+OUTBOUND]) != 1 {
|
||||
t.Error("Error adding minute bucket: ", ub.BalanceMap[MINUTES+OUTBOUND])
|
||||
}
|
||||
a = &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: mb2}
|
||||
a = &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: mb2}
|
||||
ub.debitBalanceAction(a)
|
||||
if len(ub.BalanceMap[MINUTES+OUTBOUND]) != 1 || ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 20 {
|
||||
t.Error("Error adding minute bucket: ", ub.BalanceMap[MINUTES+OUTBOUND])
|
||||
}
|
||||
a = &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: mb3}
|
||||
a = &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: mb3}
|
||||
ub.debitBalanceAction(a)
|
||||
if len(ub.BalanceMap[MINUTES+OUTBOUND]) != 2 {
|
||||
t.Error("Error adding minute bucket: ", ub.BalanceMap[MINUTES+OUTBOUND])
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceExecuteTriggeredActions(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
func TestAccountExecuteTriggeredActions(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS"}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS"}},
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Balance: &Balance{Value: 1}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Balance: &Balance{Value: 1}})
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES+OUTBOUND][0].Value)
|
||||
}
|
||||
// are set to executed
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 1}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 1}})
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES+OUTBOUND][0].Value)
|
||||
}
|
||||
// we can reset them
|
||||
ub.resetActionTriggers(nil)
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 120 || ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 30 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceExecuteTriggeredActionsBalance(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
func TestAccountExecuteTriggeredActionsBalance(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 100, ThresholdType: TRIGGER_MIN_COUNTER, ActionsId: "TEST_ACTIONS"}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 100, ThresholdType: TRIGGER_MIN_COUNTER, ActionsId: "TEST_ACTIONS"}},
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Balance: &Balance{Value: 1}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Balance: &Balance{Value: 1}})
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceExecuteTriggeredActionsOrder(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
func TestAccountExecuteTriggeredActionsOrder(t *testing.T) {
|
||||
ub := &Account{
|
||||
Id: "TEST_UB_OREDER",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS_ORDER"}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS_ORDER"}},
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 1}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 1}})
|
||||
if len(ub.BalanceMap[CREDIT+OUTBOUND]) != 1 || ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 10 {
|
||||
t.Error("Error executing triggered actions in order", ub.BalanceMap[CREDIT+OUTBOUND])
|
||||
t.Error("Error executing triggered actions in order", ub.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanExpired(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB_OREDER",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{
|
||||
&Balance{ExpirationDate: time.Now().Add(10 * time.Second)},
|
||||
@@ -979,52 +962,52 @@ func TestCleanExpired(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceUnitCounting(t *testing.T) {
|
||||
ub := &UserBalance{}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceId != CREDIT || ub.UnitCounters[0].Balances[0].Value != 10 {
|
||||
func TestAccountUnitCounting(t *testing.T) {
|
||||
ub := &Account{}
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != CREDIT || ub.UnitCounters[0].Balances[0].Value != 10 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceId != CREDIT || ub.UnitCounters[0].Balances[0].Value != 20 {
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != CREDIT || ub.UnitCounters[0].Balances[0].Value != 20 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceUnitCountingOutbound(t *testing.T) {
|
||||
ub := &UserBalance{}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceId != CREDIT || ub.UnitCounters[0].Balances[0].Value != 10 {
|
||||
func TestAccountUnitCountingOutbound(t *testing.T) {
|
||||
ub := &Account{}
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != CREDIT || ub.UnitCounters[0].Balances[0].Value != 10 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceId != CREDIT || ub.UnitCounters[0].Balances[0].Value != 20 {
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != CREDIT || ub.UnitCounters[0].Balances[0].Value != 20 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceId != CREDIT || ub.UnitCounters[0].Balances[0].Value != 30 {
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != CREDIT || ub.UnitCounters[0].Balances[0].Value != 30 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceUnitCountingOutboundInbound(t *testing.T) {
|
||||
ub := &UserBalance{}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceId != CREDIT || ub.UnitCounters[0].Balances[0].Value != 10 {
|
||||
func TestAccountUnitCountingOutboundInbound(t *testing.T) {
|
||||
ub := &Account{}
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != CREDIT || ub.UnitCounters[0].Balances[0].Value != 10 {
|
||||
t.Errorf("Error counting units: %+v", ub.UnitCounters[0])
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceId != CREDIT || ub.UnitCounters[0].Balances[0].Value != 20 {
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 1 && ub.UnitCounters[0].BalanceType != CREDIT || ub.UnitCounters[0].Balances[0].Value != 20 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: INBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 2 && ub.UnitCounters[1].BalanceId != CREDIT || ub.UnitCounters[0].Balances[0].Value != 20 || ub.UnitCounters[1].Balances[0].Value != 10 {
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: INBOUND, Balance: &Balance{Value: 10}})
|
||||
if len(ub.UnitCounters) != 2 && ub.UnitCounters[1].BalanceType != CREDIT || ub.UnitCounters[0].Balances[0].Value != 20 || ub.UnitCounters[1].Balances[0].Value != 10 {
|
||||
t.Error("Error counting units")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceRefund(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
func TestAccountRefund(t *testing.T) {
|
||||
ub := &Account{
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
CREDIT + OUTBOUND: BalanceChain{
|
||||
&Balance{Uuid: "moneya", Value: 100},
|
||||
@@ -1049,6 +1032,29 @@ func TestUserBalanceRefund(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTopupAction(t *testing.T) {
|
||||
initialUb, _ := accountingStorage.GetAccount("*out:vdf:minu")
|
||||
a := &Action{
|
||||
ActionType: "*topup",
|
||||
BalanceType: CREDIT,
|
||||
Direction: OUTBOUND,
|
||||
Balance: &Balance{Value: 25, DestinationId: "RET", Weight: 20},
|
||||
}
|
||||
|
||||
at := &ActionTiming{
|
||||
AccountIds: []string{"*out:vdf:minu"},
|
||||
actions: Actions{a},
|
||||
}
|
||||
|
||||
at.Execute()
|
||||
afterUb, _ := accountingStorage.GetAccount("*out:vdf:minu")
|
||||
initialValue := initialUb.BalanceMap[CREDIT+OUTBOUND].GetTotalValue()
|
||||
afterValue := afterUb.BalanceMap[CREDIT+OUTBOUND].GetTotalValue()
|
||||
if initialValue != 50 || afterValue != 75 {
|
||||
t.Error("Bad topup before and after: ", initialValue, afterValue)
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************** Benchmarks *******************************/
|
||||
|
||||
func BenchmarkGetSecondForPrefix(b *testing.B) {
|
||||
@@ -1056,7 +1062,7 @@ func BenchmarkGetSecondForPrefix(b *testing.B) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
|
||||
ub1 := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
ub1 := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
cd := &CallDescriptor{
|
||||
Destination: "0723",
|
||||
}
|
||||
@@ -1066,20 +1072,20 @@ func BenchmarkGetSecondForPrefix(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUserBalanceStorageStoreRestore(b *testing.B) {
|
||||
func BenchmarkAccountStorageStoreRestore(b *testing.B) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
for i := 0; i < b.N; i++ {
|
||||
accountingStorage.SetUserBalance(rifsBalance)
|
||||
accountingStorage.GetUserBalance(rifsBalance.Id)
|
||||
accountingStorage.SetAccount(rifsBalance)
|
||||
accountingStorage.GetAccount(rifsBalance.Id)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGetSecondsForPrefix(b *testing.B) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
ub1 := &Account{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{MINUTES + OUTBOUND: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
cd := &CallDescriptor{
|
||||
Destination: "0723",
|
||||
}
|
||||
@@ -39,7 +39,7 @@ Structure to be filled for each tariff plan with the bonus value for received ca
|
||||
type Action struct {
|
||||
Id string
|
||||
ActionType string
|
||||
BalanceId string
|
||||
BalanceType string
|
||||
Direction string
|
||||
ExtraParameters string
|
||||
ExpirationString string
|
||||
@@ -51,10 +51,9 @@ type Action struct {
|
||||
const (
|
||||
LOG = "*log"
|
||||
RESET_TRIGGERS = "*reset_triggers"
|
||||
SET_POSTPAID = "*set_postpaid"
|
||||
RESET_POSTPAID = "*reset_postpaid"
|
||||
SET_PREPAID = "*set_prepaid"
|
||||
RESET_PREPAID = "*reset_prepaid"
|
||||
ALLOW_NEGATIVE = "*allow_negative"
|
||||
DENY_NEGATIVE = "*deny_negative"
|
||||
RESET_ACCOUNT = "*reset_account"
|
||||
TOPUP_RESET = "*topup_reset"
|
||||
TOPUP = "*topup"
|
||||
DEBIT = "*debit"
|
||||
@@ -68,7 +67,7 @@ const (
|
||||
UNLIMITED = "*unlimited"
|
||||
)
|
||||
|
||||
type actionTypeFunc func(*UserBalance, *Action) error
|
||||
type actionTypeFunc func(*Account, *Action) error
|
||||
|
||||
func getActionFunc(typ string) (actionTypeFunc, bool) {
|
||||
switch typ {
|
||||
@@ -76,14 +75,12 @@ func getActionFunc(typ string) (actionTypeFunc, bool) {
|
||||
return logAction, true
|
||||
case RESET_TRIGGERS:
|
||||
return resetTriggersAction, true
|
||||
case SET_POSTPAID:
|
||||
return setPostpaidAction, true
|
||||
case RESET_POSTPAID:
|
||||
return resetPostpaidAction, true
|
||||
case SET_PREPAID:
|
||||
return setPrepaidAction, true
|
||||
case RESET_PREPAID:
|
||||
return resetPrepaidAction, true
|
||||
case ALLOW_NEGATIVE:
|
||||
return allowNegativeAction, true
|
||||
case DENY_NEGATIVE:
|
||||
return denyNegativeAction, true
|
||||
case RESET_ACCOUNT:
|
||||
return resetAccountAction, true
|
||||
case TOPUP_RESET:
|
||||
return topupResetAction, true
|
||||
case TOPUP:
|
||||
@@ -108,68 +105,62 @@ func getActionFunc(typ string) (actionTypeFunc, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func logAction(ub *UserBalance, a *Action) (err error) {
|
||||
func logAction(ub *Account, a *Action) (err error) {
|
||||
ubMarshal, _ := json.Marshal(ub)
|
||||
Logger.Info(fmt.Sprintf("Threshold reached, balance: %s", ubMarshal))
|
||||
return
|
||||
}
|
||||
|
||||
func resetTriggersAction(ub *UserBalance, a *Action) (err error) {
|
||||
func resetTriggersAction(ub *Account, a *Action) (err error) {
|
||||
ub.resetActionTriggers(a)
|
||||
return
|
||||
}
|
||||
|
||||
func setPostpaidAction(ub *UserBalance, a *Action) (err error) {
|
||||
ub.Type = UB_TYPE_POSTPAID
|
||||
func allowNegativeAction(ub *Account, a *Action) (err error) {
|
||||
ub.AllowNegative = true
|
||||
return
|
||||
}
|
||||
|
||||
func resetPostpaidAction(ub *UserBalance, a *Action) (err error) {
|
||||
genericReset(ub)
|
||||
return setPostpaidAction(ub, a)
|
||||
}
|
||||
|
||||
func setPrepaidAction(ub *UserBalance, a *Action) (err error) {
|
||||
ub.Type = UB_TYPE_PREPAID
|
||||
func denyNegativeAction(ub *Account, a *Action) (err error) {
|
||||
ub.AllowNegative = false
|
||||
return
|
||||
}
|
||||
|
||||
func resetPrepaidAction(ub *UserBalance, a *Action) (err error) {
|
||||
genericReset(ub)
|
||||
return setPrepaidAction(ub, a)
|
||||
func resetAccountAction(ub *Account, a *Action) (err error) {
|
||||
return genericReset(ub)
|
||||
}
|
||||
|
||||
func topupResetAction(ub *UserBalance, a *Action) (err error) {
|
||||
func topupResetAction(ub *Account, a *Action) (err error) {
|
||||
if ub.BalanceMap == nil { // Init the map since otherwise will get error if nil
|
||||
ub.BalanceMap = make(map[string]BalanceChain, 0)
|
||||
}
|
||||
ub.BalanceMap[a.BalanceId+a.Direction] = BalanceChain{}
|
||||
ub.BalanceMap[a.BalanceType+a.Direction] = BalanceChain{}
|
||||
genericMakeNegative(a)
|
||||
genericDebit(ub, a)
|
||||
return
|
||||
}
|
||||
|
||||
func topupAction(ub *UserBalance, a *Action) (err error) {
|
||||
func topupAction(ub *Account, a *Action) (err error) {
|
||||
genericMakeNegative(a)
|
||||
genericDebit(ub, a)
|
||||
return
|
||||
}
|
||||
|
||||
func debitAction(ub *UserBalance, a *Action) (err error) {
|
||||
func debitAction(ub *Account, a *Action) (err error) {
|
||||
return genericDebit(ub, a)
|
||||
}
|
||||
|
||||
func resetCounterAction(ub *UserBalance, a *Action) (err error) {
|
||||
func resetCounterAction(ub *Account, a *Action) (err error) {
|
||||
uc := ub.getUnitCounter(a)
|
||||
if uc == nil {
|
||||
uc = &UnitsCounter{BalanceId: a.BalanceId, Direction: a.Direction}
|
||||
uc = &UnitsCounter{BalanceType: a.BalanceType, Direction: a.Direction}
|
||||
ub.UnitCounters = append(ub.UnitCounters, uc)
|
||||
}
|
||||
uc.initBalances(ub.ActionTriggers)
|
||||
return
|
||||
}
|
||||
|
||||
func resetCountersAction(ub *UserBalance, a *Action) (err error) {
|
||||
func resetCountersAction(ub *Account, a *Action) (err error) {
|
||||
ub.UnitCounters = make([]*UnitsCounter, 0)
|
||||
ub.initCounters()
|
||||
return
|
||||
@@ -181,7 +172,7 @@ func genericMakeNegative(a *Action) {
|
||||
}
|
||||
}
|
||||
|
||||
func genericDebit(ub *UserBalance, a *Action) (err error) {
|
||||
func genericDebit(ub *Account, a *Action) (err error) {
|
||||
if ub.BalanceMap == nil {
|
||||
ub.BalanceMap = make(map[string]BalanceChain)
|
||||
}
|
||||
@@ -189,25 +180,26 @@ func genericDebit(ub *UserBalance, a *Action) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func enableUserAction(ub *UserBalance, a *Action) (err error) {
|
||||
func enableUserAction(ub *Account, a *Action) (err error) {
|
||||
ub.Disabled = false
|
||||
return
|
||||
}
|
||||
|
||||
func disableUserAction(ub *UserBalance, a *Action) (err error) {
|
||||
func disableUserAction(ub *Account, a *Action) (err error) {
|
||||
ub.Disabled = true
|
||||
return
|
||||
}
|
||||
|
||||
func genericReset(ub *UserBalance) {
|
||||
func genericReset(ub *Account) error {
|
||||
for k, _ := range ub.BalanceMap {
|
||||
ub.BalanceMap[k] = BalanceChain{&Balance{Value: 0}}
|
||||
}
|
||||
ub.UnitCounters = make([]*UnitsCounter, 0)
|
||||
ub.resetActionTriggers(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func callUrl(ub *UserBalance, a *Action) error {
|
||||
func callUrl(ub *Account, a *Action) error {
|
||||
body, err := json.Marshal(ub)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -217,7 +209,7 @@ func callUrl(ub *UserBalance, a *Action) error {
|
||||
}
|
||||
|
||||
// Does not block for posts, no error reports
|
||||
func callUrlAsync(ub *UserBalance, a *Action) error {
|
||||
func callUrlAsync(ub *Account, a *Action) error {
|
||||
body, err := json.Marshal(ub)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -238,7 +230,7 @@ func callUrlAsync(ub *UserBalance, a *Action) error {
|
||||
}
|
||||
|
||||
// Mails the balance hitting the threshold towards predefined list of addresses
|
||||
func mailAsync(ub *UserBalance, a *Action) error {
|
||||
func mailAsync(ub *Account, a *Action) error {
|
||||
ubJson, err := json.Marshal(ub)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -35,14 +35,14 @@ const (
|
||||
)
|
||||
|
||||
type ActionTiming struct {
|
||||
Id string // uniquely identify the timing
|
||||
Tag string // informative purpose only
|
||||
UserBalanceIds []string
|
||||
Timing *RateInterval
|
||||
Weight float64
|
||||
ActionsId string
|
||||
actions Actions
|
||||
stCache time.Time // cached time of the next start
|
||||
Id string // uniquely identify the timing
|
||||
Tag string // informative purpose only
|
||||
AccountIds []string
|
||||
Timing *RateInterval
|
||||
Weight float64
|
||||
ActionsId string
|
||||
actions Actions
|
||||
stCache time.Time // cached time of the next start
|
||||
}
|
||||
|
||||
type ActionPlan []*ActionTiming
|
||||
@@ -232,9 +232,9 @@ func (at *ActionTiming) Execute() (err error) {
|
||||
Logger.Crit(fmt.Sprintf("Function type %v not available, aborting execution!", a.ActionType))
|
||||
return
|
||||
}
|
||||
for _, ubId := range at.UserBalanceIds {
|
||||
for _, ubId := range at.AccountIds {
|
||||
_, err := AccLock.Guard(ubId, func() (float64, error) {
|
||||
ub, err := accountingStorage.GetUserBalance(ubId)
|
||||
ub, err := accountingStorage.GetAccount(ubId)
|
||||
if ub.Disabled {
|
||||
return 0, fmt.Errorf("User %s is disabled", ubId)
|
||||
}
|
||||
@@ -245,7 +245,7 @@ func (at *ActionTiming) Execute() (err error) {
|
||||
|
||||
Logger.Info(fmt.Sprintf("Executing %v on %v", a.ActionType, ub.Id))
|
||||
err = actionFunction(ub, a)
|
||||
accountingStorage.SetUserBalance(ub)
|
||||
accountingStorage.SetAccount(ub)
|
||||
return 0, nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -317,15 +317,15 @@ func RemActionTiming(ats ActionPlan, actionTimingId, balanceId string) ActionPla
|
||||
ats[idx], ats = ats[len(ats)-1], ats[:len(ats)-1]
|
||||
continue
|
||||
}
|
||||
for iBlnc, blncId := range at.UserBalanceIds {
|
||||
for iBlnc, blncId := range at.AccountIds {
|
||||
if blncId == balanceId {
|
||||
if len(at.UserBalanceIds) == 1 { // Only one balance, remove complete at
|
||||
if len(at.AccountIds) == 1 { // Only one balance, remove complete at
|
||||
if len(ats) == 1 { // Removing last item, by init empty
|
||||
return make([]*ActionTiming, 0)
|
||||
}
|
||||
ats[idx], ats = ats[len(ats)-1], ats[:len(ats)-1]
|
||||
} else {
|
||||
at.UserBalanceIds[iBlnc], at.UserBalanceIds = at.UserBalanceIds[len(at.UserBalanceIds)-1], at.UserBalanceIds[:len(at.UserBalanceIds)-1]
|
||||
at.AccountIds[iBlnc], at.AccountIds = at.AccountIds[len(at.AccountIds)-1], at.AccountIds[:len(at.AccountIds)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
type ActionTrigger struct {
|
||||
Id string // uniquely identify the trigger
|
||||
BalanceId string
|
||||
BalanceType string
|
||||
Direction string
|
||||
ThresholdType string //*min_counter, *max_counter, *min_balance, *max_balance
|
||||
ThresholdValue float64
|
||||
@@ -38,7 +38,7 @@ type ActionTrigger struct {
|
||||
Executed bool
|
||||
}
|
||||
|
||||
func (at *ActionTrigger) Execute(ub *UserBalance) (err error) {
|
||||
func (at *ActionTrigger) Execute(ub *Account) (err error) {
|
||||
if ub.Disabled {
|
||||
return fmt.Errorf("User %s is disabled", ub.Id)
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func (at *ActionTrigger) Execute(ub *UserBalance) (err error) {
|
||||
at.Executed = false
|
||||
}
|
||||
storageLogger.LogActionTrigger(ub.Id, RATER_SOURCE, at, aac)
|
||||
accountingStorage.SetUserBalance(ub)
|
||||
accountingStorage.SetAccount(ub)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ func (at *ActionTrigger) Match(a *Action) bool {
|
||||
if a == nil {
|
||||
return true
|
||||
}
|
||||
id := a.BalanceId == "" || at.BalanceId == a.BalanceId
|
||||
id := a.BalanceType == "" || at.BalanceType == a.BalanceType
|
||||
direction := a.Direction == "" || at.Direction == a.Direction
|
||||
thresholdType, thresholdValue := true, true
|
||||
if a.ExtraParameters != "" {
|
||||
|
||||
@@ -360,9 +360,9 @@ func TestActionTimingOneTimeRun(t *testing.T) {
|
||||
|
||||
func TestActionTimingLogFunction(t *testing.T) {
|
||||
a := &Action{
|
||||
ActionType: "*log",
|
||||
BalanceId: "test",
|
||||
Balance: &Balance{Value: 1.1},
|
||||
ActionType: "*log",
|
||||
BalanceType: "test",
|
||||
Balance: &Balance{Value: 1.1},
|
||||
}
|
||||
at := &ActionTiming{
|
||||
actions: []*Action{a},
|
||||
@@ -431,20 +431,20 @@ func TestActionTimingPriotityListWeight(t *testing.T) {
|
||||
|
||||
func TestActionTimingsRemoveMember(t *testing.T) {
|
||||
at1 := &ActionTiming{
|
||||
Id: "some uuid",
|
||||
Tag: "test",
|
||||
UserBalanceIds: []string{"one", "two", "three"},
|
||||
ActionsId: "TEST_ACTIONS",
|
||||
Id: "some uuid",
|
||||
Tag: "test",
|
||||
AccountIds: []string{"one", "two", "three"},
|
||||
ActionsId: "TEST_ACTIONS",
|
||||
}
|
||||
at2 := &ActionTiming{
|
||||
Id: "some uuid22",
|
||||
Tag: "test2",
|
||||
UserBalanceIds: []string{"three", "four"},
|
||||
ActionsId: "TEST_ACTIONS2",
|
||||
Id: "some uuid22",
|
||||
Tag: "test2",
|
||||
AccountIds: []string{"three", "four"},
|
||||
ActionsId: "TEST_ACTIONS2",
|
||||
}
|
||||
ats := ActionPlan{at1, at2}
|
||||
if outAts := RemActionTiming(ats, "", "four"); len(outAts[1].UserBalanceIds) != 1 {
|
||||
t.Error("Expecting fewer balance ids", outAts[1].UserBalanceIds)
|
||||
if outAts := RemActionTiming(ats, "", "four"); len(outAts[1].AccountIds) != 1 {
|
||||
t.Error("Expecting fewer balance ids", outAts[1].AccountIds)
|
||||
}
|
||||
if ats = RemActionTiming(ats, "", "three"); len(ats) != 1 {
|
||||
t.Error("Expecting fewer actionTimings", ats)
|
||||
@@ -461,7 +461,7 @@ func TestActionTimingsRemoveMember(t *testing.T) {
|
||||
func TestActionTriggerMatchNil(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
@@ -474,7 +474,7 @@ func TestActionTriggerMatchNil(t *testing.T) {
|
||||
func TestActionTriggerMatchAllBlank(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
@@ -487,11 +487,11 @@ func TestActionTriggerMatchAllBlank(t *testing.T) {
|
||||
func TestActionTriggerMatchMinuteBucketBlank(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: OUTBOUND, BalanceId: CREDIT}
|
||||
a := &Action{Direction: OUTBOUND, BalanceType: CREDIT}
|
||||
if !at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -500,7 +500,7 @@ func TestActionTriggerMatchMinuteBucketBlank(t *testing.T) {
|
||||
func TestActionTriggerMatchMinuteBucketFull(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
@@ -513,11 +513,11 @@ func TestActionTriggerMatchMinuteBucketFull(t *testing.T) {
|
||||
func TestActionTriggerMatchAllFull(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: OUTBOUND, BalanceId: CREDIT, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 2)}
|
||||
a := &Action{Direction: OUTBOUND, BalanceType: CREDIT, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 2)}
|
||||
if !at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -526,11 +526,11 @@ func TestActionTriggerMatchAllFull(t *testing.T) {
|
||||
func TestActionTriggerMatchSomeFalse(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: INBOUND, BalanceId: CREDIT, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 2)}
|
||||
a := &Action{Direction: INBOUND, BalanceType: CREDIT, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 2)}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -539,11 +539,11 @@ func TestActionTriggerMatchSomeFalse(t *testing.T) {
|
||||
func TestActionTriggerMatcBalanceFalse(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: OUTBOUND, BalanceId: CREDIT, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 3.0)}
|
||||
a := &Action{Direction: OUTBOUND, BalanceType: CREDIT, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_BALANCE, 3.0)}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -552,11 +552,11 @@ func TestActionTriggerMatcBalanceFalse(t *testing.T) {
|
||||
func TestActionTriggerMatcAllFalse(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: INBOUND, BalanceId: MINUTES, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_COUNTER, 3)}
|
||||
a := &Action{Direction: INBOUND, BalanceType: MINUTES, ExtraParameters: fmt.Sprintf(`{"ThresholdType":"%v", "ThresholdValue": %v}`, TRIGGER_MAX_COUNTER, 3)}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -575,11 +575,11 @@ func TestActionTriggerPriotityList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionResetTriggres(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 10}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetTriggersAction(ub, nil)
|
||||
if ub.ActionTriggers[0].Executed == true || ub.ActionTriggers[1].Executed == true {
|
||||
@@ -588,11 +588,11 @@ func TestActionResetTriggres(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionResetTriggresExecutesThem(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 10}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetTriggersAction(ub, nil)
|
||||
if ub.ActionTriggers[0].Executed == true || ub.BalanceMap[CREDIT][0].Value == 12 {
|
||||
@@ -601,56 +601,55 @@ func TestActionResetTriggresExecutesThem(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionResetTriggresActionFilter(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 10}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetTriggersAction(ub, &Action{BalanceId: SMS})
|
||||
resetTriggersAction(ub, &Action{BalanceType: SMS})
|
||||
if ub.ActionTriggers[0].Executed == false || ub.ActionTriggers[1].Executed == false {
|
||||
t.Error("Reset triggers action failed!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionSetPostpaid(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
setPostpaidAction(ub, nil)
|
||||
if ub.Type != UB_TYPE_POSTPAID {
|
||||
allowNegativeAction(ub, nil)
|
||||
if !ub.AllowNegative {
|
||||
t.Error("Set postpaid action failed!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionSetPrepaid(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
setPrepaidAction(ub, nil)
|
||||
if ub.Type != UB_TYPE_PREPAID {
|
||||
denyNegativeAction(ub, nil)
|
||||
if ub.AllowNegative {
|
||||
t.Error("Set prepaid action failed!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionResetPrepaid(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetPrepaidAction(ub, nil)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
resetAccountAction(ub, nil)
|
||||
if !ub.AllowNegative ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 0 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 0 ||
|
||||
@@ -661,16 +660,14 @@ func TestActionResetPrepaid(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionResetPostpaid(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetPostpaidAction(ub, nil)
|
||||
if ub.Type != UB_TYPE_POSTPAID ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 0 ||
|
||||
resetAccountAction(ub, nil)
|
||||
if ub.BalanceMap[CREDIT].GetTotalValue() != 0 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 0 ||
|
||||
ub.ActionTriggers[0].Executed == true || ub.ActionTriggers[1].Executed == true {
|
||||
@@ -679,16 +676,15 @@ func TestActionResetPostpaid(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionTopupResetCredit(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}}
|
||||
a := &Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}}
|
||||
topupResetAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue() != 10 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.BalanceMap[MINUTES+OUTBOUND]) != 2 ||
|
||||
@@ -698,18 +694,17 @@ func TestActionTopupResetCredit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionTopupResetMinutes(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}},
|
||||
MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: &Balance{Value: 5, Weight: 20, DestinationId: "NAT"}}
|
||||
a := &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: &Balance{Value: 5, Weight: 20, DestinationId: "NAT"}}
|
||||
topupResetAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[MINUTES+OUTBOUND].GetTotalValue() != 5 ||
|
||||
ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
@@ -720,16 +715,15 @@ func TestActionTopupResetMinutes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionTopupCredit(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}}
|
||||
a := &Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}}
|
||||
topupAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue() != 110 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.BalanceMap[MINUTES+OUTBOUND]) != 2 ||
|
||||
@@ -739,16 +733,15 @@ func TestActionTopupCredit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionTopupMinutes(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: &Balance{Value: 5, Weight: 20, DestinationId: "NAT"}}
|
||||
a := &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: &Balance{Value: 5, Weight: 20, DestinationId: "NAT"}}
|
||||
topupAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[MINUTES+OUTBOUND].GetTotalValue() != 15 ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
@@ -759,16 +752,15 @@ func TestActionTopupMinutes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionDebitCredit(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}}
|
||||
a := &Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}}
|
||||
debitAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue() != 90 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.BalanceMap[MINUTES+OUTBOUND]) != 2 ||
|
||||
@@ -778,16 +770,15 @@ func TestActionDebitCredit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionDebitMinutes(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: &Balance{Value: 5, Weight: 20, DestinationId: "NAT"}}
|
||||
a := &Action{BalanceType: MINUTES, Direction: OUTBOUND, Balance: &Balance{Value: 5, Weight: 20, DestinationId: "NAT"}}
|
||||
debitAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 5 ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
@@ -798,19 +789,19 @@ func TestActionDebitMinutes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionResetAllCounters(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
CREDIT: BalanceChain{&Balance{Value: 100}},
|
||||
MINUTES: BalanceChain{
|
||||
&Balance{Value: 10, Weight: 20, DestinationId: "NAT"},
|
||||
&Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetCountersAction(ub, nil)
|
||||
if ub.Type != UB_TYPE_POSTPAID ||
|
||||
if !ub.AllowNegative ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters[0].Balances) != 2 ||
|
||||
@@ -828,18 +819,18 @@ func TestActionResetAllCounters(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionResetCounterMinutes(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
CREDIT: BalanceChain{&Balance{Value: 100}},
|
||||
MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: MINUTES}
|
||||
a := &Action{BalanceType: MINUTES}
|
||||
resetCounterAction(ub, a)
|
||||
if ub.Type != UB_TYPE_POSTPAID ||
|
||||
if !ub.AllowNegative ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 2 ||
|
||||
len(ub.UnitCounters[1].Balances) != 2 ||
|
||||
@@ -860,16 +851,16 @@ func TestActionResetCounterMinutes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionResetCounterCREDIT(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES + OUTBOUND: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}, &UnitsCounter{BalanceId: SMS, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}, &UnitsCounter{BalanceType: SMS, Direction: OUTBOUND, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: CREDIT, Direction: OUTBOUND}
|
||||
a := &Action{BalanceType: CREDIT, Direction: OUTBOUND}
|
||||
resetCounterAction(ub, a)
|
||||
if ub.Type != UB_TYPE_POSTPAID ||
|
||||
if !ub.AllowNegative ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 2 ||
|
||||
len(ub.BalanceMap[MINUTES+OUTBOUND]) != 2 ||
|
||||
@@ -881,7 +872,7 @@ func TestActionResetCounterCREDIT(t *testing.T) {
|
||||
func TestActionTriggerLogging(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Id: "some_uuid",
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
Direction: OUTBOUND,
|
||||
ThresholdValue: 100.0,
|
||||
DestinationId: "NAT",
|
||||
@@ -925,12 +916,12 @@ func TestActionTimingLogging(t *testing.T) {
|
||||
},
|
||||
}
|
||||
at := &ActionTiming{
|
||||
Id: "some uuid",
|
||||
Tag: "test",
|
||||
UserBalanceIds: []string{"one", "two", "three"},
|
||||
Timing: i,
|
||||
Weight: 10.0,
|
||||
ActionsId: "TEST_ACTIONS",
|
||||
Id: "some uuid",
|
||||
Tag: "test",
|
||||
AccountIds: []string{"one", "two", "three"},
|
||||
Timing: i,
|
||||
Weight: 10.0,
|
||||
ActionsId: "TEST_ACTIONS",
|
||||
}
|
||||
as, err := accountingStorage.GetActions(at.ActionsId, false)
|
||||
if err != nil {
|
||||
@@ -965,7 +956,7 @@ func TestActionMakeNegative(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMinBalanceTriggerSimple(t *testing.T) {
|
||||
//ub := &UserBalance{}
|
||||
//ub := &Account{}
|
||||
}
|
||||
|
||||
/********************************** Benchmarks ********************************/
|
||||
|
||||
@@ -37,7 +37,7 @@ type Balance struct {
|
||||
RateSubject string
|
||||
SharedGroup string
|
||||
precision int
|
||||
userBalance *UserBalance // used to store ub reference for shared balances
|
||||
account *Account // used to store ub reference for shared balances
|
||||
}
|
||||
|
||||
func (b *Balance) Equal(o *Balance) bool {
|
||||
@@ -118,7 +118,7 @@ func (b *Balance) GetCost(cd *CallDescriptor) (*CallCost, error) {
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func (b *Balance) DebitMinutes(cc *CallCost, count bool, ub *UserBalance, moneyBalances BalanceChain) error {
|
||||
func (b *Balance) DebitMinutes(cc *CallCost, count bool, ub *Account, moneyBalances BalanceChain) error {
|
||||
for tsIndex := 0; tsIndex < len(cc.Timespans); tsIndex++ {
|
||||
if b.Value <= 0 {
|
||||
return nil
|
||||
@@ -183,7 +183,7 @@ func (b *Balance) DebitMinutes(cc *CallCost, count bool, ub *UserBalance, moneyB
|
||||
inc.Cost = 0
|
||||
inc.paid = true
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: MINUTES, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationId: cc.Destination}})
|
||||
ub.countUnits(&Action{BalanceType: MINUTES, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationId: cc.Destination}})
|
||||
}
|
||||
}
|
||||
continue
|
||||
@@ -223,8 +223,8 @@ func (b *Balance) DebitMinutes(cc *CallCost, count bool, ub *UserBalance, moneyB
|
||||
nInc.MinuteInfo = &MinuteInfo{newCC.Destination, seconds}
|
||||
nInc.paid = true
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: MINUTES, Direction: newCC.Direction, Balance: &Balance{Value: seconds, DestinationId: newCC.Destination}})
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: newCC.Direction, Balance: &Balance{Value: cost, DestinationId: newCC.Destination}})
|
||||
ub.countUnits(&Action{BalanceType: MINUTES, Direction: newCC.Direction, Balance: &Balance{Value: seconds, DestinationId: newCC.Destination}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: newCC.Direction, Balance: &Balance{Value: cost, DestinationId: newCC.Destination}})
|
||||
}
|
||||
} else {
|
||||
increment.paid = false
|
||||
@@ -258,7 +258,7 @@ func (b *Balance) DebitMinutes(cc *CallCost, count bool, ub *UserBalance, moneyB
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Balance) DebitMoney(cc *CallCost, count bool, ub *UserBalance) error {
|
||||
func (b *Balance) DebitMoney(cc *CallCost, count bool, ub *Account) error {
|
||||
for tsIndex := 0; tsIndex < len(cc.Timespans); tsIndex++ {
|
||||
if b.Value <= 0 {
|
||||
return nil
|
||||
@@ -286,7 +286,7 @@ func (b *Balance) DebitMoney(cc *CallCost, count bool, ub *UserBalance) error {
|
||||
increment.BalanceInfo.MoneyBalanceUuid = b.Uuid
|
||||
increment.paid = true
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationId: cc.Destination}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: amount, DestinationId: cc.Destination}})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -314,7 +314,7 @@ func (b *Balance) DebitMoney(cc *CallCost, count bool, ub *UserBalance) error {
|
||||
nInc.BalanceInfo.MoneyBalanceUuid = b.Uuid
|
||||
nInc.paid = true
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: newCC.Direction, Balance: &Balance{Value: amount, DestinationId: newCC.Destination}})
|
||||
ub.countUnits(&Action{BalanceType: CREDIT, Direction: newCC.Direction, Balance: &Balance{Value: amount, DestinationId: newCC.Destination}})
|
||||
}
|
||||
} else {
|
||||
increment.paid = false
|
||||
|
||||
@@ -116,7 +116,7 @@ type CallDescriptor struct {
|
||||
FallbackSubject string // the subject to check for destination if not found on primary subject
|
||||
RatingInfos RatingInfos
|
||||
Increments Increments
|
||||
userBalance *UserBalance
|
||||
userBalance *Account
|
||||
}
|
||||
|
||||
func (cd *CallDescriptor) ValidateCallData() error {
|
||||
@@ -135,7 +135,7 @@ func (cd *CallDescriptor) AddRatingInfo(ris ...*RatingInfo) {
|
||||
}
|
||||
|
||||
// Returns the key used to retrive the user balance involved in this call
|
||||
func (cd *CallDescriptor) GetUserBalanceKey() string {
|
||||
func (cd *CallDescriptor) GetAccountKey() string {
|
||||
subj := cd.Subject
|
||||
if cd.Account != "" {
|
||||
subj = cd.Account
|
||||
@@ -144,9 +144,9 @@ func (cd *CallDescriptor) GetUserBalanceKey() string {
|
||||
}
|
||||
|
||||
// Gets and caches the user balance information.
|
||||
func (cd *CallDescriptor) getUserBalance() (ub *UserBalance, err error) {
|
||||
func (cd *CallDescriptor) getAccount() (ub *Account, err error) {
|
||||
if cd.userBalance == nil {
|
||||
cd.userBalance, err = accountingStorage.GetUserBalance(cd.GetUserBalanceKey())
|
||||
cd.userBalance, err = accountingStorage.GetAccount(cd.GetAccountKey())
|
||||
}
|
||||
if cd.userBalance != nil && cd.userBalance.Disabled {
|
||||
return nil, fmt.Errorf("User %s is disabled", ub.Id)
|
||||
@@ -388,7 +388,7 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) {
|
||||
}
|
||||
err := cd.LoadRatingPlans()
|
||||
if err != nil {
|
||||
Logger.Err(fmt.Sprintf("error getting cost for key %v: %v", cd.GetUserBalanceKey(), err))
|
||||
Logger.Err(fmt.Sprintf("error getting cost for key %v: %v", cd.GetAccountKey(), err))
|
||||
return &CallCost{Cost: -1}, err
|
||||
}
|
||||
timespans := cd.splitInTimeSpans(nil)
|
||||
@@ -432,20 +432,20 @@ func (origCd *CallDescriptor) GetMaxSessionDuration() (time.Duration, error) {
|
||||
//Logger.Debug(fmt.Sprintf("MAX SESSION cd: %+v", cd))
|
||||
err := cd.LoadRatingPlans()
|
||||
if err != nil {
|
||||
Logger.Err(fmt.Sprintf("error getting cost for key %v: %v", cd.GetUserBalanceKey(), err))
|
||||
Logger.Err(fmt.Sprintf("error getting cost for key %v: %v", cd.GetAccountKey(), err))
|
||||
return 0, err
|
||||
}
|
||||
var availableDuration time.Duration
|
||||
availableCredit := 0.0
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
if userBalance.Type == UB_TYPE_POSTPAID {
|
||||
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
|
||||
if userBalance.AllowNegative {
|
||||
return -1, nil
|
||||
} else {
|
||||
availableDuration, availableCredit, _ = userBalance.getCreditForPrefix(cd)
|
||||
// Logger.Debug(fmt.Sprintf("available sec: %v credit: %v", availableSeconds, availableCredit))
|
||||
}
|
||||
} else {
|
||||
Logger.Err(fmt.Sprintf("Could not get user balance for %s: %s.", cd.GetUserBalanceKey(), err.Error()))
|
||||
Logger.Err(fmt.Sprintf("Could not get user balance for %s: %s.", cd.GetAccountKey(), err.Error()))
|
||||
return 0, err
|
||||
}
|
||||
//Logger.Debug(fmt.Sprintf("availableDuration: %v, availableCredit: %v", availableDuration, availableCredit))
|
||||
@@ -494,18 +494,18 @@ func (origCd *CallDescriptor) GetMaxSessionDuration() (time.Duration, error) {
|
||||
func (cd *CallDescriptor) Debit() (cc *CallCost, err error) {
|
||||
cc, err = cd.GetCost()
|
||||
if err != nil {
|
||||
Logger.Err(fmt.Sprintf("<Rater> Error getting cost for account key %v: %v", cd.GetUserBalanceKey(), err))
|
||||
Logger.Err(fmt.Sprintf("<Rater> Error getting cost for account key %v: %v", cd.GetAccountKey(), err))
|
||||
return
|
||||
}
|
||||
if userBalance, err := cd.getUserBalance(); err != nil {
|
||||
if userBalance, err := cd.getAccount(); err != nil {
|
||||
Logger.Err(fmt.Sprintf("<Rater> Error retrieving user balance: %v", err))
|
||||
} else if userBalance == nil {
|
||||
// Logger.Debug(fmt.Sprintf("<Rater> No user balance defined: %v", cd.GetUserBalanceKey()))
|
||||
// Logger.Debug(fmt.Sprintf("<Rater> No user balance defined: %v", cd.GetAccountKey()))
|
||||
} else {
|
||||
//Logger.Debug(fmt.Sprintf("<Rater> Attempting to debit from %v, value: %v", cd.GetUserBalanceKey(), cc.Cost+cc.ConnectFee))
|
||||
defer accountingStorage.SetUserBalance(userBalance)
|
||||
//Logger.Debug(fmt.Sprintf("<Rater> Attempting to debit from %v, value: %v", cd.GetAccountKey(), cc.Cost+cc.ConnectFee))
|
||||
defer accountingStorage.SetAccount(userBalance)
|
||||
//ub, _ := json.Marshal(userBalance)
|
||||
//Logger.Debug(fmt.Sprintf("UserBalance: %s", ub))
|
||||
//Logger.Debug(fmt.Sprintf("Account: %s", ub))
|
||||
//cCost, _ := json.Marshal(cc)
|
||||
//Logger.Debug(fmt.Sprintf("CallCost: %s", cCost))
|
||||
if cc.Cost != 0 || cc.GetConnectFee() != 0 {
|
||||
@@ -538,8 +538,8 @@ func (cd *CallDescriptor) MaxDebit() (cc *CallCost, err error) {
|
||||
}
|
||||
|
||||
func (cd *CallDescriptor) RefundIncrements() (left float64, err error) {
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
defer accountingStorage.SetUserBalance(userBalance)
|
||||
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
|
||||
defer accountingStorage.SetAccount(userBalance)
|
||||
userBalance.refundIncrements(cd.Increments, cd.Direction, true)
|
||||
}
|
||||
return 0.0, err
|
||||
@@ -550,8 +550,8 @@ Interface method used to add/substract an amount of cents from user's money bala
|
||||
The amount filed has to be filled in call descriptor.
|
||||
*/
|
||||
func (cd *CallDescriptor) DebitCents() (left float64, err error) {
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
defer accountingStorage.SetUserBalance(userBalance)
|
||||
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
|
||||
defer accountingStorage.SetAccount(userBalance)
|
||||
return userBalance.debitGenericBalance(CREDIT, cd.Direction, cd.Amount, true), nil
|
||||
}
|
||||
return 0.0, err
|
||||
@@ -562,8 +562,8 @@ Interface method used to add/substract an amount of units from user's sms balanc
|
||||
The amount filed has to be filled in call descriptor.
|
||||
*/
|
||||
func (cd *CallDescriptor) DebitSMS() (left float64, err error) {
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
defer accountingStorage.SetUserBalance(userBalance)
|
||||
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
|
||||
defer accountingStorage.SetAccount(userBalance)
|
||||
return userBalance.debitGenericBalance(SMS, cd.Direction, cd.Amount, true), nil
|
||||
}
|
||||
return 0, err
|
||||
@@ -574,8 +574,8 @@ Interface method used to add/substract an amount of seconds from user's minutes
|
||||
The amount filed has to be filled in call descriptor.
|
||||
*/
|
||||
func (cd *CallDescriptor) DebitSeconds() (err error) {
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
defer accountingStorage.SetUserBalance(userBalance)
|
||||
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
|
||||
defer accountingStorage.SetAccount(userBalance)
|
||||
return userBalance.debitCreditBalance(cd.CreateCallCost(), true)
|
||||
}
|
||||
return err
|
||||
@@ -588,7 +588,7 @@ specified in the tariff plan is applied.
|
||||
The amount filed has to be filled in call descriptor.
|
||||
*/
|
||||
func (cd *CallDescriptor) AddRecievedCallSeconds() (err error) {
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
if userBalance, err := cd.getAccount(); err == nil && userBalance != nil {
|
||||
a := &Action{
|
||||
Direction: INBOUND,
|
||||
Balance: &Balance{Value: cd.Amount, DestinationId: cd.Destination},
|
||||
|
||||
@@ -37,19 +37,25 @@ func init() {
|
||||
}
|
||||
|
||||
func populateDB() {
|
||||
minu := &UserBalance{
|
||||
Id: "*out:vdf:minu",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
ats := []*Action{
|
||||
&Action{ActionType: "*topup", BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}},
|
||||
&Action{ActionType: "*topup", BalanceType: MINUTES, Direction: OUTBOUND, Balance: &Balance{Weight: 20, Value: 10, DestinationId: "NAT"}},
|
||||
}
|
||||
ats1 := []*Action{
|
||||
&Action{ActionType: "*topup", BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}, Weight: 20},
|
||||
&Action{ActionType: "*reset_account", Weight: 10},
|
||||
}
|
||||
minu := &Account{
|
||||
Id: "*out:vdf:minu",
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
CREDIT: BalanceChain{&Balance{Value: 0}},
|
||||
CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 50}},
|
||||
MINUTES + OUTBOUND: BalanceChain{
|
||||
&Balance{Value: 200, DestinationId: "NAT", Weight: 10},
|
||||
&Balance{Value: 100, DestinationId: "RET", Weight: 20},
|
||||
}},
|
||||
}
|
||||
broker := &UserBalance{
|
||||
Id: "*out:vdf:broker",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
broker := &Account{
|
||||
Id: "*out:vdf:broker",
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
MINUTES + OUTBOUND: BalanceChain{
|
||||
&Balance{Value: 20, DestinationId: "NAT", Weight: 10, RateSubject: "rif"},
|
||||
@@ -57,9 +63,10 @@ func populateDB() {
|
||||
}},
|
||||
}
|
||||
if accountingStorage != nil {
|
||||
accountingStorage.(Storage).Flush()
|
||||
accountingStorage.SetUserBalance(broker)
|
||||
accountingStorage.SetUserBalance(minu)
|
||||
accountingStorage.SetActions("TEST_ACTIONS", ats)
|
||||
accountingStorage.SetActions("TEST_ACTIONS_ORDER", ats1)
|
||||
accountingStorage.SetAccount(broker)
|
||||
accountingStorage.SetAccount(minu)
|
||||
} else {
|
||||
log.Fatal("Could not connect to db!")
|
||||
}
|
||||
@@ -270,7 +277,7 @@ func TestMinutesCost(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxSessionTimeNoUserBalance(t *testing.T) {
|
||||
func TestMaxSessionTimeNoAccount(t *testing.T) {
|
||||
cd := &CallDescriptor{
|
||||
TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC),
|
||||
TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC),
|
||||
@@ -285,7 +292,7 @@ func TestMaxSessionTimeNoUserBalance(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxSessionTimeWithUserBalance(t *testing.T) {
|
||||
func TestMaxSessionTimeWithAccount(t *testing.T) {
|
||||
cd := &CallDescriptor{
|
||||
TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC),
|
||||
TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC),
|
||||
@@ -302,7 +309,7 @@ func TestMaxSessionTimeWithUserBalance(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxSessionTimeWithUserBalanceAccount(t *testing.T) {
|
||||
func TestMaxSessionTimeWithAccountAccount(t *testing.T) {
|
||||
cd := &CallDescriptor{
|
||||
TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC),
|
||||
TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC),
|
||||
|
||||
@@ -38,7 +38,7 @@ type CSVReader struct {
|
||||
actions map[string][]*Action
|
||||
actionsTimings map[string][]*ActionTiming
|
||||
actionsTriggers map[string][]*ActionTrigger
|
||||
accountActions []*UserBalance
|
||||
accountActions []*Account
|
||||
destinations []*Destination
|
||||
timings map[string]*utils.TPTiming
|
||||
rates map[string]*utils.TPRate
|
||||
@@ -236,7 +236,7 @@ func (csvr *CSVReader) WriteToDatabase(flush, verbose bool) (err error) {
|
||||
log.Print("Account actions")
|
||||
}
|
||||
for _, ub := range csvr.accountActions {
|
||||
err = accountingStorage.SetUserBalance(ub)
|
||||
err = accountingStorage.SetAccount(ub)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -526,7 +526,7 @@ func (csvr *CSVReader) LoadActions() (err error) {
|
||||
a := &Action{
|
||||
Id: utils.GenUUID(),
|
||||
ActionType: record[1],
|
||||
BalanceId: record[2],
|
||||
BalanceType: record[2],
|
||||
Direction: record[3],
|
||||
Weight: weight,
|
||||
ExpirationString: record[5],
|
||||
@@ -614,7 +614,7 @@ func (csvr *CSVReader) LoadActionTriggers() (err error) {
|
||||
}
|
||||
at := &ActionTrigger{
|
||||
Id: utils.GenUUID(),
|
||||
BalanceId: record[1],
|
||||
BalanceType: record[1],
|
||||
Direction: record[2],
|
||||
ThresholdType: record[3],
|
||||
ThresholdValue: value,
|
||||
@@ -644,8 +644,7 @@ func (csvr *CSVReader) LoadAccountActions() (err error) {
|
||||
// only return error if there was something ther for the tag
|
||||
return errors.New(fmt.Sprintf("Could not get action triggers for tag %v", record[4]))
|
||||
}
|
||||
ub := &UserBalance{
|
||||
Type: UB_TYPE_PREPAID,
|
||||
ub := &Account{
|
||||
Id: tag,
|
||||
ActionTriggers: aTriggers,
|
||||
}
|
||||
@@ -656,7 +655,7 @@ func (csvr *CSVReader) LoadAccountActions() (err error) {
|
||||
// must not continue here
|
||||
}
|
||||
for _, at := range aTimings {
|
||||
at.UserBalanceIds = append(at.UserBalanceIds, tag)
|
||||
at.AccountIds = append(at.AccountIds, tag)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -576,7 +576,7 @@ func TestLoadActions(t *testing.T) {
|
||||
&Action{
|
||||
Id: as[0].Id,
|
||||
ActionType: TOPUP_RESET,
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
Direction: OUTBOUND,
|
||||
ExpirationString: UNLIMITED,
|
||||
ExtraParameters: "",
|
||||
@@ -590,7 +590,7 @@ func TestLoadActions(t *testing.T) {
|
||||
&Action{
|
||||
Id: as[1].Id,
|
||||
ActionType: TOPUP,
|
||||
BalanceId: MINUTES,
|
||||
BalanceType: MINUTES,
|
||||
Direction: OUTBOUND,
|
||||
ExpirationString: UNLIMITED,
|
||||
ExtraParameters: "",
|
||||
@@ -615,9 +615,9 @@ func TestLoadActionTimings(t *testing.T) {
|
||||
}
|
||||
atm := csvr.actionsTimings["MORE_MINUTES"][0]
|
||||
expected := &ActionTiming{
|
||||
Id: atm.Id,
|
||||
Tag: "MORE_MINUTES",
|
||||
UserBalanceIds: []string{"*out:vdf:minitsboy"},
|
||||
Id: atm.Id,
|
||||
Tag: "MORE_MINUTES",
|
||||
AccountIds: []string{"*out:vdf:minitsboy"},
|
||||
Timing: &RateInterval{
|
||||
Timing: &RITiming{
|
||||
Years: utils.Years{2012},
|
||||
@@ -642,7 +642,7 @@ func TestLoadActionTriggers(t *testing.T) {
|
||||
atr := csvr.actionsTriggers["STANDARD_TRIGGER"][0]
|
||||
expected := &ActionTrigger{
|
||||
Id: atr.Id,
|
||||
BalanceId: MINUTES,
|
||||
BalanceType: MINUTES,
|
||||
Direction: OUTBOUND,
|
||||
ThresholdType: TRIGGER_MIN_COUNTER,
|
||||
ThresholdValue: 10,
|
||||
@@ -657,7 +657,7 @@ func TestLoadActionTriggers(t *testing.T) {
|
||||
atr = csvr.actionsTriggers["STANDARD_TRIGGER"][1]
|
||||
expected = &ActionTrigger{
|
||||
Id: atr.Id,
|
||||
BalanceId: MINUTES,
|
||||
BalanceType: MINUTES,
|
||||
Direction: OUTBOUND,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 200,
|
||||
@@ -676,9 +676,8 @@ func TestLoadAccountActions(t *testing.T) {
|
||||
t.Error("Failed to load account actions: ", csvr.accountActions)
|
||||
}
|
||||
aa := csvr.accountActions[0]
|
||||
expected := &UserBalance{
|
||||
expected := &Account{
|
||||
Id: "*out:vdf:minitsboy",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
ActionTriggers: csvr.actionsTriggers["STANDARD_TRIGGER"],
|
||||
}
|
||||
if !reflect.DeepEqual(aa, expected) {
|
||||
|
||||
@@ -34,7 +34,7 @@ type DbReader struct {
|
||||
actions map[string][]*Action
|
||||
actionsTimings map[string][]*ActionTiming
|
||||
actionsTriggers map[string][]*ActionTrigger
|
||||
accountActions []*UserBalance
|
||||
accountActions []*Account
|
||||
destinations []*Destination
|
||||
timings map[string]*utils.TPTiming
|
||||
rates map[string]*utils.TPRate
|
||||
@@ -180,7 +180,7 @@ func (dbr *DbReader) WriteToDatabase(flush, verbose bool) (err error) {
|
||||
log.Print("Account actions")
|
||||
}
|
||||
for _, ub := range dbr.accountActions {
|
||||
err = accountingStorage.SetUserBalance(ub)
|
||||
err = accountingStorage.SetAccount(ub)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -405,7 +405,7 @@ func (dbr *DbReader) LoadActions() (err error) {
|
||||
acts[idx] = &Action{
|
||||
Id: utils.GenUUID(),
|
||||
ActionType: tpact.Identifier,
|
||||
BalanceId: tpact.BalanceType,
|
||||
BalanceType: tpact.BalanceType,
|
||||
Direction: tpact.Direction,
|
||||
Weight: tpact.Weight,
|
||||
ExtraParameters: tpact.ExtraParameters,
|
||||
@@ -470,7 +470,7 @@ func (dbr *DbReader) LoadActionTriggers() (err error) {
|
||||
atrs := make([]*ActionTrigger, len(atrsLst))
|
||||
for idx, apiAtr := range atrsLst {
|
||||
atrs[idx] = &ActionTrigger{Id: utils.GenUUID(),
|
||||
BalanceId: apiAtr.BalanceType,
|
||||
BalanceType: apiAtr.BalanceType,
|
||||
Direction: apiAtr.Direction,
|
||||
ThresholdType: apiAtr.ThresholdType,
|
||||
ThresholdValue: apiAtr.ThresholdValue,
|
||||
@@ -494,8 +494,7 @@ func (dbr *DbReader) LoadAccountActions() (err error) {
|
||||
if !exists {
|
||||
return errors.New(fmt.Sprintf("Could not get action triggers for tag %v", aa.ActionTriggersId))
|
||||
}
|
||||
ub := &UserBalance{
|
||||
Type: UB_TYPE_PREPAID,
|
||||
ub := &Account{
|
||||
Id: aa.KeyId(),
|
||||
ActionTriggers: aTriggers,
|
||||
}
|
||||
@@ -506,7 +505,7 @@ func (dbr *DbReader) LoadAccountActions() (err error) {
|
||||
// must not continue here
|
||||
}
|
||||
for _, at := range aTimings {
|
||||
at.UserBalanceIds = append(at.UserBalanceIds, aa.KeyId())
|
||||
at.AccountIds = append(at.AccountIds, aa.KeyId())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -523,11 +522,11 @@ func (dbr *DbReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
|
||||
// action timings
|
||||
if accountAction.ActionPlanId != "" {
|
||||
// get old userBalanceIds
|
||||
var exitingUserBalanceIds []string
|
||||
var exitingAccountIds []string
|
||||
existingActionTimings, err := dbr.accountDb.GetActionTimings(accountAction.ActionPlanId)
|
||||
if err == nil && len(existingActionTimings) > 0 {
|
||||
// all action timings from a specific tag shuld have the same list of user balances from the first one
|
||||
exitingUserBalanceIds = existingActionTimings[0].UserBalanceIds
|
||||
exitingAccountIds = existingActionTimings[0].AccountIds
|
||||
}
|
||||
|
||||
actionTimingsMap, err := dbr.storDb.GetTPActionTimings(dbr.tpid, accountAction.ActionPlanId)
|
||||
@@ -571,14 +570,14 @@ func (dbr *DbReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
|
||||
actionsIds = append(actionsIds, actTmg.ActionsId)
|
||||
//add user balance id if no already in
|
||||
found := false
|
||||
for _, ubId := range exitingUserBalanceIds {
|
||||
for _, ubId := range exitingAccountIds {
|
||||
if ubId == id {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
actTmg.UserBalanceIds = append(exitingUserBalanceIds, id)
|
||||
actTmg.AccountIds = append(exitingAccountIds, id)
|
||||
}
|
||||
actionTimings = append(actionTimings, actTmg)
|
||||
}
|
||||
@@ -602,7 +601,7 @@ func (dbr *DbReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
|
||||
atrs := make([]*ActionTrigger, len(atrsLst))
|
||||
for idx, apiAtr := range atrsLst {
|
||||
atrs[idx] = &ActionTrigger{Id: utils.GenUUID(),
|
||||
BalanceId: apiAtr.BalanceType,
|
||||
BalanceType: apiAtr.BalanceType,
|
||||
Direction: apiAtr.Direction,
|
||||
ThresholdType: apiAtr.ThresholdType,
|
||||
ThresholdValue: apiAtr.ThresholdValue,
|
||||
@@ -633,7 +632,7 @@ func (dbr *DbReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
|
||||
enacts[idx] = &Action{
|
||||
Id: utils.GenUUID(),
|
||||
ActionType: tpact.Identifier,
|
||||
BalanceId: tpact.BalanceType,
|
||||
BalanceType: tpact.BalanceType,
|
||||
Direction: tpact.Direction,
|
||||
Weight: tpact.Weight,
|
||||
ExtraParameters: tpact.ExtraParameters,
|
||||
@@ -657,16 +656,15 @@ func (dbr *DbReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions)
|
||||
return err
|
||||
}
|
||||
}
|
||||
ub, err := dbr.accountDb.GetUserBalance(id)
|
||||
ub, err := dbr.accountDb.GetAccount(id)
|
||||
if err != nil {
|
||||
ub = &UserBalance{
|
||||
Type: UB_TYPE_PREPAID,
|
||||
Id: id,
|
||||
ub = &Account{
|
||||
Id: id,
|
||||
}
|
||||
}
|
||||
ub.ActionTriggers = actionTriggers
|
||||
|
||||
if err := dbr.accountDb.SetUserBalance(ub); err != nil {
|
||||
if err := dbr.accountDb.SetAccount(ub); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ var balance1 string = `{"Id":"*out:192.168.56.66:dan","Type":"*prepaid","Balance
|
||||
var callCost1 string = `{"Direction":"*out","TOR":"call","Tenant":"192.168.56.66","Subject":"dan","Account":"dan","Destination":"+4986517174963","Cost":0.6,"ConnectFee":0,"Timespans":[{"TimeStart":"2013-12-03T14:36:48+01:00","TimeEnd":"2013-12-03T14:37:48+01:00","Cost":0.6,"RateInterval":{"Timing":{"Years":[],"Months":[],"MonthDays":[],"WeekDays":[],"StartTime":"00:00:00","EndTime":""},"Rating":{"ConnectFee":0,"Rates":[{"GroupIntervalStart":0,"Value":0.6,"RateIncrement":60000000000,"RateUnit":60000000000}],"RoundingMethod":"*up","RoundingDecimals":2},"Weight":10},"CallDuration":60000000000,"Increments":null,"MatchedSubject":"*out:192.168.56.66:call:*any","MatchedPrefix":"+49"}]}`
|
||||
|
||||
func TestDebitBalanceForCall1(t *testing.T) {
|
||||
b1 := new(UserBalance)
|
||||
b1 := new(Account)
|
||||
if err := json.Unmarshal([]byte(balance1), b1); err != nil {
|
||||
t.Error("Error restoring balance1: ", err)
|
||||
}
|
||||
@@ -50,7 +50,7 @@ var balanceInsufficient = `{"Id":"*out:192.168.56.66:dan","Type":"*prepaid","Bal
|
||||
var costInsufficient = `{"Direction":"*out","TOR":"call","Tenant":"192.168.56.66","Subject":"dan","Account":"dan","Destination":"+4986517174963","Cost":1,"ConnectFee":3,"Timespans":[{"TimeStart":"2013-12-05T09:52:17+01:00","TimeEnd":"2013-12-05T09:53:17+01:00","Cost":1,"RateInterval":{"Timing":{"Years":[],"Months":[],"MonthDays":[],"WeekDays":[],"StartTime":"00:00:00","EndTime":""},"Rating":{"ConnectFee":3,"Rates":[{"GroupIntervalStart":0,"Value":1,"RateIncrement":60000000000,"RateUnit":60000000000}],"RoundingMethod":"*up","RoundingDecimals":2},"Weight":10},"CallDuration":60000000000,"Increments":null,"MatchedSubject":"*out:192.168.56.66:call:*any","MatchedPrefix":"+49"}]}`
|
||||
|
||||
func TestDebitInsufficientBalance(t *testing.T) {
|
||||
b1 := new(UserBalance)
|
||||
b1 := new(Account)
|
||||
if err := json.Unmarshal([]byte(balanceInsufficient), b1); err != nil {
|
||||
t.Error("Error restoring balance1: ", err)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func (rs *Responder) GetCost(arg CallDescriptor, reply *CallCost) (err error) {
|
||||
r, e := rs.getCallCost(&arg, "Responder.GetCost")
|
||||
*reply, err = *r, e
|
||||
} else {
|
||||
r, e := AccLock.GuardGetCost(arg.GetUserBalanceKey(), func() (*CallCost, error) {
|
||||
r, e := AccLock.GuardGetCost(arg.GetAccountKey(), func() (*CallCost, error) {
|
||||
return arg.GetCost()
|
||||
})
|
||||
*reply, err = *r, e
|
||||
@@ -56,7 +56,7 @@ func (rs *Responder) Debit(arg CallDescriptor, reply *CallCost) (err error) {
|
||||
r, e := rs.getCallCost(&arg, "Responder.Debit")
|
||||
*reply, err = *r, e
|
||||
} else {
|
||||
r, e := AccLock.GuardGetCost(arg.GetUserBalanceKey(), func() (*CallCost, error) {
|
||||
r, e := AccLock.GuardGetCost(arg.GetAccountKey(), func() (*CallCost, error) {
|
||||
return arg.Debit()
|
||||
})
|
||||
*reply, err = *r, e
|
||||
@@ -69,7 +69,7 @@ func (rs *Responder) MaxDebit(arg CallDescriptor, reply *CallCost) (err error) {
|
||||
r, e := rs.getCallCost(&arg, "Responder.MaxDebit")
|
||||
*reply, err = *r, e
|
||||
} else {
|
||||
r, e := AccLock.GuardGetCost(arg.GetUserBalanceKey(), func() (*CallCost, error) {
|
||||
r, e := AccLock.GuardGetCost(arg.GetAccountKey(), func() (*CallCost, error) {
|
||||
return arg.MaxDebit()
|
||||
})
|
||||
*reply, err = *r, e
|
||||
@@ -81,7 +81,7 @@ func (rs *Responder) RefundIncrements(arg CallDescriptor, reply *float64) (err e
|
||||
if rs.Bal != nil {
|
||||
*reply, err = rs.callMethod(&arg, "Responder.RefundIncrements")
|
||||
} else {
|
||||
r, e := AccLock.Guard(arg.GetUserBalanceKey(), func() (float64, error) {
|
||||
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
|
||||
return arg.RefundIncrements()
|
||||
})
|
||||
*reply, err = r, e
|
||||
@@ -93,7 +93,7 @@ func (rs *Responder) DebitCents(arg CallDescriptor, reply *float64) (err error)
|
||||
if rs.Bal != nil {
|
||||
*reply, err = rs.callMethod(&arg, "Responder.DebitCents")
|
||||
} else {
|
||||
r, e := AccLock.Guard(arg.GetUserBalanceKey(), func() (float64, error) {
|
||||
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
|
||||
return arg.DebitCents()
|
||||
})
|
||||
*reply, err = r, e
|
||||
@@ -105,7 +105,7 @@ func (rs *Responder) DebitSMS(arg CallDescriptor, reply *float64) (err error) {
|
||||
if rs.Bal != nil {
|
||||
*reply, err = rs.callMethod(&arg, "Responder.DebitSMS")
|
||||
} else {
|
||||
r, e := AccLock.Guard(arg.GetUserBalanceKey(), func() (float64, error) {
|
||||
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
|
||||
return arg.DebitSMS()
|
||||
})
|
||||
*reply, err = r, e
|
||||
@@ -117,7 +117,7 @@ func (rs *Responder) DebitSeconds(arg CallDescriptor, reply *float64) (err error
|
||||
if rs.Bal != nil {
|
||||
*reply, err = rs.callMethod(&arg, "Responder.DebitSeconds")
|
||||
} else {
|
||||
r, e := AccLock.Guard(arg.GetUserBalanceKey(), func() (float64, error) {
|
||||
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
|
||||
return 0, arg.DebitSeconds()
|
||||
})
|
||||
*reply, err = r, e
|
||||
@@ -129,7 +129,7 @@ func (rs *Responder) GetMaxSessionTime(arg CallDescriptor, reply *float64) (err
|
||||
if rs.Bal != nil {
|
||||
*reply, err = rs.callMethod(&arg, "Responder.GetMaxSessionTime")
|
||||
} else {
|
||||
r, e := AccLock.Guard(arg.GetUserBalanceKey(), func() (float64, error) {
|
||||
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
|
||||
d, err := arg.GetMaxSessionDuration()
|
||||
return float64(d), err
|
||||
})
|
||||
@@ -143,7 +143,7 @@ func (rs *Responder) AddRecievedCallSeconds(arg CallDescriptor, reply *float64)
|
||||
*reply, err = rs.callMethod(&arg, "Responder.AddRecievedCallSeconds")
|
||||
} else {
|
||||
|
||||
r, e := AccLock.Guard(arg.GetUserBalanceKey(), func() (float64, error) {
|
||||
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
|
||||
return 0, arg.AddRecievedCallSeconds()
|
||||
})
|
||||
*reply, err = r, e
|
||||
@@ -155,7 +155,7 @@ func (rs *Responder) FlushCache(arg CallDescriptor, reply *float64) (err error)
|
||||
if rs.Bal != nil {
|
||||
*reply, err = rs.callMethod(&arg, "Responder.FlushCache")
|
||||
} else {
|
||||
r, e := AccLock.Guard(arg.GetUserBalanceKey(), func() (float64, error) {
|
||||
r, e := AccLock.Guard(arg.GetAccountKey(), func() (float64, error) {
|
||||
return 0, arg.FlushCache()
|
||||
})
|
||||
*reply, err = r, e
|
||||
@@ -220,7 +220,7 @@ func (rs *Responder) getBalance(arg *CallDescriptor, balanceId string, reply *Ca
|
||||
return errors.New("No balancer supported for this command right now")
|
||||
}
|
||||
ubKey := arg.Direction + ":" + arg.Tenant + ":" + arg.Account
|
||||
userBalance, err := accountingStorage.GetUserBalance(ubKey)
|
||||
userBalance, err := accountingStorage.GetAccount(ubKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -248,7 +248,7 @@ func (rs *Responder) getCallCost(key *CallDescriptor, method string) (reply *Cal
|
||||
time.Sleep(1 * time.Second) // wait one second and retry
|
||||
} else {
|
||||
reply = &CallCost{}
|
||||
reply, err = AccLock.GuardGetCost(key.GetUserBalanceKey(), func() (*CallCost, error) {
|
||||
reply, err = AccLock.GuardGetCost(key.GetAccountKey(), func() (*CallCost, error) {
|
||||
err = client.Call(method, *key, reply)
|
||||
return reply, err
|
||||
})
|
||||
@@ -271,7 +271,7 @@ func (rs *Responder) callMethod(key *CallDescriptor, method string) (reply float
|
||||
Logger.Info("Waiting for raters to register...")
|
||||
time.Sleep(1 * time.Second) // wait one second and retry
|
||||
} else {
|
||||
reply, err = AccLock.Guard(key.GetUserBalanceKey(), func() (float64, error) {
|
||||
reply, err = AccLock.Guard(key.GetAccountKey(), func() (float64, error) {
|
||||
err = client.Call(method, *key, &reply)
|
||||
return reply, err
|
||||
})
|
||||
|
||||
@@ -37,7 +37,7 @@ const (
|
||||
RATING_PROFILE_PREFIX = "rpf_"
|
||||
ACTION_PREFIX = "act_"
|
||||
SHARED_GROUP_PREFIX = "shg_"
|
||||
USER_BALANCE_PREFIX = "ubl_"
|
||||
ACCOUNT_PREFIX = "ubl_"
|
||||
DESTINATION_PREFIX = "dst_"
|
||||
TEMP_DESTINATION_PREFIX = "tmp_"
|
||||
LOG_CALL_COST_PREFIX = "cco_"
|
||||
@@ -87,8 +87,8 @@ type AccountingStorage interface {
|
||||
SetActions(string, Actions) error
|
||||
GetSharedGroup(string, bool) (*SharedGroup, error)
|
||||
SetSharedGroup(string, *SharedGroup) error
|
||||
GetUserBalance(string) (*UserBalance, error)
|
||||
SetUserBalance(*UserBalance) error
|
||||
GetAccount(string) (*Account, error)
|
||||
SetAccount(*Account) error
|
||||
GetActionTimings(string) (ActionPlan, error)
|
||||
SetActionTimings(string, ActionPlan) error
|
||||
GetAllActionTimings() (map[string]ActionPlan, error)
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/cache2go"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
@@ -249,9 +250,9 @@ func (ms *MapStorage) SetSharedGroup(key string, sg *SharedGroup) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MapStorage) GetUserBalance(key string) (ub *UserBalance, err error) {
|
||||
if values, ok := ms.dict[USER_BALANCE_PREFIX+key]; ok {
|
||||
ub = &UserBalance{Id: key}
|
||||
func (ms *MapStorage) GetAccount(key string) (ub *Account, err error) {
|
||||
if values, ok := ms.dict[ACCOUNT_PREFIX+key]; ok {
|
||||
ub = &Account{Id: key}
|
||||
err = ms.ms.Unmarshal(values, ub)
|
||||
} else {
|
||||
return nil, errors.New("not found")
|
||||
@@ -259,9 +260,9 @@ func (ms *MapStorage) GetUserBalance(key string) (ub *UserBalance, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MapStorage) SetUserBalance(ub *UserBalance) (err error) {
|
||||
func (ms *MapStorage) SetAccount(ub *Account) (err error) {
|
||||
result, err := ms.ms.Marshal(ub)
|
||||
ms.dict[USER_BALANCE_PREFIX+ub.Id] = result
|
||||
ms.dict[ACCOUNT_PREFIX+ub.Id] = result
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -183,13 +183,13 @@ func (ms *MongoStorage) SetActions(key string, as Actions) error {
|
||||
return ms.db.C("actions").Insert(&AcKeyValue{Key: key, Value: as})
|
||||
}
|
||||
|
||||
func (ms *MongoStorage) GetUserBalance(key string) (result *UserBalance, err error) {
|
||||
result = new(UserBalance)
|
||||
func (ms *MongoStorage) GetAccount(key string) (result *Account, err error) {
|
||||
result = new(Account)
|
||||
err = ms.db.C("userbalances").Find(bson.M{"id": key}).One(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (ms *MongoStorage) SetUserBalance(ub *UserBalance) error {
|
||||
func (ms *MongoStorage) SetAccount(ub *Account) error {
|
||||
return ms.db.C("userbalances").Insert(ub)
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ func (rs *RedisStorage) CacheAccounting(actKeys, shgKeys []string) (err error) {
|
||||
// Used to check if specific subject is stored using prefix key attached to entity
|
||||
func (rs *RedisStorage) HasData(category, subject string) (bool, error) {
|
||||
switch category {
|
||||
case DESTINATION_PREFIX, RATING_PLAN_PREFIX, RATING_PROFILE_PREFIX, ACTION_PREFIX, ACTION_TIMING_PREFIX, USER_BALANCE_PREFIX:
|
||||
case DESTINATION_PREFIX, RATING_PLAN_PREFIX, RATING_PROFILE_PREFIX, ACTION_PREFIX, ACTION_TIMING_PREFIX, ACCOUNT_PREFIX:
|
||||
return rs.db.Exists(category + subject)
|
||||
}
|
||||
return false, errors.New("Unsupported category in ExistsData")
|
||||
@@ -342,19 +342,19 @@ func (rs *RedisStorage) SetSharedGroup(key string, sg *SharedGroup) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
func (rs *RedisStorage) GetUserBalance(key string) (ub *UserBalance, err error) {
|
||||
func (rs *RedisStorage) GetAccount(key string) (ub *Account, err error) {
|
||||
var values []byte
|
||||
if values, err = rs.db.Get(USER_BALANCE_PREFIX + key); err == nil {
|
||||
ub = &UserBalance{Id: key}
|
||||
if values, err = rs.db.Get(ACCOUNT_PREFIX + key); err == nil {
|
||||
ub = &Account{Id: key}
|
||||
err = rs.ms.Unmarshal(values, ub)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (rs *RedisStorage) SetUserBalance(ub *UserBalance) (err error) {
|
||||
func (rs *RedisStorage) SetAccount(ub *Account) (err error) {
|
||||
result, err := rs.ms.Marshal(ub)
|
||||
err = rs.db.Set(USER_BALANCE_PREFIX+ub.Id, result)
|
||||
err = rs.db.Set(ACCOUNT_PREFIX+ub.Id, result)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -117,18 +117,17 @@ func TestStoreInterfaces(t *testing.T) {
|
||||
var _ LogStorage = sql
|
||||
}
|
||||
|
||||
|
||||
/************************** Benchmarks *****************************/
|
||||
|
||||
func GetUB() *UserBalance {
|
||||
func GetUB() *Account {
|
||||
uc := &UnitsCounter{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}},
|
||||
Direction: OUTBOUND,
|
||||
BalanceType: SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}},
|
||||
}
|
||||
at := &ActionTrigger{
|
||||
Id: "some_uuid",
|
||||
BalanceId: CREDIT,
|
||||
BalanceType: CREDIT,
|
||||
Direction: OUTBOUND,
|
||||
ThresholdValue: 100.0,
|
||||
DestinationId: "NAT",
|
||||
@@ -137,9 +136,9 @@ func GetUB() *UserBalance {
|
||||
}
|
||||
var zeroTime time.Time
|
||||
zeroTime = zeroTime.UTC() // for deep equal to find location
|
||||
ub := &UserBalance{
|
||||
ub := &Account{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
AllowNegative: true,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}, MINUTES: BalanceChain{&Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{uc, uc},
|
||||
ActionTriggers: ActionTriggerPriotityList{at, at, at},
|
||||
@@ -161,7 +160,7 @@ func BenchmarkMarshallerJSONStoreRestore(b *testing.B) {
|
||||
ub := GetUB()
|
||||
|
||||
ap1 := RatingPlan{}
|
||||
ub1 := &UserBalance{}
|
||||
ub1 := &Account{}
|
||||
b.StartTimer()
|
||||
ms := new(JSONMarshaler)
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -186,7 +185,7 @@ func BenchmarkMarshallerBSONStoreRestore(b *testing.B) {
|
||||
ub := GetUB()
|
||||
|
||||
ap1 := RatingPlan{}
|
||||
ub1 := &UserBalance{}
|
||||
ub1 := &Account{}
|
||||
b.StartTimer()
|
||||
ms := new(BSONMarshaler)
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -210,7 +209,7 @@ func BenchmarkMarshallerJSONBufStoreRestore(b *testing.B) {
|
||||
ub := GetUB()
|
||||
|
||||
ap1 := RatingPlan{}
|
||||
ub1 := &UserBalance{}
|
||||
ub1 := &Account{}
|
||||
b.StartTimer()
|
||||
ms := new(JSONBufMarshaler)
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -234,7 +233,7 @@ func BenchmarkMarshallerGOBStoreRestore(b *testing.B) {
|
||||
ub := GetUB()
|
||||
|
||||
ap1 := RatingPlan{}
|
||||
ub1 := &UserBalance{}
|
||||
ub1 := &Account{}
|
||||
b.StartTimer()
|
||||
ms := new(GOBMarshaler)
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -259,7 +258,7 @@ func BenchmarkMarshallerCodecMsgpackStoreRestore(b *testing.B) {
|
||||
ub := GetUB()
|
||||
|
||||
ap1 := RatingPlan{}
|
||||
ub1 := &UserBalance{}
|
||||
ub1 := &Account{}
|
||||
b.StartTimer()
|
||||
ms := NewCodecMsgpackMarshaler()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -284,7 +283,7 @@ func BenchmarkMarshallerBincStoreRestore(b *testing.B) {
|
||||
ub := GetUB()
|
||||
|
||||
ap1 := RatingPlan{}
|
||||
ub1 := &UserBalance{}
|
||||
ub1 := &Account{}
|
||||
b.StartTimer()
|
||||
ms := NewBincMarshaler()
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
@@ -25,12 +25,14 @@ import (
|
||||
|
||||
// Amount of a trafic of a certain type
|
||||
type UnitsCounter struct {
|
||||
Direction string
|
||||
BalanceId string
|
||||
Direction string
|
||||
BalanceType string
|
||||
// Units float64
|
||||
Balances BalanceChain // first balance is the general one (no destination)
|
||||
}
|
||||
|
||||
// clears balances for this counter
|
||||
// makes sure there are balances for all action triggers
|
||||
func (uc *UnitsCounter) initBalances(ats []*ActionTrigger) {
|
||||
uc.Balances = BalanceChain{&Balance{}} // general balance
|
||||
for _, at := range ats {
|
||||
|
||||
@@ -24,9 +24,9 @@ import (
|
||||
|
||||
func TestUnitsCounterAddBalance(t *testing.T) {
|
||||
uc := &UnitsCounter{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}},
|
||||
Direction: OUTBOUND,
|
||||
BalanceType: SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}},
|
||||
}
|
||||
uc.addUnits(20, "test")
|
||||
if len(uc.Balances) != 3 {
|
||||
@@ -36,9 +36,9 @@ func TestUnitsCounterAddBalance(t *testing.T) {
|
||||
|
||||
func TestUnitsCounterAddBalanceExists(t *testing.T) {
|
||||
uc := &UnitsCounter{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}},
|
||||
Direction: OUTBOUND,
|
||||
BalanceType: SMS,
|
||||
Balances: BalanceChain{&Balance{Value: 1}, &Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}},
|
||||
}
|
||||
uc.addUnits(5, "0723")
|
||||
if len(uc.Balances) != 3 || uc.Balances[1].Value != 15 {
|
||||
|
||||
@@ -135,8 +135,12 @@ func ParseDate(date string) (expDate time.Time, err error) {
|
||||
return expDate, err
|
||||
}
|
||||
expDate = time.Now().Add(d)
|
||||
case date == "*daily":
|
||||
expDate = time.Now().AddDate(0, 0, 1) // add one day
|
||||
case date == "*monthly":
|
||||
expDate = time.Now().AddDate(0, 1, 0) // add one month
|
||||
case date == "*yearly":
|
||||
expDate = time.Now().AddDate(1, 0, 0) // add one year
|
||||
case strings.HasSuffix(date, "Z"):
|
||||
expDate, err = time.Parse(time.RFC3339, date)
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user