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) if err != nil { *reply = err.Error() return err } } accID := utils.ConcatenatedKey(attr.Tenant, attr.Account) _, err = engine.Guardian.Guard(func() (interface{}, error) { account, err := self.AccountDb.GetAccount(accID) if err != nil { return 0, utils.ErrNotFound } if account.BalanceMap == nil { account.BalanceMap = make(map[string]engine.BalanceChain, 1) } var previousSharedGroups utils.StringMap // kept for comparison var balance *engine.Balance var found bool for _, b := range account.BalanceMap[attr.BalanceType] { if b.IsExpired() { continue } if (attr.BalanceUUID != nil && b.Uuid == *attr.BalanceUUID) || (attr.BalanceID != nil && b.Id == *attr.BalanceID) { previousSharedGroups = b.SharedGroups balance = b found = true break // only set one balance } } // if it is not found then we add it to the list if balance == nil { balance = &engine.Balance{} balance.Uuid = utils.GenUUID() // alway overwrite the uuid for consistency account.BalanceMap[attr.BalanceType] = append(account.BalanceMap[attr.BalanceType], balance) } if attr.BalanceID != nil && *attr.BalanceID == utils.META_DEFAULT { balance.Id = utils.META_DEFAULT if attr.Value != nil { balance.Value = *attr.Value } } else { attr.SetBalance(balance) } if !found || !previousSharedGroups.Equal(balance.SharedGroups) { _, err = engine.Guardian.Guard(func() (interface{}, error) { for sgID := range balance.SharedGroups { // add shared group member sg, err := self.RatingDb.GetSharedGroup(sgID, false) if err != nil || sg == nil { //than is problem utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID)) } else { if _, found := sg.MemberIds[account.Id]; !found { // add member and save if sg.MemberIds == nil { sg.MemberIds = make(utils.StringMap) } sg.MemberIds[account.Id] = true self.RatingDb.SetSharedGroup(sg) } } } return 0, nil }, 0, balance.SharedGroups.Slice()...) } account.InitCounters() account.ExecuteActionTriggers(nil) self.AccountDb.SetAccount(account) return 0, nil }, 0, accID) if err != nil { *reply = err.Error() return err } *reply = utils.OK return nil }
func (attr *AttrSetBalance) SetBalance(b *engine.Balance) { if b == nil { return } if attr.Directions != nil { b.Directions = utils.StringMapFromSlice(*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.Categories != nil { b.Categories = utils.StringMapFromSlice(*attr.Categories) } if attr.DestinationIDs != nil { b.DestinationIds = utils.StringMapFromSlice(*attr.DestinationIDs) } if attr.SharedGroups != nil { b.SharedGroups = utils.StringMapFromSlice(*attr.SharedGroups) } if attr.TimingIDs != nil { b.TimingIDs = utils.StringMapFromSlice(*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 }