unit tests passing

This commit is contained in:
Radu Ioan Fericean
2016-02-16 22:45:23 +02:00
parent db787e3e35
commit e30fe4f6ce
7 changed files with 232 additions and 281 deletions

View File

@@ -353,21 +353,21 @@ func (self *ApierV1) GetAccount(attr *utils.AttrGetAccount, reply *interface{})
type AttrAddBalance struct {
Tenant string
Account string
BalanceUuid string
BalanceId string
BalanceUuid *string
BalanceId *string
BalanceType string
Directions string
Directions *string
Value float64
ExpiryTime string
RatingSubject string
Categories string
DestinationIds string
TimingIds string
Weight float64
SharedGroups string
ExpiryTime *string
RatingSubject *string
Categories *string
DestinationIds *string
TimingIds *string
Weight *float64
SharedGroups *string
Overwrite bool // When true it will reset if the balance is already there
Blocker bool
Disabled bool
Blocker *bool
Disabled *bool
}
func (self *ApierV1) AddBalance(attr *AttrAddBalance, reply *string) error {
@@ -378,13 +378,17 @@ func (self *ApierV1) DebitBalance(attr *AttrAddBalance, reply *string) error {
}
func (self *ApierV1) modifyBalance(aType string, attr *AttrAddBalance, reply *string) error {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType", "Value"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
expTime, err := utils.ParseTimeDetectLayout(attr.ExpiryTime, self.Config.DefaultTimezone)
if err != nil {
*reply = err.Error()
return err
var expTime *time.Time
if attr.ExpiryTime != nil {
expTimeVal, err := utils.ParseTimeDetectLayout(*attr.ExpiryTime, self.Config.DefaultTimezone)
if err != nil {
*reply = err.Error()
return err
}
expTime = &expTimeVal
}
accID := utils.AccountKey(attr.Tenant, attr.Account)
if _, err := self.AccountDb.GetAccount(accID); err != nil {
@@ -403,27 +407,36 @@ func (self *ApierV1) modifyBalance(aType string, attr *AttrAddBalance, reply *st
if attr.Overwrite {
aType += "_reset" // => *topup_reset/*debit_reset
}
at.SetActions(engine.Actions{
&engine.Action{
ActionType: aType,
BalanceType: attr.BalanceType,
Balance: &engine.Balance{
Uuid: attr.BalanceUuid,
Id: attr.BalanceId,
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
Directions: utils.ParseStringMap(attr.Directions),
DestinationIds: utils.ParseStringMap(attr.DestinationIds),
Categories: utils.ParseStringMap(attr.Categories),
Weight: attr.Weight,
SharedGroups: utils.ParseStringMap(attr.SharedGroups),
TimingIDs: utils.ParseStringMap(attr.TimingIds),
Blocker: attr.Blocker,
Disabled: attr.Disabled,
},
a := &engine.Action{
ActionType: aType,
Balance: &engine.BalanceFilter{
Uuid: attr.BalanceUuid,
ID: attr.BalanceId,
Type: utils.StringPointer(attr.BalanceType),
Value: utils.Float64Pointer(attr.Value),
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
Weight: attr.Weight,
Blocker: attr.Blocker,
Disabled: attr.Disabled,
},
})
}
if attr.Directions != nil {
a.Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(*attr.Directions))
}
if attr.DestinationIds != nil {
a.Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(*attr.DestinationIds))
}
if attr.Categories != nil {
a.Balance.Categories = utils.StringMapPointer(utils.ParseStringMap(*attr.Categories))
}
if attr.SharedGroups != nil {
a.Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(*attr.SharedGroups))
}
if attr.TimingIds != nil {
a.Balance.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(*attr.TimingIds))
}
at.SetActions(engine.Actions{a})
if err := at.Execute(); err != nil {
*reply = err.Error()
return err
@@ -432,7 +445,95 @@ func (self *ApierV1) modifyBalance(aType string, attr *AttrAddBalance, reply *st
return nil
}
func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) error {
type AttrSetBalance struct {
Tenant string
Account string
BalanceType string
BalanceUUID *string
BalanceID *string
Directions *string
Value *float64
ExpiryTime *string
RatingSubject *string
Categories *string
DestinationIds *string
TimingIds *string
Weight *float64
SharedGroups *string
Blocker *bool
Disabled *bool
}
func (self *ApierV1) SetBalance(aType string, attr *AttrSetBalance, reply *string) error {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if (attr.BalanceID == nil || *attr.BalanceID == "") &&
(attr.BalanceUUID == nil || *attr.BalanceUUID == "") {
return utils.NewErrMandatoryIeMissing("BalanceID", "or", "BalanceUUID")
}
var expTime *time.Time
if attr.ExpiryTime != nil {
expTimeVal, err := utils.ParseTimeDetectLayout(*attr.ExpiryTime, self.Config.DefaultTimezone)
if err != nil {
*reply = err.Error()
return err
}
expTime = &expTimeVal
}
accID := utils.AccountKey(attr.Tenant, attr.Account)
if _, err := self.AccountDb.GetAccount(accID); err != nil {
// create account if not exists
account := &engine.Account{
Id: accID,
}
if err := self.AccountDb.SetAccount(account); err != nil {
*reply = err.Error()
return err
}
}
at := &engine.ActionTiming{}
at.SetAccountIDs(utils.StringMap{accID: true})
a := &engine.Action{
ActionType: engine.SET_BALANCE,
Balance: &engine.BalanceFilter{
Uuid: attr.BalanceUUID,
ID: attr.BalanceID,
Type: utils.StringPointer(attr.BalanceType),
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
Weight: attr.Weight,
Blocker: attr.Blocker,
Disabled: attr.Disabled,
},
}
if attr.Directions != nil {
a.Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(*attr.Directions))
}
if attr.DestinationIds != nil {
a.Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(*attr.DestinationIds))
}
if attr.Categories != nil {
a.Balance.Categories = utils.StringMapPointer(utils.ParseStringMap(*attr.Categories))
}
if attr.SharedGroups != nil {
a.Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(*attr.SharedGroups))
}
if attr.TimingIds != nil {
a.Balance.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(*attr.TimingIds))
}
at.SetActions(engine.Actions{a})
if err := at.Execute(); err != nil {
*reply = err.Error()
return err
}
*reply = OK
return nil
}
/*func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) error {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
@@ -475,16 +576,20 @@ func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) e
}
*reply = OK
return nil
}
}*/
func (self *ApierV1) RemoveBalances(attr *AttrAddBalance, reply *string) error {
func (self *ApierV1) RemoveBalances(attr *AttrSetBalance, reply *string) error {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
expTime, err := utils.ParseTimeDetectLayout(attr.ExpiryTime, self.Config.DefaultTimezone)
if err != nil {
*reply = err.Error()
return err
var expTime *time.Time
if attr.ExpiryTime != nil {
expTimeVal, err := utils.ParseTimeDetectLayout(*attr.ExpiryTime, self.Config.DefaultTimezone)
if err != nil {
*reply = err.Error()
return err
}
expTime = &expTimeVal
}
accID := utils.AccountKey(attr.Tenant, attr.Account)
if _, err := self.AccountDb.GetAccount(accID); err != nil {
@@ -493,138 +598,36 @@ func (self *ApierV1) RemoveBalances(attr *AttrAddBalance, reply *string) error {
at := &engine.ActionTiming{}
at.SetAccountIDs(utils.StringMap{accID: true})
at.SetActions(engine.Actions{
&engine.Action{
ActionType: engine.REMOVE_BALANCE,
BalanceType: attr.BalanceType,
Balance: &engine.Balance{
Uuid: attr.BalanceUuid,
Id: attr.BalanceId,
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
Directions: utils.ParseStringMap(attr.Directions),
DestinationIds: utils.ParseStringMap(attr.DestinationIds),
Categories: utils.ParseStringMap(attr.Categories),
Weight: attr.Weight,
SharedGroups: utils.ParseStringMap(attr.SharedGroups),
TimingIDs: utils.ParseStringMap(attr.TimingIds),
Blocker: attr.Blocker,
Disabled: attr.Disabled,
},
a := &engine.Action{
ActionType: engine.SET_BALANCE,
Balance: &engine.BalanceFilter{
Uuid: attr.BalanceUUID,
ID: attr.BalanceID,
Type: utils.StringPointer(attr.BalanceType),
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
Weight: attr.Weight,
Blocker: attr.Blocker,
Disabled: attr.Disabled,
},
})
if err := at.Execute(); err != nil {
*reply = err.Error()
return err
}
*reply = OK
return nil
}
type AttrSetBalance struct {
Tenant string
Account string
BalanceType string
BalanceUUID *string
BalanceID *string
Directions *[]string
Value *float64
ExpiryTime *string
RatingSubject *string
Categories *[]string
DestinationIDs *[]string
SharedGroups *[]string
TimingIDs *[]string
Weight *float64
Blocker *bool
Disabled *bool
expTime time.Time
}
func (attr *AttrSetBalance) SetBalance(b *engine.Balance) {
if b == nil {
return
}
if attr.Directions != nil {
b.Directions = utils.StringMapFromSlice(*attr.Directions)
a.Balance.Directions = utils.StringMapPointer(utils.ParseStringMap(*attr.Directions))
}
if attr.Value != nil {
b.Value = *attr.Value
}
if attr.ExpiryTime != nil {
b.ExpirationDate = attr.expTime
}
if attr.RatingSubject != nil {
b.RatingSubject = *attr.RatingSubject
if attr.DestinationIds != nil {
a.Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(*attr.DestinationIds))
}
if attr.Categories != nil {
b.Categories = utils.StringMapFromSlice(*attr.Categories)
}
if attr.DestinationIDs != nil {
b.DestinationIds = utils.StringMapFromSlice(*attr.DestinationIDs)
a.Balance.Categories = utils.StringMapPointer(utils.ParseStringMap(*attr.Categories))
}
if attr.SharedGroups != nil {
b.SharedGroups = utils.StringMapFromSlice(*attr.SharedGroups)
a.Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(*attr.SharedGroups))
}
if attr.TimingIDs != nil {
b.TimingIDs = utils.StringMapFromSlice(*attr.TimingIDs)
if attr.TimingIds != nil {
a.Balance.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(*attr.TimingIds))
}
if attr.Weight != nil {
b.Weight = *attr.Weight
}
if attr.Blocker != nil {
b.Blocker = *attr.Blocker
}
if attr.Disabled != nil {
b.Disabled = *attr.Disabled
}
b.SetDirty() // Mark the balance as dirty since we have modified and it should be checked by action triggers
}
/* // SetAccount api using action and action timing to set balance,
//to be uncommented when using pointers in action.balance
func (self *ApierV1) SetBalance(attr *AttrAddBalance, reply *string) error {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if attr.BalanceID == "" && attr.BalanceUUID == "" {
return utils.NewErrMandatoryIeMissing("BalanceID", "or", "BalanceUUID")
}
expTime, err := utils.ParseTimeDetectLayout(attr.ExpiryTime, self.Config.DefaultTimezone)
if err != nil {
*reply = err.Error()
return err
}
accID := utils.ConcatenatedKey(attr.Tenant, attr.Account)
if _, err := self.AccountDb.GetAccount(accID); err != nil {
return utils.ErrNotFound
}
at := &engine.ActionTiming{}
at.SetAccountIDs(utils.StringMap{accID: true})
at.SetActions(engine.Actions{
&engine.Action{
ActionType: engine.SET_BALANCE,
BalanceType: attr.BalanceType,
Balance: &engine.Balance{
Uuuid: attr.BalanceUUID,
ID: attr.BalanceID,
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
Directions: utils.ParseStringMap(attr.Directions),
DestinationIDs: utils.ParseStringMap(attr.DestinationIDs),
Categories: utils.ParseStringMap(attr.Categories),
Weight: attr.Weight,
SharedGroups: utils.ParseStringMap(attr.SharedGroups),
TimingIDs: utils.ParseStringMap(attr.TimingIDs),
Blocker: true,
Disabled: attr.Disabled,
},
},
})
at.SetActions(engine.Actions{a})
if err := at.Execute(); err != nil {
*reply = err.Error()
return err
@@ -632,16 +635,13 @@ func (self *ApierV1) SetBalance(attr *AttrAddBalance, reply *string) error {
*reply = OK
return nil
}
*/
/* To be removed after the above one proves reliable
func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if (attr.BalanceID == nil || *attr.BalanceID == "") &&
(attr.BalanceUUID == nil || *attr.BalanceUUID == "") {
return utils.NewErrMandatoryIeMissing("BalanceID", "or", "BalanceUUID")
}
var err error
if attr.ExpiryTime != nil {
attr.expTime, err = utils.ParseTimeDetectLayout(*attr.ExpiryTime, self.Config.DefaultTimezone)
@@ -727,3 +727,4 @@ func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error {
*reply = utils.OK
return nil
}
*/

View File

@@ -19,12 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package v1
import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"path"
"strconv"
"strings"
"time"
@@ -502,23 +502,37 @@ func (self *ApierV1) SetActions(attrs utils.AttrSetActions, reply *string) error
}
storeActions := make(engine.Actions, len(attrs.Actions))
for idx, apiAct := range attrs.Actions {
var units *float64
if x, err := strconv.ParseFloat(apiAct.Units, 64); err == nil {
units = &x
} else {
return err
}
var weight *float64
if x, err := strconv.ParseFloat(apiAct.BalanceWeight, 64); err == nil {
weight = &x
} else {
return err
}
a := &engine.Action{
Id: utils.GenUUID(),
ActionType: apiAct.Identifier,
BalanceType: apiAct.BalanceType,
Weight: apiAct.Weight,
ExpirationString: apiAct.ExpiryTime,
ExtraParameters: apiAct.ExtraParameters,
Filter: apiAct.Filter,
Balance: &engine.Balance{
Uuid: utils.GenUUID(),
Id: apiAct.BalanceId,
Value: apiAct.Units,
Weight: apiAct.BalanceWeight,
Directions: utils.ParseStringMap(apiAct.Directions),
DestinationIds: utils.ParseStringMap(apiAct.DestinationIds),
RatingSubject: apiAct.RatingSubject,
SharedGroups: utils.ParseStringMap(apiAct.SharedGroups),
Balance: &engine.BalanceFilter{ // TODO: update this part
Uuid: utils.StringPointer(utils.GenUUID()),
ID: utils.StringPointer(apiAct.BalanceId),
Type: utils.StringPointer(apiAct.BalanceType),
Value: units,
Weight: weight,
Directions: utils.StringMapPointer(utils.ParseStringMap(apiAct.Directions)),
DestinationIDs: utils.StringMapPointer(utils.ParseStringMap(apiAct.DestinationIds)),
RatingSubject: utils.StringPointer(apiAct.RatingSubject),
SharedGroups: utils.StringMapPointer(utils.ParseStringMap(apiAct.SharedGroups)),
},
}
storeActions[idx] = a
@@ -543,24 +557,25 @@ func (self *ApierV1) GetActions(actsId string, reply *[]*utils.TPAction) error {
}
for _, engAct := range engActs {
act := &utils.TPAction{Identifier: engAct.ActionType,
BalanceType: engAct.BalanceType,
ExpiryTime: engAct.ExpirationString,
ExtraParameters: engAct.ExtraParameters,
Filter: engAct.Filter,
Weight: engAct.Weight,
}
if engAct.Balance != nil {
act.Units = engAct.Balance.GetValue()
act.Directions = engAct.Balance.Directions.String()
act.DestinationIds = engAct.Balance.DestinationIds.String()
act.RatingSubject = engAct.Balance.RatingSubject
act.SharedGroups = engAct.Balance.SharedGroups.String()
act.BalanceWeight = engAct.Balance.Weight
act.TimingTags = engAct.Balance.TimingIDs.String()
act.BalanceId = engAct.Balance.Id
act.Categories = engAct.Balance.Categories.String()
act.BalanceBlocker = engAct.Balance.Blocker
act.BalanceDisabled = engAct.Balance.Disabled
bf := engAct.Balance
if bf != nil {
act.BalanceType = bf.GetType()
act.Units = strconv.FormatFloat(bf.GetValue(), 'f', -1, 64)
act.Directions = bf.GetDirections().String()
act.DestinationIds = bf.GetDestinationIDs().String()
act.RatingSubject = bf.GetRatingSubject()
act.SharedGroups = bf.GetSharedGroups().String()
act.BalanceWeight = strconv.FormatFloat(bf.GetWeight(), 'f', -1, 64)
act.TimingTags = bf.GetTimingIDs().String()
act.BalanceId = bf.GetID()
act.Categories = bf.GetCategories().String()
act.BalanceBlocker = strconv.FormatBool(bf.GetBlocker())
act.BalanceDisabled = strconv.FormatBool(bf.GetDisabled())
}
acts = append(acts, act)
}
@@ -663,74 +678,6 @@ func (self *ApierV1) GetActionPlan(attr AttrGetActionPlan, reply *[]*engine.Acti
return nil
}
type AttrResetTriggeredAction struct {
Id string
Tenant string
Account string
Directions string
BalanceType string
ThresholdType string
ThresholdValue float64
DestinationId string
BalanceWeight float64
BalanceRatingSubject string
BalanceSharedGroup string
}
func (self *ApierV1) ResetTriggeredActions(attr AttrResetTriggeredAction, reply *string) error {
var a *engine.Action
if attr.Id != "" {
// we can identify the trigger by the id
a = &engine.Action{Id: attr.Id}
} else {
extraParameters, err := json.Marshal(struct {
ThresholdType string
ThresholdValue float64
DestinationId string
BalanceWeight float64
BalanceRatingSubject string
BalanceDirections string
BalanceSharedGroup string
}{
attr.ThresholdType,
attr.ThresholdValue,
attr.DestinationId,
attr.BalanceWeight,
attr.Directions,
attr.BalanceRatingSubject,
attr.BalanceSharedGroup,
})
if err != nil {
*reply = err.Error()
return err
}
a = &engine.Action{
BalanceType: attr.BalanceType,
ExtraParameters: string(extraParameters),
}
}
accID := utils.AccountKey(attr.Tenant, attr.Account)
_, err := engine.Guardian.Guard(func() (interface{}, error) {
acc, err := self.AccountDb.GetAccount(accID)
if err != nil {
return 0, err
}
acc.ResetActionTriggers(a)
if err = self.AccountDb.SetAccount(acc); err != nil {
return 0, err
}
return 0, nil
}, 0, accID)
if err != nil {
*reply = err.Error()
return err
}
*reply = OK
return nil
}
// Process dependencies and load a specific AccountActions profile from storDb into dataDb.
func (self *ApierV1) LoadAccountActions(attrs utils.TPAccountActions, reply *string) error {
if len(attrs.TPid) == 0 {

View File

@@ -488,8 +488,8 @@ func TestApierTPActions(t *testing.T) {
}
reply := ""
act := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: "PREPAID_10", Actions: []*utils.TPAction{
&utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited",
DestinationIds: "*any", BalanceWeight: 10, Weight: 10},
&utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: "10", ExpiryTime: "*unlimited",
DestinationIds: "*any", BalanceWeight: "10", Weight: 10},
}}
actWarn := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: "WARN_VIA_HTTP", Actions: []*utils.TPAction{
&utils.TPAction{Identifier: "*call_url", ExtraParameters: "http://localhost:8000", Weight: 10},
@@ -955,7 +955,7 @@ func TestApierSetActions(t *testing.T) {
if !*testLocal {
return
}
act1 := &utils.TPAction{Identifier: engine.TOPUP_RESET, BalanceType: utils.MONETARY, Directions: utils.OUT, Units: 75.0, ExpiryTime: engine.UNLIMITED, Weight: 20.0}
act1 := &utils.TPAction{Identifier: engine.TOPUP_RESET, BalanceType: utils.MONETARY, Directions: utils.OUT, Units: "75.0", ExpiryTime: engine.UNLIMITED, Weight: 20.0}
attrs1 := &utils.AttrSetActions{ActionsId: "ACTS_1", Actions: []*utils.TPAction{act1}}
reply1 := ""
if err := rater.Call("ApierV1.SetActions", attrs1, &reply1); err != nil {
@@ -974,7 +974,7 @@ func TestApierGetActions(t *testing.T) {
return
}
expectActs := []*utils.TPAction{
&utils.TPAction{Identifier: engine.TOPUP_RESET, BalanceType: utils.MONETARY, Directions: utils.OUT, Units: 75.0, ExpiryTime: engine.UNLIMITED, Weight: 20.0}}
&utils.TPAction{Identifier: engine.TOPUP_RESET, BalanceType: utils.MONETARY, Directions: utils.OUT, Units: "75.0", ExpiryTime: engine.UNLIMITED, Weight: 20.0}}
var reply []*utils.TPAction
if err := rater.Call("ApierV1.GetActions", "ACTS_1", &reply); err != nil {

View File

@@ -238,44 +238,44 @@ func (self *ApierV1) SetAccountActionTriggers(attr AttrSetAccountActionTriggers,
at.ActivationDate = actTime
}
if attr.BalanceId != nil {
at.BalanceId = *attr.BalanceId
at.Balance.ID = attr.BalanceId
}
if attr.BalanceType != nil {
at.BalanceType = *attr.BalanceType
at.Balance.Type = attr.BalanceType
}
if attr.BalanceDirections != nil {
at.BalanceDirections = utils.NewStringMap(*attr.BalanceDirections...)
at.Balance.Directions = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceDirections...))
}
if attr.BalanceDestinationIds != nil {
at.BalanceDestinationIds = utils.NewStringMap(*attr.BalanceDestinationIds...)
at.Balance.DestinationIDs = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceDestinationIds...))
}
if attr.BalanceWeight != nil {
at.BalanceWeight = *attr.BalanceWeight
at.Balance.Weight = attr.BalanceWeight
}
if attr.BalanceExpirationDate != nil {
balanceExpTime, err := utils.ParseDate(*attr.BalanceExpirationDate)
if err != nil {
return 0, err
}
at.BalanceExpirationDate = balanceExpTime
at.Balance.ExpirationDate = &balanceExpTime
}
if attr.BalanceTimingTags != nil {
at.BalanceTimingTags = utils.NewStringMap(*attr.BalanceTimingTags...)
at.Balance.TimingIDs = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceTimingTags...))
}
if attr.BalanceRatingSubject != nil {
at.BalanceRatingSubject = *attr.BalanceRatingSubject
at.Balance.RatingSubject = attr.BalanceRatingSubject
}
if attr.BalanceCategories != nil {
at.BalanceCategories = utils.NewStringMap(*attr.BalanceCategories...)
at.Balance.Categories = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceCategories...))
}
if attr.BalanceSharedGroups != nil {
at.BalanceSharedGroups = utils.NewStringMap(*attr.BalanceSharedGroups...)
at.Balance.SharedGroups = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceSharedGroups...))
}
if attr.BalanceBlocker != nil {
at.BalanceBlocker = *attr.BalanceBlocker
at.Balance.Blocker = attr.BalanceBlocker
}
if attr.BalanceDisabled != nil {
at.BalanceDisabled = *attr.BalanceDisabled
at.Balance.Disabled = attr.BalanceDisabled
}
if attr.MinQueuedItems != nil {
at.MinQueuedItems = *attr.MinQueuedItems

View File

@@ -723,6 +723,9 @@ func (acc *Account) InitCounters() {
}
}
}
if len(acc.UnitCounters) == 0 {
acc.UnitCounters = nil // leave it nil if empty
}
}
func (acc *Account) CleanExpiredStuff() {

View File

@@ -57,7 +57,7 @@ const (
DENY_NEGATIVE = "*deny_negative"
RESET_ACCOUNT = "*reset_account"
REMOVE_ACCOUNT = "*remove_account"
SET_BALANCE = "*set_balance" // not ready for production until switching to pointers
SET_BALANCE = "*set_balance"
REMOVE_BALANCE = "*remove_balance"
TOPUP_RESET = "*topup_reset"
TOPUP = "*topup"

View File

@@ -86,7 +86,7 @@ func TestAcntActsDisableAcnt(t *testing.T) {
if acnt, err := acntDbAcntActs.GetAccount(acnt1Tag); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expectAcnt, acnt) {
t.Errorf("Expecting: %+v, received: %+v", expectAcnt, acnt)
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectAcnt), utils.ToJSON(acnt))
}
}