diff --git a/apier/v1/accounts.go b/apier/v1/accounts.go index 1e34a1aad..52885983e 100644 --- a/apier/v1/accounts.go +++ b/apier/v1/accounts.go @@ -20,6 +20,7 @@ package v1 import ( "fmt" + "log" "math" "strings" "time" @@ -482,6 +483,7 @@ func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error { expTime = &expTimeVal } accID := utils.AccountKey(attr.Tenant, attr.Account) + log.Print("ACC: ", utils.ToIJSON(attr)) if _, err := self.AccountDb.GetAccount(accID); err != nil { // create account if not exists account := &engine.Account{ @@ -533,51 +535,6 @@ func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error { 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...) - } - 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.ENABLE_DISABLE_BALANCE, - BalanceType: attr.BalanceType, - Balance: &engine.Balance{ - Uuid: attr.BalanceUuid, - Id: attr.BalanceId, - Value: attr.Value, - ExpirationDate: expTime, - RatingSubject: attr.RatingSubject, - Categories: utils.ParseStringMap(attr.Categories), - Directions: utils.ParseStringMap(attr.Directions), - DestinationIds: utils.ParseStringMap(attr.DestinationIds), - Weight: attr.Weight, - SharedGroups: utils.ParseStringMap(attr.SharedGroups), - TimingIDs: utils.ParseStringMap(attr.TimingIds), - Blocker: attr.Blocker, - Disabled: attr.Disabled, - }, - }, - }) - if err := at.Execute(); err != nil { - *reply = err.Error() - return err - } - *reply = OK - return nil -}*/ - 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...) diff --git a/engine/account.go b/engine/account.go index 5043ba404..ef3f6a88f 100644 --- a/engine/account.go +++ b/engine/account.go @@ -90,90 +90,76 @@ func (ub *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duratio } // sets all the fields of the balance -func (ub *Account) setBalanceAction(a *Action) error { +func (acc *Account) setBalanceAction(a *Action) error { if a == nil { return errors.New("nil action") } - bClone := a.Balance.CreateBalance() - if bClone == nil { - return errors.New("nil balance") + if a.Balance.Type == nil { + return errors.New("missing balance type") } - // load ValueFactor if defined in extra parametrs - if a.ExtraParameters != "" { - vf := ValueFactor{} - err := json.Unmarshal([]byte(a.ExtraParameters), &vf) - if err == nil { - bClone.Factor = vf - } else { - utils.Logger.Warning(fmt.Sprintf("Could load value factor from actions: extra parametrs: %s", a.ExtraParameters)) - } + balanceType := *a.Balance.Type + if acc.BalanceMap == nil { + acc.BalanceMap = make(map[string]BalanceChain, 1) } - if ub.BalanceMap == nil { - ub.BalanceMap = make(map[string]BalanceChain, 1) - } - found := false - balanceType := a.Balance.GetType() var previousSharedGroups utils.StringMap // kept for comparison - for _, b := range ub.BalanceMap[balanceType] { + var balance *Balance + var found bool + for _, b := range acc.BalanceMap[balanceType] { if b.IsExpired() { - continue // just to be safe (cleaned expired balances above) + continue } - b.account = ub - if b.MatchFilter(a.Balance, false) { // for Id or Uuid only - bClone.Id = b.Id - bClone.Uuid = b.Uuid + if (a.Balance.Uuid != nil && b.Uuid == *a.Balance.Uuid) || + (a.Balance.ID != nil && b.Id == *a.Balance.ID) { previousSharedGroups = b.SharedGroups - if bClone.Id != utils.META_DEFAULT { - *b = *bClone - } else { - b.Value = bClone.GetValue() - } + balance = b found = true break // only set one balance } } + // if it is not found then we add it to the list - if !found { - // check if the Id is *default (user trying to create the default balance) - // use only it's value value - if bClone.Id == utils.META_DEFAULT { - bClone = &Balance{ - Id: utils.META_DEFAULT, - Value: bClone.GetValue(), - } - } - bClone.dirty = true // Mark the balance as dirty since we have modified and it should be checked by action triggers - bClone.Uuid = utils.GenUUID() // alway overwrite the uuid for consistency - ub.BalanceMap[balanceType] = append(ub.BalanceMap[balanceType], bClone) + if balance == nil { + balance = &Balance{} + balance.Uuid = utils.GenUUID() // alway overwrite the uuid for consistency + acc.BalanceMap[balanceType] = append(acc.BalanceMap[balanceType], balance) } - if !found || !previousSharedGroups.Equal(bClone.SharedGroups) { + if a.Balance.ID != nil && *a.Balance.ID == utils.META_DEFAULT { + balance.Id = utils.META_DEFAULT + if a.Balance.Value != nil { + balance.Value = *a.Balance.Value + } + } else { + a.Balance.ModifyBalance(balance) + } + + if !found || !previousSharedGroups.Equal(balance.SharedGroups) { _, err := Guardian.Guard(func() (interface{}, error) { - for sgId := range bClone.SharedGroups { + for sgID := range balance.SharedGroups { // add shared group member - sg, err := ratingStorage.GetSharedGroup(sgId, false) + sg, err := ratingStorage.GetSharedGroup(sgID, false) if err != nil || sg == nil { //than is problem - utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgId)) + utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID)) } else { - if _, found := sg.MemberIds[ub.Id]; !found { + if _, found := sg.MemberIds[acc.Id]; !found { // add member and save if sg.MemberIds == nil { sg.MemberIds = make(utils.StringMap) } - sg.MemberIds[ub.Id] = true + sg.MemberIds[acc.Id] = true ratingStorage.SetSharedGroup(sg) } } } return 0, nil - }, 0, bClone.SharedGroups.Slice()...) + }, 0, balance.SharedGroups.Slice()...) if err != nil { return err } } - ub.InitCounters() - ub.ExecuteActionTriggers(nil) + acc.InitCounters() + acc.ExecuteActionTriggers(nil) return nil } diff --git a/engine/action_plan.go b/engine/action_plan.go index a9081b90a..b27f7e448 100644 --- a/engine/action_plan.go +++ b/engine/action_plan.go @@ -283,7 +283,7 @@ func (at *ActionTiming) Execute() (err error) { } for accID, _ := range at.accountIDs { _, err = Guardian.Guard(func() (interface{}, error) { - ub, err := accountingStorage.GetAccount(accID) + acc, err := accountingStorage.GetAccount(accID) if err != nil { utils.Logger.Warning(fmt.Sprintf("Could not get account id: %s. Skipping!", accID)) return 0, err @@ -294,7 +294,7 @@ func (at *ActionTiming) Execute() (err error) { //log.Print("A: ", utils.ToJSON(a)) // check action filter if len(a.Filter) > 0 { - matched, err := ub.matchActionFilter(a.Filter) + matched, err := acc.matchActionFilter(a.Filter) //log.Print("Checkng: ", a.Filter, matched) if err != nil { return 0, err @@ -303,7 +303,7 @@ func (at *ActionTiming) Execute() (err error) { continue } } - if ub.Disabled && a.ActionType != ENABLE_ACCOUNT { + if acc.Disabled && a.ActionType != ENABLE_ACCOUNT { continue // disabled acocunts are not removed from action plan //return 0, fmt.Errorf("Account %s is disabled", accID) } @@ -320,7 +320,7 @@ func (at *ActionTiming) Execute() (err error) { transactionFailed = true break } - if err := actionFunction(ub, nil, a, aac); err != nil { + if err := actionFunction(acc, nil, a, aac); err != nil { utils.Logger.Err(fmt.Sprintf("Error executing action %s: %v!", a.ActionType, err)) transactionFailed = true break @@ -330,7 +330,7 @@ func (at *ActionTiming) Execute() (err error) { } } if !transactionFailed && !removeAccountActionFound { - accountingStorage.SetAccount(ub) + accountingStorage.SetAccount(acc) } return 0, nil }, 0, accID) diff --git a/engine/balance_filter.go b/engine/balance_filter.go index 28d9c912f..1c8a214ba 100644 --- a/engine/balance_filter.go +++ b/engine/balance_filter.go @@ -279,3 +279,43 @@ func (bp *BalanceFilter) HasExpirationDate() bool { } return (*bp.ExpirationDate).IsZero() } + +func (bf *BalanceFilter) ModifyBalance(b *Balance) { + if b == nil { + return + } + if bf.Directions != nil { + b.Directions = *bf.Directions + } + if bf.Value != nil { + b.Value = *bf.Value + } + if bf.ExpirationDate != nil { + b.ExpirationDate = *bf.ExpirationDate + } + if bf.RatingSubject != nil { + b.RatingSubject = *bf.RatingSubject + } + if bf.Categories != nil { + b.Categories = *bf.Categories + } + if bf.DestinationIDs != nil { + b.DestinationIds = *bf.DestinationIDs + } + if bf.SharedGroups != nil { + b.SharedGroups = *bf.SharedGroups + } + if bf.TimingIDs != nil { + b.TimingIDs = *bf.TimingIDs + } + if bf.Weight != nil { + b.Weight = *bf.Weight + } + if bf.Blocker != nil { + b.Blocker = *bf.Blocker + } + if bf.Disabled != nil { + b.Disabled = *bf.Disabled + } + b.SetDirty() // Mark the balance as dirty since we have modified and it should be checked by action triggers +}