diff --git a/apier/v1/accounts.go b/apier/v1/accounts.go deleted file mode 100644 index da0449699..000000000 --- a/apier/v1/accounts.go +++ /dev/null @@ -1,738 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package v1 - -import ( - "errors" - "math" - "strings" - "time" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/guardian" - "github.com/cgrates/cgrates/utils" -) - -type AccountActionTiming struct { - ActionPlanId string // The id of the ActionPlanId profile attached to the account - Uuid string // The id to reference this particular ActionTiming - ActionsId string // The id of actions which will be executed - NextExecTime time.Time // Next execution time -} - -func (apierSv1 *APIerSv1) GetAccountActionPlan(attrs *utils.TenantAccount, reply *[]*AccountActionTiming) error { - if missing := utils.MissingStructFields(attrs, []string{utils.AccountField}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(strings.Join(missing, ","), "") - } - tnt := attrs.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - acntID := utils.ConcatenatedKey(tnt, attrs.Account) - acntATsIf, err := guardian.Guardian.Guard(func() (interface{}, error) { - acntAPids, err := apierSv1.DataManager.GetAccountActionPlans(acntID, false, utils.NonTransactional) - if err != nil && err != utils.ErrNotFound { - return nil, utils.NewErrServerError(err) - } - var acntAPs []*engine.ActionPlan - for _, apID := range acntAPids { - if ap, err := apierSv1.DataManager.GetActionPlan(apID, false, utils.NonTransactional); err != nil { - return nil, err - } else if ap != nil { - acntAPs = append(acntAPs, ap) - } - } - - accountATs := make([]*AccountActionTiming, 0) // needs to be initialized if remains empty - for _, ap := range acntAPs { - for _, at := range ap.ActionTimings { - accountATs = append(accountATs, &AccountActionTiming{ - ActionPlanId: ap.Id, - Uuid: at.Uuid, - ActionsId: at.ActionsID, - NextExecTime: at.GetNextStartTime(time.Now()), - }) - } - } - return accountATs, nil - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.ActionPlanPrefix) - if err != nil { - return err - } - *reply = acntATsIf.([]*AccountActionTiming) - return nil -} - -type AttrRemoveActionTiming struct { - ActionPlanId string // Id identifying the ActionTimings profile - ActionTimingId string // Internal CGR id identifying particular ActionTiming, *all for all user related ActionTimings to be canceled - Tenant string // Tenant the account belongs to - Account string // Account name - ReloadScheduler bool // If set it will reload the scheduler after adding -} - -// Removes an ActionTimings or parts of it depending on filters being set -func (apierSv1 *APIerSv1) RemoveActionTiming(attrs *AttrRemoveActionTiming, reply *string) (err error) { - if missing := utils.MissingStructFields(attrs, []string{"ActionPlanId"}); len(missing) != 0 { // Only mandatory ActionPlanId - return utils.NewErrMandatoryIeMissing(missing...) - } - var accID string - if len(attrs.Account) != 0 { // Presence of Account requires complete account details to be provided - if missing := utils.MissingStructFields(attrs, []string{utils.AccountField}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - tnt := attrs.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - accID = utils.ConcatenatedKey(tnt, attrs.Account) - } - - var remAcntAPids []string // list of accounts who's indexes need modification - _, err = guardian.Guardian.Guard(func() (interface{}, error) { - ap, err := apierSv1.DataManager.GetActionPlan(attrs.ActionPlanId, false, utils.NonTransactional) - if err != nil { - return 0, err - } else if ap == nil { - return 0, utils.ErrNotFound - } - if accID != "" { - delete(ap.AccountIDs, accID) - remAcntAPids = append(remAcntAPids, accID) - err = apierSv1.DataManager.SetActionPlan(ap.Id, ap, true, utils.NonTransactional) - goto UPDATE - } - if attrs.ActionTimingId != "" { // delete only a action timing from action plan - for i, at := range ap.ActionTimings { - if at.Uuid == attrs.ActionTimingId { - ap.ActionTimings[i] = ap.ActionTimings[len(ap.ActionTimings)-1] - ap.ActionTimings = ap.ActionTimings[:len(ap.ActionTimings)-1] - break - } - } - err = apierSv1.DataManager.SetActionPlan(ap.Id, ap, true, utils.NonTransactional) - goto UPDATE - } - if attrs.ActionPlanId != "" { // delete the entire action plan - ap.ActionTimings = nil // will delete the action plan - for acntID := range ap.AccountIDs { // Make sure we clear indexes for all accounts - remAcntAPids = append(remAcntAPids, acntID) - } - err = apierSv1.DataManager.SetActionPlan(ap.Id, ap, true, utils.NonTransactional) - goto UPDATE - } - - UPDATE: - if err != nil { - return 0, err - } - if err := apierSv1.ConnMgr.Call(apierSv1.Config.ApierCfg().CachesConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{utils.ActionPlanIDs: {attrs.ActionPlanId}}, - }, reply); err != nil { - return 0, err - } - for _, acntID := range remAcntAPids { - if err = apierSv1.DataManager.RemAccountActionPlans(acntID, []string{attrs.ActionPlanId}); err != nil { - return 0, nil - } - } - if len(remAcntAPids) != 0 { - if err := apierSv1.ConnMgr.Call(apierSv1.Config.ApierCfg().CachesConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{utils.AccountActionPlanIDs: remAcntAPids}, - }, reply); err != nil { - return 0, err - } - } - return 0, nil - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.ActionPlanPrefix) - if err != nil { - *reply = err.Error() - return utils.NewErrServerError(err) - } - if attrs.ReloadScheduler { - sched := apierSv1.SchedulerService.GetScheduler() - if sched == nil { - return errors.New(utils.SchedulerNotRunningCaps) - } - sched.Reload() - } - *reply = utils.OK - return nil -} - -// SetAccount adds a new account into dataDb. If already defined, returns success. -func (apierSv1 *APIerSv1) SetAccount(attr *utils.AttrSetAccount, reply *string) (err error) { - if missing := utils.MissingStructFields(attr, []string{utils.AccountField}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - accID := utils.ConcatenatedKey(tnt, attr.Account) - dirtyActionPlans := make(map[string]*engine.ActionPlan) - _, err = guardian.Guardian.Guard(func() (interface{}, error) { - var ub *engine.Account - if bal, _ := apierSv1.DataManager.GetAccount(accID); bal != nil { - ub = bal - } else { // Not found in db, create it here - ub = &engine.Account{ - ID: accID, - } - } - if attr.ActionPlanID != "" { - _, err := guardian.Guardian.Guard(func() (interface{}, error) { - acntAPids, err := apierSv1.DataManager.GetAccountActionPlans(accID, false, utils.NonTransactional) - if err != nil && err != utils.ErrNotFound { - return 0, err - } - // clean previous action plans - for i := 0; i < len(acntAPids); { - apID := acntAPids[i] - if apID == attr.ActionPlanID { - i++ // increase index since we don't remove from slice - continue - } - ap, err := apierSv1.DataManager.GetActionPlan(apID, false, utils.NonTransactional) - if err != nil { - return 0, err - } - delete(ap.AccountIDs, accID) - dirtyActionPlans[apID] = ap - acntAPids = append(acntAPids[:i], acntAPids[i+1:]...) // remove the item from the list so we can overwrite the real list - } - if !utils.IsSliceMember(acntAPids, attr.ActionPlanID) { // Account not yet attached to action plan, do it here - ap, err := apierSv1.DataManager.GetActionPlan(attr.ActionPlanID, false, utils.NonTransactional) - if err != nil { - return 0, err - } - if ap.AccountIDs == nil { - ap.AccountIDs = make(utils.StringMap) - } - ap.AccountIDs[accID] = true - dirtyActionPlans[attr.ActionPlanID] = ap - acntAPids = append(acntAPids, attr.ActionPlanID) - // create tasks - for _, at := range ap.ActionTimings { - if at.IsASAP() { - t := &engine.Task{ - Uuid: utils.GenUUID(), - AccountID: accID, - ActionsID: at.ActionsID, - } - if err = apierSv1.DataManager.DataDB().PushTask(t); err != nil { - return 0, err - } - } - } - } - apIDs := make([]string, len(dirtyActionPlans)) - i := 0 - for actionPlanID, ap := range dirtyActionPlans { - if err := apierSv1.DataManager.SetActionPlan(actionPlanID, ap, true, utils.NonTransactional); err != nil { - return 0, err - } - apIDs[i] = actionPlanID - i++ - } - if err := apierSv1.DataManager.SetAccountActionPlans(accID, acntAPids, true); err != nil { - return 0, err - } - if err := apierSv1.ConnMgr.Call(apierSv1.Config.ApierCfg().CachesConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{utils.AccountActionPlanIDs: {accID}, utils.ActionPlanIDs: apIDs}, - }, reply); err != nil { - return 0, err - } - return 0, nil - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.ActionPlanPrefix) - if err != nil { - return 0, err - } - } - - if attr.ActionTriggersID != "" { - atrs, err := apierSv1.DataManager.GetActionTriggers(attr.ActionTriggersID, false, utils.NonTransactional) - if err != nil { - return 0, err - } - ub.ActionTriggers = atrs - ub.InitCounters() - } - - if alNeg, has := attr.ExtraOptions[utils.AllowNegative]; has { - ub.AllowNegative = alNeg - } - if dis, has := attr.ExtraOptions[utils.Disabled]; has { - ub.Disabled = dis - } - // All prepared, save account - if err := apierSv1.DataManager.SetAccount(ub); err != nil { - return 0, err - } - return 0, nil - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.AccountPrefix+accID) - if err != nil { - return utils.NewErrServerError(err) - } - if attr.ReloadScheduler && len(dirtyActionPlans) != 0 { - sched := apierSv1.SchedulerService.GetScheduler() - if sched == nil { - return errors.New(utils.SchedulerNotRunningCaps) - } - sched.Reload() - } - *reply = utils.OK // This will mark saving of the account, error still can show up in actionTimingsId - return nil -} - -func (apierSv1 *APIerSv1) RemoveAccount(attr *utils.AttrRemoveAccount, reply *string) (err error) { - if missing := utils.MissingStructFields(attr, []string{utils.AccountField}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - dirtyActionPlans := make(map[string]*engine.ActionPlan) - accID := utils.ConcatenatedKey(tnt, attr.Account) - _, err = guardian.Guardian.Guard(func() (interface{}, error) { - // remove it from all action plans - _, err := guardian.Guardian.Guard(func() (interface{}, error) { - actionPlansMap, err := apierSv1.DataManager.GetAllActionPlans() - if err == utils.ErrNotFound { - // no action plans - return 0, nil - } - if err != nil { - return 0, err - } - - for actionPlanID, ap := range actionPlansMap { - if _, exists := ap.AccountIDs[accID]; exists { - delete(ap.AccountIDs, accID) - dirtyActionPlans[actionPlanID] = ap - } - } - - for actionPlanID, ap := range dirtyActionPlans { - if err := apierSv1.DataManager.SetActionPlan(actionPlanID, ap, true, - utils.NonTransactional); err != nil { - return 0, err - } - } - return 0, nil - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.ActionPlanPrefix) - if err != nil { - return 0, err - } - if err := apierSv1.DataManager.RemoveAccount(accID); err != nil { - return 0, err - } - return 0, nil - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.AccountPrefix+accID) - if err != nil { - return utils.NewErrServerError(err) - } - if err = apierSv1.DataManager.RemAccountActionPlans(accID, nil); err != nil && - err.Error() != utils.ErrNotFound.Error() { - return err - } - if err = apierSv1.ConnMgr.Call(apierSv1.Config.ApierCfg().CachesConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{utils.AccountActionPlanIDs: {accID}}, - }, reply); err != nil { - return - } - *reply = utils.OK - return nil -} - -func (apierSv1 *APIerSv1) GetAccounts(attr *utils.AttrGetAccounts, reply *[]interface{}) error { - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - var accountKeys []string - var err error - if len(attr.AccountIDs) == 0 { - if accountKeys, err = apierSv1.DataManager.DataDB().GetKeysForPrefix(utils.AccountPrefix + tnt); err != nil { - return err - } - } else { - for _, acntID := range attr.AccountIDs { - if len(acntID) == 0 { // Source of error returned from redis (key not found) - continue - } - accountKeys = append(accountKeys, utils.AccountPrefix+utils.ConcatenatedKey(tnt, acntID)) - } - } - if len(accountKeys) == 0 { - return nil - } - var limitedAccounts []string - if attr.Limit != 0 { - max := math.Min(float64(attr.Offset+attr.Limit), float64(len(accountKeys))) - limitedAccounts = accountKeys[attr.Offset:int(max)] - } else { - limitedAccounts = accountKeys[attr.Offset:] - } - retAccounts := make([]interface{}, 0) - for _, acntKey := range limitedAccounts { - if acnt, err := apierSv1.DataManager.GetAccount(acntKey[len(utils.AccountPrefix):]); err != nil && err != utils.ErrNotFound { // Not found is not an error here - return err - } else if acnt != nil { - if alNeg, has := attr.Filter[utils.AllowNegative]; has && alNeg != acnt.AllowNegative { - continue - } - if dis, has := attr.Filter[utils.Disabled]; has && dis != acnt.Disabled { - continue - } - retAccounts = append(retAccounts, acnt.AsOldStructure()) - } - } - *reply = retAccounts - return nil -} - -// GetAccount returns the account -func (apierSv1 *APIerSv1) GetAccount(attr *utils.AttrGetAccount, reply *interface{}) error { - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - tag := utils.ConcatenatedKey(tnt, attr.Account) - userBalance, err := apierSv1.DataManager.GetAccount(tag) - if err != nil { - return err - } - - *reply = userBalance.AsOldStructure() - return nil -} - -type AttrAddBalance struct { - Tenant string - Account string - BalanceType string - Value float64 - Balance map[string]interface{} - ActionExtraData *map[string]interface{} - Overwrite bool // When true it will reset if the balance is already there - Cdrlog bool -} - -func (apierSv1 *APIerSv1) AddBalance(attr *AttrAddBalance, reply *string) error { - return apierSv1.modifyBalance(utils.MetaTopUp, attr, reply) -} -func (apierSv1 *APIerSv1) DebitBalance(attr *AttrAddBalance, reply *string) error { - return apierSv1.modifyBalance(utils.MetaDebit, attr, reply) -} - -func (apierSv1 *APIerSv1) modifyBalance(aType string, attr *AttrAddBalance, reply *string) (err error) { - if missing := utils.MissingStructFields(attr, []string{utils.AccountField, utils.BalanceType, utils.Value}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - var balance *engine.BalanceFilter - if balance, err = engine.NewBalanceFilter(attr.Balance, apierSv1.Config.GeneralCfg().DefaultTimezone); err != nil { - return - } - balance.Type = utils.StringPointer(attr.BalanceType) - if attr.Value != 0 { - balance.Value = &utils.ValueFormula{Static: math.Abs(attr.Value)} - } - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - accID := utils.ConcatenatedKey(tnt, attr.Account) - if _, err = apierSv1.DataManager.GetAccount(accID); err != nil { - // create account if does not exist - account := &engine.Account{ - ID: accID, - } - if err = apierSv1.DataManager.SetAccount(account); err != nil { - return - } - } - at := &engine.ActionTiming{} - //check if we have extra data - if attr.ActionExtraData != nil && len(*attr.ActionExtraData) != 0 { - at.ExtraData = *attr.ActionExtraData - } - at.SetAccountIDs(utils.StringMap{accID: true}) - - if attr.Overwrite { - aType += "_reset" // => *topup_reset/*debit_reset - } - if balance.TimingIDs != nil { - for _, timingID := range balance.TimingIDs.Slice() { - var tmg *utils.TPTiming - if tmg, err = apierSv1.DataManager.GetTiming(timingID, false, utils.NonTransactional); err != nil { - return - } - balance.Timings = append(balance.Timings, &engine.RITiming{ - ID: tmg.ID, - Years: tmg.Years, - Months: tmg.Months, - MonthDays: tmg.MonthDays, - WeekDays: tmg.WeekDays, - StartTime: tmg.StartTime, - EndTime: tmg.EndTime, - }) - } - } - - a := &engine.Action{ - ActionType: aType, - Balance: balance, - } - publishAction := &engine.Action{ - ActionType: utils.MetaPublishAccount, - } - acts := engine.Actions{a, publishAction} - if attr.Cdrlog { - acts = engine.Actions{a, publishAction, &engine.Action{ - ActionType: utils.CDRLog, - }} - } - at.SetActions(acts) - if err := at.Execute(nil, nil); err != nil { - return err - } - *reply = utils.OK - return nil -} - -// SetBalance sets the balance for the given account -// if the account is not already created it will create the account also -func (apierSv1 *APIerSv1) SetBalance(attr *utils.AttrSetBalance, reply *string) (err error) { - if missing := utils.MissingStructFields(attr, []string{utils.AccountField, utils.BalanceType}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - var balance *engine.BalanceFilter - if balance, err = engine.NewBalanceFilter(attr.Balance, apierSv1.Config.GeneralCfg().DefaultTimezone); err != nil { - return - } - balance.Type = utils.StringPointer(attr.BalanceType) - if attr.Value != 0 { - balance.Value = &utils.ValueFormula{Static: math.Abs(attr.Value)} - } - if (balance.ID == nil || *balance.ID == "") && - (balance.Uuid == nil || *balance.Uuid == "") { - return utils.NewErrMandatoryIeMissing("BalanceID", "or", "BalanceUUID") - } - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - - accID := utils.ConcatenatedKey(tnt, attr.Account) - if _, err = apierSv1.DataManager.GetAccount(accID); err != nil { - // create account if not exists - account := &engine.Account{ - ID: accID, - } - if err = apierSv1.DataManager.SetAccount(account); err != nil { - return - } - } - at := &engine.ActionTiming{} - //check if we have extra data - if attr.ActionExtraData != nil && len(*attr.ActionExtraData) != 0 { - at.ExtraData = *attr.ActionExtraData - } - at.SetAccountIDs(utils.StringMap{accID: true}) - if balance.TimingIDs != nil { - for _, timingID := range balance.TimingIDs.Slice() { - var tmg *utils.TPTiming - if tmg, err = apierSv1.DataManager.GetTiming(timingID, false, utils.NonTransactional); err != nil { - return - } - balance.Timings = append(balance.Timings, &engine.RITiming{ - ID: tmg.ID, - Years: tmg.Years, - Months: tmg.Months, - MonthDays: tmg.MonthDays, - WeekDays: tmg.WeekDays, - StartTime: tmg.StartTime, - EndTime: tmg.EndTime, - }) - } - } - - a := &engine.Action{ - ActionType: utils.MetaSetBalance, - Balance: balance, - } - publishAction := &engine.Action{ - ActionType: utils.MetaPublishAccount, - } - acts := engine.Actions{a, publishAction} - if attr.Cdrlog { - acts = engine.Actions{a, publishAction, &engine.Action{ - ActionType: utils.CDRLog, - }} - } - at.SetActions(acts) - if err = at.Execute(nil, nil); err != nil { - return - } - *reply = utils.OK - return -} - -// SetBalances sets multiple balances for the given account -// if the account is not already created it will create the account also -func (apierSv1 *APIerSv1) SetBalances(attr *utils.AttrSetBalances, reply *string) (err error) { - if missing := utils.MissingStructFields(attr, []string{utils.AccountField, utils.BalancesFld}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - - accID := utils.ConcatenatedKey(tnt, attr.Account) - if _, err = apierSv1.DataManager.GetAccount(accID); err != nil { - // create account if not exists - account := &engine.Account{ - ID: accID, - } - if err = apierSv1.DataManager.SetAccount(account); err != nil { - return - } - } - for _, bal := range attr.Balances { - at := &engine.ActionTiming{} - - var balFltr *engine.BalanceFilter - if balFltr, err = engine.NewBalanceFilter(bal.Balance, apierSv1.Config.GeneralCfg().DefaultTimezone); err != nil { - return - } - balFltr.Type = utils.StringPointer(bal.BalanceType) - if bal.Value != 0 { - balFltr.Value = &utils.ValueFormula{Static: math.Abs(bal.Value)} - } - if (balFltr.ID == nil || *balFltr.ID == "") && - (balFltr.Uuid == nil || *balFltr.Uuid == "") { - return utils.NewErrMandatoryIeMissing("BalanceID", "or", "BalanceUUID") - } - - //check if we have extra data - if bal.ActionExtraData != nil && len(*bal.ActionExtraData) != 0 { - at.ExtraData = *bal.ActionExtraData - } - - at.SetAccountIDs(utils.StringMap{accID: true}) - if balFltr.TimingIDs != nil { - for _, timingID := range balFltr.TimingIDs.Slice() { - var tmg *utils.TPTiming - if tmg, err = apierSv1.DataManager.GetTiming(timingID, false, utils.NonTransactional); err != nil { - return - } - balFltr.Timings = append(balFltr.Timings, &engine.RITiming{ - ID: tmg.ID, - Years: tmg.Years, - Months: tmg.Months, - MonthDays: tmg.MonthDays, - WeekDays: tmg.WeekDays, - StartTime: tmg.StartTime, - EndTime: tmg.EndTime, - }) - } - } - - a := &engine.Action{ - ActionType: utils.MetaSetBalance, - Balance: balFltr, - } - publishAction := &engine.Action{ - ActionType: utils.MetaPublishAccount, - } - acts := engine.Actions{a, publishAction} - if bal.Cdrlog { - acts = engine.Actions{a, publishAction, &engine.Action{ - ActionType: utils.CDRLog, - }} - } - at.SetActions(acts) - if err = at.Execute(nil, nil); err != nil { - return - } - } - - *reply = utils.OK - return -} - -// RemoveBalances remove the matching balances for the account -func (apierSv1 *APIerSv1) RemoveBalances(attr *utils.AttrSetBalance, reply *string) (err error) { - if missing := utils.MissingStructFields(attr, []string{utils.AccountField, utils.BalanceType}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - var balance *engine.BalanceFilter - if balance, err = engine.NewBalanceFilter(attr.Balance, apierSv1.Config.GeneralCfg().DefaultTimezone); err != nil { - return - } - balance.Type = utils.StringPointer(attr.BalanceType) - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - - accID := utils.ConcatenatedKey(tnt, attr.Account) - if _, err := apierSv1.DataManager.GetAccount(accID); err != nil { - return utils.ErrNotFound - } - - at := &engine.ActionTiming{} - //check if we have extra data - if attr.ActionExtraData != nil && len(*attr.ActionExtraData) != 0 { - at.ExtraData = *attr.ActionExtraData - } - at.SetAccountIDs(utils.StringMap{accID: true}) - a := &engine.Action{ - ActionType: utils.MetaRemoveBalance, - Balance: balance, - } - at.SetActions(engine.Actions{a}) - if err := at.Execute(nil, nil); err != nil { - *reply = err.Error() - return err - } - *reply = utils.OK - return nil -} - -func (apierSv1 *APIerSv1) GetAccountsCount(attr *utils.TenantWithAPIOpts, reply *int) (err error) { - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apierSv1.Config.GeneralCfg().DefaultTenant - } - var accountKeys []string - if accountKeys, err = apierSv1.DataManager.DataDB().GetKeysForPrefix(utils.AccountPrefix + tnt); err != nil { - return - } - *reply = len(accountKeys) - return -} diff --git a/apier/v1/accounts_it_test.go b/apier/v1/accounts_it_test.go deleted file mode 100644 index c19c3ce60..000000000 --- a/apier/v1/accounts_it_test.go +++ /dev/null @@ -1,1351 +0,0 @@ -// +build integration - -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package v1 - -import ( - "net/rpc" - "path" - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" -) - -var ( - accExist bool - accCfgPath string - accCfg *config.CGRConfig - accRPC *rpc.Client - accAcount = "refundAcc" - accTenant = "cgrates.org" - accBallID = "Balance1" - accTestsConfig string //run tests for specific configuration - - accTests = []func(t *testing.T){ - testAccITLoadConfig, - testAccITResetDataDB, - testAccITResetStorDb, - testAccITStartEngine, - testAccITRPCConn, - testAccITAddVoiceBalance, - testAccITDebitBalance, - testAccITDebitBalanceWithoutTenant, - testAccITAddBalance, - testAccITAddBalanceWithoutTenant, - testAccITAddBalanceWithValue0, - testAccITAddBalanceWithValueInMap, - testAccITSetBalance, - testAccITSetBalanceWithoutTenant, - testAccITSetBalanceWithVaslue0, - testAccITSetBalanceWithVaslueInMap, - testAccITSetBalanceWithExtraData, - testAccITSetBalanceWithExtraData2, - testAccITSetBalanceTimingIds, - testAccITAddBalanceWithNegative, - testAccITGetDisabledAccounts, - testAccITGetDisabledAccountsWithoutTenant, - testAccITCountAccounts, - testAccITCountAccountsWithoutTenant, - testAccITRemoveAccountWithoutTenant, - testAccITTPFromFolder, - testAccITAddBalanceWithDestinations, - testAccITAccountWithTriggers, - testAccITAccountMonthlyEstimated, - testAccITMultipleBalance, - testAccITMultipleBalanceWithoutTenant, - testAccITRemoveBalances, - testAccITAddVoiceBalanceWithDestinations, - testAccITStopCgrEngine, - } -) - -func TestAccITWithRemove(t *testing.T) { - switch *dbType { - case utils.MetaInternal: - accTestsConfig = "tutinternal" - case utils.MetaMySQL: - accTestsConfig = "tutmysql" - case utils.MetaMongo: - accTestsConfig = "tutmongo" - case utils.MetaPostgres: - t.SkipNow() - default: - t.Fatal("Unknown Database type") - } - accCfgPath = path.Join(*dataDir, "conf", "samples", accTestsConfig) - - for _, stest := range accTests { - t.Run(accTestsConfig, stest) - } -} - -func TestAccITWithoutRemove(t *testing.T) { - switch *dbType { - case utils.MetaInternal: - accTestsConfig = "acc_balance_keep_internal" - case utils.MetaMySQL: - accTestsConfig = "acc_balance_keep_mysql" - case utils.MetaMongo: - accTestsConfig = "acc_balance_keep_mongo" - case utils.MetaPostgres: - t.SkipNow() - default: - t.Fatalf("Unknown Database type <%s>", *dbType) - } - if *encoding == utils.MetaGOB { - accTestsConfig += "_gob" - } - accCfgPath = path.Join(*dataDir, "conf", "samples", accTestsConfig) - - accExist = true - for _, stest := range accTests { - t.Run(accTestsConfig, stest) - } -} - -func testAccITLoadConfig(t *testing.T) { - var err error - if accCfg, err = config.NewCGRConfigFromPath(accCfgPath); err != nil { - t.Error(err) - } -} - -func testAccITResetDataDB(t *testing.T) { - if err := engine.InitDataDb(accCfg); err != nil { - t.Fatal(err) - } -} - -func testAccITResetStorDb(t *testing.T) { - if err := engine.InitStorDb(accCfg); err != nil { - t.Fatal(err) - } -} - -func testAccITStartEngine(t *testing.T) { - if _, err := engine.StopStartEngine(accCfgPath, *waitRater); err != nil { - t.Fatal(err) - } -} - -func testAccITRPCConn(t *testing.T) { - var err error - if accRPC, err = newRPCClient(accCfg.ListenCfg()); err != nil { - t.Fatal(err) - } -} - -func testAccountBalance(t *testing.T, sracc, srten, balType string, expected float64) { - var acnt *engine.Account - attrs := &utils.AttrGetAccount{ - Tenant: srten, - Account: sracc, - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrs, &acnt); err != nil { - t.Error(err) - } else if rply := acnt.BalanceMap[balType].GetTotalValue(); rply != expected { - t.Errorf("Expecting: %v, received: %v", - expected, rply) - } -} - -func testBalanceIfExists(t *testing.T, acc, ten, balType, balID string) (has bool) { - var acnt *engine.Account - attrs := &utils.AttrGetAccount{ - Tenant: ten, - Account: acc, - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrs, &acnt); err != nil { - t.Error(err) - return false - } - for _, bal := range acnt.BalanceMap[balType] { - if bal.ID == balID { - return true - } - } - return false -} - -func testAccITAddVoiceBalance(t *testing.T) { - attrSetBalance := utils.AttrSetBalance{ - Tenant: accTenant, - Account: accAcount, - BalanceType: utils.MetaVoice, - Value: 2 * float64(time.Second), - Balance: map[string]interface{}{ - utils.ID: accBallID, - utils.RatingSubject: "*zero5ms", - utils.ExpiryTime: time.Now().Add(5 * time.Second).Format("2006-01-02 15:04:05"), - }, - } - var reply string - if err := accRPC.Call(utils.APIerSv2SetBalance, &attrSetBalance, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - t.Run("TestAddVoiceBalance", func(t *testing.T) { - testAccountBalance(t, accAcount, accTenant, utils.MetaVoice, 2*float64(time.Second)) - }) -} - -func testAccITSetBalanceTimingIds(t *testing.T) { - tpTiming := &utils.ApierTPTiming{ - TPid: "TEST_TPID1", - ID: "Timing", - Years: "2017", - Months: "05", - MonthDays: "01", - WeekDays: "1", - Time: "15:00:00Z", - } - var reply string - if err := accRPC.Call(utils.APIerSv1SetTPTiming, &tpTiming, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Error("Unexpected reply returned", reply) - } - - if err := accRPC.Call(utils.APIerSv1LoadTariffPlanFromStorDb, - &AttrLoadTpFromStorDb{TPid: "TEST_TPID1"}, &reply); err != nil { - t.Errorf("Got error on %s: %+v", utils.APIerSv1LoadTariffPlanFromStorDb, err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling %s got reply: %+v", utils.APIerSv1LoadTariffPlanFromStorDb, reply) - } - - args := &utils.AttrSetBalance{ - Tenant: accTenant, - Account: accAcount, - BalanceType: utils.MetaVoice, - Balance: map[string]interface{}{ - utils.ID: "testBalanceID", - utils.TimingIDs: "Timing", - }, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, args, &reply); err != nil { - t.Error("Got error on SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling SetBalance received: %s", reply) - } - - // verify if Timing IDs is populated - var acnt engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: accTenant, - Account: accAcount, - } - eOut := []*engine.RITiming{ - { - ID: "Timing", - Years: utils.Years{2017}, - Months: utils.Months{05}, - MonthDays: utils.MonthDays{1}, - WeekDays: utils.WeekDays{1}, - StartTime: "15:00:00Z", - EndTime: "", - }, - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } - - for _, value := range acnt.BalanceMap[utils.MetaVoice] { - // check only where balance ID is testBalanceID (SetBalance function call was made with this Balance ID) - if value.ID == "testBalanceID" { - if !reflect.DeepEqual(eOut, value.Timings) { - t.Errorf("Expecting %+v, \nreceived: %+v", utils.ToJSON(eOut), utils.ToJSON(value.Timings)) - } - break - } - } -} - -func testAccITDebitBalance(t *testing.T) { - time.Sleep(5 * time.Second) - var reply string - if err := accRPC.Call(utils.APIerSv1DebitBalance, &AttrAddBalance{ - Tenant: accTenant, - Account: accAcount, - BalanceType: utils.MetaVoice, - Value: 0, - }, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - if has := testBalanceIfExists(t, accAcount, accTenant, utils.MetaVoice, accBallID); accExist != has { - var exstr string - if !accExist { - exstr = "not " - } - t.Fatalf("Balance with ID %s should %s exist", accBallID, exstr) - } - t.Run("TestAddVoiceBalance", func(t *testing.T) { testAccountBalance(t, accAcount, accTenant, utils.MetaVoice, 0) }) -} - -func testAccITDebitBalanceWithoutTenant(t *testing.T) { - var reply string - if err := accRPC.Call(utils.APIerSv1DebitBalance, &AttrAddBalance{ - Account: accAcount, - BalanceType: utils.MetaVoice, - Value: 0, - }, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - if has := testBalanceIfExists(t, accAcount, accTenant, utils.MetaVoice, accBallID); accExist != has { - var exstr string - if !accExist { - exstr = "not " - } - t.Fatalf("Balance with ID %s should %s exist", accBallID, exstr) - } - t.Run("TestAddVoiceBalance", func(t *testing.T) { testAccountBalance(t, accAcount, accTenant, utils.MetaVoice, 0) }) -} - -func testAccITAddBalance(t *testing.T) { - var reply string - attrs := &AttrAddBalance{ - Tenant: "cgrates.org", - Account: "testAccAddBalance", - BalanceType: utils.MetaMonetary, - Value: 1.5, - Cdrlog: true, - } - if err := accRPC.Call(utils.APIerSv1AddBalance, attrs, &reply); err != nil { - t.Error("Got error on APIerSv1.AddBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.AddBalance received: %s", reply) - } - time.Sleep(50 * time.Millisecond) - // verify the cdr from CdrLog - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Sources: []string{utils.CDRLog}} - if err := accRPC.Call(utils.APIerSv2GetCDRs, &req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } -} - -func testAccITAddBalanceWithoutTenant(t *testing.T) { - var reply string - attrs := &AttrAddBalance{ - Account: "testAccAddBalance", - BalanceType: utils.MetaMonetary, - Value: 1.5, - Cdrlog: true, - } - if err := accRPC.Call(utils.APIerSv1AddBalance, &attrs, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.AddBalance received: %s", reply) - } - time.Sleep(50 * time.Millisecond) - // verify the cdr from CdrLog - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Sources: []string{utils.CDRLog}} - if err := accRPC.Call(utils.APIerSv2GetCDRs, &req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 2 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } -} - -func testAccITSetBalance(t *testing.T) { - var reply string - attrs := &utils.AttrSetBalance{ - Tenant: "cgrates.org", - Account: "testAccSetBalance", - BalanceType: "*monetary", - Value: 1.5, - Balance: map[string]interface{}{ - utils.ID: "testAccSetBalance", - }, - Cdrlog: true, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, attrs, &reply); err != nil { - t.Error("Got error on APIerSv1.SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetBalance received: %s", reply) - } - time.Sleep(50 * time.Millisecond) - // verify the cdr from CdrLog - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Sources: []string{utils.CDRLog}} - if err := accRPC.Call(utils.APIerSv2GetCDRs, &req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 3 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } -} - -func testAccITSetBalanceWithoutTenant(t *testing.T) { - var reply string - attrs := &utils.AttrSetBalance{ - Account: "testrandomAccoutSetBalance", - BalanceType: "*monetary", - Value: 1.5, - Balance: map[string]interface{}{ - utils.ID: "testAccSetBalance", - }, - Cdrlog: true, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, &attrs, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetBalance received: %s", reply) - } - time.Sleep(50 * time.Millisecond) - // verify the cdr from CdrLog - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Sources: []string{utils.CDRLog}} - if err := accRPC.Call(utils.APIerSv1GetCDRs, &req, &cdrs); err != nil { - t.Error(err) - } else if len(cdrs) != 4 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } - -} - -func testAccITSetBalanceWithExtraData(t *testing.T) { - extraDataMap := map[string]interface{}{ - "ExtraField": "ExtraValue", - "ExtraField2": "RandomValue", - } - var reply string - attrs := &utils.AttrSetBalance{ - Tenant: "cgrates.org", - Account: "testAccITSetBalanceWithExtraData", - BalanceType: utils.MetaMonetary, - Value: 1.5, - Balance: map[string]interface{}{ - utils.ID: "testAccITSetBalanceWithExtraData", - }, - Cdrlog: true, - ActionExtraData: &extraDataMap, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, attrs, &reply); err != nil { - t.Error("Got error on APIerSv1.SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetBalance received: %s", reply) - } - time.Sleep(50 * time.Millisecond) - // verify the cdr from CdrLog - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Sources: []string{utils.CDRLog}, Accounts: []string{"testAccITSetBalanceWithExtraData"}} - if err := accRPC.Call(utils.APIerSv2GetCDRs, &req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else if len(cdrs[0].ExtraFields) != 2 { - t.Error("Unexpected number of ExtraFields returned: ", len(cdrs[0].ExtraFields)) - } -} - -func testAccITSetBalanceWithExtraData2(t *testing.T) { - extraDataMap := map[string]interface{}{ - "ExtraField": "ExtraValue", - "ActionVal": "~*act.ActionValue", - } - var reply string - attrs := &utils.AttrSetBalance{ - Tenant: "cgrates.org", - Account: "testAccITSetBalanceWithExtraData2", - BalanceType: utils.MetaMonetary, - Value: 1.5, - Balance: map[string]interface{}{ - utils.ID: "testAccITSetBalanceWithExtraData2", - }, - Cdrlog: true, - ActionExtraData: &extraDataMap, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, attrs, &reply); err != nil { - t.Error("Got error on APIerSv1.SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetBalance received: %s", reply) - } - time.Sleep(50 * time.Millisecond) - // verify the cdr from CdrLog - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Sources: []string{utils.CDRLog}, Accounts: []string{"testAccITSetBalanceWithExtraData2"}} - if err := accRPC.Call(utils.APIerSv2GetCDRs, &req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else if len(cdrs[0].ExtraFields) != 2 { - t.Error("Unexpected number of ExtraFields returned: ", len(cdrs[0].ExtraFields)) - } else if cdrs[0].ExtraFields["ActionVal"] != "1.5" { - t.Error("Unexpected value of ExtraFields[ActionVal] returned: ", cdrs[0].ExtraFields["ActionVal"]) - } -} - -func testAccITAddBalanceWithNegative(t *testing.T) { - var acnt *engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: "cgrates.org", - Account: "AddBalanceWithNegative", - } - - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err.Error() != utils.ErrNotFound.Error() { - t.Error(err) - } - - //topup with a negative value - var reply string - attrs := &AttrAddBalance{ - Tenant: "cgrates.org", - Account: "AddBalanceWithNegative", - BalanceType: utils.MetaMonetary, - Value: -3.5, - } - if err := accRPC.Call(utils.APIerSv1AddBalance, attrs, &reply); err != nil { - t.Error("Got error on APIerSv1.AddBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.AddBalance received: %s", reply) - } - //give time to create the account and execute the action - time.Sleep(50 * time.Millisecond) - - attrAcc = &utils.AttrGetAccount{ - Tenant: "cgrates.org", - Account: "AddBalanceWithNegative", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Error(err) - } else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != 3.5 { - t.Errorf("Unexpected balance received : %+v", acnt.BalanceMap[utils.MetaMonetary].GetTotalValue()) - } - - if err := accRPC.Call(utils.APIerSv1DebitBalance, &AttrAddBalance{ - Tenant: "cgrates.org", - Account: "AddBalanceWithNegative", - BalanceType: utils.MetaMonetary, - Value: 2, - }, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Error(err) - } else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != 1.5 { - t.Errorf("Unexpected balance received : %+v", acnt.BalanceMap[utils.MetaMonetary].GetTotalValue()) - } - - if err := accRPC.Call(utils.APIerSv1DebitBalance, &AttrAddBalance{ - Tenant: "cgrates.org", - Account: "AddBalanceWithNegative", - BalanceType: utils.MetaMonetary, - Value: -1, - }, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Error(err) - } else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != 0.5 { - t.Errorf("Unexpected balance received : %+v", acnt.BalanceMap[utils.MetaMonetary].GetTotalValue()) - } -} - -func testAccITGetDisabledAccounts(t *testing.T) { - var reply string - acnt1 := utils.AttrSetAccount{Tenant: "cgrates.org", Account: "account1", ExtraOptions: map[string]bool{utils.Disabled: true}} - acnt2 := utils.AttrSetAccount{Tenant: "cgrates.org", Account: "account2", ExtraOptions: map[string]bool{utils.Disabled: false}} - acnt3 := utils.AttrSetAccount{Tenant: "cgrates.org", Account: "account3", ExtraOptions: map[string]bool{utils.Disabled: true}} - acnt4 := utils.AttrSetAccount{Tenant: "cgrates.org", Account: "account4", ExtraOptions: map[string]bool{utils.Disabled: true}} - - for _, account := range []utils.AttrSetAccount{acnt1, acnt2, acnt3, acnt4} { - if err := accRPC.Call(utils.APIerSv1SetAccount, account, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetAccount received: %s", reply) - } - } - - var acnts []*engine.Account - if err := accRPC.Call(utils.APIerSv2GetAccounts, &utils.AttrGetAccounts{Tenant: "cgrates.org", Filter: map[string]bool{utils.Disabled: true}}, - &acnts); err != nil { - t.Error(err) - } else if len(acnts) != 3 { - t.Errorf("Accounts received: %+v", acnts) - } -} - -func testAccITGetDisabledAccountsWithoutTenant(t *testing.T) { - var reply string - acnt1 := utils.AttrSetAccount{Account: "account1", ExtraOptions: map[string]bool{utils.Disabled: true}} - acnt2 := utils.AttrSetAccount{Account: "account2", ExtraOptions: map[string]bool{utils.Disabled: false}} - acnt3 := utils.AttrSetAccount{Account: "account3", ExtraOptions: map[string]bool{utils.Disabled: true}} - acnt4 := utils.AttrSetAccount{Account: "account4", ExtraOptions: map[string]bool{utils.Disabled: true}} - - for _, account := range []utils.AttrSetAccount{acnt1, acnt2, acnt3, acnt4} { - if err := accRPC.Call(utils.APIerSv1SetAccount, account, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetAccount received: %s", reply) - } - } - - var acnts []*engine.Account - if err := accRPC.Call(utils.APIerSv2GetAccounts, &utils.AttrGetAccounts{Filter: map[string]bool{utils.Disabled: true}}, - &acnts); err != nil { - t.Error(err) - } else if len(acnts) != 3 { - t.Errorf("Accounts received: %+v", acnts) - } -} - -func testAccITRemoveAccountWithoutTenant(t *testing.T) { - var reply string - acnt1 := utils.AttrSetAccount{Account: "randomAccount"} - if err := accRPC.Call(utils.APIerSv1SetAccount, acnt1, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetAccount received: %s", reply) - } - var result *engine.Account - if err := accRPC.Call(utils.APIerSv2GetAccount, - &utils.AttrGetAccount{Account: "randomAccount"}, - &result); err != nil { - t.Fatal(err) - } else if result.ID != "cgrates.org:randomAccount" { - t.Errorf("Expected %+v, received %+v", "cgrates.org:randomAccount", result.ID) - } - - if err := accRPC.Call(utils.APIerSv1RemoveAccount, - &utils.AttrRemoveAccount{Account: "randomAccount"}, - &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv2.RemoveAccount received: %s", reply) - } - if err := accRPC.Call(utils.APIerSv2GetAccount, - &utils.AttrGetAccount{Account: "randomAccount"}, - &result); err == nil || utils.ErrNotFound.Error() != err.Error() { - t.Error(err) - } -} - -func testAccITCountAccounts(t *testing.T) { - var reply int - args := &utils.TenantWithAPIOpts{ - Tenant: "cgrates.org", - } - if err := accRPC.Call(utils.APIerSv1GetAccountsCount, &args, &reply); err != nil { - t.Error(err) - } else if reply != 11 { - t.Errorf("Expecting: %v, received: %v", 11, reply) - } -} -func testAccITCountAccountsWithoutTenant(t *testing.T) { - var reply int - if err := accRPC.Call(utils.APIerSv1GetAccountsCount, - &utils.TenantIDWithAPIOpts{}, - &reply); err != nil { - t.Error(err) - } else if reply != 11 { - t.Errorf("Expecting: %v, received: %v", 11, reply) - } -} - -func testAccITStopCgrEngine(t *testing.T) { - if err := engine.KillEngine(100); err != nil { - t.Error(err) - } -} - -func testAccITSetBalanceWithVaslue0(t *testing.T) { - var reply string - args := &utils.AttrSetBalance{ - Tenant: "cgrates.org", - Account: "testAccSetBalance", - BalanceType: "*monetary", - Balance: map[string]interface{}{ - utils.ID: "testAccSetBalance", - utils.Weight: 10, - }, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, args, &reply); err != nil { - t.Error("Got error on SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling SetBalance received: %s", reply) - } - - var acnt engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: accTenant, - Account: "testAccSetBalance", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } - - for _, value := range acnt.BalanceMap[utils.MetaMonetary] { - // check only where balance ID is testBalanceID (SetBalance function call was made with this Balance ID) - if value.ID == "testAccSetBalance" { - if value.GetValue() != 1.5 { - t.Errorf("Expecting %+v, received: %+v", 1.5, value.GetValue()) - } - if value.Weight != 10 { - t.Errorf("Expecting %+v, received: %+v", 10, value.Weight) - } - break - } - } -} - -func testAccITSetBalanceWithVaslueInMap(t *testing.T) { - var reply string - args := &utils.AttrSetBalance{ - Tenant: "cgrates.org", - Account: "testAccSetBalance", - BalanceType: "*monetary", - Balance: map[string]interface{}{ - utils.ID: "testAccSetBalance", - utils.Weight: 10, - utils.Value: 2, - }, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, args, &reply); err != nil { - t.Error("Got error on SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling SetBalance received: %s", reply) - } - - var acnt engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: accTenant, - Account: "testAccSetBalance", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } - - for _, value := range acnt.BalanceMap[utils.MetaMonetary] { - // check only where balance ID is testBalanceID (SetBalance function call was made with this Balance ID) - if value.ID == "testAccSetBalance" { - if value.GetValue() != 2 { - t.Errorf("Expecting %+v, received: %+v", 2, value.GetValue()) - } - if value.Weight != 10 { - t.Errorf("Expecting %+v, received: %+v", 10, value.Weight) - } - break - } - } -} - -func testAccITAddBalanceWithValue0(t *testing.T) { - var reply string - attrs := &AttrAddBalance{ - Tenant: "cgrates.org", - Account: "testAccAddBalance", - BalanceType: utils.MetaMonetary, - } - if err := accRPC.Call(utils.APIerSv1AddBalance, attrs, &reply); err != nil { - t.Error("Got error on APIerSv1.AddBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.AddBalance received: %s", reply) - } - - var acnt engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: accTenant, - Account: "testAccAddBalance", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } - - for _, value := range acnt.BalanceMap[utils.MetaMonetary] { - // check only where balance ID is testBalanceID (SetBalance function call was made with this Balance ID) - if value.ID == "testAccSetBalance" { - if value.GetValue() != 1.5 { - t.Errorf("Expecting %+v, received: %+v", 1.5, value.GetValue()) - } - break - } - } -} - -func testAccITAddBalanceWithValueInMap(t *testing.T) { - var reply string - attrs := &AttrAddBalance{ - Tenant: "cgrates.org", - Account: "testAccAddBalance", - BalanceType: utils.MetaMonetary, - Balance: map[string]interface{}{ - utils.Value: 1.5, - }, - } - if err := accRPC.Call(utils.APIerSv1AddBalance, attrs, &reply); err != nil { - t.Error("Got error on APIerSv1.AddBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.AddBalance received: %s", reply) - } - - var acnt engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: accTenant, - Account: "testAccAddBalance", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } - - for _, value := range acnt.BalanceMap[utils.MetaMonetary] { - // check only where balance ID is testBalanceID (SetBalance function call was made with this Balance ID) - if value.ID == "testAccSetBalance" { - if value.GetValue() != 3 { - t.Errorf("Expecting %+v, received: %+v", 3, value.GetValue()) - } - break - } - } -} - -// Load the tariff plan, creating accounts and their balances -func testAccITTPFromFolder(t *testing.T) { - attrs := &utils.AttrLoadTpFromFolder{ - FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")} - var loadInst utils.LoadInstance - if err := accRPC.Call(utils.APIerSv2LoadTariffPlanFromFolder, - attrs, &loadInst); err != nil { - t.Error(err) - } - time.Sleep(100 * time.Millisecond) -} - -func testAccITAddBalanceWithDestinations(t *testing.T) { - var reply string - args := &utils.AttrSetBalance{ - Tenant: "cgrates.org", - Account: "testAccITAddBalanceWithDestinations", - BalanceType: utils.MetaMonetary, - Balance: map[string]interface{}{ - utils.ID: "testAccITAddBalanceWithDestinations", - utils.DestinationIDs: "DST_1002;!DST_1001;!DST_1003", - utils.Weight: 10, - utils.Value: 2, - }, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, args, &reply); err != nil { - t.Error("Got error on SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling SetBalance received: %s", reply) - } - - var acnt engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: accTenant, - Account: "testAccITAddBalanceWithDestinations", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } - - for _, value := range acnt.BalanceMap[utils.MetaMonetary] { - // check only where balance ID is testBalanceID (SetBalance function call was made with this Balance ID) - if value.ID == "testAccITAddBalanceWithDestinations" { - if value.GetValue() != 2 { - t.Errorf("Expecting %+v, received: %+v", 2, value.GetValue()) - } - if value.Weight != 10 { - t.Errorf("Expecting %+v, received: %+v", 10, value.Weight) - } - dstMp := utils.StringMap{ - "DST_1002": true, "DST_1001": false, "DST_1003": false, - } - if !reflect.DeepEqual(value.DestinationIDs, dstMp) { - t.Errorf("Expecting %+v, received: %+v", dstMp, value.DestinationIDs) - } - - break - } - } - - tStart := time.Date(2016, 3, 31, 0, 0, 0, 0, time.UTC) - cd := &engine.CallDescriptorWithAPIOpts{ - CallDescriptor: &engine.CallDescriptor{ - Category: "sms", - Tenant: "cgrates.org", - Subject: "testAccITAddBalanceWithDestinations", - Account: "testAccITAddBalanceWithDestinations", - Destination: "1003", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tStart.Add(time.Nanosecond), - }, - } - var cc engine.CallCost - if err := accRPC.Call(utils.ResponderMaxDebit, cd, &cc); err != nil { - t.Error("Got error on Responder.Debit: ", err.Error()) - } else if cc.GetDuration() != 0 { - t.Errorf("Calling Responder.MaxDebit got callcost: %v", utils.ToIJSON(cc)) - } - - tStart = time.Date(2016, 3, 31, 0, 0, 0, 0, time.UTC) - cd = &engine.CallDescriptorWithAPIOpts{ - CallDescriptor: &engine.CallDescriptor{ - Category: "sms", - Tenant: "cgrates.org", - Subject: "testAccITAddBalanceWithDestinations", - Account: "testAccITAddBalanceWithDestinations", - Destination: "1002", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tStart.Add(time.Nanosecond), - }, - } - if err := accRPC.Call(utils.ResponderMaxDebit, cd, &cc); err != nil { - t.Error("Got error on Responder.Debit: ", err.Error()) - } else if cc.GetDuration() != 1 { - t.Errorf("Calling Responder.MaxDebit got callcost: %v", utils.ToIJSON(cc)) - } -} - -func testAccITAccountWithTriggers(t *testing.T) { - var reply string - args := &utils.AttrSetBalance{ - Tenant: "cgrates.org", - Account: "testAccITAccountWithTriggers", - BalanceType: utils.MetaMonetary, - Balance: map[string]interface{}{ - utils.ID: "testAccITAccountWithTriggers", - utils.Weight: 10, - utils.Value: 5, - }, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, args, &reply); err != nil { - t.Error("Got error on SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling SetBalance received: %s", reply) - } - - // add an action that contains topup and reset_triggers - topupAction := &utils.AttrSetActions{ActionsId: "TOPUP_WITH_RESET_TRIGGER", Actions: []*utils.TPAction{ - {Identifier: utils.MetaTopUpReset, BalanceId: "testAccITAccountWithTriggers", - BalanceType: utils.MetaMonetary, Units: "5", Weight: 10.0}, - {Identifier: utils.MetaResetTriggers}, - }} - - if err := accRPC.Call(utils.APIerSv2SetActions, topupAction, &reply); err != nil { - t.Error("Got error on APIerSv2.SetActions: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv2.SetActions received: %s", reply) - } - - // add an action to be executed when the trigger is triggered - actTrigger := &utils.AttrSetActions{ActionsId: "ACT_TRIGGER", Actions: []*utils.TPAction{ - {Identifier: utils.MetaTopUp, BalanceId: "CustomBanalce", - BalanceType: utils.MetaMonetary, Units: "5", Weight: 10.0}, - }} - - if err := accRPC.Call(utils.APIerSv2SetActions, actTrigger, &reply); err != nil { - t.Error("Got error on APIerSv2.SetActions: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv2.SetActions received: %s", reply) - } - - attrsAddTrigger := &AttrAddActionTrigger{Tenant: "cgrates.org", Account: "testAccITAccountWithTriggers", BalanceType: utils.MetaMonetary, - ThresholdType: "*min_balance", ThresholdValue: 2, Weight: 10, ActionsId: "ACT_TRIGGER"} - if err := accRPC.Call(utils.APIerSv1AddTriggeredAction, attrsAddTrigger, &reply); err != nil { - t.Error("Got error on APIerSv1.AddTriggeredAction: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.AddTriggeredAction received: %s", reply) - } - - var acnt engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: accTenant, - Account: "testAccITAccountWithTriggers", - } - - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } else { - for _, value := range acnt.BalanceMap[utils.MetaMonetary] { - if value.ID == "testAccITAccountWithTriggers" { - if value.GetValue() != 5 { - t.Errorf("Expecting %+v, received: %+v", 5, value.GetValue()) - } - if value.Weight != 10 { - t.Errorf("Expecting %+v, received: %+v", 10, value.Weight) - } - break - } - } - if len(acnt.ActionTriggers) != 1 { - t.Errorf("Expected 1, received: %+v", len(acnt.ActionTriggers)) - } else { - if acnt.ActionTriggers[0].Executed { - t.Errorf("Expected false, received: %+v", acnt.ActionTriggers[0].Executed) - } - } - } - - // Debit balance will trigger the Trigger from the account - if err := accRPC.Call(utils.APIerSv1DebitBalance, &AttrAddBalance{ - Tenant: "cgrates.org", - Account: "testAccITAccountWithTriggers", - BalanceType: utils.MetaMonetary, - Value: 3, - }, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } else { - for _, value := range acnt.BalanceMap[utils.MetaMonetary] { - if value.ID == "testAccITAccountWithTriggers" { - if value.GetValue() != 2 { - t.Errorf("Expecting %+v, received: %+v", 2, value.GetValue()) - } - } else if value.ID == "CustomBanalce" { - if value.GetValue() != 5 { - t.Errorf("Expecting %+v, received: %+v", 5, value.GetValue()) - } - } - } - if len(acnt.ActionTriggers) != 1 { - t.Errorf("Expected 1, received: %+v", len(acnt.ActionTriggers)) - } else { - if !acnt.ActionTriggers[0].Executed { - t.Errorf("Expected true, received: %+v", acnt.ActionTriggers[0].Executed) - } - } - } - - // execute the action that topup_reset the balance and reset the trigger - attrsEA := &utils.AttrExecuteAction{Tenant: "cgrates.org", Account: "testAccITAccountWithTriggers", - ActionsId: "TOPUP_WITH_RESET_TRIGGER"} - if err := accRPC.Call(utils.APIerSv1ExecuteAction, attrsEA, &reply); err != nil { - t.Error("Got error on APIerSv1.ExecuteAction: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.ExecuteAction received: %s", reply) - } - - acnt = engine.Account{} - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } else { - for _, value := range acnt.BalanceMap[utils.MetaMonetary] { - if value.ID == "testAccITAccountWithTriggers" { - if value.GetValue() != 5 { - t.Errorf("Expecting %+v, received: %+v", 5, value.GetValue()) - } - } else if value.ID == "CustomBanalce" { - if value.GetValue() != 5 { - t.Errorf("Expecting %+v, received: %+v", 5, value.GetValue()) - } - } - } - if len(acnt.ActionTriggers) != 1 { - t.Errorf("Expected 1, received: %+v", len(acnt.ActionTriggers)) - } else { - if acnt.ActionTriggers[0].Executed { - t.Errorf("Expected false, received: %+v", acnt.ActionTriggers[0].Executed) - } - } - } - -} - -func testAccITAccountMonthlyEstimated(t *testing.T) { - var reply string - // add an action that contains topup - topupAction := &utils.AttrSetActions{ActionsId: "TOPUP_ACTION", Actions: []*utils.TPAction{ - {Identifier: utils.MetaTopUpReset, BalanceId: "testAccITAccountMonthlyEstimated", - BalanceType: utils.MetaMonetary, Units: "5", Weight: 10.0}, - }} - - if err := accRPC.Call(utils.APIerSv2SetActions, topupAction, &reply); err != nil { - t.Error("Got error on APIerSv2.SetActions: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv2.SetActions received: %s", reply) - } - - atms1 := &AttrSetActionPlan{ - Id: "ATMS_1", - ReloadScheduler: true, - ActionPlan: []*AttrActionPlan{{ - ActionsId: "TOPUP_ACTION", - MonthDays: "31", - Time: "00:00:00", - Weight: 20.0, - TimingID: utils.MetaMonthlyEstimated, - }}, - } - if err := accRPC.Call(utils.APIerSv1SetActionPlan, &atms1, &reply); err != nil { - t.Error("Got error on APIerSv1.SetActionPlan: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetActionPlan received: %s", reply) - } - - acnt1 := utils.AttrSetAccount{Tenant: "cgrates.org", - Account: "testAccITAccountMonthlyEstimated", - ReloadScheduler: true, - ActionPlanID: "ATMS_1", - } - if err := accRPC.Call(utils.APIerSv1SetAccount, acnt1, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.SetAccount received: %s", reply) - } - - var aps []*engine.ActionPlan - accIDsStrMp := utils.StringMap{ - "cgrates.org:testAccITAccountMonthlyEstimated": true, - } - if err := accRPC.Call(utils.APIerSv1GetActionPlan, - &AttrGetActionPlan{ID: "ATMS_1"}, &aps); err != nil { - t.Error(err) - } else if len(aps) != 1 { - t.Errorf("Expected: %v,\n received: %v", 1, len(aps)) - } else if aps[0].Id != "ATMS_1" { - t.Errorf("Expected: %v,\n received: %v", "AP_PACKAGE_10", aps[0].Id) - } else if !reflect.DeepEqual(aps[0].AccountIDs, accIDsStrMp) { - t.Errorf("Expected: %v,\n received: %v", accIDsStrMp, aps[0].AccountIDs) - } else if len(aps[0].ActionTimings) != 1 { - t.Errorf("Expected: %v,\n received: %v", 1, len(aps)) - } else { - // verify the GetNextTimeStart - endOfMonth := utils.GetEndOfMonth(time.Now()) - if execDay := aps[0].ActionTimings[0].GetNextStartTime(time.Now()).Day(); execDay != endOfMonth.Day() { - t.Errorf("Expected: %v,\n received: %v", endOfMonth.Day(), execDay) - } - } -} - -func testAccITMultipleBalance(t *testing.T) { - attrSetBalance := utils.AttrSetBalances{ - Tenant: "cgrates.org", - Account: "testAccITMultipleBalance", - Balances: []*utils.AttrBalance{ - { - BalanceType: utils.MetaVoice, - Value: 2 * float64(time.Second), - Balance: map[string]interface{}{ - utils.ID: "Balance1", - utils.RatingSubject: "*zero5ms", - }, - }, - { - BalanceType: utils.MetaVoice, - Value: 10 * float64(time.Second), - Balance: map[string]interface{}{ - utils.ID: "Balance2", - utils.RatingSubject: "*zero5ms", - }, - }, - { - BalanceType: utils.MetaMonetary, - Value: 10, - Balance: map[string]interface{}{ - utils.ID: "MonBalance", - }, - }, - }, - } - var reply string - if err := accRPC.Call(utils.APIerSv1SetBalances, &attrSetBalance, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - - var acnt *engine.Account - attrs := &utils.AttrGetAccount{ - Tenant: "cgrates.org", - Account: "testAccITMultipleBalance", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrs, &acnt); err != nil { - t.Error(err) - } else if len(acnt.BalanceMap[utils.MetaVoice]) != 2 { - t.Errorf("Expected %+v, received: %+v", 2, len(acnt.BalanceMap[utils.MetaVoice])) - } else if acnt.BalanceMap[utils.MetaVoice].GetTotalValue() != float64(12*time.Second) { - t.Errorf("Expected %+v, received: %+v", float64(12*time.Second), acnt.BalanceMap[utils.MetaVoice].GetTotalValue()) - } else if len(acnt.BalanceMap[utils.MetaMonetary]) != 1 { - t.Errorf("Expected %+v, received: %+v", 1, len(acnt.BalanceMap[utils.MetaMonetary])) - } else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != 10.0 { - t.Errorf("Expected %+v, received: %+v", 10.0, acnt.BalanceMap[utils.MetaMonetary].GetTotalValue()) - } - -} - -func testAccITMultipleBalanceWithoutTenant(t *testing.T) { - attrSetBalance := utils.AttrSetBalances{ - Account: "testAccITMultipleBalance", - Balances: []*utils.AttrBalance{ - { - BalanceType: utils.MetaVoice, - Value: 2 * float64(time.Second), - Balance: map[string]interface{}{ - utils.ID: "Balance1", - utils.RatingSubject: "*zero5ms", - }, - }, - { - BalanceType: utils.MetaVoice, - Value: 10 * float64(time.Second), - Balance: map[string]interface{}{ - utils.ID: "Balance2", - utils.RatingSubject: "*zero5ms", - }, - }, - { - BalanceType: utils.MetaMonetary, - Value: 10, - Balance: map[string]interface{}{ - utils.ID: "MonBalance", - }, - }, - }, - } - var reply string - if err := accRPC.Call(utils.APIerSv1SetBalances, &attrSetBalance, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - - var acnt *engine.Account - attrs := &utils.AttrGetAccount{ - Account: "testAccITMultipleBalance", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrs, &acnt); err != nil { - t.Error(err) - } else if len(acnt.BalanceMap[utils.MetaVoice]) != 2 { - t.Errorf("Expected %+v, received: %+v", 2, len(acnt.BalanceMap[utils.MetaVoice])) - } else if acnt.BalanceMap[utils.MetaVoice].GetTotalValue() != float64(12*time.Second) { - t.Errorf("Expected %+v, received: %+v", float64(12*time.Second), acnt.BalanceMap[utils.MetaVoice].GetTotalValue()) - } else if len(acnt.BalanceMap[utils.MetaMonetary]) != 1 { - t.Errorf("Expected %+v, received: %+v", 1, len(acnt.BalanceMap[utils.MetaMonetary])) - } else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != 10.0 { - t.Errorf("Expected %+v, received: %+v", 10.0, acnt.BalanceMap[utils.MetaMonetary].GetTotalValue()) - } -} - -func testAccITRemoveBalances(t *testing.T) { - var reply string - if err := accRPC.Call(utils.APIerSv1RemoveBalances, - &utils.AttrSetBalance{Account: "testAccITMultipleBalance", BalanceType: utils.MetaVoice}, - &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Received: %s", reply) - } - attrs := &AttrAddBalance{ - Account: "testAccITMultipleBalance", - BalanceType: utils.MetaMonetary, - Value: 1.5, - Cdrlog: true, - } - if err := accRPC.Call(utils.APIerSv1AddBalance, &attrs, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Calling APIerSv1.AddBalance received: %s", reply) - } -} - -func testAccITAddVoiceBalanceWithDestinations(t *testing.T) { - var reply string - args := &utils.AttrSetBalance{ - Tenant: "cgrates.com", - Account: "testAccITAddVoiceBalanceWithDestinations", - BalanceType: utils.MetaVoice, - Balance: map[string]interface{}{ - utils.ID: "testAccITAddVoiceBalanceWithDestinations", - utils.DestinationIDs: "DST_1002", - utils.RatingSubject: "RP_1001", - utils.Weight: 10, - utils.Value: time.Hour, - }, - } - if err := accRPC.Call(utils.APIerSv1SetBalance, args, &reply); err != nil { - t.Error("Got error on SetBalance: ", err.Error()) - } else if reply != utils.OK { - t.Errorf("Calling SetBalance received: %s", reply) - } - - var acnt engine.Account - attrAcc := &utils.AttrGetAccount{ - Tenant: "cgrates.com", - Account: "testAccITAddVoiceBalanceWithDestinations", - } - if err := accRPC.Call(utils.APIerSv2GetAccount, attrAcc, &acnt); err != nil { - t.Fatal(err) - } - - for _, value := range acnt.BalanceMap[utils.MetaVoice] { - // check only where balance ID is testBalanceID (SetBalance function call was made with this Balance ID) - if value.ID == "testAccITAddVoiceBalanceWithDestinations" { - if value.GetValue() != 3.6e+12 { - t.Errorf("Expecting %+v, received: %+v", 3.6e+12, value.GetValue()) - } - if value.Weight != 10 { - t.Errorf("Expecting %+v, received: %+v", 10, value.Weight) - } - if value.RatingSubject != "RP_1001" { - t.Errorf("Expecting %+v, received: %+v", "RP_1001", value.Weight) - } - dstMp := utils.StringMap{ - "DST_1002": true, - } - if !reflect.DeepEqual(value.DestinationIDs, dstMp) { - t.Errorf("Expecting %+v, received: %+v", dstMp, value.DestinationIDs) - } - break - } - } - - tStart := time.Date(2016, 3, 31, 0, 0, 0, 0, time.UTC) - cd := &engine.CallDescriptorWithAPIOpts{ - CallDescriptor: &engine.CallDescriptor{ - Category: "call", - Tenant: "cgrates.com", - Subject: "testAccITAddVoiceBalanceWithDestinations", - Account: "testAccITAddVoiceBalanceWithDestinations", - Destination: "1002", - DurationIndex: time.Minute, - TimeStart: tStart, - TimeEnd: tStart.Add(time.Minute), - }, - } - var rply time.Duration - if err := accRPC.Call(utils.ResponderGetMaxSessionTime, cd, &rply); err != nil { - t.Error("Got error on Responder.Debit: ", err.Error()) - } else if rply != 0 { - t.Errorf("Expecting %+v, received: %+v", 0, rply) - } -} diff --git a/apier/v1/accounts_test.go b/apier/v1/accounts_test.go deleted file mode 100644 index 5fdc2d553..000000000 --- a/apier/v1/accounts_test.go +++ /dev/null @@ -1,109 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package v1 - -import ( - "testing" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" -) - -var ( - apierAcnts *APIerSv1 - apierAcntsAcntStorage *engine.InternalDB -) - -func init() { - cfg := config.NewDefaultCGRConfig() - apierAcntsAcntStorage = engine.NewInternalDB(nil, nil, true) - apierAcnts = &APIerSv1{ - DataManager: engine.NewDataManager(apierAcntsAcntStorage, config.CgrConfig().CacheCfg(), nil), - Config: cfg, - } -} - -func TestSetAccounts(t *testing.T) { - cgrTenant := "cgrates.org" - iscTenant := "itsyscom.com" - b10 := &engine.Balance{Value: 10, Weight: 10} - cgrAcnt1 := &engine.Account{ID: utils.ConcatenatedKey(cgrTenant, "account1"), - BalanceMap: map[string]engine.Balances{utils.MetaMonetary + utils.MetaOut: {b10}}} - cgrAcnt2 := &engine.Account{ID: utils.ConcatenatedKey(cgrTenant, "account2"), - BalanceMap: map[string]engine.Balances{utils.MetaMonetary + utils.MetaOut: {b10}}} - cgrAcnt3 := &engine.Account{ID: utils.ConcatenatedKey(cgrTenant, "account3"), - BalanceMap: map[string]engine.Balances{utils.MetaMonetary + utils.MetaOut: {b10}}} - iscAcnt1 := &engine.Account{ID: utils.ConcatenatedKey(iscTenant, "account1"), - BalanceMap: map[string]engine.Balances{utils.MetaMonetary + utils.MetaOut: {b10}}} - iscAcnt2 := &engine.Account{ID: utils.ConcatenatedKey(iscTenant, "account2"), - BalanceMap: map[string]engine.Balances{utils.MetaMonetary + utils.MetaOut: {b10}}} - for _, account := range []*engine.Account{cgrAcnt1, cgrAcnt2, cgrAcnt3, iscAcnt1, iscAcnt2} { - if err := apierAcntsAcntStorage.SetAccountDrv(account); err != nil { - t.Error(err) - } - } - //apierAcntsAcntStorage.CacheRatingPrefixes(utils.ActionPrefix) -} - -/* This was a comment -func TestGetAccountIds(t *testing.T) { - var accountIds []string - var attrs AttrGetAccountIds - if err := apierAcnts.GetAccountIds(attrs, &accountIds); err != nil { - t.Error("Unexpected error", err.Error()) - } else if len(accountIds) != 5 { - t.Errorf("Accounts returned: %+v", accountIds) - } -} -*/ - -func TestGetAccounts(t *testing.T) { - var accounts []interface{} - var attrs utils.AttrGetAccounts - if err := apierAcnts.GetAccounts(&utils.AttrGetAccounts{Tenant: "cgrates.org"}, &accounts); err != nil { - t.Error("Unexpected error", err.Error()) - } else if len(accounts) != 3 { - t.Errorf("Accounts returned: %+v", accounts) - } - attrs = utils.AttrGetAccounts{Tenant: "itsyscom.com"} - if err := apierAcnts.GetAccounts(&attrs, &accounts); err != nil { - t.Error("Unexpected error", err.Error()) - } else if len(accounts) != 2 { - t.Errorf("Accounts returned: %+v", accounts) - } - attrs = utils.AttrGetAccounts{Tenant: "cgrates.org", AccountIDs: []string{"account1"}} - if err := apierAcnts.GetAccounts(&attrs, &accounts); err != nil { - t.Error("Unexpected error", err.Error()) - } else if len(accounts) != 1 { - t.Errorf("Accounts returned: %+v", accounts) - } - attrs = utils.AttrGetAccounts{Tenant: "itsyscom.com", AccountIDs: []string{"INVALID"}} - if err := apierAcnts.GetAccounts(&attrs, &accounts); err != nil { - t.Error("Unexpected error", err.Error()) - } else if len(accounts) != 0 { - t.Errorf("Accounts returned: %+v", accounts) - } - attrs = utils.AttrGetAccounts{Tenant: "INVALID"} - if err := apierAcnts.GetAccounts(&attrs, &accounts); err != nil { - t.Error("Unexpected error", err.Error()) - } else if len(accounts) != 0 { - t.Errorf("Accounts returned: %+v", accounts) - } -} diff --git a/apier/v1/api_interfaces_test.go b/apier/v1/api_interfaces_test.go index 3abd44b35..633643f09 100644 --- a/apier/v1/api_interfaces_test.go +++ b/apier/v1/api_interfaces_test.go @@ -79,11 +79,6 @@ func TestGuardianSv1Interface(t *testing.T) { _ = GuardianSv1Interface(NewGuardianSv1()) } -func TestSchedulerSv1Interface(t *testing.T) { - _ = SchedulerSv1Interface(NewDispatcherSchedulerSv1(nil)) - _ = SchedulerSv1Interface(NewSchedulerSv1(nil, nil)) -} - func TestCDRsV1Interface(t *testing.T) { _ = CDRsV1Interface(NewDispatcherSCDRsV1(nil)) _ = CDRsV1Interface(NewCDRsV1(nil)) diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 1baf20aee..992edf685 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -624,81 +624,6 @@ func (attr *AttrActionPlan) getRITiming(dm *engine.DataManager) (timing *engine. return } -func (apierSv1 *APIerSv1) SetActionPlan(attrs *AttrSetActionPlan, reply *string) (err error) { - if missing := utils.MissingStructFields(attrs, []string{"Id", "ActionPlan"}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - for _, at := range attrs.ActionPlan { - requiredFields := []string{"ActionsId", "Time", "Weight"} - if missing := utils.MissingStructFields(at, requiredFields); len(missing) != 0 { - return fmt.Errorf("%s:Action:%s:%v", utils.ErrMandatoryIeMissing.Error(), at.ActionsId, missing) - } - } - _, err = guardian.Guardian.Guard(func() (interface{}, error) { - var prevAccountIDs utils.StringMap - if prevAP, err := apierSv1.DataManager.GetActionPlan(attrs.Id, false, utils.NonTransactional); err != nil && err != utils.ErrNotFound { - return 0, utils.NewErrServerError(err) - } else if err == nil && !attrs.Overwrite { - return 0, utils.ErrExists - } else if prevAP != nil { - prevAccountIDs = prevAP.AccountIDs - } - ap := &engine.ActionPlan{ - Id: attrs.Id, - } - for _, apiAtm := range attrs.ActionPlan { - if exists, err := apierSv1.DataManager.HasData(utils.ActionPrefix, apiAtm.ActionsId, ""); err != nil { - return 0, utils.NewErrServerError(err) - } else if !exists { - return 0, fmt.Errorf("%s:%s", utils.ErrBrokenReference.Error(), apiAtm.ActionsId) - } - timing, err := apiAtm.getRITiming(apierSv1.DataManager) - if err != nil { - return 0, err - } - ap.ActionTimings = append(ap.ActionTimings, &engine.ActionTiming{ - Uuid: utils.GenUUID(), - Weight: apiAtm.Weight, - Timing: &engine.RateInterval{Timing: timing}, - ActionsID: apiAtm.ActionsId, - }) - } - if err := apierSv1.DataManager.SetActionPlan(ap.Id, ap, true, utils.NonTransactional); err != nil { - return 0, utils.NewErrServerError(err) - } - if err := apierSv1.ConnMgr.Call(apierSv1.Config.ApierCfg().CachesConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{utils.ActionPlanIDs: {ap.Id}}, - }, reply); err != nil { - return 0, err - } - for acntID := range prevAccountIDs { - if err := apierSv1.DataManager.RemAccountActionPlans(acntID, []string{attrs.Id}); err != nil { - return 0, utils.NewErrServerError(err) - } - } - if len(prevAccountIDs) != 0 { - sl := prevAccountIDs.Slice() - if err := apierSv1.ConnMgr.Call(apierSv1.Config.ApierCfg().CachesConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{utils.AccountActionPlanIDs: sl}, - }, reply); err != nil { - return 0, err - } - } - return 0, nil - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.ActionPlanPrefix) - if err != nil { - return err - } - //generate a loadID for CacheActionPlans and store it in database - if err := apierSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheActionPlans: time.Now().UnixNano()}); err != nil { - return utils.APIErrorHandler(err) - } - *reply = utils.OK - return nil -} - func verifyFormat(tStr string) bool { if tStr == utils.EmptyString || tStr == utils.MetaASAP { @@ -873,29 +798,6 @@ func (apierSv1 *APIerSv1) RemoveActionPlan(attr *AttrGetActionPlan, reply *strin return nil } -// Process dependencies and load a specific AccountActions profile from storDb into dataDb. -func (apierSv1 *APIerSv1) LoadAccountActions(attrs *utils.TPAccountActions, reply *string) error { - if len(attrs.TPid) == 0 { - return utils.NewErrMandatoryIeMissing("TPid") - } - dbReader, err := engine.NewTpReader(apierSv1.DataManager.DataDB(), apierSv1.StorDb, - attrs.TPid, apierSv1.Config.GeneralCfg().DefaultTimezone, - apierSv1.Config.ApierCfg().CachesConns, apierSv1.Config.ApierCfg().ActionConns, - apierSv1.Config.DataDbCfg().Type == utils.INTERNAL) - if err != nil { - return utils.NewErrServerError(err) - } - if _, err := guardian.Guardian.Guard(func() (interface{}, error) { - return 0, dbReader.LoadAccountActionsFiltered(attrs) - }, config.CgrConfig().GeneralCfg().LockingTimeout, attrs.LoadId); err != nil { - return utils.NewErrServerError(err) - } - // ToDo: Get the action keys loaded by dbReader so we reload only these in cache - // Need to do it before scheduler otherwise actions to run will be unknown - *reply = utils.OK - return nil -} - func (apierSv1 *APIerSv1) LoadTariffPlanFromFolder(attrs *utils.AttrLoadTpFromFolder, reply *string) error { // verify if FolderPath is present if len(attrs.FolderPath) == 0 { diff --git a/apier/v2/accounts.go b/apier/v2/accounts.go deleted file mode 100644 index 97c1ae549..000000000 --- a/apier/v2/accounts.go +++ /dev/null @@ -1,273 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package v2 - -import ( - "errors" - "math" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/guardian" - "github.com/cgrates/cgrates/utils" -) - -func (apiv2 *APIerSv2) GetAccounts(attr *utils.AttrGetAccounts, reply *[]*engine.Account) error { - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apiv2.Config.GeneralCfg().DefaultTenant - } - var accountKeys []string - var err error - if len(attr.AccountIDs) == 0 { - if accountKeys, err = apiv2.DataManager.DataDB().GetKeysForPrefix(utils.AccountPrefix + tnt); err != nil { - return err - } - } else { - for _, acntID := range attr.AccountIDs { - if len(acntID) == 0 { // Source of error returned from redis (key not found) - continue - } - accountKeys = append(accountKeys, utils.AccountPrefix+utils.ConcatenatedKey(tnt, acntID)) - } - } - if len(accountKeys) == 0 { - return nil - } - if attr.Offset > len(accountKeys) { - attr.Offset = len(accountKeys) - } - if attr.Offset < 0 { - attr.Offset = 0 - } - var limitedAccounts []string - if attr.Limit != 0 { - max := math.Min(float64(attr.Offset+attr.Limit), float64(len(accountKeys))) - limitedAccounts = accountKeys[attr.Offset:int(max)] - } else { - limitedAccounts = accountKeys[attr.Offset:] - } - retAccounts := make([]*engine.Account, 0) - for _, acntKey := range limitedAccounts { - if acnt, err := apiv2.DataManager.GetAccount(acntKey[len(utils.AccountPrefix):]); err != nil && err != utils.ErrNotFound { // Not found is not an error here - return err - } else if acnt != nil { - if alNeg, has := attr.Filter[utils.AllowNegative]; has && alNeg != acnt.AllowNegative { - continue - } - if dis, has := attr.Filter[utils.Disabled]; has && dis != acnt.Disabled { - continue - } - retAccounts = append(retAccounts, acnt) - } - } - *reply = retAccounts - return nil -} - -// GetAccountsCount sets in reply var the total number of accounts registered for the received tenant -// returns ErrNotFound in case of 0 accounts -func (apiv2 *APIerSv2) GetAccountsCount(attr *utils.AttrGetAccountsCount, reply *int) (err error) { - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apiv2.Config.GeneralCfg().DefaultTenant - } - var accountKeys []string - if accountKeys, err = apiv2.DataManager.DataDB().GetKeysForPrefix(utils.AccountPrefix + tnt); err != nil { - return err - } - if len(accountKeys) == 0 { - return utils.ErrNotFound - } - *reply = len(accountKeys) - - return -} - -// Get balance -func (apiv2 *APIerSv2) GetAccount(attr *utils.AttrGetAccount, reply *engine.Account) error { - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apiv2.Config.GeneralCfg().DefaultTenant - } - tag := utils.ConcatenatedKey(tnt, attr.Account) - account, err := apiv2.DataManager.GetAccount(tag) - if err != nil { - return err - } - *reply = *account - return nil -} - -type AttrSetAccount struct { - Tenant string - Account string - ActionPlanIDs []string - ActionPlansOverwrite bool - ActionTriggerIDs []string - ActionTriggerOverwrite bool - ExtraOptions map[string]bool - ReloadScheduler bool -} - -func (apiv2 *APIerSv2) SetAccount(attr *AttrSetAccount, reply *string) error { - if missing := utils.MissingStructFields(attr, []string{utils.AccountField}); len(missing) != 0 { - return utils.NewErrMandatoryIeMissing(missing...) - } - tnt := attr.Tenant - if tnt == utils.EmptyString { - tnt = apiv2.Config.GeneralCfg().DefaultTenant - } - accID := utils.ConcatenatedKey(tnt, attr.Account) - dirtyActionPlans := make(map[string]*engine.ActionPlan) - var ub *engine.Account - var schedNeedsReload bool - _, err := guardian.Guardian.Guard(func() (interface{}, error) { - if bal, _ := apiv2.DataManager.GetAccount(accID); bal != nil { - ub = bal - } else { // Not found in db, create it here - ub = &engine.Account{ - ID: accID, - } - } - _, err := guardian.Guardian.Guard(func() (interface{}, error) { - acntAPids, err := apiv2.DataManager.GetAccountActionPlans(accID, false, utils.NonTransactional) - if err != nil && err != utils.ErrNotFound { - return 0, err - } - if attr.ActionPlansOverwrite { - // clean previous action plans - for i := 0; i < len(acntAPids); { - apID := acntAPids[i] - if utils.IsSliceMember(attr.ActionPlanIDs, apID) { - i++ // increase index since we don't remove from slice - continue // not removing the ones where - } - ap, err := apiv2.DataManager.GetActionPlan(apID, false, utils.NonTransactional) - if err != nil { - return 0, err - } - delete(ap.AccountIDs, accID) - dirtyActionPlans[apID] = ap - acntAPids = append(acntAPids[:i], acntAPids[i+1:]...) // remove the item from the list so we can overwrite the real list - } - } - for _, apID := range attr.ActionPlanIDs { - ap, err := apiv2.DataManager.GetActionPlan(apID, false, utils.NonTransactional) - if err != nil { - return 0, err - } - // create tasks - var schedTasks int // keep count on the number of scheduled tasks so we can compare with actions needed - for _, at := range ap.ActionTimings { - if at.IsASAP() { - t := &engine.Task{ - Uuid: utils.GenUUID(), - AccountID: accID, - ActionsID: at.ActionsID, - } - if err = apiv2.DataManager.DataDB().PushTask(t); err != nil { - return 0, err - } - schedTasks++ - } - } - if schedTasks != 0 && !schedNeedsReload { - schedNeedsReload = true - } - if schedTasks == len(ap.ActionTimings) || // scheduled all actions, no need to add account to AP - utils.IsSliceMember(acntAPids, apID) { - continue // No need to reschedule since already there - } - if ap.AccountIDs == nil { - ap.AccountIDs = make(utils.StringMap) - } - ap.AccountIDs[accID] = true - dirtyActionPlans[apID] = ap - acntAPids = append(acntAPids, apID) - } - if len(dirtyActionPlans) != 0 && !schedNeedsReload { - schedNeedsReload = true - } - apIDs := make([]string, len(dirtyActionPlans)) - i := 0 - for actionPlanID, ap := range dirtyActionPlans { - if err := apiv2.DataManager.SetActionPlan(actionPlanID, ap, true, utils.NonTransactional); err != nil { - return 0, err - } - apIDs[i] = actionPlanID - i++ - } - if err := apiv2.DataManager.SetAccountActionPlans(accID, acntAPids, true); err != nil { - return 0, err - } - return 0, apiv2.ConnMgr.Call(apiv2.Config.ApierCfg().CachesConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{utils.AccountActionPlanIDs: {accID}, utils.ActionPlanIDs: apIDs}, - }, reply) - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.ActionPlanPrefix) - if err != nil { - return 0, err - } - - if attr.ActionTriggerOverwrite { - ub.ActionTriggers = make(engine.ActionTriggers, 0) - } - for _, actionTriggerID := range attr.ActionTriggerIDs { - atrs, err := apiv2.DataManager.GetActionTriggers(actionTriggerID, false, utils.NonTransactional) - if err != nil { - return 0, err - } - for _, at := range atrs { - var found bool - for _, existingAt := range ub.ActionTriggers { - if existingAt.Equals(at) { - found = true - break - } - } - if !found { - ub.ActionTriggers = append(ub.ActionTriggers, at) - } - } - } - - ub.InitCounters() - if alNeg, has := attr.ExtraOptions[utils.AllowNegative]; has { - ub.AllowNegative = alNeg - } - if dis, has := attr.ExtraOptions[utils.Disabled]; has { - ub.Disabled = dis - } - // All prepared, save account - return 0, apiv2.DataManager.SetAccount(ub) - }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.AccountPrefix+accID) - if err != nil { - return utils.NewErrServerError(err) - } - if attr.ReloadScheduler && schedNeedsReload { - sched := apiv2.SchedulerService.GetScheduler() - if sched == nil { - return errors.New(utils.SchedulerNotRunningCaps) - } - sched.Reload() - } - *reply = utils.OK // This will mark saving of the account, error still can show up in actionTimingsId - return nil -} diff --git a/apier/v2/apier.go b/apier/v2/apier.go index 195e5e9bc..0e17d7fe8 100644 --- a/apier/v2/apier.go +++ b/apier/v2/apier.go @@ -30,7 +30,6 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/guardian" "github.com/cgrates/cgrates/utils" ) @@ -79,33 +78,6 @@ type AttrLoadAccountActions struct { AccountActionsId string } -// Process dependencies and load a specific AccountActions profile from storDb into dataDb. -func (apiv2 *APIerSv2) LoadAccountActions(attrs *AttrLoadAccountActions, reply *string) error { - if len(attrs.TPid) == 0 { - return utils.NewErrMandatoryIeMissing("TPid") - } - dbReader, err := engine.NewTpReader(apiv2.DataManager.DataDB(), apiv2.StorDb, - attrs.TPid, apiv2.Config.GeneralCfg().DefaultTimezone, - apiv2.Config.ApierCfg().CachesConns, apiv2.Config.ApierCfg().ActionConns, - apiv2.Config.DataDbCfg().Type == utils.INTERNAL) - if err != nil { - return utils.NewErrServerError(err) - } - tpAa := &utils.TPAccountActions{TPid: attrs.TPid} - tpAa.SetAccountActionsId(attrs.AccountActionsId) - if _, err := guardian.Guardian.Guard(func() (interface{}, error) { - return 0, dbReader.LoadAccountActionsFiltered(tpAa) - }, config.CgrConfig().GeneralCfg().LockingTimeout, attrs.AccountActionsId); err != nil { - return utils.NewErrServerError(err) - } - acts := apiv2.ActionService.GetAction() - if acts != nil { - //acts.Reload() - } - *reply = utils.OK - return nil -} - func (apiv2 *APIerSv2) LoadTariffPlanFromFolder(attrs *utils.AttrLoadTpFromFolder, reply *utils.LoadInstance) error { if len(attrs.FolderPath) == 0 { return fmt.Errorf("%s:%s", utils.ErrMandatoryIeMissing.Error(), "FolderPath") diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index dd1019fb6..8290702bb 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -648,7 +648,7 @@ func main() { internalRALsChan, internalResponderChan, shdChan, connManager, anz, srvDep) - apiSv1 := services.NewAPIerSv1Service(cfg, dmService, storDBService, filterSChan, server, schS, rals.GetResponder(), + apiSv1 := services.NewAPIerSv1Service(cfg, dmService, storDBService, filterSChan, server, rals.GetResponder(), internalAPIerSv1Chan, connManager, anz, srvDep) apiSv2 := services.NewAPIerSv2Service(apiSv1, cfg, server, internalAPIerSv2Chan, anz, srvDep) @@ -661,7 +661,7 @@ func main() { ldrs := services.NewLoaderService(cfg, dmService, filterSChan, server, internalLoaderSChan, connManager, anz, srvDep) - srvManager.AddServices(gvService, attrS, chrS, tS, stS, reS, routeS, schS, rals, + srvManager.AddServices(gvService, attrS, chrS, tS, stS, reS, routeS, rals, apiSv1, apiSv2, cdrS, smg, coreS, services.NewEventReaderService(cfg, filterSChan, shdChan, connManager, srvDep), services.NewDNSAgent(cfg, filterSChan, shdChan, connManager, srvDep), diff --git a/engine/action.go b/engine/action.go new file mode 100644 index 000000000..27ce5240d --- /dev/null +++ b/engine/action.go @@ -0,0 +1,1028 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package engine + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "html/template" + "net" + "net/http" + "net/smtp" + "reflect" + "sort" + "strconv" + "strings" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" + "github.com/cgrates/rpcclient" + "github.com/mitchellh/mapstructure" +) + +// Action will be filled for each tariff plan with the bonus value for received calls minutes. +type Action struct { + Id string + ActionType string + ExtraParameters string + Filter string + ExpirationString string // must stay as string because it can have relative values like 1month + Weight float64 + Balance *BalanceFilter + balanceValue float64 // balance value after action execution, used with cdrlog +} + +// Clone returns a clone of the action +func (a *Action) Clone() (cln *Action) { + if a == nil { + return + } + return &Action{ + Id: a.Id, + ActionType: a.ActionType, + ExtraParameters: a.ExtraParameters, + Filter: a.Filter, + ExpirationString: a.ExpirationString, + Weight: a.Weight, + Balance: a.Balance.Clone(), + } +} + +type actionTypeFunc func(*Account, *Action, Actions, interface{}) error + +func getActionFunc(typ string) (actionTypeFunc, bool) { + actionFuncMap := map[string]actionTypeFunc{ + utils.MetaLog: logAction, + utils.MetaResetTriggers: resetTriggersAction, + utils.CDRLog: cdrLogAction, + utils.MetaSetRecurrent: setRecurrentAction, + utils.MetaUnsetRecurrent: unsetRecurrentAction, + utils.MetaAllowNegative: allowNegativeAction, + utils.MetaDenyNegative: denyNegativeAction, + utils.MetaResetAccount: resetAccountAction, + utils.MetaTopUpReset: topupResetAction, + utils.MetaTopUp: topupAction, + utils.MetaDebitReset: debitResetAction, + utils.MetaDebit: debitAction, + utils.MetaResetCounters: resetCountersAction, + utils.MetaEnableAccount: enableAccountAction, + utils.MetaDisableAccount: disableAccountAction, + utils.MetaHTTPPost: callURL, + utils.HttpPostAsync: callURLAsync, + utils.MetaMailAsync: mailAsync, + utils.MetaSetDDestinations: setddestinations, + // utils.MetaRemoveAccount: removeAccountAction, + utils.MetaRemoveBalance: removeBalanceAction, + utils.MetaSetBalance: setBalanceAction, + utils.MetaTransferMonetaryDefault: transferMonetaryDefaultAction, + utils.MetaCgrRpc: cgrRPCAction, + utils.TopUpZeroNegative: topupZeroNegativeAction, + utils.SetExpiry: setExpiryAction, + utils.MetaPublishAccount: publishAccount, + utils.MetaRemoveSessionCosts: removeSessionCosts, + utils.MetaRemoveExpired: removeExpired, + utils.MetaPostEvent: postEvent, + utils.MetaCDRAccount: resetAccountCDR, + utils.MetaExport: export, + utils.MetaResetThreshold: resetThreshold, + utils.MetaResetStatQueue: resetStatQueue, + utils.MetaRemoteSetAccount: remoteSetAccount, + } + f, exists := actionFuncMap[typ] + return f, exists +} + +func logAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + switch { + case ub != nil: + body, _ := json.Marshal(ub) + utils.Logger.Info(fmt.Sprintf("LOG Account: %s", body)) + case extraData != nil: + body, _ := json.Marshal(extraData) + utils.Logger.Info(fmt.Sprintf("LOG ExtraData: %s", body)) + } + return +} + +func cdrLogAction(acc *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if len(config.CgrConfig().SchedulerCfg().CDRsConns) == 0 { + return fmt.Errorf("No connection with CDR Server") + } + defaultTemplate := map[string]config.RSRParsers{ + utils.ToR: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+utils.MetaAcnt+utils.NestingSep+utils.BalanceType, utils.InfieldSep), + utils.OriginHost: config.NewRSRParsersMustCompile("127.0.0.1", utils.InfieldSep), + utils.RequestType: config.NewRSRParsersMustCompile(utils.MetaNone, utils.InfieldSep), + utils.Tenant: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+utils.MetaAcnt+utils.NestingSep+utils.Tenant, utils.InfieldSep), + utils.AccountField: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+utils.MetaAcnt+utils.NestingSep+utils.AccountField, utils.InfieldSep), + utils.Subject: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+utils.MetaAcnt+utils.NestingSep+utils.AccountField, utils.InfieldSep), + utils.Cost: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+utils.MetaAct+utils.NestingSep+utils.ActionValue, utils.InfieldSep), + } + template := make(map[string]string) + // overwrite default template + if a.ExtraParameters != "" { + if err = json.Unmarshal([]byte(a.ExtraParameters), &template); err != nil { + return + } + for field, rsr := range template { + if defaultTemplate[field], err = config.NewRSRParsers(rsr, + config.CgrConfig().GeneralCfg().RSRSep); err != nil { + return + } + } + } + //In case that we have extra data we populate default templates + mapExtraData, _ := extraData.(map[string]interface{}) + for key, val := range mapExtraData { + if defaultTemplate[key], err = config.NewRSRParsers(utils.IfaceAsString(val), + config.CgrConfig().GeneralCfg().RSRSep); err != nil { + return + } + } + + // set stored cdr values + var cdrs []*CDR + for _, action := range acs { + if !utils.SliceHasMember([]string{utils.MetaDebit, utils.MetaDebitReset, utils.MetaSetBalance, utils.MetaTopUp, utils.MetaTopUpReset}, action.ActionType) || + action.Balance == nil { + continue // Only log specific actions + } + cdrLogProvider := newCdrLogProvider(acc, action) + cdr := &CDR{ + RunID: action.ActionType, + Source: utils.CDRLog, + SetupTime: time.Now(), + AnswerTime: time.Now(), + OriginID: utils.GenUUID(), + ExtraFields: make(map[string]string), + PreRated: true, + Usage: time.Duration(1), + } + cdr.CGRID = utils.Sha1(cdr.OriginID, cdr.OriginHost) + elem := reflect.ValueOf(cdr).Elem() + for key, rsrFlds := range defaultTemplate { + parsedValue, err := rsrFlds.ParseDataProvider(cdrLogProvider) + if err != nil { + return err + } + field := elem.FieldByName(key) + if field.IsValid() && field.CanSet() { + switch field.Kind() { + case reflect.Float64: + value, err := strconv.ParseFloat(parsedValue, 64) + if err != nil { + continue + } + field.SetFloat(value) + case reflect.String: + field.SetString(parsedValue) + case reflect.Int64: + value, err := strconv.ParseInt(parsedValue, 10, 64) + if err != nil { + continue + } + field.SetInt(value) + } + } else { // invalid fields go in extraFields of CDR + cdr.ExtraFields[key] = parsedValue + } + } + cdrs = append(cdrs, cdr) + var rply string + // After compute the CDR send it to CDR Server to be processed + if err := connMgr.Call(config.CgrConfig().SchedulerCfg().CDRsConns, nil, + utils.CDRsV1ProcessEvent, + &ArgV1ProcessEvent{ + Flags: []string{utils.ConcatenatedKey(utils.MetaChargers, "false")}, // do not try to get the chargers for cdrlog + CGREvent: *cdr.AsCGREvent(), + }, &rply); err != nil { + return err + } + } + b, _ := json.Marshal(cdrs) + a.ExpirationString = string(b) // testing purpose only + return +} + +func resetTriggersAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + ub.ResetActionTriggers(a) + return +} + +func setRecurrentAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + ub.SetRecurrent(a, true) + return +} + +func unsetRecurrentAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + ub.SetRecurrent(a, false) + return +} + +func allowNegativeAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + ub.AllowNegative = true + return +} + +func denyNegativeAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + ub.AllowNegative = false + return +} + +func resetAccountAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + return genericReset(ub) +} + +func topupResetAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + if ub.BalanceMap == nil { // Init the map since otherwise will get error if nil + ub.BalanceMap = make(map[string]Balances) + } + c := a.Clone() + genericMakeNegative(c) + err = genericDebit(ub, c, true) + a.balanceValue = c.balanceValue + return +} + +func topupAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + c := a.Clone() + genericMakeNegative(c) + err = genericDebit(ub, c, false) + a.balanceValue = c.balanceValue + return +} + +func debitResetAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + if ub.BalanceMap == nil { // Init the map since otherwise will get error if nil + ub.BalanceMap = make(map[string]Balances) + } + return genericDebit(ub, a, true) +} + +func debitAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + err = genericDebit(ub, a, false) + return +} + +func resetCountersAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if ub == nil { + return errors.New("nil account") + } + if ub.UnitCounters != nil { + ub.UnitCounters.resetCounters(a) + } + return +} + +func genericMakeNegative(a *Action) { + if a.Balance != nil && a.Balance.GetValue() > 0 { // only apply if not allready negative + a.Balance.SetValue(-a.Balance.GetValue()) + } +} + +func genericDebit(ub *Account, a *Action, reset bool) (err error) { + if ub == nil { + return errors.New("nil account") + } + if ub.BalanceMap == nil { + ub.BalanceMap = make(map[string]Balances) + } + return ub.debitBalanceAction(a, reset, false) +} + +func enableAccountAction(acc *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if acc == nil { + return errors.New("nil account") + } + acc.Disabled = false + return +} + +func disableAccountAction(acc *Account, a *Action, acs Actions, extraData interface{}) (err error) { + if acc == nil { + return errors.New("nil account") + } + acc.Disabled = true + return +} + +/*func enableDisableBalanceAction(ub *Account, sq *CDRStatsQueueTriggered, a *Action, acs Actions) (err error) { + if ub == nil { + return errors.New("nil account") + } + ub.enableDisableBalanceAction(a) + return +}*/ + +func genericReset(ub *Account) error { + for k := range ub.BalanceMap { + ub.BalanceMap[k] = Balances{&Balance{Value: 0}} + } + ub.InitCounters() + ub.ResetActionTriggers(nil) + return nil +} + +func getOneData(ub *Account, extraData interface{}) ([]byte, error) { + switch { + case ub != nil: + return json.Marshal(ub) + case extraData != nil: + return json.Marshal(extraData) + } + return nil, nil +} + +func callURL(ub *Account, a *Action, acs Actions, extraData interface{}) error { + body, err := getOneData(ub, extraData) + if err != nil { + return err + } + pstr, err := NewHTTPPoster(config.CgrConfig().GeneralCfg().ReplyTimeout, a.ExtraParameters, + utils.ContentJSON, config.CgrConfig().GeneralCfg().PosterAttempts) + if err != nil { + return err + } + err = pstr.PostValues(body, make(http.Header)) + if err != nil && config.CgrConfig().GeneralCfg().FailedPostsDir != utils.MetaNone { + AddFailedPost(a.ExtraParameters, utils.MetaHTTPjson, utils.ActionsPoster+utils.HierarchySep+a.ActionType, body, make(map[string]interface{})) + err = nil + } + return err +} + +// Does not block for posts, no error reports +func callURLAsync(ub *Account, a *Action, acs Actions, extraData interface{}) error { + body, err := getOneData(ub, extraData) + if err != nil { + return err + } + pstr, err := NewHTTPPoster(config.CgrConfig().GeneralCfg().ReplyTimeout, a.ExtraParameters, + utils.ContentJSON, config.CgrConfig().GeneralCfg().PosterAttempts) + if err != nil { + return err + } + go func() { + err := pstr.PostValues(body, make(http.Header)) + if err != nil && config.CgrConfig().GeneralCfg().FailedPostsDir != utils.MetaNone { + AddFailedPost(a.ExtraParameters, utils.MetaHTTPjson, utils.ActionsPoster+utils.HierarchySep+a.ActionType, body, make(map[string]interface{})) + } + }() + return nil +} + +// Mails the balance hitting the threshold towards predefined list of addresses +func mailAsync(ub *Account, a *Action, acs Actions, extraData interface{}) error { + cgrCfg := config.CgrConfig() + params := strings.Split(a.ExtraParameters, string(utils.CSVSep)) + if len(params) == 0 { + return errors.New("Unconfigured parameters for mail action") + } + toAddrs := strings.Split(params[0], string(utils.FallbackSep)) + toAddrStr := "" + for idx, addr := range toAddrs { + if idx != 0 { + toAddrStr += ", " + } + toAddrStr += addr + } + var message []byte + if ub != nil { + balJsn, err := json.Marshal(ub) + if err != nil { + return err + } + message = []byte(fmt.Sprintf("To: %s\r\nSubject: [CGR Notification] Threshold hit on Balance: %s\r\n\r\nTime: \r\n\t%s\r\n\r\nBalance:\r\n\t%s\r\n\r\nYours faithfully,\r\nCGR Balance Monitor\r\n", toAddrStr, ub.ID, time.Now(), balJsn)) + } + auth := smtp.PlainAuth("", cgrCfg.MailerCfg().MailerAuthUser, cgrCfg.MailerCfg().MailerAuthPass, strings.Split(cgrCfg.MailerCfg().MailerServer, ":")[0]) // We only need host part, so ignore port + go func() { + for i := 0; i < 5; i++ { // Loop so we can increase the success rate on best effort + if err := smtp.SendMail(cgrCfg.MailerCfg().MailerServer, auth, cgrCfg.MailerCfg().MailerFromAddr, toAddrs, message); err == nil { + break + } else if i == 4 { + if ub != nil { + utils.Logger.Warning(fmt.Sprintf(" WARNING: Failed emailing, params: [%s], error: [%s], BalanceId: %s", a.ExtraParameters, err.Error(), ub.ID)) + } + break + } + time.Sleep(time.Duration(i) * time.Minute) + } + }() + return nil +} + +func setddestinations(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + var ddcDestID string + for _, bchain := range ub.BalanceMap { + for _, b := range bchain { + for destID := range b.DestinationIDs { + if strings.HasPrefix(destID, utils.MetaDDC) { + ddcDestID = destID + break + } + } + if ddcDestID != "" { + break + } + } + if ddcDestID != "" { + break + } + } + if ddcDestID != "" { + destinations := utils.NewStringSet(nil) + for _, statID := range strings.Split(a.ExtraParameters, utils.InfieldSep) { + if statID == utils.EmptyString { + continue + } + var sts StatQueue + if err = connMgr.Call(config.CgrConfig().RalsCfg().StatSConns, nil, utils.StatSv1GetStatQueue, + &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, + ID: statID, + }, + }, &sts); err != nil { + return + } + ddcIface, has := sts.SQMetrics[utils.MetaDDC] + if !has { + continue + } + ddcMetric := ddcIface.(*StatDDC) + + // make slice from prefixes + // Review here prefixes + for p := range ddcMetric.FieldValues { + destinations.Add(p) + } + } + + newDest := &Destination{Id: ddcDestID, Prefixes: destinations.AsSlice()} + oldDest, err := dm.GetDestination(ddcDestID, true, true, utils.NonTransactional) + if err != nil { + return err + } + // update destid in storage + if err = dm.SetDestination(newDest, utils.NonTransactional); err != nil { + return err + } + if err = dm.CacheDataFromDB(utils.DestinationPrefix, []string{ddcDestID}, true); err != nil { + return err + } + + if err == nil && oldDest != nil { + if err = dm.UpdateReverseDestination(oldDest, newDest, utils.NonTransactional); err != nil { + return err + } + } + } else { + return utils.ErrNotFound + } + return nil +} + +func removeBalanceAction(ub *Account, a *Action, acs Actions, extraData interface{}) error { + if ub == nil { + return fmt.Errorf("nil account for %s action", utils.ToJSON(a)) + } + if _, exists := ub.BalanceMap[a.Balance.GetType()]; !exists { + return utils.ErrNotFound + } + bChain := ub.BalanceMap[a.Balance.GetType()] + found := false + for i := 0; i < len(bChain); i++ { + if bChain[i].MatchFilter(a.Balance, false, false) { + // delete without preserving order + bChain[i] = bChain[len(bChain)-1] + bChain = bChain[:len(bChain)-1] + i-- + found = true + } + } + ub.BalanceMap[a.Balance.GetType()] = bChain + if !found { + return utils.ErrNotFound + } + return nil +} + +func setBalanceAction(ub *Account, a *Action, acs Actions, extraData interface{}) error { + if ub == nil { + return fmt.Errorf("nil account for %s action", utils.ToJSON(a)) + } + return ub.setBalanceAction(a) +} + +func transferMonetaryDefaultAction(ub *Account, a *Action, acs Actions, extraData interface{}) error { + if ub == nil { + utils.Logger.Err("*transfer_monetary_default called without account") + return utils.ErrAccountNotFound + } + if _, exists := ub.BalanceMap[utils.MetaMonetary]; !exists { + return utils.ErrNotFound + } + defaultBalance := ub.GetDefaultMoneyBalance() + bChain := ub.BalanceMap[utils.MetaMonetary] + for _, balance := range bChain { + if balance.Uuid != defaultBalance.Uuid && + balance.ID != defaultBalance.ID && // extra caution + balance.MatchFilter(a.Balance, false, false) { + if balance.Value > 0 { + defaultBalance.Value += balance.Value + balance.Value = 0 + } + } + } + return nil +} + +// RPCRequest used by rpc action +type RPCRequest struct { + Address string + Transport string + Method string + Attempts int + Async bool + Params map[string]interface{} +} + +/* +<< .Object.Property >> + +Property can be a attribute or a method both used without () +Please also note the initial dot . + +Currently there are following objects that can be used: + +Account - the account that this action is called on +Action - the action with all it's attributs +Actions - the list of actions in the current action set +Sq - CDRStatsQueueTriggered object + +We can actually use everythiong that go templates offer. You can read more here: https://golang.org/pkg/text/template/ +*/ +func cgrRPCAction(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + // parse template + tmpl := template.New("extra_params") + tmpl.Delims("<<", ">>") + if tmpl, err = tmpl.Parse(a.ExtraParameters); err != nil { + utils.Logger.Err(fmt.Sprintf("error parsing *cgr_rpc template: %s", err.Error())) + return + } + var buf bytes.Buffer + if err = tmpl.Execute(&buf, struct { + Account *Account + Action *Action + Actions Actions + ExtraData interface{} + }{ub, a, acs, extraData}); err != nil { + utils.Logger.Err(fmt.Sprintf("error executing *cgr_rpc template %s:", err.Error())) + return + } + var req RPCRequest + if err = json.Unmarshal(buf.Bytes(), &req); err != nil { + return + } + var params *utils.RpcParams + if params, err = utils.GetRpcParams(req.Method); err != nil { + return + } + var client rpcclient.ClientConnector + if req.Address == utils.MetaInternal { + client = params.Object.(rpcclient.ClientConnector) + } else if client, err = rpcclient.NewRPCClient(utils.TCP, req.Address, false, "", "", "", + req.Attempts, 0, config.CgrConfig().GeneralCfg().ConnectTimeout, + config.CgrConfig().GeneralCfg().ReplyTimeout, req.Transport, + nil, false, nil); err != nil { + return + } + in, out := params.InParam, params.OutParam + //utils.Logger.Info("Params: " + utils.ToJSON(req.Params)) + //p, err := utils.FromMapStringInterfaceValue(req.Params, in) + if err = mapstructure.Decode(req.Params, in); err != nil { + utils.Logger.Info("<*cgr_rpc> err: " + err.Error()) + return + } + if in == nil { + utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> nil params err: req.Params: %+v params: %+v", req.Params, params)) + return utils.ErrParserError + } + utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> calling: %s with: %s and result %v", req.Method, utils.ToJSON(in), out)) + if !req.Async { + err = client.Call(req.Method, in, out) + utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> result: %s err: %v", utils.ToJSON(out), err)) + return + } + go func() { + err := client.Call(req.Method, in, out) + utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> result: %s err: %v", utils.ToJSON(out), err)) + }() + return +} + +func topupZeroNegativeAction(ub *Account, a *Action, acs Actions, extraData interface{}) error { + if ub == nil { + return errors.New("nil account") + } + if ub.BalanceMap == nil { + ub.BalanceMap = make(map[string]Balances) + } + return ub.debitBalanceAction(a, false, true) +} + +func setExpiryAction(ub *Account, a *Action, acs Actions, extraData interface{}) error { + if ub == nil { + return errors.New("nil account") + } + balanceType := a.Balance.GetType() + for _, b := range ub.BalanceMap[balanceType] { + if b.MatchFilter(a.Balance, false, true) { + b.ExpirationDate = a.Balance.GetExpirationDate() + } + } + return nil +} + +// publishAccount will publish the account as well as each balance received to ThresholdS +func publishAccount(ub *Account, a *Action, acs Actions, extraData interface{}) error { + if ub == nil { + return errors.New("nil account") + } + ub.Publish() + return nil +} + +// Actions used to store actions according to weight +type Actions []*Action + +func (apl Actions) Len() int { + return len(apl) +} + +func (apl Actions) Swap(i, j int) { + apl[i], apl[j] = apl[j], apl[i] +} + +// we need higher weights earlyer in the list +func (apl Actions) Less(j, i int) bool { + return apl[i].Weight < apl[j].Weight +} + +// Sort used to implement sort interface +func (apl Actions) Sort() { + sort.Sort(apl) +} + +// Clone returns a clone from object +func (apl Actions) Clone() (interface{}, error) { + if apl == nil { + return nil, nil + } + cln := make(Actions, len(apl)) + for i, action := range apl { + cln[i] = action.Clone() + } + return cln, nil +} + +// newCdrLogProvider constructs a DataProvider +func newCdrLogProvider(acnt *Account, action *Action) (dP utils.DataProvider) { + dP = &cdrLogProvider{acnt: acnt, action: action, cache: utils.MapStorage{}} + return +} + +// cdrLogProvider implements utils.DataProvider so we can pass it to filters +type cdrLogProvider struct { + acnt *Account + action *Action + cache utils.MapStorage +} + +// String is part of utils.DataProvider interface +// when called, it will display the already parsed values out of cache +func (cdrP *cdrLogProvider) String() string { + return utils.ToJSON(cdrP) +} + +// FieldAsInterface is part of utils.DataProvider interface +func (cdrP *cdrLogProvider) FieldAsInterface(fldPath []string) (data interface{}, err error) { + if data, err = cdrP.cache.FieldAsInterface(fldPath); err == nil || + err != utils.ErrNotFound { // item found in cache + return + } + err = nil // cancel previous err + if len(fldPath) == 2 { + switch fldPath[0] { + case utils.MetaAcnt: + switch fldPath[1] { + case utils.AccountID: + data = cdrP.acnt.ID + case utils.Tenant: + tntAcnt := new(utils.TenantAccount) // Init with empty values + if cdrP.acnt != nil { + if tntAcnt, err = utils.NewTAFromAccountKey(cdrP.acnt.ID); err != nil { + return + } + } + data = tntAcnt.Tenant + case utils.AccountField: + tntAcnt := new(utils.TenantAccount) // Init with empty values + if cdrP.acnt != nil { + if tntAcnt, err = utils.NewTAFromAccountKey(cdrP.acnt.ID); err != nil { + return + } + } + data = tntAcnt.Account + case utils.BalanceType: + data = cdrP.action.Balance.GetType() + case utils.BalanceUUID: + data = cdrP.action.Balance.CreateBalance().Uuid + case utils.BalanceID: + data = cdrP.action.Balance.CreateBalance().ID + case utils.BalanceValue: + data = strconv.FormatFloat(cdrP.action.balanceValue, 'f', -1, 64) + case utils.DestinationIDs: + data = cdrP.action.Balance.CreateBalance().DestinationIDs.String() + case utils.ExtraParameters: + data = cdrP.action.ExtraParameters + case utils.RatingSubject: + data = cdrP.action.Balance.CreateBalance().RatingSubject + case utils.Category: + data = cdrP.action.Balance.Categories.String() + case utils.SharedGroups: + data = cdrP.action.Balance.SharedGroups.String() + } + case utils.MetaAct: + switch fldPath[1] { + case utils.ActionID: + data = cdrP.action.Id + case utils.ActionType: + data = cdrP.action.ActionType + case utils.ActionValue: + data = strconv.FormatFloat(cdrP.action.Balance.CreateBalance().GetValue(), 'f', -1, 64) + } + } + } else { + data = fldPath[0] + } + cdrP.cache.Set(fldPath, data) + return +} + +// FieldAsString is part of utils.DataProvider interface +func (cdrP *cdrLogProvider) FieldAsString(fldPath []string) (data string, err error) { + var valIface interface{} + valIface, err = cdrP.FieldAsInterface(fldPath) + if err != nil { + return + } + return utils.IfaceAsString(valIface), nil +} + +// RemoteHost is part of utils.DataProvider interface +func (cdrP *cdrLogProvider) RemoteHost() net.Addr { + return utils.LocalAddr() +} + +func removeSessionCosts(_ *Account, action *Action, _ Actions, _ interface{}) error { // FiltersID;inlineFilter + tenant := config.CgrConfig().GeneralCfg().DefaultTenant + smcFilter := new(utils.SMCostFilter) + for _, fltrID := range strings.Split(action.ExtraParameters, utils.InfieldSep) { + if len(fltrID) == 0 { + continue + } + fltr, err := dm.GetFilter(tenant, fltrID, true, true, utils.NonTransactional) + if err != nil { + utils.Logger.Warning(fmt.Sprintf("<%s> Error: %s for filter: %s in action: <%s>", + utils.Actions, err.Error(), fltrID, utils.MetaRemoveSessionCosts)) + continue + } + for _, rule := range fltr.Rules { + smcFilter, err = utils.AppendToSMCostFilter(smcFilter, rule.Type, rule.Element, rule.Values, config.CgrConfig().GeneralCfg().DefaultTimezone) + if err != nil { + utils.Logger.Warning(fmt.Sprintf("<%s> %s in action: <%s>", utils.Actions, err.Error(), utils.MetaRemoveSessionCosts)) + } + } + } + return cdrStorage.RemoveSMCosts(smcFilter) +} + +func removeExpired(acc *Account, action *Action, _ Actions, extraData interface{}) error { + if acc == nil { + return fmt.Errorf("nil account for %s action", utils.ToJSON(action)) + } + + bChain, exists := acc.BalanceMap[action.Balance.GetType()] + if !exists { + return utils.ErrNotFound + } + + found := false + for i := 0; i < len(bChain); i++ { + if bChain[i].IsExpiredAt(time.Now()) { + // delete without preserving order + bChain[i] = bChain[len(bChain)-1] + bChain = bChain[:len(bChain)-1] + i-- + found = true + } + } + acc.BalanceMap[action.Balance.GetType()] = bChain + if !found { + return utils.ErrNotFound + } + return nil +} + +func postEvent(ub *Account, a *Action, acs Actions, extraData interface{}) error { + body, err := json.Marshal(extraData) + if err != nil { + return err + } + pstr, err := NewHTTPPoster(config.CgrConfig().GeneralCfg().ReplyTimeout, a.ExtraParameters, + utils.ContentJSON, config.CgrConfig().GeneralCfg().PosterAttempts) + if err != nil { + return err + } + err = pstr.PostValues(body, make(http.Header)) + if err != nil && config.CgrConfig().GeneralCfg().FailedPostsDir != utils.MetaNone { + AddFailedPost(a.ExtraParameters, utils.MetaHTTPjson, utils.ActionsPoster+utils.HierarchySep+a.ActionType, body, make(map[string]interface{})) + err = nil + } + return err +} + +// resetAccountCDR resets the account out of values from CDR +func resetAccountCDR(ub *Account, action *Action, acts Actions, _ interface{}) error { + if ub == nil { + return errors.New("nil account") + } + if cdrStorage == nil { + return fmt.Errorf("nil cdrStorage for %s action", utils.ToJSON(action)) + } + account := ub.GetID() + filter := &utils.CDRsFilter{ + Accounts: []string{account}, + NotCosts: []float64{-1}, + OrderBy: fmt.Sprintf("%s%sdesc", utils.OrderID, utils.InfieldSep), + Paginator: utils.Paginator{Limit: utils.IntPointer(1)}, + } + cdrs, _, err := cdrStorage.GetCDRs(filter, false) + if err != nil { + return err + } + cd := cdrs[0].CostDetails + if cd == nil { + return errors.New("nil CostDetails") + } + acs := cd.AccountSummary + if acs == nil { + return errors.New("nil AccountSummary") + } + for _, bsum := range acs.BalanceSummaries { + if bsum == nil { + continue + } + if err := ub.setBalanceAction(&Action{ + Balance: &BalanceFilter{ + Uuid: &bsum.UUID, + ID: &bsum.ID, + Type: &bsum.Type, + Value: &utils.ValueFormula{Static: bsum.Value}, + Disabled: &bsum.Disabled, + }, + }); err != nil { + utils.Logger.Warning(fmt.Sprintf("<%s> Error %s setting balance %s for account: %s", utils.Actions, err, bsum.UUID, account)) + } + } + return nil +} + +func export(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + var cgrEv *utils.CGREvent + switch { + case ub != nil: + cgrEv = &utils.CGREvent{ + Tenant: utils.NewTenantID(ub.ID).Tenant, + ID: utils.GenUUID(), + Event: map[string]interface{}{ + utils.AccountField: ub.ID, + utils.EventType: utils.AccountUpdate, + utils.EventSource: utils.AccountService, + utils.AllowNegative: ub.AllowNegative, + utils.Disabled: ub.Disabled, + utils.BalanceMap: ub.BalanceMap, + utils.UnitCounters: ub.UnitCounters, + utils.ActionTriggers: ub.ActionTriggers, + utils.UpdateTime: ub.UpdateTime, + }, + + APIOpts: map[string]interface{}{ + utils.MetaEventType: utils.AccountUpdate, + }, + } + case extraData != nil: + ev, canCast := extraData.(*utils.CGREvent) + if !canCast { + return + } + cgrEv = ev // only export CGREvents + default: + return // nothing to post + } + args := &utils.CGREventWithEeIDs{ + EeIDs: strings.Split(a.ExtraParameters, utils.InfieldSep), + CGREvent: cgrEv, + } + var rply map[string]map[string]interface{} + return connMgr.Call(config.CgrConfig().ApierCfg().EEsConns, nil, + utils.EeSv1ProcessEvent, args, &rply) +} + +func resetThreshold(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + args := &utils.TenantIDWithAPIOpts{ + TenantID: utils.NewTenantID(a.ExtraParameters), + } + var rply string + return connMgr.Call(config.CgrConfig().SchedulerCfg().ThreshSConns, nil, + utils.ThresholdSv1ResetThreshold, args, &rply) +} + +func resetStatQueue(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + args := &utils.TenantIDWithAPIOpts{ + TenantID: utils.NewTenantID(a.ExtraParameters), + } + var rply string + return connMgr.Call(config.CgrConfig().SchedulerCfg().StatSConns, nil, + utils.StatSv1ResetStatQueue, args, &rply) +} + +func remoteSetAccount(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) { + client := &http.Client{Transport: httpPstrTransport} + var resp *http.Response + req := new(bytes.Buffer) + if err = json.NewEncoder(req).Encode(ub); err != nil { + return + } + if resp, err = client.Post(a.ExtraParameters, "application/json", req); err != nil { + return + } + acc := new(Account) + err = json.NewDecoder(resp.Body).Decode(acc) + if err != nil { + return + } + if len(acc.BalanceMap) != 0 { + *ub = *acc + } + return +} diff --git a/engine/action_plan_test.go b/engine/action_plan_test.go deleted file mode 100644 index b3db2f6f7..000000000 --- a/engine/action_plan_test.go +++ /dev/null @@ -1,419 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package engine - -import ( - "reflect" - "sort" - "testing" - "time" - - "github.com/cgrates/cgrates/utils" -) - -func TestActionTimingTasks(t *testing.T) { - //empty check - actionTiming := new(ActionTiming) - eOut := []*Task{{Uuid: "", ActionsID: ""}} - rcv := actionTiming.Tasks() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", eOut, rcv) - } - //multiple check - actionTiming.ActionsID = "test" - actionTiming.Uuid = "test" - actionTiming.accountIDs = utils.StringMap{"1001": true, "1002": true, "1003": true} - eOut = []*Task{ - {Uuid: "test", AccountID: "1001", ActionsID: "test"}, - {Uuid: "test", AccountID: "1002", ActionsID: "test"}, - {Uuid: "test", AccountID: "1003", ActionsID: "test"}, - } - rcv = actionTiming.Tasks() - sort.Slice(rcv, func(i, j int) bool { return rcv[i].AccountID < rcv[j].AccountID }) - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", eOut, rcv) - } -} - -func TestActionTimingRemoveAccountID(t *testing.T) { - actionTiming := &ActionTiming{ - accountIDs: utils.StringMap{"1001": true, "1002": true, "1003": true}, - } - eOut := utils.StringMap{"1002": true, "1003": true} - rcv := actionTiming.RemoveAccountID("1001") - if !rcv { - t.Errorf("Account ID not found ") - } - if !reflect.DeepEqual(eOut, actionTiming.accountIDs) { - t.Errorf("Expecting: %+v, received: %+v", eOut, actionTiming.accountIDs) - } - //check for Account ID not found - rcv = actionTiming.RemoveAccountID("1001") - if rcv { - t.Errorf("Expected AccountID to be not found") - } -} - -func TestActionPlanRemoveAccountID(t *testing.T) { - actionPlan := &ActionPlan{ - AccountIDs: utils.StringMap{"1001": true, "1002": true, "1003": true}, - } - eOut := utils.StringMap{"1002": true, "1003": true} - rcv := actionPlan.RemoveAccountID("1001") - if !rcv { - t.Errorf("Account ID not found ") - } - if !reflect.DeepEqual(eOut, actionPlan.AccountIDs) { - t.Errorf("Expecting: %+v, received: %+v", eOut, actionPlan.AccountIDs) - } - //check for Account ID not found - rcv = actionPlan.RemoveAccountID("1001") - if rcv { - t.Errorf("Expected AccountID to be not found") - } -} - -func TestActionPlanClone(t *testing.T) { - at1 := &ActionPlan{ - Id: "test", - AccountIDs: utils.StringMap{"one": true, "two": true, "three": true}, - ActionTimings: []*ActionTiming{ - { - Uuid: "Uuid_test1", - ActionsID: "ActionsID_test1", - Weight: 0.8, - Timing: &RateInterval{ - Weight: 0.7, - }, - }, - }, - } - clned, err := at1.Clone() - if err != nil { - t.Error(err) - } - at1Cloned := clned.(*ActionPlan) - if !reflect.DeepEqual(at1, at1Cloned) { - t.Errorf("Expecting: %+v,\n received: %+v", at1, at1Cloned) - } -} - -func TestActionTimingClone(t *testing.T) { - at := &ActionTiming{ - Uuid: "Uuid_test", - ActionsID: "ActionsID_test", - Weight: 0.7, - } - if cloned := at.Clone(); !reflect.DeepEqual(at, cloned) { - t.Errorf("Expecting: %+v,\n received: %+v", at, cloned) - } -} - -func TestActionTimindSetActions(t *testing.T) { - actionTiming := new(ActionTiming) - - actions := Actions{ - &Action{ActionType: "test", Filter: "test"}, - &Action{ActionType: "test1", Filter: "test1"}, - } - actionTiming.SetActions(actions) - if !reflect.DeepEqual(actions, actionTiming.actions) { - t.Errorf("Expecting: %+v, received: %+v", actions, actionTiming.actions) - } -} - -func TestActionTimingSetAccountIDs(t *testing.T) { - actionTiming := new(ActionTiming) - accountIDs := utils.StringMap{"one": true, "two": true, "three": true} - actionTiming.SetAccountIDs(accountIDs) - - if !reflect.DeepEqual(accountIDs, actionTiming.accountIDs) { - t.Errorf("Expecting: %+v, received: %+v", accountIDs, actionTiming.accountIDs) - } -} - -func TestActionTimingGetAccountIDs(t *testing.T) { - actionTiming := &ActionTiming{ - accountIDs: utils.StringMap{"one": true, "two": true, "three": true}, - } - accIDs := utils.StringMap{"one": true, "two": true, "three": true} - rcv := actionTiming.GetAccountIDs() - - if !reflect.DeepEqual(accIDs, rcv) { - t.Errorf("Expecting: %+v, received: %+v", accIDs, rcv) - } -} -func TestActionTimingSetActionPlanID(t *testing.T) { - actionTiming := new(ActionTiming) - id := "test" - actionTiming.SetActionPlanID(id) - if !reflect.DeepEqual(id, actionTiming.actionPlanID) { - t.Errorf("Expecting: %+v, received: %+v", id, actionTiming.actionPlanID) - } -} - -func TestActionTimingGetActionPlanID(t *testing.T) { - id := "test" - actionTiming := new(ActionTiming) - actionTiming.actionPlanID = id - - rcv := actionTiming.GetActionPlanID() - if !reflect.DeepEqual(id, rcv) { - t.Errorf("Expecting: %+v, received: %+v", id, rcv) - } -} - -func TestActionTimingIsASAP(t *testing.T) { - actionTiming := new(ActionTiming) - if rcv := actionTiming.IsASAP(); rcv { - t.Error("Expecting false return") - } -} - -func TestAtplLen(t *testing.T) { - atpl := &ActionTimingWeightOnlyPriorityList{ - &ActionTiming{Uuid: "first", accountIDs: utils.StringMap{"1001": true, "1002": true}}, - &ActionTiming{Uuid: "second", accountIDs: utils.StringMap{"1004": true, "1005": true}}, - &ActionTiming{Uuid: "third", accountIDs: utils.StringMap{"1001": true, "1002": true}}, - } - eOut := len(*atpl) - rcv := atpl.Len() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", eOut, rcv) - } -} -func TestAtplSwap(t *testing.T) { - atpl := &ActionTimingWeightOnlyPriorityList{ - &ActionTiming{Uuid: "first", accountIDs: utils.StringMap{"1001": true, "1002": true}}, - &ActionTiming{Uuid: "second", accountIDs: utils.StringMap{"1004": true, "1005": true}}, - } - atpl2 := &ActionTimingWeightOnlyPriorityList{ - &ActionTiming{Uuid: "second", accountIDs: utils.StringMap{"1004": true, "1005": true}}, - &ActionTiming{Uuid: "first", accountIDs: utils.StringMap{"1001": true, "1002": true}}, - } - atpl.Swap(0, 1) - if !reflect.DeepEqual(atpl, atpl2) { - t.Errorf("Expecting: %+v, received: %+v", atpl, atpl2) - } -} - -func TestAtplLess(t *testing.T) { - atpl := &ActionTimingWeightOnlyPriorityList{ - &ActionTiming{Uuid: "first", Weight: 0.07}, - &ActionTiming{Uuid: "second", Weight: 1.07}, - } - rcv := atpl.Less(1, 0) - if !rcv { - t.Errorf("Expecting false, Received: true") - } - rcv = atpl.Less(0, 1) - if rcv { - t.Errorf("Expecting true, Received: false") - } -} - -func TestAtplSort(t *testing.T) { - - atpl := &ActionTimingWeightOnlyPriorityList{ - &ActionTiming{Uuid: "first", accountIDs: utils.StringMap{"1001": true, "1002": true}}, - &ActionTiming{Uuid: "second", accountIDs: utils.StringMap{"1004": true, "1005": true}}, - } - atpl2 := &ActionTimingWeightOnlyPriorityList{ - &ActionTiming{Uuid: "first", accountIDs: utils.StringMap{"1001": true, "1002": true}}, - &ActionTiming{Uuid: "second", accountIDs: utils.StringMap{"1004": true, "1005": true}}, - } - - sort.Sort(atpl) - atpl2.Sort() - if !reflect.DeepEqual(atpl, atpl2) { - t.Errorf("Expecting: %+v, received: %+v", atpl, atpl2) - } -} - -func TestCacheGetCloned(t *testing.T) { - at1 := &ActionPlan{ - Id: "test", - AccountIDs: utils.StringMap{"one": true, "two": true, "three": true}, - } - if err := Cache.Set(utils.CacheActionPlans, "MYTESTAPL", at1, nil, true, ""); err != nil { - t.Errorf("Expecting nil, received: %s", err) - } - clned, err := Cache.GetCloned(utils.CacheActionPlans, "MYTESTAPL") - if err != nil { - t.Error(err) - } - at1Cloned := clned.(*ActionPlan) - if !reflect.DeepEqual(at1, at1Cloned) { - t.Errorf("Expecting: %+v, received: %+v", at1, at1Cloned) - } -} - -func TestActionTimingGetNextStartTime(t *testing.T) { - t1 := time.Date(2020, 2, 7, 14, 25, 0, 0, time.UTC) - at := &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "00:00:00"}}} - exp := time.Date(2020, 2, 29, 0, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - - t1 = time.Date(2020, 2, 17, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{16}, - StartTime: "00:00:00"}}} - exp = time.Date(2020, 3, 16, 0, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - - t1 = time.Date(2020, 12, 17, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{16}, - StartTime: "00:00:00"}}} - exp = time.Date(2021, 1, 16, 0, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - - t1 = time.Date(2020, 12, 17, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "00:00:00"}}} - exp = time.Date(2020, 12, 31, 0, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - - t1 = time.Date(2020, 7, 31, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "15:00:00"}}} - exp = time.Date(2020, 7, 31, 15, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - - t1 = time.Date(2020, 2, 17, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{17}, - StartTime: "15:00:00"}}} - exp = time.Date(2020, 2, 17, 15, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - - t1 = time.Date(2020, 2, 17, 15, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{17}, - StartTime: "10:00:00"}}} - exp = time.Date(2020, 3, 17, 10, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - t1 = time.Date(2020, 9, 29, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "00:00:00"}}} - exp = time.Date(2020, 9, 30, 0, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - t1 = time.Date(2020, 9, 30, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "00:00:00"}}} - exp = time.Date(2020, 10, 31, 0, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - - t1 = time.Date(2020, 9, 30, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "15:00:00", - }}} - exp = time.Date(2020, 9, 30, 15, 0, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - - t1 = time.Date(2020, 9, 30, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "14:25:01"}}} - exp = time.Date(2020, 9, 30, 14, 25, 1, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - t1 = time.Date(2020, 12, 31, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "14:25:01"}}} - exp = time.Date(2020, 12, 31, 14, 25, 1, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } - t1 = time.Date(2020, 12, 31, 14, 25, 0, 0, time.UTC) - at = &ActionTiming{ - Timing: &RateInterval{ - Timing: &RITiming{ - ID: utils.MetaMonthlyEstimated, - MonthDays: utils.MonthDays{31}, - StartTime: "14:25:00"}}} - exp = time.Date(2021, 1, 31, 14, 25, 0, 0, time.UTC) - if st := at.GetNextStartTime(t1); !st.Equal(exp) { - t.Errorf("Expecting: %+v, received: %+v", exp, st) - } -} diff --git a/engine/action_trigger.go b/engine/action_trigger.go deleted file mode 100644 index 60bc5c66e..000000000 --- a/engine/action_trigger.go +++ /dev/null @@ -1,216 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package engine - -import ( - "encoding/json" - "fmt" - "sort" - "time" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/utils" -) - -type ActionTrigger struct { - ID string // original csv tag - UniqueID string // individual id - ThresholdType string //*min_event_counter, *max_event_counter, *min_balance_counter, *max_balance_counter, *min_balance, *max_balance, *balance_expired - ThresholdValue float64 - Recurrent bool // reset excuted flag each run - MinSleep time.Duration // Minimum duration between two executions in case of recurrent triggers - ExpirationDate time.Time - ActivationDate time.Time - //BalanceType string // *monetary/*voice etc - Balance *BalanceFilter - Weight float64 - ActionsID string - MinQueuedItems int // Trigger actions only if this number is hit (stats only) - Executed bool - LastExecutionTime time.Time -} - -func (at *ActionTrigger) Execute(ub *Account) (err error) { - // check for min sleep time - if at.Recurrent && !at.LastExecutionTime.IsZero() && time.Since(at.LastExecutionTime) < at.MinSleep { - return - } - at.LastExecutionTime = time.Now() - if ub != nil && ub.Disabled { - return fmt.Errorf("User %s is disabled and there are triggers in action!", ub.ID) - } - // does NOT need to Lock() because it is triggered from a method that took the Lock - var aac Actions - aac, err = dm.GetActions(at.ActionsID, false, utils.NonTransactional) - if err != nil { - utils.Logger.Err(fmt.Sprintf("Failed to get actions: %v", err)) - return - } - aac.Sort() - at.Executed = true - transactionFailed := false - removeAccountActionFound := false - for _, a := range aac { - // check action filter - if len(a.Filter) > 0 { - matched, err := ub.matchActionFilter(a.Filter) - if err != nil { - return err - } - if !matched { - continue - } - } - if a.Balance == nil { - a.Balance = &BalanceFilter{} - } - if a.ExpirationString != "" { // if it's *unlimited then it has to be zero time' - if expDate, parseErr := utils.ParseTimeDetectLayout(a.ExpirationString, - config.CgrConfig().GeneralCfg().DefaultTimezone); parseErr == nil { - a.Balance.ExpirationDate = &time.Time{} - *a.Balance.ExpirationDate = expDate - } - } - - actionFunction, exists := getActionFunc(a.ActionType) - if !exists { - utils.Logger.Err(fmt.Sprintf("Function type %v not available, aborting execution!", a.ActionType)) - transactionFailed = false - break - } - //go utils.Logger.Info(fmt.Sprintf("Executing %v, %v: %v", ub, sq, a)) - if err := actionFunction(ub, a, aac, nil); err != nil { - utils.Logger.Err(fmt.Sprintf("Error executing action %s: %v!", a.ActionType, err)) - transactionFailed = false - break - } - if a.ActionType == utils.MetaRemoveAccount { - removeAccountActionFound = true - } - } - if transactionFailed || at.Recurrent { - at.Executed = false - } - if !transactionFailed && ub != nil && !removeAccountActionFound { - dm.SetAccount(ub) - } - return -} - -// returns true if the field of the action timing are equeal to the non empty -// fields of the action -func (at *ActionTrigger) Match(a *Action) bool { - if a == nil || a.Balance == nil { - return true - } - if a.Balance.Type != nil && a.Balance.GetType() != at.Balance.GetType() { - return false - } - thresholdType := true // by default we consider that we don't have ExtraParameters - if a.ExtraParameters != "" { - t := struct { - GroupID string - UniqueID string - ThresholdType string - }{} - json.Unmarshal([]byte(a.ExtraParameters), &t) - // check Ids first - if t.GroupID != "" { - return at.ID == t.GroupID - } - if t.UniqueID != "" { - return at.UniqueID == t.UniqueID - } - thresholdType = t.ThresholdType == "" || at.ThresholdType == t.ThresholdType - } - return thresholdType && at.Balance.CreateBalance().MatchFilter(a.Balance, false, false) -} - -func (at *ActionTrigger) CreateBalance() *Balance { - b := at.Balance.CreateBalance() - b.ID = at.UniqueID - return b -} - -// makes a shallow copy of the receiver -func (at *ActionTrigger) Clone() *ActionTrigger { - if at == nil { - return nil - } - return &ActionTrigger{ - ID: at.ID, - UniqueID: at.UniqueID, - ThresholdType: at.ThresholdType, - ThresholdValue: at.ThresholdValue, - Recurrent: at.Recurrent, - MinSleep: at.MinSleep, - ExpirationDate: at.ExpirationDate, - ActivationDate: at.ActivationDate, - Weight: at.Weight, - ActionsID: at.ActionsID, - MinQueuedItems: at.MinQueuedItems, - Executed: at.Executed, - LastExecutionTime: at.LastExecutionTime, - Balance: at.Balance.Clone(), - } -} - -func (at *ActionTrigger) Equals(oat *ActionTrigger) bool { - // ids only - return at.ID == oat.ID && at.UniqueID == oat.UniqueID -} - -func (at *ActionTrigger) IsActive(t time.Time) bool { - return at.ActivationDate.IsZero() || t.After(at.ActivationDate) -} - -func (at *ActionTrigger) IsExpired(t time.Time) bool { - return !at.ExpirationDate.IsZero() && t.After(at.ExpirationDate) -} - -// Structure to store actions according to weight -type ActionTriggers []*ActionTrigger - -func (atpl ActionTriggers) Len() int { - return len(atpl) -} - -func (atpl ActionTriggers) Swap(i, j int) { - atpl[i], atpl[j] = atpl[j], atpl[i] -} - -//we need higher weights earlyer in the list -func (atpl ActionTriggers) Less(j, i int) bool { - return atpl[i].Weight < atpl[j].Weight -} - -func (atpl ActionTriggers) Sort() { - sort.Sort(atpl) -} - -func (atpl ActionTriggers) Clone() ActionTriggers { - if atpl == nil { - return nil - } - clone := make(ActionTriggers, len(atpl)) - for i, at := range atpl { - clone[i] = at.Clone() - } - return clone -} diff --git a/engine/action_trigger_test.go b/engine/action_trigger_test.go deleted file mode 100644 index f03185f0c..000000000 --- a/engine/action_trigger_test.go +++ /dev/null @@ -1,118 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package engine - -import ( - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/utils" -) - -func TestActionTriggerClone(t *testing.T) { - var at *ActionTrigger - if rcv := at.Clone(); at != nil { - t.Errorf("Expecting : nil, received: %s", utils.ToJSON(rcv)) - } - at = &ActionTrigger{} - eOut := &ActionTrigger{} - if rcv := at.Clone(); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting : %s, received: %s", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - ttime := time.Now() - at = &ActionTrigger{ - ID: "testID", - UniqueID: "testUniqueID", - ThresholdType: "testThresholdType", - ThresholdValue: 0.1, - Recurrent: true, - MinSleep: 10, - ExpirationDate: ttime, - ActivationDate: ttime.Add(5), - Weight: 0.1, - ActionsID: "testActionsID", - MinQueuedItems: 7, - Executed: true, - LastExecutionTime: ttime.Add(1), - Balance: &BalanceFilter{ - Uuid: utils.StringPointer("testUuid"), - }, - } - eOut = &ActionTrigger{ - ID: "testID", - UniqueID: "testUniqueID", - ThresholdType: "testThresholdType", - ThresholdValue: 0.1, - Recurrent: true, - MinSleep: 10, - ExpirationDate: ttime, - ActivationDate: ttime.Add(5), - Weight: 0.1, - ActionsID: "testActionsID", - MinQueuedItems: 7, - Executed: true, - LastExecutionTime: ttime.Add(1), - Balance: &BalanceFilter{ - Uuid: utils.StringPointer("testUuid"), - }, - } - rcv := at.Clone() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting : %s, received: %s", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - rcv.Balance.Uuid = utils.StringPointer("modified") - if at.Balance.Uuid == utils.StringPointer("modified") { - t.Errorf("Expedcting: modified, received %s", utils.ToJSON(at.Balance.Uuid)) - } - -} - -func TestActionTriggersClone(t *testing.T) { - var atpl ActionTriggers - if rcv := atpl.Clone(); rcv != nil { - t.Errorf("Expecting : nil, received: %s", utils.ToJSON(rcv)) - } - atpl = make(ActionTriggers, 0) - eOut := make(ActionTriggers, 0) - if rcv := atpl.Clone(); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting : %s, received: %s", utils.ToJSON(eOut), utils.ToJSON(rcv)) - - } - atpl = []*ActionTrigger{ - { - ID: "test1", - }, - { - ID: "test2", - }, - } - eOut = []*ActionTrigger{ - { - ID: "test1", - }, - { - ID: "test2", - }, - } - if rcv := atpl.Clone(); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting : %s, received: %s", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - -} diff --git a/engine/balances.go b/engine/balances.go index 3bc3fb0f6..dbdf7e1d8 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -155,10 +155,6 @@ func (b *Balance) MatchDestination(destinationID string) bool { return !b.HasDestination() || b.DestinationIDs[destinationID] } -func (b *Balance) MatchActionTrigger(at *ActionTrigger) bool { - return b.HardMatchFilter(at.Balance, false) -} - func (b *Balance) Clone() *Balance { if b == nil { return nil @@ -760,7 +756,6 @@ func (bc Balances) SaveDirtyBalances(acc *Account) { savedAccounts := make(map[string]*Account) for _, b := range bc { if b.account != nil && b.account != acc && b.dirty && savedAccounts[b.account.ID] == nil { - dm.SetAccount(b.account) savedAccounts[b.account.ID] = b.account } } diff --git a/engine/datadbmock.go b/engine/datadbmock.go index 2ea1d31b8..d2f1798ee 100644 --- a/engine/datadbmock.go +++ b/engine/datadbmock.go @@ -64,26 +64,6 @@ func (dbM *DataDBMock) HasDataDrv(string, string, string) (bool, error) { return false, utils.ErrNotImplemented } -func (dbM *DataDBMock) GetRatingPlanDrv(string) (*RatingPlan, error) { - return nil, utils.ErrNotImplemented -} - -func (dbM *DataDBMock) SetRatingPlanDrv(*RatingPlan) error { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) RemoveRatingPlanDrv(key string) (err error) { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) GetRatingProfileDrv(string) (*RatingProfile, error) { - return nil, utils.ErrNotImplemented -} - -func (dbM *DataDBMock) SetRatingProfileDrv(*RatingProfile) error { - return utils.ErrNotImplemented -} - func (dbM *DataDBMock) GetDestinationDrv(string, string) (*Destination, error) { return nil, utils.ErrNotImplemented } @@ -120,59 +100,6 @@ func (dbM *DataDBMock) RemoveActionsDrv(string) error { return utils.ErrNotImplemented } -func (dbM *DataDBMock) GetSharedGroupDrv(string) (*SharedGroup, error) { - return nil, utils.ErrNotImplemented -} - -func (dbM *DataDBMock) SetSharedGroupDrv(*SharedGroup) error { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) RemoveSharedGroupDrv(id string) (err error) { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) GetActionTriggersDrv(string) (ActionTriggers, error) { - return nil, utils.ErrNotImplemented -} - -func (dbM *DataDBMock) SetActionTriggersDrv(string, ActionTriggers) error { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) RemoveActionTriggersDrv(string) error { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) GetActionPlanDrv(string, bool, string) (*ActionPlan, error) { - return nil, utils.ErrNotImplemented -} - -func (dbM *DataDBMock) SetActionPlanDrv(string, *ActionPlan, bool, string) error { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) RemoveActionPlanDrv(key string, transactionID string) error { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) GetAllActionPlansDrv() (map[string]*ActionPlan, error) { - return nil, utils.ErrNotImplemented -} - -func (dbM *DataDBMock) GetAccountActionPlansDrv(acntID string, skipCache bool, - transactionID string) (apIDs []string, err error) { - return nil, utils.ErrNotImplemented -} - -func (dbM *DataDBMock) SetAccountActionPlansDrv(acntID string, apIDs []string, overwrite bool) (err error) { - return utils.ErrNotImplemented -} - -func (dbM *DataDBMock) RemAccountActionPlansDrv(acntID string, apIDs []string) (err error) { - return utils.ErrNotImplemented -} - func (dbM *DataDBMock) PushTask(*Task) error { return utils.ErrNotImplemented } diff --git a/engine/datamanager.go b/engine/datamanager.go index 71b2dbd3f..d94d67062 100644 --- a/engine/datamanager.go +++ b/engine/datamanager.go @@ -171,20 +171,8 @@ func (dm *DataManager) CacheDataFromDB(prfx string, ids []string, mustBeCached b _, err = dm.GetDestination(dataID, false, true, utils.NonTransactional) case utils.ReverseDestinationPrefix: _, err = dm.GetReverseDestination(dataID, false, true, utils.NonTransactional) - case utils.RatingPlanPrefix: - _, err = dm.GetRatingPlan(dataID, true, utils.NonTransactional) - case utils.RatingProfilePrefix: - _, err = dm.GetRatingProfile(dataID, true, utils.NonTransactional) case utils.ActionPrefix: _, err = dm.GetActions(dataID, true, utils.NonTransactional) - case utils.ActionPlanPrefix: - _, err = dm.GetActionPlan(dataID, true, utils.NonTransactional) - case utils.AccountActionPlansPrefix: - _, err = dm.GetAccountActionPlans(dataID, true, utils.NonTransactional) - case utils.ActionTriggerPrefix: - _, err = dm.GetActionTriggers(dataID, true, utils.NonTransactional) - case utils.SharedGroupPrefix: - _, err = dm.GetSharedGroup(dataID, true, utils.NonTransactional) case utils.ResourceProfilesPrefix: tntID := utils.NewTenantID(dataID) _, err = dm.GetResourceProfile(tntID.Tenant, tntID.ID, false, true, utils.NonTransactional) @@ -342,25 +330,6 @@ func (dm *DataManager) RebuildReverseForPrefix(prefix string) (err error) { return err } } - case utils.AccountActionPlansPrefix: - if err = dm.dataDB.RemoveKeysForPrefix(prefix); err != nil { - return - } - var keys []string - if keys, err = dm.dataDB.GetKeysForPrefix(utils.ActionPlanPrefix); err != nil { - return - } - for _, key := range keys { - var apl *ActionPlan - if apl, err = dm.GetActionPlan(key[len(utils.ActionPlanPrefix):], true, utils.NonTransactional); err != nil { - return err - } - for acntID := range apl.AccountIDs { - if err = dm.SetAccountActionPlans(acntID, []string{apl.Id}, false); err != nil { - return err - } - } - } default: return utils.ErrInvalidKey } @@ -587,77 +556,6 @@ func (dm *DataManager) UpdateReverseDestination(oldDest, newDest *Destination, return dm.SetReverseDestination(newDest.Id, addedPrefixes, transactionID) } -func (dm *DataManager) GetAccount(id string) (acc *Account, err error) { - if dm == nil { - err = utils.ErrNoDatabaseConn - return - } - acc, err = dm.dataDB.GetAccountDrv(id) - if err != nil { - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaAccounts]; err == utils.ErrNotFound && - itm.Remote { - splt := utils.SplitConcatenatedKey(id) - tenant := utils.FirstNonEmpty(splt[0], config.CgrConfig().GeneralCfg().DefaultTenant) - if err = dm.connMgr.Call(config.CgrConfig().DataDbCfg().RmtConns, nil, - utils.ReplicatorSv1GetAccount, &utils.StringWithAPIOpts{ - Arg: id, - Tenant: tenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, utils.EmptyString, - utils.FirstNonEmpty(config.CgrConfig().DataDbCfg().RmtConnID, - config.CgrConfig().GeneralCfg().NodeID)), - }, &acc); err == nil { - err = dm.dataDB.SetAccountDrv(acc) - } - } - if err != nil { - err = utils.CastRPCErr(err) - return nil, err - } - } - return -} - -func (dm *DataManager) SetAccount(acc *Account) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.dataDB.SetAccountDrv(acc); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaAccounts]; itm.Replicate { - err = replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.AccountPrefix, acc.ID, // this are used to get the host IDs from cache - utils.ReplicatorSv1SetAccount, - &AccountWithAPIOpts{ - Account: acc, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - utils.EmptyString, utils.EmptyString)}) // the account doesn't have cache - } - return -} - -func (dm *DataManager) RemoveAccount(id string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.dataDB.RemoveAccountDrv(id); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaAccounts]; itm.Replicate { - replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.AccountPrefix, id, // this are used to get the host IDs from cache - utils.ReplicatorSv1RemoveAccount, - &utils.StringWithAPIOpts{ - Arg: id, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - utils.EmptyString, utils.EmptyString)}) - } - return -} - // GetStatQueue retrieves a StatQueue from dataDB // handles caching and deserialization of metrics func (dm *DataManager) GetStatQueue(tenant, id string, @@ -1649,208 +1547,6 @@ func (dm *DataManager) RemoveResourceProfile(tenant, id, transactionID string, w return } -func (dm *DataManager) GetActionTriggers(id string, skipCache bool, - transactionID string) (attrs ActionTriggers, err error) { - if !skipCache { - if x, ok := Cache.Get(utils.CacheActionTriggers, id); ok { - if x == nil { - return nil, utils.ErrNotFound - } - return x.(ActionTriggers), nil - } - } - if dm == nil { - err = utils.ErrNoDatabaseConn - return - } - attrs, err = dm.dataDB.GetActionTriggersDrv(id) - if err != nil { - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaActionTriggers]; err == utils.ErrNotFound && itm.Remote { - if err = dm.connMgr.Call(config.CgrConfig().DataDbCfg().RmtConns, nil, utils.ReplicatorSv1GetActionTriggers, - &utils.StringWithAPIOpts{ - Arg: id, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, utils.EmptyString, - utils.FirstNonEmpty(config.CgrConfig().DataDbCfg().RmtConnID, - config.CgrConfig().GeneralCfg().NodeID)), - }, attrs); err == nil { - err = dm.dataDB.SetActionTriggersDrv(id, attrs) - } - } - if err != nil { - err = utils.CastRPCErr(err) - if err == utils.ErrNotFound { - if errCh := Cache.Set(utils.CacheActionTriggers, id, nil, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - } - return nil, err - } - } - if errCh := Cache.Set(utils.CacheActionTriggers, id, attrs, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - return -} - -func (dm *DataManager) RemoveActionTriggers(id, transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.DataDB().RemoveActionTriggersDrv(id); err != nil { - return - } - if errCh := Cache.Remove(utils.CacheActionTriggers, id, - cacheCommit(transactionID), transactionID); errCh != nil { - return errCh - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaActionTriggers]; itm.Replicate { - replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.ActionTriggerPrefix, id, // this are used to get the host IDs from cache - utils.ReplicatorSv1RemoveActionTriggers, - &utils.StringWithAPIOpts{ - Arg: id, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -//SetActionTriggersArgWithAPIOpts is used to send the key and the ActionTriggers to Replicator -type SetActionTriggersArgWithAPIOpts struct { - Key string - Attrs ActionTriggers - Tenant string - APIOpts map[string]interface{} -} - -func (dm *DataManager) SetActionTriggers(key string, attr ActionTriggers, - transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.DataDB().SetActionTriggersDrv(key, attr); err != nil { - return - } - if err = dm.CacheDataFromDB(utils.ActionTriggerPrefix, []string{key}, true); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaActionTriggers]; itm.Replicate { - err = replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.ActionTriggerPrefix, key, // this are used to get the host IDs from cache - utils.ReplicatorSv1SetActionTriggers, - &SetActionTriggersArgWithAPIOpts{ - Attrs: attr, - Key: key, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -func (dm *DataManager) GetSharedGroup(key string, skipCache bool, - transactionID string) (sg *SharedGroup, err error) { - if !skipCache { - if x, ok := Cache.Get(utils.CacheSharedGroups, key); ok { - if x != nil { - return x.(*SharedGroup), nil - } - return nil, utils.ErrNotFound - } - } - if dm == nil { - err = utils.ErrNoDatabaseConn - return - } - sg, err = dm.DataDB().GetSharedGroupDrv(key) - if err != nil { - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaSharedGroups]; err == utils.ErrNotFound && itm.Remote { - if err = dm.connMgr.Call(config.CgrConfig().DataDbCfg().RmtConns, nil, - utils.ReplicatorSv1GetSharedGroup, &utils.StringWithAPIOpts{ - Arg: key, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, utils.EmptyString, - utils.FirstNonEmpty(config.CgrConfig().DataDbCfg().RmtConnID, - config.CgrConfig().GeneralCfg().NodeID)), - }, &sg); err == nil { - err = dm.dataDB.SetSharedGroupDrv(sg) - } - } - if err != nil { - err = utils.CastRPCErr(err) - if err == utils.ErrNotFound { - if errCh := Cache.Set(utils.CacheSharedGroups, key, nil, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - } - return nil, err - } - } - if errCh := Cache.Set(utils.CacheSharedGroups, key, sg, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - return -} - -func (dm *DataManager) SetSharedGroup(sg *SharedGroup, - transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.DataDB().SetSharedGroupDrv(sg); err != nil { - return - } - if err = dm.CacheDataFromDB(utils.SharedGroupPrefix, - []string{sg.Id}, true); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaSharedGroups]; itm.Replicate { - err = replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.SharedGroupPrefix, sg.Id, // this are used to get the host IDs from cache - utils.ReplicatorSv1SetSharedGroup, - &SharedGroupWithAPIOpts{ - SharedGroup: sg, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -func (dm *DataManager) RemoveSharedGroup(id, transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.DataDB().RemoveSharedGroupDrv(id); err != nil { - return - } - if errCh := Cache.Remove(utils.CacheSharedGroups, id, - cacheCommit(transactionID), transactionID); errCh != nil { - return errCh - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaSharedGroups]; itm.Replicate { - replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.SharedGroupPrefix, id, // this are used to get the host IDs from cache - utils.ReplicatorSv1RemoveSharedGroup, - &utils.StringWithAPIOpts{ - Arg: id, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - func (dm *DataManager) GetActions(key string, skipCache bool, transactionID string) (as Actions, err error) { if !skipCache { if x, err := Cache.GetCloned(utils.CacheActions, key); err != nil { @@ -1950,387 +1646,6 @@ func (dm *DataManager) RemoveActions(key, transactionID string) (err error) { return } -func (dm *DataManager) GetActionPlan(key string, skipCache bool, transactionID string) (ats *ActionPlan, err error) { - if dm == nil { - err = utils.ErrNoDatabaseConn - return - } - ats, err = dm.dataDB.GetActionPlanDrv(key, skipCache, transactionID) - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaActionPlans]; err == utils.ErrNotFound && itm.Remote { - if err = dm.connMgr.Call(config.CgrConfig().DataDbCfg().RmtConns, nil, - utils.ReplicatorSv1GetActionPlan, &utils.StringWithAPIOpts{ - Arg: key, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, utils.EmptyString, - utils.FirstNonEmpty(config.CgrConfig().DataDbCfg().RmtConnID, - config.CgrConfig().GeneralCfg().NodeID)), - }, &ats); err == nil { - err = dm.dataDB.SetActionPlanDrv(key, ats, true, utils.NonTransactional) - } - } - if err != nil { - err = utils.CastRPCErr(err) - return nil, err - } - return -} - -// SetActionPlanArgWithAPIOpts is used in replicatorV1 for dispatcher -type SetActionPlanArgWithAPIOpts struct { - Key string - Ats *ActionPlan - Overwrite bool - Tenant string - APIOpts map[string]interface{} -} - -func (dm *DataManager) SetActionPlan(key string, ats *ActionPlan, - overwrite bool, transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.dataDB.SetActionPlanDrv(key, ats, overwrite, transactionID); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaActionPlans]; itm.Replicate { - err = replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.ActionPlanPrefix, key, // this are used to get the host IDs from cache - utils.ReplicatorSv1SetActionPlan, - &SetActionPlanArgWithAPIOpts{ - Key: key, - Ats: ats, - Overwrite: overwrite, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -func (dm *DataManager) GetAllActionPlans() (ats map[string]*ActionPlan, err error) { - if dm == nil { - err = utils.ErrNoDatabaseConn - return - } - ats, err = dm.dataDB.GetAllActionPlansDrv() - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaActionPlans]; ((err == nil && len(ats) == 0) || err == utils.ErrNotFound) && itm.Remote { - err = dm.connMgr.Call(config.CgrConfig().DataDbCfg().RmtConns, nil, - utils.ReplicatorSv1GetAllActionPlans, - &utils.StringWithAPIOpts{ - Arg: utils.EmptyString, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, utils.EmptyString, - utils.FirstNonEmpty(config.CgrConfig().DataDbCfg().RmtConnID, - config.CgrConfig().GeneralCfg().NodeID)), - }, &ats) - } - if err != nil { - err = utils.CastRPCErr(err) - return nil, err - } - return -} - -func (dm *DataManager) RemoveActionPlan(key string, transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.dataDB.RemoveActionPlanDrv(key, transactionID); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaActionPlans]; itm.Replicate { - replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.ActionPlanPrefix, key, // this are used to get the host IDs from cache - utils.ReplicatorSv1RemoveActionPlan, - &utils.StringWithAPIOpts{ - Arg: key, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} -func (dm *DataManager) GetAccountActionPlans(acntID string, - skipCache bool, transactionID string) (apIDs []string, err error) { - if dm == nil { - err = utils.ErrNoDatabaseConn - return - } - apIDs, err = dm.dataDB.GetAccountActionPlansDrv(acntID, skipCache, transactionID) - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaAccountActionPlans]; ((err == nil && len(apIDs) == 0) || err == utils.ErrNotFound) && itm.Remote { - if err = dm.connMgr.Call(config.CgrConfig().DataDbCfg().RmtConns, nil, - utils.ReplicatorSv1GetAccountActionPlans, - &utils.StringWithAPIOpts{ - Arg: acntID, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, utils.EmptyString, - utils.FirstNonEmpty(config.CgrConfig().DataDbCfg().RmtConnID, - config.CgrConfig().GeneralCfg().NodeID)), - }, &apIDs); err == nil { - err = dm.dataDB.SetAccountActionPlansDrv(acntID, apIDs, true) - } - } - if err != nil { - err = utils.CastRPCErr(err) - return nil, err - } - return -} - -//SetAccountActionPlansArgWithAPIOpts is used to send the key and the Actions to replicator -type SetAccountActionPlansArgWithAPIOpts struct { - AcntID string - AplIDs []string - Overwrite bool - Tenant string - APIOpts map[string]interface{} -} - -func (dm *DataManager) SetAccountActionPlans(acntID string, aPlIDs []string, overwrite bool) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.dataDB.SetAccountActionPlansDrv(acntID, aPlIDs, overwrite); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaAccountActionPlans]; itm.Replicate { - err = replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.AccountActionPlansPrefix, acntID, // this are used to get the host IDs from cache - utils.ReplicatorSv1SetAccountActionPlans, - &SetAccountActionPlansArgWithAPIOpts{ - AcntID: acntID, - AplIDs: aPlIDs, - Overwrite: overwrite, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -// RemAccountActionPlansArgsWithAPIOpts is used in replicatorV1 for dispatcher -type RemAccountActionPlansArgsWithAPIOpts struct { - AcntID string - ApIDs []string - Tenant string - APIOpts map[string]interface{} -} - -func (dm *DataManager) RemAccountActionPlans(acntID string, apIDs []string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.dataDB.RemAccountActionPlansDrv(acntID, apIDs); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaAccountActionPlans]; itm.Replicate { - replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.AccountActionPlansPrefix, acntID, // this are used to get the host IDs from cache - utils.ReplicatorSv1RemAccountActionPlans, - &RemAccountActionPlansArgsWithAPIOpts{ - AcntID: acntID, - ApIDs: apIDs, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -func (dm *DataManager) GetRatingPlan(key string, skipCache bool, - transactionID string) (rp *RatingPlan, err error) { - if !skipCache { - if x, ok := Cache.Get(utils.CacheRatingPlans, key); ok { - if x != nil { - return x.(*RatingPlan), nil - } - return nil, utils.ErrNotFound - } - } - if dm == nil { - err = utils.ErrNoDatabaseConn - return - } - rp, err = dm.DataDB().GetRatingPlanDrv(key) - if err != nil { - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaRatingPlans]; err == utils.ErrNotFound && itm.Remote { - if err = dm.connMgr.Call(config.CgrConfig().DataDbCfg().RmtConns, nil, - utils.ReplicatorSv1GetRatingPlan, - &utils.StringWithAPIOpts{ - Arg: key, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, utils.EmptyString, - utils.FirstNonEmpty(config.CgrConfig().DataDbCfg().RmtConnID, - config.CgrConfig().GeneralCfg().NodeID)), - }, &rp); err == nil { - err = dm.dataDB.SetRatingPlanDrv(rp) - } - } - if err != nil { - err = utils.CastRPCErr(err) - if err == utils.ErrNotFound { - if errCh := Cache.Set(utils.CacheRatingPlans, key, nil, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - } - return nil, err - } - } - if errCh := Cache.Set(utils.CacheRatingPlans, key, rp, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - return -} - -func (dm *DataManager) SetRatingPlan(rp *RatingPlan, transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.DataDB().SetRatingPlanDrv(rp); err != nil { - return - } - if err = dm.CacheDataFromDB(utils.RatingPlanPrefix, []string{rp.Id}, true); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaRatingPlans]; itm.Replicate { - err = replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.RatingPlanPrefix, rp.Id, // this are used to get the host IDs from cache - utils.ReplicatorSv1SetRatingPlan, - &RatingPlanWithAPIOpts{ - RatingPlan: rp, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -func (dm *DataManager) RemoveRatingPlan(key string, transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.DataDB().RemoveRatingPlanDrv(key); err != nil { - return - } - if errCh := Cache.Remove(utils.CacheRatingPlans, key, - cacheCommit(transactionID), transactionID); errCh != nil { - return errCh - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaRatingPlans]; itm.Replicate { - replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.RatingPlanPrefix, key, // this are used to get the host IDs from cache - utils.ReplicatorSv1RemoveRatingPlan, - &utils.StringWithAPIOpts{ - Arg: key, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -// GetRatingProfile returns the RatingProfile for the key -func (dm *DataManager) GetRatingProfile(key string, skipCache bool, - transactionID string) (rpf *RatingProfile, err error) { - if !skipCache { - for _, cacheRP := range []string{utils.CacheRatingProfilesTmp, utils.CacheRatingProfiles} { - if x, ok := Cache.Get(cacheRP, key); ok { - if x != nil { - return x.(*RatingProfile), nil - } - return nil, utils.ErrNotFound - } - } - } - if dm == nil { - err = utils.ErrNoDatabaseConn - return - } - rpf, err = dm.DataDB().GetRatingProfileDrv(key) - if err != nil { - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaRatingProfiles]; err == utils.ErrNotFound && itm.Remote { - if err = dm.connMgr.Call(config.CgrConfig().DataDbCfg().RmtConns, nil, - utils.ReplicatorSv1GetRatingProfile, - &utils.StringWithAPIOpts{ - Arg: key, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, utils.EmptyString, - utils.FirstNonEmpty(config.CgrConfig().DataDbCfg().RmtConnID, - config.CgrConfig().GeneralCfg().NodeID)), - }, &rpf); err == nil { - err = dm.dataDB.SetRatingProfileDrv(rpf) - } - } - if err != nil { - err = utils.CastRPCErr(err) - if err == utils.ErrNotFound { - if errCh := Cache.Set(utils.CacheRatingProfiles, key, nil, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - } - return nil, err - } - } - if errCh := Cache.Set(utils.CacheRatingProfiles, key, rpf, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - return -} - -func (dm *DataManager) SetRatingProfile(rpf *RatingProfile, - transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.DataDB().SetRatingProfileDrv(rpf); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaRatingProfiles]; itm.Replicate { - err = replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.RatingProfilePrefix, rpf.Id, // this are used to get the host IDs from cache - utils.ReplicatorSv1SetRatingProfile, - &RatingProfileWithAPIOpts{ - RatingProfile: rpf, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - -func (dm *DataManager) RemoveRatingProfile(key string, - transactionID string) (err error) { - if dm == nil { - return utils.ErrNoDatabaseConn - } - if err = dm.DataDB().RemoveRatingProfileDrv(key); err != nil { - return - } - if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaRatingProfiles]; itm.Replicate { - replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, - config.CgrConfig().DataDbCfg().RplFiltered, - utils.RatingProfilePrefix, key, // this are used to get the host IDs from cache - utils.ReplicatorSv1RemoveRatingProfile, - &utils.StringWithAPIOpts{ - Arg: key, - Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, - APIOpts: utils.GenerateDBItemOpts(itm.APIKey, itm.RouteID, - config.CgrConfig().DataDbCfg().RplCache, utils.EmptyString)}) - } - return -} - func (dm *DataManager) HasData(category, subject, tenant string) (has bool, err error) { if dm == nil { err = utils.ErrNoDatabaseConn diff --git a/engine/filters.go b/engine/filters.go index f4b30aced..f8040b38d 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -486,7 +486,7 @@ func (fltr *FilterRule) passDestinations(dDP utils.DataProvider) (bool, error) { } return false, err } - for _, p := range utils.SplitPrefix(dst, MIN_PREFIX_MATCH) { + for _, p := range utils.SplitPrefix(dst, 1) { var destIDs []string if err = connMgr.Call(config.CgrConfig().FilterSCfg().ApierSConns, nil, utils.APIerSv1GetReverseDestination, &p, &destIDs); err != nil { continue diff --git a/engine/libeventcost.go b/engine/libeventcost.go index 788b5668d..68dcffe63 100644 --- a/engine/libeventcost.go +++ b/engine/libeventcost.go @@ -100,7 +100,7 @@ func (cIl *ChargingInterval) Cost() float64 { for _, incr := range cIl.Increments { cost += incr.Cost * float64(incr.CompressFactor) } - cost = utils.Round(cost, globalRoundingDecimals, utils.MetaRoundingMiddle) + cost = utils.Round(cost, 6, utils.MetaRoundingMiddle) cIl.cost = &cost } return *cIl.cost @@ -109,7 +109,7 @@ func (cIl *ChargingInterval) Cost() float64 { // TotalCost returns the cost of charges func (cIl *ChargingInterval) TotalCost() float64 { return utils.Round((cIl.Cost() * float64(cIl.CompressFactor)), - globalRoundingDecimals, utils.MetaRoundingMiddle) + 6, utils.MetaRoundingMiddle) } // Clone returns a new instance of ChargingInterval with independent data diff --git a/engine/libtest.go b/engine/libtest.go index 0ab682fd5..2f14848b0 100644 --- a/engine/libtest.go +++ b/engine/libtest.go @@ -65,106 +65,7 @@ WORKDAYS_18,*any,*any,*any,1;2;3;4;5,18:00:00 WEEKENDS,*any,*any,*any,6;7,00:00:00 ONE_TIME_RUN,2012,,,,*asap ` - RatesCSVContent = ` -R1,0,0.2,60s,1s,0s -R2,0,0.1,60s,1s,0s -R3,0,0.05,60s,1s,0s -R4,1,1,1s,1s,0s -R5,0,0.5,1s,1s,0s -LANDLINE_OFFPEAK,0,1,1s,60s,0s -LANDLINE_OFFPEAK,0,1,1s,1s,60s -GBP_71,0.000000,5.55555,1s,1s,0s -GBP_72,0.000000,7.77777,1s,1s,0s -GBP_70,0.000000,1,1s,1s,0s -RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s -RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s -R_URG,0,0,1s,1s,0s -MX,0,1,1s,1s,0s -DY,0.15,0.05,60s,1s,0s -CF,1.12,0,1s,1s,0s -` - DestinationRatesCSVContent = ` -RT_STANDARD,GERMANY,R1,*middle,4,0, -RT_STANDARD,GERMANY_O2,R2,*middle,4,0, -RT_STANDARD,GERMANY_PREMIUM,R2,*middle,4,0, -RT_DEFAULT,ALL,R2,*middle,4,0, -RT_STD_WEEKEND,GERMANY,R2,*middle,4,0, -RT_STD_WEEKEND,GERMANY_O2,R3,*middle,4,0, -P1,NAT,R4,*middle,4,0, -P2,NAT,R5,*middle,4,0, -T1,NAT,LANDLINE_OFFPEAK,*middle,4,0, -T2,GERMANY,GBP_72,*middle,4,0, -T2,GERMANY_O2,GBP_70,*middle,4,0, -T2,GERMANY_PREMIUM,GBP_71,*middle,4,0, -GER,GERMANY,R4,*middle,4,0, -DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*middle,4,, -DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*middle,4,, -DATA_RATE,*any,LANDLINE_OFFPEAK,*middle,4,0, -RT_URG,URG,R_URG,*middle,4,0, -MX_FREE,RET,MX,*middle,4,10,*free -MX_DISC,RET,MX,*middle,4,10,*disconnect -RT_DY,RET,DY,*up,2,0, -RT_DY,EU_LANDLINE,CF,*middle,4,0, -` - RatingPlansCSVContent = ` -STANDARD,RT_STANDARD,WORKDAYS_00,10 -STANDARD,RT_STD_WEEKEND,WORKDAYS_18,10 -STANDARD,RT_STD_WEEKEND,WEEKENDS,10 -STANDARD,RT_URG,*any,20 -PREMIUM,RT_STANDARD,WORKDAYS_00,10 -PREMIUM,RT_STD_WEEKEND,WORKDAYS_18,10 -PREMIUM,RT_STD_WEEKEND,WEEKENDS,10 -DEFAULT,RT_DEFAULT,WORKDAYS_00,10 -EVENING,P1,WORKDAYS_00,10 -EVENING,P2,WORKDAYS_18,10 -EVENING,P2,WEEKENDS,10 -TDRT,T1,WORKDAYS_00,10 -TDRT,T2,WORKDAYS_00,10 -G,RT_STANDARD,WORKDAYS_00,10 -R,P1,WORKDAYS_00,10 -RP_UK_Mobile_BIG5_PKG,DR_UK_Mobile_BIG5_PKG,*any,10 -RP_UK,DR_UK_Mobile_BIG5,*any,10 -RP_DATA,DATA_RATE,*any,10 -RP_MX,MX_DISC,WORKDAYS_00,10 -RP_MX,MX_FREE,WORKDAYS_18,10 -GER_ONLY,GER,*any,10 -ANY_PLAN,DATA_RATE,*any,10 -DY_PLAN,RT_DY,*any,10 -` - RatingProfilesCSVContent = ` -CUSTOMER_1,0,rif:from:tm,2012-01-01T00:00:00Z,PREMIUM,danb -CUSTOMER_1,0,rif:from:tm,2012-02-28T00:00:00Z,STANDARD,danb -CUSTOMER_2,0,danb:87.139.12.167,2012-01-01T00:00:00Z,STANDARD,danb -CUSTOMER_1,0,danb,2012-01-01T00:00:00Z,PREMIUM, -vdf,0,rif,2012-01-01T00:00:00Z,EVENING, -vdf,call,rif,2012-02-28T00:00:00Z,EVENING, -vdf,call,dan,2012-01-01T00:00:00Z,EVENING, -vdf,0,minu,2012-01-01T00:00:00Z,EVENING, -vdf,0,*any,2012-02-28T00:00:00Z,EVENING, -vdf,0,one,2012-02-28T00:00:00Z,STANDARD, -vdf,0,inf,2012-02-28T00:00:00Z,STANDARD,inf -vdf,0,fall,2012-02-28T00:00:00Z,PREMIUM,rif -test,0,trp,2013-10-01T00:00:00Z,TDRT,rif;danb -vdf,0,fallback1,2013-11-18T13:45:00Z,G,fallback2 -vdf,0,fallback1,2013-11-18T13:46:00Z,G,fallback2 -vdf,0,fallback1,2013-11-18T13:47:00Z,G,fallback2 -vdf,0,fallback2,2013-11-18T13:45:00Z,R,rif -cgrates.org,call,*any,2013-01-06T00:00:00Z,RP_UK, -cgrates.org,call,discounted_minutes,2013-01-06T00:00:00Z,RP_UK_Mobile_BIG5_PKG, -cgrates.org,data,rif,2013-01-06T00:00:00Z,RP_DATA, -cgrates.org,call,max,2013-03-23T00:00:00Z,RP_MX, -cgrates.org,call,nt,2012-02-28T00:00:00Z,GER_ONLY, -cgrates.org,LCR_STANDARD,max,2013-03-23T00:00:00Z,RP_MX, -cgrates.org,call,money,2015-02-28T00:00:00Z,EVENING, -cgrates.org,call,dy,2015-02-28T00:00:00Z,DY_PLAN, -cgrates.org,call,block,2015-02-28T00:00:00Z,DY_PLAN, -cgrates.org,call,round,2016-06-30T00:00:00Z,DEFAULT, -` - SharedGroupsCSVContent = ` -SG1,*any,*lowest, -SG2,*any,*lowest,one -SG3,*any,*lowest, -` + ActionsCSVContent = ` MINI,*topup_reset,,,,*monetary,,,,,*unlimited,,10,10,false,false,10 MINI,*topup,,,,*voice,,NAT,test,,*unlimited,,100s,10,false,false,10 @@ -187,47 +88,8 @@ EXP,*topup,,,,*voice,,,,,*monthly,*any,300s,10,false,false,10 NOEXP,*topup,,,,*voice,,,,,*unlimited,*any,50s,10,false,false,10 VF,*debit,,,,*monetary,,,,,*unlimited,*any,"{""Method"":""*incremental"",""Params"":{""Units"":10, ""Interval"":""month"", ""Increment"":""day""}}",10,false,false,10 TOPUP_RST_GNR_1000,*topup_reset,"{""*voice"": 60.0,""*data"":1024.0,""*sms"":1.0}",,,*generic,,*any,,,*unlimited,,1000,20,false,false,10 -` - ActionPlansCSVContent = ` -MORE_MINUTES,MINI,ONE_TIME_RUN,10 -MORE_MINUTES,SHARED,ONE_TIME_RUN,10 -TOPUP10_AT,TOPUP10_AC,*asap,10 -TOPUP10_AT,TOPUP10_AC1,*asap,10 -TOPUP_SHARED0_AT,SE0,*asap,10 -TOPUP_SHARED10_AT,SE10,*asap,10 -TOPUP_EMPTY_AT,EE0,*asap,10 -POST_AT,NEG,*asap,10 -BLOCK_AT,BLOCK,*asap,10 -BLOCK_EMPTY_AT,BLOCK_EMPTY,*asap,10 -EXP_AT,EXP,*asap,10 ` - ActionTriggersCSVContent = ` -STANDARD_TRIGGER,st0,*min_event_counter,10,false,0,,,,*voice,,GERMANY_O2,,,,,,,,SOME_1,10 -STANDARD_TRIGGER,st1,*max_balance,200,false,0,,,,*voice,,GERMANY,,,,,,,,SOME_2,10 -STANDARD_TRIGGERS,,*min_balance,2,false,0,,,,*monetary,,,,,,,,,,LOG_WARNING,10 -STANDARD_TRIGGERS,,*max_balance,20,false,0,,,,*monetary,,,,,,,,,,LOG_WARNING,10 -STANDARD_TRIGGERS,,*max_event_counter,5,false,0,,,,*monetary,,FS_USERS,,,,,,,,LOG_WARNING,10 -` - AccountActionsCSVContent = ` -vdf,minitsboy,MORE_MINUTES,STANDARD_TRIGGER,, -cgrates.org,12345,TOPUP10_AT,STANDARD_TRIGGERS,, -cgrates.org,123456,TOPUP10_AT,STANDARD_TRIGGERS,, -cgrates.org,dy,TOPUP10_AT,STANDARD_TRIGGERS,, -cgrates.org,remo,TOPUP10_AT,,, -vdf,empty0,TOPUP_SHARED0_AT,,, -vdf,empty10,TOPUP_SHARED10_AT,,, -vdf,emptyX,TOPUP_EMPTY_AT,,, -vdf,emptyY,TOPUP_EMPTY_AT,,, -vdf,post,POST_AT,,, -cgrates.org,alodis,TOPUP_EMPTY_AT,,true,true -cgrates.org,block,BLOCK_AT,,false,false -cgrates.org,block_empty,BLOCK_EMPTY_AT,,false,false -cgrates.org,expo,EXP_AT,,false,false -cgrates.org,expnoexp,,,false,false -cgrates.org,vf,,,false,false -cgrates.org,round,TOPUP10_AT,,false,false -` ResourcesCSVContent = ` #Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],TTL[4],Limit[5],AllocationMessage[6],Blocker[7],Stored[8],Weight[9],Thresholds[10] cgrates.org,ResGroup21,*string:~*req.Account:1001,2014-07-29T15:00:00Z,1s,2,call,true,true,10, diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 678f2fe65..6ffbc2a1b 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -37,8 +37,7 @@ var csvr *TpReader func init() { var err error csvr, err = NewTpReader(dm.dataDB, NewStringCSVStorage(utils.CSVSep, - DestinationsCSVContent, TimingsCSVContent, RatesCSVContent, DestinationRatesCSVContent, - RatingPlansCSVContent, RatingProfilesCSVContent, SharedGroupsCSVContent, + DestinationsCSVContent, TimingsCSVContent, ActionsCSVContent, ActionPlansCSVContent, ActionTriggersCSVContent, AccountActionsCSVContent, ResourcesCSVContent, StatsCSVContent, ThresholdsCSVContent, FiltersCSVContent, RoutesCSVContent, AttributesCSVContent, ChargersCSVContent, DispatcherCSVContent, @@ -70,15 +69,6 @@ func init() { if err := csvr.LoadActions(); err != nil { log.Print("error in LoadActions:", err) } - if err := csvr.LoadActionPlans(); err != nil { - log.Print("error in LoadActionPlans:", err) - } - if err := csvr.LoadActionTriggers(); err != nil { - log.Print("error in LoadActionTriggers:", err) - } - if err := csvr.LoadAccountActions(); err != nil { - log.Print("error in LoadAccountActions:", err) - } if err := csvr.LoadFilters(); err != nil { log.Print("error in LoadFilter:", err) } diff --git a/engine/model_helpers.go b/engine/model_helpers.go index 5ab70e67c..5efe246b5 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -261,426 +261,6 @@ func APItoModelTimings(ts []*utils.ApierTPTiming) (result TimingMdls) { return result } -type RateMdls []RateMdl - -func (tps RateMdls) AsMapRates() (map[string]*utils.TPRateRALs, error) { - result := make(map[string]*utils.TPRateRALs) - for _, tp := range tps { - r := &utils.TPRateRALs{ - TPid: tp.Tpid, - ID: tp.Tag, - } - rs := &utils.RateSlot{ - ConnectFee: tp.ConnectFee, - Rate: tp.Rate, - RateUnit: tp.RateUnit, - RateIncrement: tp.RateIncrement, - GroupIntervalStart: tp.GroupIntervalStart, - } - if err := rs.SetDurations(); err != nil { - return nil, err - } - if existing, exists := result[r.ID]; !exists { - r.RateSlots = []*utils.RateSlot{rs} - result[r.ID] = r - } else { - existing.RateSlots = append(existing.RateSlots, rs) - } - } - return result, nil -} - -func (tps RateMdls) AsTPRates() (result []*utils.TPRateRALs, err error) { - if atps, err := tps.AsMapRates(); err != nil { - return nil, err - } else { - for _, tp := range atps { - result = append(result, tp) - } - return result, nil - } -} - -func MapTPRates(s []*utils.TPRateRALs) (map[string]*utils.TPRateRALs, error) { - result := make(map[string]*utils.TPRateRALs) - for _, e := range s { - if _, found := result[e.ID]; !found { - result[e.ID] = e - } else { - return nil, fmt.Errorf("Non unique ID %+v", e.ID) - } - } - return result, nil -} - -func APItoModelRate(r *utils.TPRateRALs) (result RateMdls) { - if r != nil { - for _, rs := range r.RateSlots { - result = append(result, RateMdl{ - Tpid: r.TPid, - Tag: r.ID, - ConnectFee: rs.ConnectFee, - Rate: rs.Rate, - RateUnit: rs.RateUnit, - RateIncrement: rs.RateIncrement, - GroupIntervalStart: rs.GroupIntervalStart, - }) - } - if len(r.RateSlots) == 0 { - result = append(result, RateMdl{ - Tpid: r.TPid, - Tag: r.ID, - }) - } - } - return -} - -func APItoModelRates(rs []*utils.TPRateRALs) (result RateMdls) { - for _, r := range rs { - result = append(result, APItoModelRate(r)...) - } - return result -} - -type DestinationRateMdls []DestinationRateMdl - -func (tps DestinationRateMdls) AsMapDestinationRates() (result map[string]*utils.TPDestinationRate) { - result = make(map[string]*utils.TPDestinationRate) - for _, tp := range tps { - dr := &utils.TPDestinationRate{ - TPid: tp.Tpid, - ID: tp.Tag, - DestinationRates: []*utils.DestinationRate{ - { - DestinationId: tp.DestinationsTag, - RateId: tp.RatesTag, - RoundingMethod: tp.RoundingMethod, - RoundingDecimals: tp.RoundingDecimals, - MaxCost: tp.MaxCost, - MaxCostStrategy: tp.MaxCostStrategy, - }, - }, - } - existing, exists := result[tp.Tag] - if exists { - existing.DestinationRates = append(existing.DestinationRates, dr.DestinationRates[0]) - } else { - existing = dr - } - result[tp.Tag] = existing - } - return -} - -func (tps DestinationRateMdls) AsTPDestinationRates() (result []*utils.TPDestinationRate) { - for _, tp := range tps.AsMapDestinationRates() { - result = append(result, tp) - } - return -} - -func MapTPDestinationRates(s []*utils.TPDestinationRate) (map[string]*utils.TPDestinationRate, error) { - result := make(map[string]*utils.TPDestinationRate) - for _, e := range s { - if _, found := result[e.ID]; !found { - result[e.ID] = e - } else { - return nil, fmt.Errorf("Non unique ID %+v", e.ID) - } - } - return result, nil -} - -func APItoModelDestinationRate(d *utils.TPDestinationRate) (result DestinationRateMdls) { - if d != nil { - for _, dr := range d.DestinationRates { - result = append(result, DestinationRateMdl{ - Tpid: d.TPid, - Tag: d.ID, - DestinationsTag: dr.DestinationId, - RatesTag: dr.RateId, - RoundingMethod: dr.RoundingMethod, - RoundingDecimals: dr.RoundingDecimals, - MaxCost: dr.MaxCost, - MaxCostStrategy: dr.MaxCostStrategy, - }) - } - if len(d.DestinationRates) == 0 { - result = append(result, DestinationRateMdl{ - Tpid: d.TPid, - Tag: d.ID, - }) - } - } - return -} - -func APItoModelDestinationRates(drs []*utils.TPDestinationRate) (result DestinationRateMdls) { - for _, dr := range drs { - result = append(result, APItoModelDestinationRate(dr)...) - } - return result -} - -type RatingPlanMdls []RatingPlanMdl - -func (tps RatingPlanMdls) AsMapTPRatingPlans() (result map[string]*utils.TPRatingPlan) { - result = make(map[string]*utils.TPRatingPlan) - for _, tp := range tps { - rp := &utils.TPRatingPlan{ - TPid: tp.Tpid, - ID: tp.Tag, - } - rpb := &utils.TPRatingPlanBinding{ - DestinationRatesId: tp.DestratesTag, - TimingId: tp.TimingTag, - Weight: tp.Weight, - } - if existing, exists := result[rp.ID]; !exists { - rp.RatingPlanBindings = []*utils.TPRatingPlanBinding{rpb} - result[rp.ID] = rp - } else { - existing.RatingPlanBindings = append(existing.RatingPlanBindings, rpb) - } - } - return -} - -func (tps RatingPlanMdls) AsTPRatingPlans() (result []*utils.TPRatingPlan) { - for _, tp := range tps.AsMapTPRatingPlans() { - result = append(result, tp) - } - return -} - -func GetRateInterval(rpl *utils.TPRatingPlanBinding, dr *utils.DestinationRate) (i *RateInterval) { - i = &RateInterval{ - Timing: &RITiming{ - ID: rpl.Timing().ID, - Years: rpl.Timing().Years, - Months: rpl.Timing().Months, - MonthDays: rpl.Timing().MonthDays, - WeekDays: rpl.Timing().WeekDays, - StartTime: rpl.Timing().StartTime, - tag: rpl.Timing().ID, - }, - Weight: rpl.Weight, - Rating: &RIRate{ - ConnectFee: dr.Rate.RateSlots[0].ConnectFee, - RoundingMethod: dr.RoundingMethod, - RoundingDecimals: dr.RoundingDecimals, - MaxCost: dr.MaxCost, - MaxCostStrategy: dr.MaxCostStrategy, - tag: dr.Rate.ID, - }, - } - for _, rl := range dr.Rate.RateSlots { - i.Rating.Rates = append(i.Rating.Rates, &RGRate{ - GroupIntervalStart: rl.GroupIntervalStartDuration(), - Value: rl.Rate, - RateIncrement: rl.RateIncrementDuration(), - RateUnit: rl.RateUnitDuration(), - }) - } - return -} - -func MapTPRatingPlanBindings(s []*utils.TPRatingPlan) map[string][]*utils.TPRatingPlanBinding { - result := make(map[string][]*utils.TPRatingPlanBinding) - for _, e := range s { - for _, rpb := range e.RatingPlanBindings { - if _, found := result[e.ID]; !found { - result[e.ID] = []*utils.TPRatingPlanBinding{rpb} - } else { - result[e.ID] = append(result[e.ID], rpb) - } - } - } - return result -} - -func APItoModelRatingPlan(rp *utils.TPRatingPlan) (result RatingPlanMdls) { - if rp != nil { - for _, rpb := range rp.RatingPlanBindings { - result = append(result, RatingPlanMdl{ - Tpid: rp.TPid, - Tag: rp.ID, - DestratesTag: rpb.DestinationRatesId, - TimingTag: rpb.TimingId, - Weight: rpb.Weight, - }) - } - if len(rp.RatingPlanBindings) == 0 { - result = append(result, RatingPlanMdl{ - Tpid: rp.TPid, - Tag: rp.ID, - }) - } - } - return -} - -func APItoModelRatingPlans(rps []*utils.TPRatingPlan) (result RatingPlanMdls) { - for _, rp := range rps { - result = append(result, APItoModelRatingPlan(rp)...) - } - return result -} - -type RatingProfileMdls []RatingProfileMdl - -func (tps RatingProfileMdls) AsMapTPRatingProfiles() (result map[string]*utils.TPRatingProfile) { - result = make(map[string]*utils.TPRatingProfile) - for _, tp := range tps { - rp := &utils.TPRatingProfile{ - TPid: tp.Tpid, - LoadId: tp.Loadid, - Tenant: tp.Tenant, - Category: tp.Category, - Subject: tp.Subject, - } - ra := &utils.TPRatingActivation{ - ActivationTime: tp.ActivationTime, - RatingPlanId: tp.RatingPlanTag, - FallbackSubjects: tp.FallbackSubjects, - } - if existing, exists := result[rp.GetId()]; !exists { - rp.RatingPlanActivations = []*utils.TPRatingActivation{ra} - result[rp.GetId()] = rp - } else { - existing.RatingPlanActivations = append(existing.RatingPlanActivations, ra) - } - } - return -} - -func (tps RatingProfileMdls) AsTPRatingProfiles() (result []*utils.TPRatingProfile) { - for _, tp := range tps.AsMapTPRatingProfiles() { - result = append(result, tp) - } - return -} - -func MapTPRatingProfiles(s []*utils.TPRatingProfile) (map[string]*utils.TPRatingProfile, error) { - result := make(map[string]*utils.TPRatingProfile) - for _, e := range s { - if _, found := result[e.GetId()]; !found { - result[e.GetId()] = e - } else { - return nil, fmt.Errorf("Non unique id %+v", e.GetId()) - } - } - return result, nil -} - -func APItoModelRatingProfile(rp *utils.TPRatingProfile) (result RatingProfileMdls) { - if rp != nil { - for _, rpa := range rp.RatingPlanActivations { - result = append(result, RatingProfileMdl{ - Tpid: rp.TPid, - Loadid: rp.LoadId, - Tenant: rp.Tenant, - Category: rp.Category, - Subject: rp.Subject, - ActivationTime: rpa.ActivationTime, - RatingPlanTag: rpa.RatingPlanId, - FallbackSubjects: rpa.FallbackSubjects, - }) - } - if len(rp.RatingPlanActivations) == 0 { - result = append(result, RatingProfileMdl{ - Tpid: rp.TPid, - Loadid: rp.LoadId, - Tenant: rp.Tenant, - Category: rp.Category, - Subject: rp.Subject, - }) - } - } - return -} - -func APItoModelRatingProfiles(rps []*utils.TPRatingProfile) (result RatingProfileMdls) { - for _, rp := range rps { - result = append(result, APItoModelRatingProfile(rp)...) - } - return result -} - -type SharedGroupMdls []SharedGroupMdl - -func (tps SharedGroupMdls) AsMapTPSharedGroups() (result map[string]*utils.TPSharedGroups) { - result = make(map[string]*utils.TPSharedGroups) - for _, tp := range tps { - sgs := &utils.TPSharedGroups{ - TPid: tp.Tpid, - ID: tp.Tag, - } - sg := &utils.TPSharedGroup{ - Account: tp.Account, - Strategy: tp.Strategy, - RatingSubject: tp.RatingSubject, - } - if existing, exists := result[sgs.ID]; !exists { - sgs.SharedGroups = []*utils.TPSharedGroup{sg} - result[sgs.ID] = sgs - } else { - existing.SharedGroups = append(existing.SharedGroups, sg) - } - } - return -} - -func (tps SharedGroupMdls) AsTPSharedGroups() (result []*utils.TPSharedGroups) { - for _, tp := range tps.AsMapTPSharedGroups() { - result = append(result, tp) - } - return -} - -func MapTPSharedGroup(s []*utils.TPSharedGroups) map[string][]*utils.TPSharedGroup { - result := make(map[string][]*utils.TPSharedGroup) - for _, e := range s { - for _, sg := range e.SharedGroups { - if _, found := result[e.ID]; !found { - result[e.ID] = []*utils.TPSharedGroup{sg} - } else { - result[e.ID] = append(result[e.ID], sg) - } - } - } - return result -} - -func APItoModelSharedGroup(sgs *utils.TPSharedGroups) (result SharedGroupMdls) { - if sgs != nil { - for _, sg := range sgs.SharedGroups { - result = append(result, SharedGroupMdl{ - Tpid: sgs.TPid, - Tag: sgs.ID, - Account: sg.Account, - Strategy: sg.Strategy, - RatingSubject: sg.RatingSubject, - }) - } - if len(sgs.SharedGroups) == 0 { - result = append(result, SharedGroupMdl{ - Tpid: sgs.TPid, - Tag: sgs.ID, - }) - } - } - return -} - -func APItoModelSharedGroups(sgs []*utils.TPSharedGroups) (result SharedGroupMdls) { - for _, sg := range sgs { - result = append(result, APItoModelSharedGroup(sg)...) - } - return result -} - type ActionMdls []ActionMdl func (tps ActionMdls) AsMapTPActions() (result map[string]*utils.TPActions) { @@ -780,249 +360,6 @@ func APItoModelActions(as []*utils.TPActions) (result ActionMdls) { return result } -type ActionPlanMdls []ActionPlanMdl - -func (tps ActionPlanMdls) AsMapTPActionPlans() (result map[string]*utils.TPActionPlan) { - result = make(map[string]*utils.TPActionPlan) - for _, tp := range tps { - as := &utils.TPActionPlan{ - TPid: tp.Tpid, - ID: tp.Tag, - } - a := &utils.TPActionTiming{ - ActionsId: tp.ActionsTag, - TimingId: tp.TimingTag, - Weight: tp.Weight, - } - if existing, exists := result[as.ID]; !exists { - as.ActionPlan = []*utils.TPActionTiming{a} - result[as.ID] = as - } else { - existing.ActionPlan = append(existing.ActionPlan, a) - } - } - return -} - -func (tps ActionPlanMdls) AsTPActionPlans() (result []*utils.TPActionPlan) { - for _, tp := range tps.AsMapTPActionPlans() { - result = append(result, tp) - } - return -} - -func MapTPActionTimings(s []*utils.TPActionPlan) map[string][]*utils.TPActionTiming { - result := make(map[string][]*utils.TPActionTiming) - for _, e := range s { - for _, at := range e.ActionPlan { - if _, found := result[e.ID]; !found { - result[e.ID] = []*utils.TPActionTiming{at} - } else { - result[e.ID] = append(result[e.ID], at) - } - } - } - return result -} - -func APItoModelActionPlan(a *utils.TPActionPlan) (result ActionPlanMdls) { - if a != nil { - for _, ap := range a.ActionPlan { - result = append(result, ActionPlanMdl{ - Tpid: a.TPid, - Tag: a.ID, - ActionsTag: ap.ActionsId, - TimingTag: ap.TimingId, - Weight: ap.Weight, - }) - } - if len(a.ActionPlan) == 0 { - result = append(result, ActionPlanMdl{ - Tpid: a.TPid, - Tag: a.ID, - }) - } - } - return -} - -func APItoModelActionPlans(aps []*utils.TPActionPlan) (result ActionPlanMdls) { - for _, ap := range aps { - result = append(result, APItoModelActionPlan(ap)...) - } - return result -} - -type ActionTriggerMdls []ActionTriggerMdl - -func (tps ActionTriggerMdls) AsMapTPActionTriggers() (result map[string]*utils.TPActionTriggers) { - result = make(map[string]*utils.TPActionTriggers) - for _, tp := range tps { - ats := &utils.TPActionTriggers{ - TPid: tp.Tpid, - ID: tp.Tag, - } - at := &utils.TPActionTrigger{ - Id: tp.Tag, - UniqueID: tp.UniqueId, - ThresholdType: tp.ThresholdType, - ThresholdValue: tp.ThresholdValue, - Recurrent: tp.Recurrent, - MinSleep: tp.MinSleep, - ExpirationDate: tp.ExpiryTime, - ActivationDate: tp.ActivationTime, - BalanceId: tp.BalanceTag, - BalanceType: tp.BalanceType, - BalanceDestinationIds: tp.BalanceDestinationTags, - BalanceWeight: tp.BalanceWeight, - BalanceExpirationDate: tp.BalanceExpiryTime, - BalanceTimingTags: tp.BalanceTimingTags, - BalanceRatingSubject: tp.BalanceRatingSubject, - BalanceCategories: tp.BalanceCategories, - BalanceSharedGroups: tp.BalanceSharedGroups, - BalanceBlocker: tp.BalanceBlocker, - BalanceDisabled: tp.BalanceDisabled, - Weight: tp.Weight, - ActionsId: tp.ActionsTag, - } - if existing, exists := result[ats.ID]; !exists { - ats.ActionTriggers = []*utils.TPActionTrigger{at} - result[ats.ID] = ats - } else { - existing.ActionTriggers = append(existing.ActionTriggers, at) - } - } - return -} - -func (tps ActionTriggerMdls) AsTPActionTriggers() (result []*utils.TPActionTriggers) { - for _, tp := range tps.AsMapTPActionTriggers() { - result = append(result, tp) - } - return -} - -func MapTPActionTriggers(s []*utils.TPActionTriggers) map[string][]*utils.TPActionTrigger { - result := make(map[string][]*utils.TPActionTrigger) - for _, e := range s { - for _, at := range e.ActionTriggers { - if _, found := result[e.ID]; !found { - result[e.ID] = []*utils.TPActionTrigger{at} - } else { - result[e.ID] = append(result[e.ID], at) - } - } - } - return result -} - -func APItoModelActionTrigger(ats *utils.TPActionTriggers) (result ActionTriggerMdls) { - if ats != nil { - for _, at := range ats.ActionTriggers { - result = append(result, ActionTriggerMdl{ - Tpid: ats.TPid, - Tag: ats.ID, - UniqueId: at.UniqueID, - ThresholdType: at.ThresholdType, - ThresholdValue: at.ThresholdValue, - Recurrent: at.Recurrent, - MinSleep: at.MinSleep, - ExpiryTime: at.ExpirationDate, - ActivationTime: at.ActivationDate, - BalanceTag: at.BalanceId, - BalanceType: at.BalanceType, - BalanceDestinationTags: at.BalanceDestinationIds, - BalanceWeight: at.BalanceWeight, - BalanceExpiryTime: at.BalanceExpirationDate, - BalanceTimingTags: at.BalanceTimingTags, - BalanceRatingSubject: at.BalanceRatingSubject, - BalanceCategories: at.BalanceCategories, - BalanceSharedGroups: at.BalanceSharedGroups, - BalanceBlocker: at.BalanceBlocker, - BalanceDisabled: at.BalanceDisabled, - ActionsTag: at.ActionsId, - Weight: at.Weight, - }) - } - if len(ats.ActionTriggers) == 0 { - result = append(result, ActionTriggerMdl{ - Tpid: ats.TPid, - Tag: ats.ID, - }) - } - } - return -} - -func APItoModelActionTriggers(ts []*utils.TPActionTriggers) (result ActionTriggerMdls) { - for _, t := range ts { - result = append(result, APItoModelActionTrigger(t)...) - } - return result -} - -type AccountActionMdls []AccountActionMdl - -func (tps AccountActionMdls) AsMapTPAccountActions() (map[string]*utils.TPAccountActions, error) { - result := make(map[string]*utils.TPAccountActions) - for _, tp := range tps { - aas := &utils.TPAccountActions{ - TPid: tp.Tpid, - LoadId: tp.Loadid, - Tenant: tp.Tenant, - Account: tp.Account, - ActionPlanId: tp.ActionPlanTag, - ActionTriggersId: tp.ActionTriggersTag, - AllowNegative: tp.AllowNegative, - Disabled: tp.Disabled, - } - result[aas.KeyId()] = aas - } - return result, nil -} - -func (tps AccountActionMdls) AsTPAccountActions() (result []*utils.TPAccountActions) { - atps, _ := tps.AsMapTPAccountActions() - for _, tp := range atps { - result = append(result, tp) - } - return result -} - -func MapTPAccountActions(s []*utils.TPAccountActions) (map[string]*utils.TPAccountActions, error) { - result := make(map[string]*utils.TPAccountActions) - for _, e := range s { - if _, found := result[e.KeyId()]; !found { - result[e.KeyId()] = e - } else { - return nil, fmt.Errorf("Non unique ID %+v", e.KeyId()) - } - } - return result, nil -} - -func APItoModelAccountAction(aa *utils.TPAccountActions) *AccountActionMdl { - return &AccountActionMdl{ - Tpid: aa.TPid, - Loadid: aa.LoadId, - Tenant: aa.Tenant, - Account: aa.Account, - ActionPlanTag: aa.ActionPlanId, - ActionTriggersTag: aa.ActionTriggersId, - AllowNegative: aa.AllowNegative, - Disabled: aa.Disabled, - } -} - -func APItoModelAccountActions(aas []*utils.TPAccountActions) (result AccountActionMdls) { - for _, aa := range aas { - if aa != nil { - result = append(result, *APItoModelAccountAction(aa)) - } - } - return result -} - type ResourceMdls []*ResourceMdl // CSVHeader return the header for csv fields as a slice of string diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index a43a29e96..259dcc090 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -254,110 +254,6 @@ func TestMapTPTimings(t *testing.T) { } } -func TestMapTPRates(t *testing.T) { - s := []*utils.TPRateRALs{} - eOut := map[string]*utils.TPRateRALs{} - if rcv, err := MapTPRates(s); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - - s = []*utils.TPRateRALs{ - { - ID: "ID", - TPid: "TPid", - RateSlots: []*utils.RateSlot{ - { - ConnectFee: 0.100, - Rate: 0.200, - RateUnit: "60", - RateIncrement: "60", - GroupIntervalStart: "0"}, - { - ConnectFee: 0.0, - Rate: 0.1, - RateUnit: "1", - RateIncrement: "60", - GroupIntervalStart: "60"}, - }, - }, - } - eOut = map[string]*utils.TPRateRALs{ - "ID": { - TPid: "TPid", - ID: "ID", - RateSlots: []*utils.RateSlot{ - { - ConnectFee: 0.1, - Rate: 0.2, - RateUnit: "60", - RateIncrement: "60", - GroupIntervalStart: "0", - }, { - ConnectFee: 0, - Rate: 0.1, - RateUnit: "1", - RateIncrement: "60", - GroupIntervalStart: "60", - }, - }, - }, - } - if rcv, err := MapTPRates(s); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - - s = []*utils.TPRateRALs{ - { - ID: "", - TPid: "", - RateSlots: []*utils.RateSlot{ - {ConnectFee: 0.8}, - {ConnectFee: 0.7}, - }, - }, - } - eOut = map[string]*utils.TPRateRALs{ - "": { - TPid: "", - ID: "", - RateSlots: []*utils.RateSlot{ - {ConnectFee: 0.8}, - {ConnectFee: 0.7}, - }, - }, - } - if rcv, err := MapTPRates(s); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - s = []*utils.TPRateRALs{ - { - ID: "SameID", - TPid: "", - RateSlots: []*utils.RateSlot{ - {ConnectFee: 0.8}, - {ConnectFee: 0.7}, - }, - }, - { - ID: "SameID", - TPid: "", - RateSlots: []*utils.RateSlot{ - {ConnectFee: 0.9}, - {ConnectFee: 0.1}, - }, - }, - } - if _, err := MapTPRates(s); err == nil || err.Error() != "Non unique ID SameID" { - t.Error(err) - } -} - func TestAPItoModelTimings(t *testing.T) { ts := []*utils.ApierTPTiming{} eOut := TimingMdls{} @@ -417,316 +313,6 @@ func TestAPItoModelTimings(t *testing.T) { } } -func TestTPRateAsExportSlice(t *testing.T) { - tpRate := &utils.TPRateRALs{ - TPid: "TEST_TPID", - ID: "TEST_RATEID", - RateSlots: []*utils.RateSlot{ - { - ConnectFee: 0.100, - Rate: 0.200, - RateUnit: "60", - RateIncrement: "60", - GroupIntervalStart: "0"}, - { - ConnectFee: 0.0, - Rate: 0.1, - RateUnit: "1", - RateIncrement: "60", - GroupIntervalStart: "60"}, - }, - } - expectedSlc := [][]string{ - {"TEST_RATEID", "0.1", "0.2", "60", "60", "0"}, - {"TEST_RATEID", "0", "0.1", "1", "60", "60"}, - } - - ms := APItoModelRate(tpRate) - var slc [][]string - for _, m := range ms { - lc, err := CsvDump(m) - if err != nil { - t.Error("Error dumping to csv: ", err) - } - slc = append(slc, lc) - } - if !reflect.DeepEqual(expectedSlc, slc) { - t.Errorf("Expecting: %+v, received: %+v", expectedSlc[0], slc[0]) - } -} - -func TestAPItoModelRates(t *testing.T) { - rs := []*utils.TPRateRALs{} - eOut := RateMdls{} - if rcv := APItoModelRates(rs); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", utils.ToJSON(rcv)) - } - - rs = []*utils.TPRateRALs{ - { - ID: "SomeID", - TPid: "TPid", - RateSlots: []*utils.RateSlot{ - { - ConnectFee: 0.7, - Rate: 0.8, - }, - { - ConnectFee: 0.77, - Rate: 0.88, - }, - }, - }, - } - eOut = RateMdls{ - RateMdl{ - Tpid: "TPid", - Tag: "SomeID", - ConnectFee: 0.7, - Rate: 0.8, - }, - RateMdl{ - Tpid: "TPid", - Tag: "SomeID", - ConnectFee: 0.77, - Rate: 0.88, - }, - } - if rcv := APItoModelRates(rs); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - rs = []*utils.TPRateRALs{ - { - ID: "SomeID", - TPid: "TPid", - RateSlots: []*utils.RateSlot{}, - }, - } - eOut = RateMdls{ - RateMdl{ - Tpid: "TPid", - Tag: "SomeID", - }, - } - if rcv := APItoModelRates(rs); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - -func TestTPDestinationRateAsExportSlice(t *testing.T) { - tpDstRate := &utils.TPDestinationRate{ - TPid: "TEST_TPID", - ID: "TEST_DSTRATE", - DestinationRates: []*utils.DestinationRate{ - { - DestinationId: "TEST_DEST1", - RateId: "TEST_RATE1", - RoundingMethod: "*up", - RoundingDecimals: 4}, - { - DestinationId: "TEST_DEST2", - RateId: "TEST_RATE2", - RoundingMethod: "*up", - RoundingDecimals: 4}, - }, - } - expectedSlc := [][]string{ - {"TEST_DSTRATE", "TEST_DEST1", "TEST_RATE1", "*up", "4", "0", ""}, - {"TEST_DSTRATE", "TEST_DEST2", "TEST_RATE2", "*up", "4", "0", ""}, - } - ms := APItoModelDestinationRate(tpDstRate) - var slc [][]string - for _, m := range ms { - lc, err := CsvDump(m) - if err != nil { - t.Error("Error dumping to csv: ", err) - } - slc = append(slc, lc) - } - - if !reflect.DeepEqual(expectedSlc, slc) { - t.Errorf("Expecting: %+v, received: %+v", expectedSlc, slc) - } - - tpDstRate = &utils.TPDestinationRate{ - TPid: "TEST_TPID", - ID: "TEST_DSTRATE", - DestinationRates: []*utils.DestinationRate{}, - } - eOut := DestinationRateMdls{ - DestinationRateMdl{ - Tpid: "TEST_TPID", - Tag: "TEST_DSTRATE", - }, - } - if rcv := APItoModelDestinationRate(tpDstRate); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", eOut, rcv) - - } -} - -func TestAPItoModelDestinationRates(t *testing.T) { - var drs []*utils.TPDestinationRate - if rcv := APItoModelDestinationRates(drs); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - drs = []*utils.TPDestinationRate{ - { - TPid: "TEST_TPID", - ID: "TEST_DSTRATE", - DestinationRates: []*utils.DestinationRate{ - { - DestinationId: "TEST_DEST1", - RateId: "TEST_RATE1", - RoundingMethod: "*up", - RoundingDecimals: 4}, - { - DestinationId: "TEST_DEST2", - RateId: "TEST_RATE2", - RoundingMethod: "*up", - RoundingDecimals: 4}, - }, - }, - } - eOut := DestinationRateMdls{ - DestinationRateMdl{ - Tpid: "TEST_TPID", - Tag: "TEST_DSTRATE", - DestinationsTag: "TEST_DEST1", - RatesTag: "TEST_RATE1", - RoundingMethod: "*up", - RoundingDecimals: 4, - }, - DestinationRateMdl{ - Tpid: "TEST_TPID", - Tag: "TEST_DSTRATE", - DestinationsTag: "TEST_DEST2", - RatesTag: "TEST_RATE2", - RoundingMethod: "*up", - RoundingDecimals: 4, - }, - } - if rcv := APItoModelDestinationRates(drs); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", eOut, rcv) - } -} - -func TestTpDestinationRatesAsTPDestinationRates(t *testing.T) { - pts := DestinationRateMdls{} - eOut := []*utils.TPDestinationRate{} - rcv := pts.AsTPDestinationRates() - if rcv != nil { - t.Errorf("Expecting: nil, received: %+v", utils.ToJSON(rcv)) - } - - pts = DestinationRateMdls{ - DestinationRateMdl{ - Id: 66, - Tpid: "Tpid", - Tag: "Tag", - DestinationsTag: "DestinationsTag", - RatesTag: "RatesTag", - RoundingMethod: "*up", - RoundingDecimals: 2, - MaxCost: 0.7, - MaxCostStrategy: "*free", - }, - } - eOut = []*utils.TPDestinationRate{ - { - TPid: "Tpid", - ID: "Tag", - DestinationRates: []*utils.DestinationRate{ - { - DestinationId: "DestinationsTag", - RateId: "RatesTag", - RoundingMethod: "*up", - RoundingDecimals: 2, - MaxCost: 0.7, - MaxCostStrategy: "*free", - }, - }, - }, - } - rcv = pts.AsTPDestinationRates() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - -} - -func TestMapTPDestinationRates(t *testing.T) { - var s []*utils.TPDestinationRate - eOut := map[string]*utils.TPDestinationRate{} - if rcv, err := MapTPDestinationRates(s); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - - s = []*utils.TPDestinationRate{ - { - TPid: "TEST_TPID", - ID: "TEST_DSTRATE", - DestinationRates: []*utils.DestinationRate{ - { - DestinationId: "TEST_DEST1", - RateId: "TEST_RATE1", - RoundingMethod: "*up", - RoundingDecimals: 4}, - { - DestinationId: "TEST_DEST2", - RateId: "TEST_RATE2", - RoundingMethod: "*up", - RoundingDecimals: 4}, - }, - }, - } - eOut = map[string]*utils.TPDestinationRate{ - "TEST_DSTRATE": { - TPid: "TEST_TPID", - ID: "TEST_DSTRATE", - DestinationRates: []*utils.DestinationRate{ - { - DestinationId: "TEST_DEST1", - RateId: "TEST_RATE1", - RoundingMethod: "*up", - RoundingDecimals: 4, - }, - { - DestinationId: "TEST_DEST2", - RateId: "TEST_RATE2", - RoundingMethod: "*up", - RoundingDecimals: 4, - }, - }, - }, - } - if rcv, err := MapTPDestinationRates(s); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - s = []*utils.TPDestinationRate{ - { - TPid: "TEST_TPID", - ID: "TEST_DSTRATE", - DestinationRates: []*utils.DestinationRate{}, - }, - { - TPid: "TEST_TPID", - ID: "TEST_DSTRATE", - DestinationRates: []*utils.DestinationRate{}, - }, - } - if rcv, err := MapTPDestinationRates(s); err == nil || err.Error() != "Non unique ID TEST_DSTRATE" { - t.Error(err) - } else if rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - -} - func TestApierTPTimingAsExportSlice(t *testing.T) { tpTiming := &utils.ApierTPTiming{ TPid: "TEST_TPID", @@ -753,274 +339,6 @@ func TestApierTPTimingAsExportSlice(t *testing.T) { } } -func TestTPRatingPlanAsExportSlice(t *testing.T) { - tpRpln := &utils.TPRatingPlan{ - TPid: "TEST_TPID", - ID: "TEST_RPLAN", - RatingPlanBindings: []*utils.TPRatingPlanBinding{ - { - DestinationRatesId: "TEST_DSTRATE1", - TimingId: "TEST_TIMING1", - Weight: 10.0}, - { - DestinationRatesId: "TEST_DSTRATE2", - TimingId: "TEST_TIMING2", - Weight: 20.0}, - }} - expectedSlc := [][]string{ - {"TEST_RPLAN", "TEST_DSTRATE1", "TEST_TIMING1", "10"}, - {"TEST_RPLAN", "TEST_DSTRATE2", "TEST_TIMING2", "20"}, - } - - ms := APItoModelRatingPlan(tpRpln) - var slc [][]string - for _, m := range ms { - lc, err := CsvDump(m) - if err != nil { - t.Error("Error dumping to csv: ", err) - } - slc = append(slc, lc) - } - if !reflect.DeepEqual(expectedSlc, slc) { - t.Errorf("Expecting: %+v, received: %+v", expectedSlc, slc) - } -} - -func TestAPItoModelRatingPlan(t *testing.T) { - rp := &utils.TPRatingPlan{} - eOut := RatingPlanMdls{RatingPlanMdl{}} - if rcv := APItoModelRatingPlan(rp); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - rp = &utils.TPRatingPlan{ - TPid: "TEST_TPID", - ID: "TEST_RPLAN", - RatingPlanBindings: []*utils.TPRatingPlanBinding{ - { - DestinationRatesId: "TEST_DSTRATE1", - TimingId: "TEST_TIMING1", - Weight: 10.0}, - { - DestinationRatesId: "TEST_DSTRATE2", - TimingId: "TEST_TIMING2", - Weight: 20.0}, - }} - - eOut = RatingPlanMdls{ - RatingPlanMdl{ - Tpid: "TEST_TPID", - Tag: "TEST_RPLAN", - DestratesTag: "TEST_DSTRATE1", - TimingTag: "TEST_TIMING1", - Weight: 10.0, - }, - RatingPlanMdl{ - Tpid: "TEST_TPID", - Tag: "TEST_RPLAN", - DestratesTag: "TEST_DSTRATE2", - TimingTag: "TEST_TIMING2", - Weight: 20.0, - }, - } - if rcv := APItoModelRatingPlan(rp); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - rp = &utils.TPRatingPlan{ - TPid: "TEST_TPID", - ID: "TEST_RPLAN", - } - eOut = RatingPlanMdls{ - RatingPlanMdl{ - Tpid: "TEST_TPID", - Tag: "TEST_RPLAN", - }, - } - if rcv := APItoModelRatingPlan(rp); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - -func TestAPItoModelRatingPlans(t *testing.T) { - var rps []*utils.TPRatingPlan - if rcv := APItoModelRatingPlans(rps); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", utils.ToJSON(rcv)) - } - rps = []*utils.TPRatingPlan{ - { - ID: "ID", - TPid: "TPid", - RatingPlanBindings: []*utils.TPRatingPlanBinding{ - { - DestinationRatesId: "DestinationRatesId", - TimingId: "TimingId", - Weight: 0.7, - }, - }, - }, - } - eOut := RatingPlanMdls{ - RatingPlanMdl{ - Tag: "ID", - Tpid: "TPid", - DestratesTag: "DestinationRatesId", - TimingTag: "TimingId", - Weight: 0.7, - }, - } - if rcv := APItoModelRatingPlans(rps); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - -} - -func TestTPRatingProfileAsExportSlice(t *testing.T) { - tpRpf := &utils.TPRatingProfile{ - TPid: "TEST_TPID", - LoadId: "TEST_LOADID", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - RatingPlanActivations: []*utils.TPRatingActivation{ - { - ActivationTime: "2014-01-14T00:00:00Z", - RatingPlanId: "TEST_RPLAN1", - FallbackSubjects: "subj1;subj2"}, - { - ActivationTime: "2014-01-15T00:00:00Z", - RatingPlanId: "TEST_RPLAN2", - FallbackSubjects: "subj1;subj2"}, - }, - } - expectedSlc := [][]string{ - {"cgrates.org", "call", "*any", "2014-01-14T00:00:00Z", "TEST_RPLAN1", "subj1;subj2"}, - {"cgrates.org", "call", "*any", "2014-01-15T00:00:00Z", "TEST_RPLAN2", "subj1;subj2"}, - } - - ms := APItoModelRatingProfile(tpRpf) - var slc [][]string - for _, m := range ms { - lc, err := CsvDump(m) - if err != nil { - t.Error("Error dumping to csv: ", err) - } - slc = append(slc, lc) - } - - if !reflect.DeepEqual(expectedSlc, slc) { - t.Errorf("Expecting: %+v, received: %+v", expectedSlc, slc) - } -} - -func TestAPItoModelRatingProfile(t *testing.T) { - var rp *utils.TPRatingProfile - if rcv := APItoModelRatingProfile(rp); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - rp = &utils.TPRatingProfile{ - TPid: "TEST_TPID", - LoadId: "TEST_LOADID", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - RatingPlanActivations: []*utils.TPRatingActivation{ - { - ActivationTime: "2014-01-14T00:00:00Z", - RatingPlanId: "TEST_RPLAN1", - FallbackSubjects: "subj1;subj2"}, - { - ActivationTime: "2014-01-15T00:00:00Z", - RatingPlanId: "TEST_RPLAN2", - FallbackSubjects: "subj1;subj2"}, - }, - } - eOut := RatingProfileMdls{ - RatingProfileMdl{ - Tpid: "TEST_TPID", - Loadid: "TEST_LOADID", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - RatingPlanTag: "TEST_RPLAN1", - FallbackSubjects: "subj1;subj2", - ActivationTime: "2014-01-14T00:00:00Z", - }, - RatingProfileMdl{ - Tpid: "TEST_TPID", - Loadid: "TEST_LOADID", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - RatingPlanTag: "TEST_RPLAN2", - FallbackSubjects: "subj1;subj2", - ActivationTime: "2014-01-15T00:00:00Z", - }, - } - if rcv := APItoModelRatingProfile(rp); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - rp = &utils.TPRatingProfile{ - TPid: "TEST_TPID", - LoadId: "TEST_LOADID", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - } - eOut = RatingProfileMdls{ - RatingProfileMdl{ - Tpid: "TEST_TPID", - Loadid: "TEST_LOADID", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - }, - } - if rcv := APItoModelRatingProfile(rp); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - -func TestAPItoModelRatingProfiles(t *testing.T) { - var rps []*utils.TPRatingProfile - if rcv := APItoModelRatingProfiles(rps); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - rps = []*utils.TPRatingProfile{ - { - TPid: "TEST_TPID", - LoadId: "TEST_LOADID", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - }, - { - TPid: "TEST_TPID2", - LoadId: "TEST_LOADID2", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - }, - } - eOut := RatingProfileMdls{ - RatingProfileMdl{ - Tpid: "TEST_TPID", - Loadid: "TEST_LOADID", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - }, - RatingProfileMdl{ - Tpid: "TEST_TPID2", - Loadid: "TEST_LOADID2", - Tenant: "cgrates.org", - Category: "call", - Subject: "*any", - }, - } - if rcv := APItoModelRatingProfiles(rps); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - func TestTPActionsAsExportSlice(t *testing.T) { tpActs := &utils.TPActions{ TPid: "TEST_TPID", @@ -1072,550 +390,6 @@ func TestTPActionsAsExportSlice(t *testing.T) { } } -// SHARED_A,*any,*highest, -func TestTPSharedGroupsAsExportSlice(t *testing.T) { - tpSGs := &utils.TPSharedGroups{ - TPid: "TEST_TPID", - ID: "SHARED_GROUP_TEST", - SharedGroups: []*utils.TPSharedGroup{ - { - Account: "*any", - Strategy: "*highest", - RatingSubject: "special1"}, - { - Account: "second", - Strategy: "*highest", - RatingSubject: "special2"}, - }, - } - expectedSlc := [][]string{ - {"SHARED_GROUP_TEST", "*any", "*highest", "special1"}, - {"SHARED_GROUP_TEST", "second", "*highest", "special2"}, - } - - ms := APItoModelSharedGroup(tpSGs) - var slc [][]string - for _, m := range ms { - lc, err := CsvDump(m) - if err != nil { - t.Error("Error dumping to csv: ", err) - } - slc = append(slc, lc) - } - if !reflect.DeepEqual(expectedSlc, slc) { - t.Errorf("Expecting: %+v, received: %+v", expectedSlc, slc) - } -} - -func TestAPItoModelSharedGroups(t *testing.T) { - sgs := []*utils.TPSharedGroups{} - if rcv := APItoModelSharedGroups(sgs); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - sgs = []*utils.TPSharedGroups{ - { - TPid: "TEST_TPID", - ID: "SHARED_GROUP_TEST", - SharedGroups: []*utils.TPSharedGroup{ - { - Account: "*any", - Strategy: "*highest", - RatingSubject: "special1"}, - { - Account: "*second", - Strategy: "*highest", - RatingSubject: "special2"}, - }, - }, - } - eOut := SharedGroupMdls{ - SharedGroupMdl{ - Tpid: "TEST_TPID", - Tag: "SHARED_GROUP_TEST", - Account: "*any", - Strategy: "*highest", - RatingSubject: "special1", - }, - SharedGroupMdl{ - Tpid: "TEST_TPID", - Tag: "SHARED_GROUP_TEST", - Account: "*second", - Strategy: "*highest", - RatingSubject: "special2", - }, - } - if rcv := APItoModelSharedGroups(sgs); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - sgs = []*utils.TPSharedGroups{ - { - TPid: "TEST_TPID", - ID: "SHARED_GROUP_TEST", - }, - } - eOut = SharedGroupMdls{ - SharedGroupMdl{ - Tpid: "TEST_TPID", - Tag: "SHARED_GROUP_TEST", - }, - } - if rcv := APItoModelSharedGroups(sgs); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - sgs = []*utils.TPSharedGroups{ - { - TPid: "TEST_TPID", - ID: "SHARED_GROUP_TEST", - SharedGroups: []*utils.TPSharedGroup{ - { - Account: "*any", - Strategy: "*highest", - RatingSubject: "special1"}, - { - Account: "*second", - Strategy: "*highest", - RatingSubject: "special2"}, - }, - }, - { - TPid: "TEST_TPID2", - ID: "SHARED_GROUP_TEST2", - SharedGroups: []*utils.TPSharedGroup{ - { - Account: "*any", - Strategy: "*highest", - RatingSubject: "special1"}, - { - Account: "second", - Strategy: "*highest", - RatingSubject: "special2"}, - }, - }, - } - eOut = SharedGroupMdls{ - SharedGroupMdl{ - Tpid: "TEST_TPID", - Tag: "SHARED_GROUP_TEST", - Account: "*any", - Strategy: "*highest", - RatingSubject: "special1", - }, - SharedGroupMdl{ - Tpid: "TEST_TPID", - Tag: "SHARED_GROUP_TEST", - Account: "*second", - Strategy: "*highest", - RatingSubject: "special2", - }, - SharedGroupMdl{ - Tpid: "TEST_TPID2", - Tag: "SHARED_GROUP_TEST2", - Account: "*any", - Strategy: "*highest", - RatingSubject: "special1", - }, - SharedGroupMdl{ - Tpid: "TEST_TPID2", - Tag: "SHARED_GROUP_TEST2", - Account: "second", - Strategy: "*highest", - RatingSubject: "special2", - }, - } - if rcv := APItoModelSharedGroups(sgs); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - -func TestTPActionTriggersAsExportSlice(t *testing.T) { - ap := &utils.TPActionPlan{ - TPid: "TEST_TPID", - ID: "PACKAGE_10", - ActionPlan: []*utils.TPActionTiming{ - { - ActionsId: "TOPUP_RST_10", - TimingId: "ASAP", - Weight: 10.0}, - { - ActionsId: "TOPUP_RST_5", - TimingId: "ASAP", - Weight: 20.0}, - }, - } - expectedSlc := [][]string{ - {"PACKAGE_10", "TOPUP_RST_10", "ASAP", "10"}, - {"PACKAGE_10", "TOPUP_RST_5", "ASAP", "20"}, - } - ms := APItoModelActionPlan(ap) - var slc [][]string - for _, m := range ms { - lc, err := CsvDump(m) - if err != nil { - t.Error("Error dumping to csv: ", err) - } - slc = append(slc, lc) - } - if !reflect.DeepEqual(expectedSlc, slc) { - t.Errorf("Expecting: %+v, received: %+v", expectedSlc, slc) - } -} - -func TestAPItoModelActionPlan(t *testing.T) { - var a *utils.TPActionPlan - if rcv := APItoModelActionPlan(a); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - a = &utils.TPActionPlan{ - TPid: "TEST_TPID", - ID: "PACKAGE_10", - ActionPlan: []*utils.TPActionTiming{ - { - ActionsId: "TOPUP_RST_10", - TimingId: "ASAP", - Weight: 10.0}, - { - ActionsId: "TOPUP_RST_5", - TimingId: "ASAP", - Weight: 20.0}, - }, - } - - eOut := ActionPlanMdls{ - ActionPlanMdl{ - Tpid: "TEST_TPID", - Tag: "PACKAGE_10", - ActionsTag: "TOPUP_RST_10", - TimingTag: "ASAP", - Weight: 10, - }, - ActionPlanMdl{ - Tpid: "TEST_TPID", - Tag: "PACKAGE_10", - ActionsTag: "TOPUP_RST_5", - TimingTag: "ASAP", - Weight: 20, - }, - } - if rcv := APItoModelActionPlan(a); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - a = &utils.TPActionPlan{ - TPid: "TEST_TPID", - ID: "PACKAGE_10", - } - eOut = ActionPlanMdls{ - ActionPlanMdl{ - Tpid: "TEST_TPID", - Tag: "PACKAGE_10", - }, - } - if rcv := APItoModelActionPlan(a); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - -func TestAPItoModelActionPlans(t *testing.T) { - var a []*utils.TPActionPlan - if rcv := APItoModelActionPlans(a); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - a = []*utils.TPActionPlan{ - { - TPid: "TEST_TPID", - ID: "PACKAGE_10", - ActionPlan: []*utils.TPActionTiming{ - { - ActionsId: "TOPUP_RST_10", - TimingId: "ASAP", - Weight: 10.0}, - { - ActionsId: "TOPUP_RST_5", - TimingId: "ASAP", - Weight: 20.0}, - }, - }, - } - eOut := ActionPlanMdls{ - ActionPlanMdl{ - Tpid: "TEST_TPID", - Tag: "PACKAGE_10", - ActionsTag: "TOPUP_RST_10", - TimingTag: "ASAP", - Weight: 10, - }, - ActionPlanMdl{ - Tpid: "TEST_TPID", - Tag: "PACKAGE_10", - ActionsTag: "TOPUP_RST_5", - TimingTag: "ASAP", - Weight: 20, - }, - } - if rcv := APItoModelActionPlans(a); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - a = []*utils.TPActionPlan{ - { - TPid: "TEST_TPID", - ID: "PACKAGE_10", - }, - } - eOut = ActionPlanMdls{ - ActionPlanMdl{ - Tpid: "TEST_TPID", - Tag: "PACKAGE_10", - }, - } - if rcv := APItoModelActionPlans(a); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - -func TestTPActionPlanAsExportSlice(t *testing.T) { - at := &utils.TPActionTriggers{ - TPid: "TEST_TPID", - ID: "STANDARD_TRIGGERS", - ActionTriggers: []*utils.TPActionTrigger{ - { - Id: "STANDARD_TRIGGERS", - UniqueID: "1", - ThresholdType: "*min_balance", - ThresholdValue: 2.0, - Recurrent: false, - MinSleep: "0", - BalanceId: "b1", - BalanceType: "*monetary", - BalanceDestinationIds: "", - BalanceWeight: "0.0", - BalanceExpirationDate: "*never", - BalanceTimingTags: "T1", - BalanceRatingSubject: "special1", - BalanceCategories: "call", - BalanceSharedGroups: "SHARED_1", - BalanceBlocker: "false", - BalanceDisabled: "false", - ActionsId: "LOG_WARNING", - Weight: 10}, - { - Id: "STANDARD_TRIGGERS", - UniqueID: "2", - ThresholdType: "*max_event_counter", - ThresholdValue: 5.0, - Recurrent: false, - MinSleep: "0", - BalanceId: "b2", - BalanceType: "*monetary", - BalanceDestinationIds: "FS_USERS", - BalanceWeight: "0.0", - BalanceExpirationDate: "*never", - BalanceTimingTags: "T1", - BalanceRatingSubject: "special1", - BalanceCategories: "call", - BalanceSharedGroups: "SHARED_1", - BalanceBlocker: "false", - BalanceDisabled: "false", - ActionsId: "LOG_WARNING", - Weight: 10}, - }, - } - expectedSlc := [][]string{ - {"STANDARD_TRIGGERS", "1", "*min_balance", "2", "false", "0", "", "", "b1", "*monetary", "call", "", "special1", "SHARED_1", "*never", "T1", "0.0", "false", "false", "LOG_WARNING", "10"}, - {"STANDARD_TRIGGERS", "2", "*max_event_counter", "5", "false", "0", "", "", "b2", "*monetary", "call", "FS_USERS", "special1", "SHARED_1", "*never", "T1", "0.0", "false", "false", "LOG_WARNING", "10"}, - } - ms := APItoModelActionTrigger(at) - var slc [][]string - for _, m := range ms { - lc, err := CsvDump(m) - if err != nil { - t.Error("Error dumping to csv: ", err) - } - slc = append(slc, lc) - } - if !reflect.DeepEqual(expectedSlc, slc) { - t.Errorf("Expecting: %+v, received: %+v", expectedSlc, slc) - } -} - -func TestAPItoModelActionTrigger(t *testing.T) { - var at *utils.TPActionTriggers - if rcv := APItoModelActionTrigger(at); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - - at = &utils.TPActionTriggers{ - TPid: "TEST_TPID", - ID: "STANDARD_TRIGGERS", - ActionTriggers: []*utils.TPActionTrigger{ - { - Id: "STANDARD_TRIGGERS", - UniqueID: "1", - ThresholdType: "*min_balance", - ThresholdValue: 2.0, - Recurrent: false, - MinSleep: "0", - BalanceId: "b1", - BalanceType: "*monetary", - BalanceDestinationIds: "", - BalanceWeight: "0.0", - BalanceExpirationDate: "*never", - BalanceTimingTags: "T1", - BalanceRatingSubject: "special1", - BalanceCategories: "call", - BalanceSharedGroups: "SHARED_1", - BalanceBlocker: "false", - BalanceDisabled: "false", - ActionsId: "LOG_WARNING", - Weight: 10}, - { - Id: "STANDARD_TRIGGERS", - UniqueID: "2", - ThresholdType: "*max_event_counter", - ThresholdValue: 5.0, - Recurrent: false, - MinSleep: "0", - BalanceId: "b2", - BalanceType: "*monetary", - BalanceDestinationIds: "FS_USERS", - BalanceWeight: "0.0", - BalanceExpirationDate: "*never", - BalanceTimingTags: "T1", - BalanceRatingSubject: "special1", - BalanceCategories: "call", - BalanceSharedGroups: "SHARED_1", - BalanceBlocker: "false", - BalanceDisabled: "false", - ActionsId: "LOG_WARNING", - Weight: 10}, - }, - } - eOut := ActionTriggerMdls{ - ActionTriggerMdl{ - Tpid: "TEST_TPID", - Tag: "STANDARD_TRIGGERS", - UniqueId: "1", - ThresholdType: "*min_balance", - ThresholdValue: 2, - MinSleep: "0", - BalanceTag: "b1", - BalanceType: "*monetary", - BalanceCategories: "call", - BalanceRatingSubject: "special1", - BalanceSharedGroups: "SHARED_1", - BalanceExpiryTime: "*never", - BalanceTimingTags: "T1", - BalanceWeight: "0.0", - BalanceBlocker: "false", - BalanceDisabled: "false", - ActionsTag: "LOG_WARNING", - Weight: 10, - }, - ActionTriggerMdl{ - Tpid: "TEST_TPID", - Tag: "STANDARD_TRIGGERS", - UniqueId: "2", - ThresholdType: "*max_event_counter", - ThresholdValue: 5, - MinSleep: "0", - BalanceTag: "b2", - BalanceType: "*monetary", - BalanceCategories: "call", - BalanceDestinationTags: "FS_USERS", - BalanceRatingSubject: "special1", - BalanceSharedGroups: "SHARED_1", - BalanceExpiryTime: "*never", - BalanceTimingTags: "T1", - BalanceWeight: "0.0", - BalanceBlocker: "false", - BalanceDisabled: "false", - ActionsTag: "LOG_WARNING", - Weight: 10, - }, - } - if rcv := APItoModelActionTrigger(at); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - at = &utils.TPActionTriggers{ - TPid: "TEST_TPID", - ID: "STANDARD_TRIGGERS", - } - eOut = ActionTriggerMdls{ - ActionTriggerMdl{ - Tpid: "TEST_TPID", - Tag: "STANDARD_TRIGGERS", - }, - } - if rcv := APItoModelActionTrigger(at); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - -func TestTPAccountActionsAsExportSlice(t *testing.T) { - aa := &utils.TPAccountActions{ - TPid: "TEST_TPID", - LoadId: "TEST_LOADID", - Tenant: "cgrates.org", - Account: "1001", - ActionPlanId: "PACKAGE_10_SHARED_A_5", - ActionTriggersId: "STANDARD_TRIGGERS", - } - expectedSlc := [][]string{ - {"cgrates.org", "1001", "PACKAGE_10_SHARED_A_5", "STANDARD_TRIGGERS", "false", "false"}, - } - ms := APItoModelAccountAction(aa) - var slc [][]string - lc, err := CsvDump(*ms) - if err != nil { - t.Error("Error dumping to csv: ", err) - } - slc = append(slc, lc) - if !reflect.DeepEqual(expectedSlc, slc) { - t.Errorf("Expecting: %+v, received: %+v", expectedSlc, slc) - } -} -func TestAPItoModelActionTriggers(t *testing.T) { - var ts []*utils.TPActionTriggers - if rcv := APItoModelActionTriggers(ts); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } - ts = []*utils.TPActionTriggers{ - { - TPid: "TEST_TPID", - ID: "STANDARD_TRIGGERS", - ActionTriggers: []*utils.TPActionTrigger{ - { - Id: "STANDARD_TRIGGERS", - UniqueID: "1", - ThresholdType: "*min_balance", - Weight: 0.7}, - { - Id: "STANDARD_TRIGGERS", - UniqueID: "2", - ThresholdType: "*max_event_counter", - Weight: 0.8}, - }, - }, - } - eOut := ActionTriggerMdls{ - ActionTriggerMdl{ - Tpid: "TEST_TPID", - Tag: "STANDARD_TRIGGERS", - UniqueId: "1", - ThresholdType: "*min_balance", - Weight: 0.7, - }, - ActionTriggerMdl{ - Tpid: "TEST_TPID", - Tag: "STANDARD_TRIGGERS", - UniqueId: "2", - ThresholdType: "*max_event_counter", - Weight: 0.8, - }, - } - if rcv := APItoModelActionTriggers(ts); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v,\nreceived: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - func TestAPItoModelAction(t *testing.T) { var as *utils.TPActions if rcv := APItoModelAction(as); rcv != nil { diff --git a/engine/rateinterval.go b/engine/rateinterval.go index 1c5b35871..cf1e4866b 100644 --- a/engine/rateinterval.go +++ b/engine/rateinterval.go @@ -20,210 +20,12 @@ package engine import ( "fmt" - "reflect" "sort" - "strconv" - "strings" "time" "github.com/cgrates/cgrates/utils" ) -/* -Defines a time interval for which a certain set of prices will apply -*/ -type RateInterval struct { - Timing *RITiming - Rating *RIRate - Weight float64 -} - -// Separate structure used for rating plan size optimization -type RITiming struct { - ID string - Years utils.Years - Months utils.Months - MonthDays utils.MonthDays - WeekDays utils.WeekDays - StartTime, EndTime string // ##:##:## format - cronString string - tag string // loading validation only -} - -func (rit *RITiming) CronString() string { - if rit.cronString != "" && rit.ID != utils.MetaMonthlyEstimated { - return rit.cronString - } - var sec, min, hour, monthday, month, weekday, year string - switch rit.StartTime { - case "": - hour, min, sec = "*", "*", "*" - case utils.MetaEveryMinute: - hour, min, sec = "*", "*", "0" - case utils.MetaHourly: - hour, min, sec = "*", "0", "0" - default: - hms := strings.Split(rit.StartTime, ":") - if len(hms) == 3 { - hour, min, sec = hms[0], hms[1], hms[2] - } else { - hour, min, sec = "*", "*", "*" - } - hour = strings.TrimPrefix(hour, "0") - min = strings.TrimPrefix(min, "0") - sec = strings.TrimPrefix(sec, "0") - } - if len(rit.MonthDays) == 0 { - monthday = "*" - } else { - for i, md := range rit.MonthDays { - if i > 0 { - monthday += "," - } - monthday += strconv.Itoa(md) - } - } - if len(rit.Months) == 0 { - month = "*" - } else { - for i, md := range rit.Months { - if i > 0 { - month += "," - } - month += strconv.Itoa(int(md)) - } - } - if len(rit.WeekDays) == 0 { - weekday = "*" - } else { - for i, md := range rit.WeekDays { - if i > 0 { - weekday += "," - } - weekday += strconv.Itoa(int(md)) - } - } - if len(rit.Years) == 0 { - year = "*" - } else { - for i, md := range rit.Years { - if i > 0 { - year += "," - } - year += strconv.Itoa(int(md)) - } - } - if monthday == "-1" { // in case we receive -1 we send to cron special character L ( Last ) - monthday = "L" - } - rit.cronString = fmt.Sprintf("%s %s %s %s %s %s %s", sec, min, hour, monthday, month, weekday, year) - return rit.cronString -} - -/* -Returns a time object that represents the end of the interval realtive to the received time -*/ -func (rit *RITiming) getRightMargin(t time.Time) (rigthtTime time.Time) { - year, month, day := t.Year(), t.Month(), t.Day() - hour, min, sec, nsec := 23, 59, 59, 0 - loc := t.Location() - if rit.EndTime != "" { - split := strings.Split(rit.EndTime, ":") - hour, _ = strconv.Atoi(split[0]) - min, _ = strconv.Atoi(split[1]) - sec, _ = strconv.Atoi(split[2]) - //log.Print("RIGHT1: ", time.Date(year, month, day, hour, min, sec, nsec, loc)) - return time.Date(year, month, day, hour, min, sec, nsec, loc) - } - //log.Print("RIGHT2: ", time.Date(year, month, day, hour, min, sec, nsec, loc).Add(time.Second)) - return time.Date(year, month, day, hour, min, sec, nsec, loc).Add(time.Second) -} - -//Returns a time object that represents the start of the interval realtive to the received time -func (rit *RITiming) getLeftMargin(t time.Time) (rigthtTime time.Time) { - year, month, day := t.Year(), t.Month(), t.Day() - hour, min, sec, nsec := 0, 0, 0, 0 - loc := t.Location() - if rit.StartTime != "" { - split := strings.Split(rit.StartTime, ":") - hour, _ = strconv.Atoi(split[0]) - min, _ = strconv.Atoi(split[1]) - sec, _ = strconv.Atoi(split[2]) - } - //log.Print("LEFT: ", time.Date(year, month, day, hour, min, sec, nsec, loc)) - return time.Date(year, month, day, hour, min, sec, nsec, loc) -} - -// Returns wheter the Timing is active at the specified time -func (rit *RITiming) IsActiveAt(t time.Time) bool { - // check for years - if len(rit.Years) > 0 && !rit.Years.Contains(t.Year()) { - return false - } - // check for months - if len(rit.Months) > 0 && !rit.Months.Contains(t.Month()) { - return false - } - // check for month days - if len(rit.MonthDays) > 0 && !rit.MonthDays.Contains(t.Day()) { - return false - } - // check for weekdays - if len(rit.WeekDays) > 0 && !rit.WeekDays.Contains(t.Weekday()) { - return false - } - //log.Print("Time: ", t) - - //log.Print("Left Margin: ", rit.getLeftMargin(t)) - // check for start hour - if t.Before(rit.getLeftMargin(t)) { - return false - } - - //log.Print("Right Margin: ", rit.getRightMargin(t)) - // check for end hour - if t.After(rit.getRightMargin(t)) { - return false - } - return true -} - -// IsActive returns wheter the Timing is active now -func (rit *RITiming) IsActive() bool { - return rit.IsActiveAt(time.Now()) -} - -func (rit *RITiming) IsBlank() bool { - return len(rit.Years) == 0 && - len(rit.Months) == 0 && - len(rit.MonthDays) == 0 && - len(rit.WeekDays) == 0 && - rit.StartTime == "00:00:00" -} - -func (rit *RITiming) Stringify() string { - return utils.Sha1(fmt.Sprintf("%v", rit))[:8] -} - -// Separate structure used for rating plan size optimization -type RIRate struct { - ConnectFee float64 - RoundingMethod string - RoundingDecimals int - MaxCost float64 - MaxCostStrategy string - Rates RateGroups // GroupRateInterval (start time): RGRate - tag string // loading validation only -} - -func (rir *RIRate) Stringify() string { - str := fmt.Sprintf("%v %v %v %v %v", rir.ConnectFee, rir.RoundingMethod, rir.RoundingDecimals, rir.MaxCost, rir.MaxCostStrategy) - for _, r := range rir.Rates { - str += r.Stringify() - } - return utils.Sha1(str)[:8] -} - type RGRate struct { GroupIntervalStart time.Duration Value float64 @@ -327,43 +129,6 @@ func (pg RateGroups) Clone() (cln RateGroups) { return } -/* -Returns true if the received time result inside the interval -*/ -func (i *RateInterval) Contains(t time.Time, endTime bool) bool { - if endTime { - if utils.TimeIs0h(t) { // back one second to 23:59:59 - t = t.Add(-1 * time.Second) - } - } - return i.Timing.IsActiveAt(t) -} - -func (i *RateInterval) String_DISABLED() string { - return fmt.Sprintf("%v %v %v %v %v %v", i.Timing.Years, i.Timing.Months, i.Timing.MonthDays, i.Timing.WeekDays, i.Timing.StartTime, i.Timing.EndTime) -} - -func (i *RateInterval) Equal(o *RateInterval) bool { - if i == nil && o == nil { - return true - } - if i == nil || o == nil { - return false // considering the earlier test - } - if i.Weight != o.Weight { - return false - } - if i.Timing == nil && o.Timing == nil { - return true - } - return reflect.DeepEqual(i.Timing.Years, o.Timing.Years) && - reflect.DeepEqual(i.Timing.Months, o.Timing.Months) && - reflect.DeepEqual(i.Timing.MonthDays, o.Timing.MonthDays) && - reflect.DeepEqual(i.Timing.WeekDays, o.Timing.WeekDays) && - i.Timing.StartTime == o.Timing.StartTime && - i.Timing.EndTime == o.Timing.EndTime -} - func (i *RateInterval) GetCost(duration, startSecond time.Duration) float64 { price, _, rateUnit := i.GetRateParameters(startSecond) price /= float64(rateUnit.Nanoseconds()) diff --git a/engine/rateinterval_test.go b/engine/rateinterval_test.go deleted file mode 100644 index d44776e09..000000000 --- a/engine/rateinterval_test.go +++ /dev/null @@ -1,816 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package engine - -import ( - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/utils" -) - -var ( - ACTIVE_TIME = time.Now() -) - -func TestRateIntervalSimpleContains(t *testing.T) { - i := &RateInterval{ - Timing: &RITiming{ - WeekDays: utils.WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, - StartTime: "18:00:00", - EndTime: "", - }, - } - d := time.Date(2012, time.February, 27, 23, 59, 59, 0, time.UTC) - if !i.Contains(d, false) { - t.Errorf("Date %+v shoud be in interval %+v", d, i) - } -} - -func TestRateIntervalMonth(t *testing.T) { - i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}}} - d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) - d1 := time.Date(2012, time.January, 10, 23, 0, 0, 0, time.UTC) - if !i.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i) - } - if i.Contains(d1, false) { - t.Errorf("Date %v shoud not be in interval %v", d1, i) - } -} - -func TestRateIntervalMonthDay(t *testing.T) { - i := &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{10}}} - d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) - d1 := time.Date(2012, time.February, 11, 23, 0, 0, 0, time.UTC) - if !i.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i) - } - if i.Contains(d1, false) { - t.Errorf("Date %v shoud not be in interval %v", d1, i) - } -} - -func TestRateIntervalMonthAndMonthDay(t *testing.T) { - i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}, MonthDays: utils.MonthDays{10}}} - d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) - d1 := time.Date(2012, time.February, 11, 23, 0, 0, 0, time.UTC) - d2 := time.Date(2012, time.January, 10, 23, 0, 0, 0, time.UTC) - if !i.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i) - } - if i.Contains(d1, false) { - t.Errorf("Date %v shoud not be in interval %v", d1, i) - } - if i.Contains(d2, false) { - t.Errorf("Date %v shoud not be in interval %v", d2, i) - } -} - -func TestRateIntervalWeekDays(t *testing.T) { - i := &RateInterval{Timing: &RITiming{WeekDays: []time.Weekday{time.Wednesday}}} - i2 := &RateInterval{Timing: &RITiming{WeekDays: []time.Weekday{time.Wednesday, time.Thursday}}} - d := time.Date(2012, time.February, 1, 23, 0, 0, 0, time.UTC) - d1 := time.Date(2012, time.February, 2, 23, 0, 0, 0, time.UTC) - if !i.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i) - } - if i.Contains(d1, false) { - t.Errorf("Date %v shoud not be in interval %v", d1, i) - } - if !i2.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i2) - } - if !i2.Contains(d1, false) { - t.Errorf("Date %v shoud be in interval %v", d1, i2) - } -} - -func TestRateIntervalMonthAndMonthDayAndWeekDays(t *testing.T) { - i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}, MonthDays: utils.MonthDays{1}, WeekDays: []time.Weekday{time.Wednesday}}} - i2 := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}, MonthDays: utils.MonthDays{2}, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}}} - d := time.Date(2012, time.February, 1, 23, 0, 0, 0, time.UTC) - d1 := time.Date(2012, time.February, 2, 23, 0, 0, 0, time.UTC) - if !i.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i) - } - if i.Contains(d1, false) { - t.Errorf("Date %v shoud not be in interval %v", d1, i) - } - if i2.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i2) - } - if !i2.Contains(d1, false) { - t.Errorf("Date %v shoud be in interval %v", d1, i2) - } -} - -func TestRateIntervalHours(t *testing.T) { - i := &RateInterval{Timing: &RITiming{StartTime: "14:30:00", EndTime: "15:00:00"}} - d := time.Date(2012, time.February, 10, 14, 30, 1, 0, time.UTC) - d1 := time.Date(2012, time.January, 10, 14, 29, 0, 0, time.UTC) - d2 := time.Date(2012, time.January, 10, 14, 59, 0, 0, time.UTC) - d3 := time.Date(2012, time.January, 10, 15, 01, 0, 0, time.UTC) - if !i.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i) - } - if i.Contains(d1, false) { - t.Errorf("Date %v shoud not be in interval %v", d1, i) - } - if !i.Contains(d2, false) { - t.Errorf("Date %v shoud be in interval %v", d2, i) - } - if i.Contains(d3, false) { - t.Errorf("Date %v shoud not be in interval %v", d3, i) - } -} - -func TestRateIntervalEverything(t *testing.T) { - i := &RateInterval{ - Timing: &RITiming{ - Months: utils.Months{time.February}, - Years: utils.Years{2012}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) - d1 := time.Date(2012, time.February, 1, 14, 29, 1, 0, time.UTC) - d2 := time.Date(2012, time.February, 1, 15, 00, 00, 0, time.UTC) - d3 := time.Date(2012, time.February, 1, 15, 0, 1, 0, time.UTC) - d4 := time.Date(2011, time.February, 1, 15, 00, 00, 0, time.UTC) - if !i.Contains(d, false) { - t.Errorf("Date %v shoud be in interval %v", d, i) - } - if i.Contains(d1, false) { - t.Errorf("Date %v shoud not be in interval %v", d1, i) - } - if !i.Contains(d2, false) { - t.Errorf("Date %v shoud be in interval %v", d2, i) - } - if i.Contains(d3, false) { - t.Errorf("Date %v shoud not be in interval %v", d3, i) - } - if i.Contains(d4, false) { - t.Errorf("Date %v shoud not be in interval %v", d3, i) - } -} - -func TestRateIntervalEqual(t *testing.T) { - i1 := &RateInterval{ - Timing: &RITiming{ - Months: utils.Months{time.February}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - i2 := &RateInterval{Timing: &RITiming{ - Months: utils.Months{time.February}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - if !i1.Equal(i2) || !i2.Equal(i1) { - t.Errorf("%v and %v are not equal", i1, i2) - } -} - -func TestRateIntervalEqualWeight(t *testing.T) { - i1 := &RateInterval{Weight: 1} - i2 := &RateInterval{Weight: 2} - if i1.Equal(i2) { - t.Errorf("%v and %v should not be equal", i1, i2) - } -} - -func TestRateIntervalNotEqual(t *testing.T) { - i1 := &RateInterval{ - Timing: &RITiming{ - Months: utils.Months{time.February}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - i2 := &RateInterval{Timing: &RITiming{ - Months: utils.Months{time.February}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - if i1.Equal(i2) || i2.Equal(i1) { - t.Errorf("%v and %v not equal", i1, i2) - } -} - -func TestRitStrigyfy(t *testing.T) { - rit1 := &RITiming{ - Years: utils.Years{}, - Months: utils.Months{time.January, time.February}, - MonthDays: utils.MonthDays{}, - StartTime: "00:00:00", - } - rit2 := &RITiming{ - Years: utils.Years{}, - Months: utils.Months{time.January, time.February}, - MonthDays: utils.MonthDays{}, - StartTime: "00:00:00", - } - if rit1.Stringify() != rit2.Stringify() { - t.Error("Error in rir stringify: ", rit1.Stringify(), rit2.Stringify()) - } -} - -func TestRirStrigyfy(t *testing.T) { - rir1 := &RIRate{ - ConnectFee: 0.1, - Rates: RateGroups{ - &RGRate{ - GroupIntervalStart: time.Hour, - Value: 0.17, - RateIncrement: time.Second, - RateUnit: time.Minute, - }, - &RGRate{ - GroupIntervalStart: 0, - Value: 0.7, - RateIncrement: time.Second, - RateUnit: time.Minute, - }, - }, - RoundingMethod: utils.MetaRoundingMiddle, - RoundingDecimals: 4, - } - rir2 := &RIRate{ - ConnectFee: 0.1, - Rates: RateGroups{ - &RGRate{ - GroupIntervalStart: time.Hour, - Value: 0.17, - RateIncrement: time.Second, - RateUnit: time.Minute, - }, - &RGRate{ - GroupIntervalStart: 0, - Value: 0.7, - RateIncrement: time.Second, - RateUnit: time.Minute, - }, - }, - RoundingMethod: utils.MetaRoundingMiddle, - RoundingDecimals: 4, - } - if rir1.Stringify() != rir2.Stringify() { - t.Error("Error in rate stringify: ", rir1.Stringify(), rir2.Stringify()) - } -} - -func TestRateStrigyfy(t *testing.T) { - r1 := &RGRate{ - GroupIntervalStart: time.Hour, - Value: 0.17, - RateUnit: time.Minute, - } - r2 := &RGRate{ - GroupIntervalStart: time.Hour, - Value: 0.17, - RateUnit: time.Minute, - } - if r1.Stringify() != r2.Stringify() { - t.Error("Error in rate stringify: ", r1.Stringify(), r2.Stringify()) - } -} - -func TestRateIntervalCronAll(t *testing.T) { - rit := &RITiming{ - Years: utils.Years{2012}, - Months: utils.Months{time.February}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Sunday}, - StartTime: "14:30:00", - } - expected := "0 30 14 1 2 0 2012" - cron := rit.CronString() - if cron != expected { - t.Errorf("Expected %s was %s", expected, cron) - } -} - -func TestRateIntervalCronMultiple(t *testing.T) { - rit := &RITiming{ - Years: utils.Years{2012, 2014}, - Months: utils.Months{time.February, time.January}, - MonthDays: utils.MonthDays{15, 16}, - WeekDays: []time.Weekday{time.Sunday, time.Monday}, - StartTime: "14:30:00", - } - expected := "0 30 14 15,16 2,1 0,1 2012,2014" - cron := rit.CronString() - - if cron != expected { - t.Errorf("Expected %s was %s", expected, cron) - } -} - -func TestRateIntervalCronStar(t *testing.T) { - rit := &RITiming{ - StartTime: "*:30:00", - } - expected := "0 30 * * * * *" - cron := rit.CronString() - - if cron != expected { - t.Errorf("Expected %s was %s", expected, cron) - } -} - -func TestRateIntervalCronEmpty(t *testing.T) { - rit := &RITiming{} - expected := "* * * * * * *" - cron := rit.CronString() - - if cron != expected { - t.Errorf("Expected %s was %s", expected, cron) - } -} - -func TestRITimingCronEveryX(t *testing.T) { - rit := &RITiming{ - StartTime: utils.MetaEveryMinute, - } - eCronStr := "0 * * * * * *" - if cronStr := rit.CronString(); cronStr != eCronStr { - t.Errorf("Expecting: <%s>, received: <%s>", eCronStr, cronStr) - } - rit = &RITiming{ - StartTime: utils.MetaHourly, - } - eCronStr = "0 0 * * * * *" - if cronStr := rit.CronString(); cronStr != eCronStr { - t.Errorf("Expecting: <%s>, received: <%s>", eCronStr, cronStr) - } -} - -func TestRateIntervalCost(t *testing.T) { - ri := &RateInterval{ - Rating: &RIRate{ - Rates: RateGroups{ - &RGRate{ - Value: 0.1, - RateIncrement: time.Second, - RateUnit: 60 * time.Second, - }, - }, - }, - } - x := ri.GetCost(60*time.Second, 0) - if x != 0.1 { - t.Error("expected 0.1 was: ", x) - } -} - -func TestRateGroupsEquals(t *testing.T) { - rg1 := RateGroups{ - &RGRate{ - GroupIntervalStart: 0, - Value: 0.1, - RateIncrement: time.Minute, - RateUnit: 60 * time.Second, - }, - &RGRate{ - GroupIntervalStart: 60 * time.Second, - Value: 0.05, - RateIncrement: time.Second, - RateUnit: time.Second, - }, - } - rg2 := RateGroups{ - &RGRate{ - GroupIntervalStart: 0, - Value: 0.1, - RateIncrement: time.Minute, - RateUnit: 60 * time.Second, - }, - &RGRate{ - GroupIntervalStart: 60 * time.Second, - Value: 0.05, - RateIncrement: time.Second, - RateUnit: time.Second, - }, - } - if !rg1.Equals(rg2) { - t.Error("not equal") - } - rg2 = RateGroups{ - &RGRate{ - GroupIntervalStart: 0, - Value: 0.1, - RateIncrement: time.Minute, - RateUnit: 60 * time.Second, - }, - &RGRate{ - GroupIntervalStart: 60 * time.Second, - Value: 0.3, - RateIncrement: time.Second, - RateUnit: time.Second, - }, - } - if rg1.Equals(rg2) { - t.Error("equals") - } - rg2 = RateGroups{ - &RGRate{ - GroupIntervalStart: 0, - Value: 0.1, - RateIncrement: time.Minute, - RateUnit: 60 * time.Second, - }, - } - if rg1.Equals(rg2) { - t.Error("equals") - } -} - -func TestRateIntervalClone(t *testing.T) { - var i, cln RateInterval - if cloned := i.Clone(); !reflect.DeepEqual(cln, *cloned) { - t.Errorf("Expecting: %+v, received: %+v", cln, *cloned) - } - i = RateInterval{ - Weight: 0.7, - } - cln = RateInterval{ - Weight: 0.7, - } - if cloned := i.Clone(); !reflect.DeepEqual(cln, *cloned) { - t.Errorf("Expecting: %+v, received: %+v", cln, *cloned) - } -} - -func TestRITimingClone(t *testing.T) { - var rit, cln RITiming - if cloned := rit.Clone(); !reflect.DeepEqual(cln, *cloned) { - t.Errorf("Expecting: %+v, received: %+v", cln, *cloned) - } - rit = RITiming{ - Years: utils.Years{2019}, - Months: utils.Months{4}, - MonthDays: utils.MonthDays{18}, - WeekDays: utils.WeekDays{5}, - StartTime: "StartTime_test", - EndTime: "EndTime_test", - } - cln = RITiming{ - Years: utils.Years{2019}, - Months: utils.Months{4}, - MonthDays: utils.MonthDays{18}, - WeekDays: utils.WeekDays{5}, - StartTime: "StartTime_test", - EndTime: "EndTime_test", - } - cloned := rit.Clone() - if !reflect.DeepEqual(cln, *cloned) { - t.Errorf("Expecting: %+v, received: %+v", cln, *cloned) - } - rit.Years = utils.Years{2020} - if cloned.Years[0] != cln.Years[0] { - t.Errorf("Expecting: 2019, received: %+v", cloned.Years) - } -} - -func TestRITimingClone2(t *testing.T) { - var rit, cln RITiming - rit = RITiming{ - Years: utils.Years{2019}, - Months: utils.Months{4}, - MonthDays: utils.MonthDays{18}, - WeekDays: utils.WeekDays{5}, - StartTime: "StartTime_test", - EndTime: "EndTime_test", - } - cln = RITiming{ - Years: utils.Years{2019}, - Months: utils.Months{4}, - MonthDays: utils.MonthDays{18}, - WeekDays: utils.WeekDays{5}, - StartTime: "StartTime_test", - EndTime: "EndTime_test", - } - cloned := rit.Clone() - if !reflect.DeepEqual(cln, *cloned) { - t.Errorf("Expecting: %+v, received: %+v", cln, *cloned) - } - rit.Years[0] = 2020 - if cloned.Years[0] != cln.Years[0] { - t.Errorf("Expecting: 2019, received: %+v", cloned.Years) - } -} - -func TestRIRateClone(t *testing.T) { - var rit, cln RIRate - if cloned := rit.Clone(); !reflect.DeepEqual(cln, *cloned) { - t.Errorf("Expecting: %+v,\n received: %+v", cln, *cloned) - } - rit = RIRate{ - ConnectFee: 0.7, - RoundingMethod: "RoundingMethod_test", - RoundingDecimals: 7, - MaxCost: 0.7, - MaxCostStrategy: "MaxCostStrategy_test", - Rates: RateGroups{ - &RGRate{ - GroupIntervalStart: 10, - Value: 0.7, - RateIncrement: 10, - RateUnit: 10, - }, - }, - } - cln = RIRate{ - ConnectFee: 0.7, - RoundingMethod: "RoundingMethod_test", - RoundingDecimals: 7, - MaxCost: 0.7, - MaxCostStrategy: "MaxCostStrategy_test", - Rates: RateGroups{ - &RGRate{ - GroupIntervalStart: 10, - Value: 0.7, - RateIncrement: 10, - RateUnit: 10, - }, - }, - } - cloned := rit.Clone() - if !reflect.DeepEqual(cln, *cloned) { - t.Errorf("Expecting: %+v, received: %+v", cln, *cloned) - } - rit.Rates[0].GroupIntervalStart = 7 - if cloned.Rates[0].GroupIntervalStart != 10 { - t.Errorf("Expecting: 10,\n received: %+v", cloned.Rates[0].GroupIntervalStart) - } -} - -/*********************************Benchmarks**************************************/ - -func BenchmarkRateIntervalContainsDate(b *testing.B) { - i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}, MonthDays: utils.MonthDays{1}, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, StartTime: "14:30:00", EndTime: "15:00:00"}} - d := time.Date(2012, time.February, 1, 14, 30, 0, 0, time.UTC) - for x := 0; x < b.N; x++ { - i.Contains(d, false) - } -} - -func TestRateIntervalCronStringDefault(t *testing.T) { - rit := &RITiming{ - StartTime: "223000", - } - cron := rit.CronString() - if !reflect.DeepEqual(cron, "* * * * * * *") { - t.Errorf("\nExpecting: <* * * * * * *>,\n Received: <%+v>", cron) - } -} - -func TestRateIntervalCronStringMonthDayNegative(t *testing.T) { - rit := &RITiming{ - StartTime: "223000", - MonthDays: utils.MonthDays{-1}, - } - cron := rit.CronString() - if !reflect.DeepEqual(cron, "* * * L * * *") { - t.Errorf("\nExpecting: <* * * L * * *>,\n Received: <%+v>", cron) - } -} - -func TestRateIntervalIsActiveAt(t *testing.T) { - rit := &RITiming{} - cronActive := rit.IsActive() - if !reflect.DeepEqual(cronActive, true) { - t.Errorf("\nExpecting: ,\n Received: <%+v>", cronActive) - } -} - -func TestRateIntervalIsActiveAtNot(t *testing.T) { - rit := &RITiming{ - Years: utils.Years{1000}, - } - cronActive := rit.IsActive() - if !reflect.DeepEqual(cronActive, false) { - t.Errorf("\nExpecting: ,\n Received: <%+v>", cronActive) - } -} - -func TestRateIntervalFieldAsInterfaceError(t *testing.T) { - rateTest := &RGRate{ - Value: 2.2, - } - _, err := rateTest.FieldAsInterface([]string{"FALSE"}) - if err == nil && err.Error() != "unsupported field prefix: " { - t.Errorf("\nExpecting: >,\n Received: <%+v>", err) - } -} - -func TestRateIntervalFieldAsInterfaceError2(t *testing.T) { - rateTest := &RGRate{} - _, err := rateTest.FieldAsInterface([]string{"value1", "value2"}) - - if err == nil && err != utils.ErrNotFound { - t.Errorf("\nExpecting: ,\n Received: <%+v>", err) - } -} - -func TestRateIntervalFieldAsInterfaceRateIncrement(t *testing.T) { - rateTest := &RGRate{ - RateIncrement: time.Second, - } - if result, err := rateTest.FieldAsInterface([]string{"RateIncrement"}); err != nil { - t.Errorf("\nExpecting: ,\n Received: <%+v>", err) - } else if !reflect.DeepEqual(result, time.Second) { - t.Errorf("\nExpecting: <1s>,\n Received: <%+v>", result) - } - -} - -func TestRateIntervalFieldAsInterfaceGroupIntervalStart(t *testing.T) { - rateTest := &RGRate{ - GroupIntervalStart: time.Second, - } - if result, err := rateTest.FieldAsInterface([]string{"GroupIntervalStart"}); err != nil { - t.Errorf("\nExpecting: ,\n Received: <%+v>", err) - } else if !reflect.DeepEqual(result, time.Second) { - t.Errorf("\nExpecting: <1s>,\n Received: <%+v>", result) - } - -} - -func TestRateIntervalFieldAsInterfaceRateUnit(t *testing.T) { - rateTest := &RGRate{ - RateUnit: time.Second, - } - if result, err := rateTest.FieldAsInterface([]string{"RateUnit"}); err != nil { - t.Errorf("\nExpecting: ,\n Received: <%+v>", err) - } else if !reflect.DeepEqual(result, time.Second) { - t.Errorf("\nExpecting: <1s>,\n Received: <%+v>", result) - } - -} - -func TestRateGroupsEqual(t *testing.T) { - rateGroupOG := RateGroups{&RGRate{ - Value: 2.2, - }} - rateGroupOther := RateGroups{&RGRate{ - Value: 2.2, - }} - result := rateGroupOG.Equal(rateGroupOther) - if !reflect.DeepEqual(result, true) { - t.Errorf("\nExpecting: ,\n Received: <%+v>", result) - } -} - -func TestRateGroupsEqualFalse(t *testing.T) { - rateGroupOG := RateGroups{&RGRate{ - Value: 2.2, - }} - rateGroupOther := RateGroups{&RGRate{ - Value: 2.5, - }} - result := rateGroupOG.Equal(rateGroupOther) - if !reflect.DeepEqual(result, false) { - t.Errorf("\nExpecting: ,\n Received: <%+v>", result) - } -} - -func TestRateGroupsUnEqual(t *testing.T) { - rateGroupOG := RateGroups{&RGRate{ - Value: 2.2, - }, - &RGRate{}, - } - rateGroupOther := RateGroups{&RGRate{ - Value: 2.5, - }} - result := rateGroupOG.Equal(rateGroupOther) - if !reflect.DeepEqual(result, false) { - t.Errorf("\nExpecting: ,\n Received: <%+v>", result) - } -} - -func TestRateGroupsAddRate(t *testing.T) { - rateGroupOG := &RateGroups{&RGRate{ - Value: 2.2, - }} - rateGroupOther := &RateGroups{&RGRate{ - Value: 2.2, - }} - rateGroupOther.AddRate(&RGRate{}) - if reflect.DeepEqual(rateGroupOther, rateGroupOG) { - t.Errorf("\nExpecting: ,\n Received: ") - } -} - -func TestRateGroupsAddRateEmpty(t *testing.T) { - rateGroupOG := &RateGroups{&RGRate{ - Value: 2.2, - }} - rateGroupOther := &RateGroups{&RGRate{ - Value: 2.2, - }} - rateGroupOther.AddRate() - if !reflect.DeepEqual(rateGroupOther, rateGroupOG) { - t.Errorf("\nExpecting: ,\n Received: ") - } -} - -func TestRateGroupsAddRateSame(t *testing.T) { - rateGroupOG := &RateGroups{&RGRate{ - Value: 2.2, - }} - rateGroupOther := &RateGroups{&RGRate{ - Value: 2.2, - }} - rateGroupOther.AddRate(&RGRate{ - Value: 2.2, - }) - if !reflect.DeepEqual(rateGroupOther, rateGroupOG) { - t.Errorf("\nExpecting: ,\n Received: ") - } -} - -func TestRateIntervalStringDisabled(t *testing.T) { - testInterval := &RateInterval{ - Timing: &RITiming{ - Years: utils.Years{1000}, - }, - Rating: &RIRate{ - ConnectFee: 2, - }, - Weight: 6.5, - } - result := testInterval.String_DISABLED() - if !reflect.DeepEqual(result, "[1000] [] [] [] ") { - t.Errorf("\nExpecting: <[1000] [] [] [] >,\n Received: <%+v>", result) - } -} - -func TestRateIntervalEqualError(t *testing.T) { - testRateInterval := &RateInterval{ - Weight: 2, - } - var testRateInterval2 *RateInterval = nil - result := testRateInterval.Equal(testRateInterval2) - if !reflect.DeepEqual(result, false) { - t.Errorf("\nExpecting: ,\n Received: <%+v>", result) - } -} - -func TestRateIntervalGetRateParametersEmpty(t *testing.T) { - testRateInterval := &RateInterval{ - Rating: &RIRate{}, - Weight: 2, - } - rate, rateIncrement, rateUnit := testRateInterval.GetRateParameters(time.Second) - - if !reflect.DeepEqual(rate, float64(-1)) { - t.Errorf("\nExpecting: <-1>,\n Received: <%+v> ", rate) - } - if !reflect.DeepEqual(rateIncrement.String(), "-1ns") { - t.Errorf("\nExpecting: <-1ns>,\n Received: <%+v> ", rateIncrement.String()) - } - if !reflect.DeepEqual(rateUnit.String(), "-1ns") { - t.Errorf("\nExpecting: <-1ns>,\n Received: <%+v> ", rateUnit) - } -} - -func TestRateIntervalGetMaxCost(t *testing.T) { - testRateInterval := &RateInterval{ - Weight: 2, - } - result, result2 := testRateInterval.GetMaxCost() - if !reflect.DeepEqual(result, float64(0.0)) || !reflect.DeepEqual(result2, "") { - t.Errorf("\nExpecting: <0> and <>,\n Received: <%+v> and <%+v>", result, result2) - } -} - -func TestRGRateCloneNil(t *testing.T) { - var testRate *RGRate = nil - result := testRate.Clone() - if !reflect.DeepEqual(result, testRate) { - t.Errorf("\nExpecting: ,\n Received: <%+v>", result) - } -} diff --git a/engine/ratingplan.go b/engine/ratingplan.go deleted file mode 100644 index 256193897..000000000 --- a/engine/ratingplan.go +++ /dev/null @@ -1,170 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package engine - -import ( - "math" -) - -/* -The struture that is saved to storage. -*/ -type RatingPlan struct { - Id string - Timings map[string]*RITiming - Ratings map[string]*RIRate - DestinationRates map[string]RPRateList -} - -// RatingPlanWithOpts is used in replicatorV1 for dispatcher -type RatingPlanWithAPIOpts struct { - *RatingPlan - Tenant string - APIOpts map[string]interface{} -} - -type RPRate struct { - Timing string - Rating string - Weight float64 -} - -func (rpr *RPRate) Equal(orpr *RPRate) bool { - return rpr.Timing == orpr.Timing && rpr.Rating == orpr.Rating && rpr.Weight == orpr.Weight -} - -type RPRateList []*RPRate - -func (rp *RatingPlan) RateIntervalList(dId string) RateIntervalList { - ril := make(RateIntervalList, len(rp.DestinationRates[dId])) - for i, rpr := range rp.DestinationRates[dId] { - ril[i] = &RateInterval{ - Timing: rp.Timings[rpr.Timing], - Rating: rp.Ratings[rpr.Rating], - Weight: rpr.Weight, - } - } - return ril -} - -// no sorter because it's sorted with RateIntervalTimeSorter - -/* -Adds one ore more intervals to the internal interval list only if it is not allready in the list. -*/ -func (rp *RatingPlan) AddRateInterval(dId string, ris ...*RateInterval) { - if rp.DestinationRates == nil { - rp.Timings = make(map[string]*RITiming) - rp.Ratings = make(map[string]*RIRate) - rp.DestinationRates = make(map[string]RPRateList, 1) - } - for _, ri := range ris { - rpr := &RPRate{Weight: ri.Weight} - if ri.Timing != nil { - timingTag := ri.Timing.Stringify() - rp.Timings[timingTag] = ri.Timing - rpr.Timing = timingTag - } - if ri.Rating != nil { - ratingTag := ri.Rating.Stringify() - rp.Ratings[ratingTag] = ri.Rating - rpr.Rating = ratingTag - } - found := false - for _, erpr := range rp.DestinationRates[dId] { - if erpr.Equal(rpr) { - found = true - break - } - } - if !found { - rp.DestinationRates[dId] = append(rp.DestinationRates[dId], rpr) - } - } -} - -func (rp *RatingPlan) Equal(o *RatingPlan) bool { - return rp.Id == o.Id -} - -// IsValid determines if the rating plan covers a continous period of time -func (rp *RatingPlan) isContinous() bool { - weekdays := make([]int, 7) - for _, tm := range rp.Timings { - // if it is a blank timing than it will match all - if tm.IsBlank() { - return true - } - // skip the special timings (for specific dates) - if len(tm.Years) != 0 || len(tm.Months) != 0 || len(tm.MonthDays) != 0 { - continue - } - // if the startime is not midnight than is an extra time - if tm.StartTime != "00:00:00" { - continue - } - //check if all weekdays are covered - for _, wd := range tm.WeekDays { - weekdays[wd] = 1 - } - allWeekdaysCovered := true - for _, wd := range weekdays { - if wd != 1 { - allWeekdaysCovered = false - break - } - } - if allWeekdaysCovered { - return true - } - } - return false -} - -func (rp *RatingPlan) getFirstUnsaneRating() string { - for _, rating := range rp.Ratings { - rating.Rates.Sort() - for i, rate := range rating.Rates { - if i < (len(rating.Rates) - 1) { - nextRate := rating.Rates[i+1] - if nextRate.GroupIntervalStart <= rate.GroupIntervalStart { - return rating.tag - } - if math.Mod(float64(nextRate.GroupIntervalStart.Nanoseconds()), - float64(rate.RateIncrement.Nanoseconds())) != 0 { - return rating.tag - } - if rate.RateUnit == 0 || rate.RateIncrement == 0 { - return rating.tag - } - } - } - } - return "" -} - -func (rp *RatingPlan) getFirstUnsaneTiming() string { - for _, timing := range rp.Timings { - if (len(timing.Years) != 0 || len(timing.Months) != 0 || len(timing.MonthDays) != 0) && - len(timing.WeekDays) != 0 { - return timing.tag - } - } - return "" -} diff --git a/engine/ratingplan_test.go b/engine/ratingplan_test.go deleted file mode 100644 index 988704175..000000000 --- a/engine/ratingplan_test.go +++ /dev/null @@ -1,453 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package engine - -import ( - "encoding/json" - - "github.com/cgrates/cgrates/utils" - - "reflect" - "testing" - "time" -) - -func TestApRestoreFromStorage(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), - Category: "0", - Tenant: "CUSTOMER_1", - Subject: "rif:from:tm", - Destination: "49"} - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 1 { - t.Errorf("Error restoring activation periods: %+v", cd.RatingInfos[0]) - } -} - -func TestApStoreRestoreJson(t *testing.T) { - i := &RateInterval{Timing: &RITiming{ - Months: []time.Month{time.February}, - MonthDays: []int{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - ap := &RatingPlan{Id: "test"} - ap.AddRateInterval("NAT", i) - result, _ := json.Marshal(ap) - ap1 := &RatingPlan{} - json.Unmarshal(result, ap1) - if !reflect.DeepEqual(ap, ap1) { - t.Errorf("Expected %v was %v", ap, ap1) - } -} - -func TestApStoreRestoreBlank(t *testing.T) { - i := &RateInterval{} - ap := &RatingPlan{Id: "test"} - ap.AddRateInterval("NAT", i) - result, _ := json.Marshal(ap) - ap1 := RatingPlan{} - json.Unmarshal(result, &ap1) - if reflect.DeepEqual(ap, ap1) { - t.Errorf("Expected %v was %v", ap, ap1) - } -} - -func TestFallbackDirect(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), - Category: "0", - Tenant: "CUSTOMER_2", - Subject: "danb:87.139.12.167", - Destination: "41"} - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 1 { - t.Error("Error restoring activation periods: ", len(cd.RatingInfos)) - } -} - -func TestFallbackMultiple(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), - Category: "0", - Tenant: "vdf", - Subject: "fall", - Destination: "0723045"} - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 1 { - t.Errorf("Error restoring rating plans: %+v", cd.RatingInfos) - } -} - -func TestFallbackWithBackTrace(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), - Category: "0", - Tenant: "CUSTOMER_2", - Subject: "danb:87.139.12.167", - Destination: "4123"} - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 1 { - t.Error("Error restoring activation periods: ", len(cd.RatingInfos)) - } -} - -func TestFallbackNoDefault(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), - Category: "0", - Tenant: "vdf", - Subject: "one", - Destination: "0723"} - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 0 { - t.Error("Error restoring activation periods: ", len(cd.RatingInfos)) - } -} - -func TestFallbackNoInfiniteLoop(t *testing.T) { - cd := &CallDescriptor{Category: "0", - Tenant: "vdf", Subject: "rif", Destination: "0721"} - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 0 { - t.Error("Error restoring activation periods: ", len(cd.RatingInfos)) - } -} - -func TestFallbackNoInfiniteLoopSelf(t *testing.T) { - cd := &CallDescriptor{Category: "0", - Tenant: "vdf", Subject: "inf", Destination: "0721"} - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 0 { - t.Error("Error restoring activation periods: ", len(cd.RatingInfos)) - } -} - -func TestApAddIntervalIfNotPresent(t *testing.T) { - i1 := &RateInterval{ - Timing: &RITiming{ - Months: utils.Months{time.February}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - i2 := &RateInterval{Timing: &RITiming{ - Months: utils.Months{time.February}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - i3 := &RateInterval{Timing: &RITiming{ - Months: utils.Months{time.February}, - MonthDays: utils.MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - rp := &RatingPlan{} - rp.AddRateInterval("NAT", i1) - rp.AddRateInterval("NAT", i2) - if len(rp.DestinationRates["NAT"]) != 1 { - t.Error("Wronfullyrppended interval ;)") - } - rp.AddRateInterval("NAT", i3) - if len(rp.DestinationRates["NAT"]) != 2 { - t.Error("Wronfully not appended interval ;)", rp.DestinationRates) - } -} - -func TestApAddRateIntervalGroups(t *testing.T) { - i1 := &RateInterval{ - Rating: &RIRate{Rates: RateGroups{&RGRate{0, 1, time.Second, time.Second}}}, - } - i2 := &RateInterval{ - Rating: &RIRate{Rates: RateGroups{&RGRate{30 * time.Second, 2, time.Second, time.Second}}}, - } - i3 := &RateInterval{ - Rating: &RIRate{Rates: RateGroups{&RGRate{30 * time.Second, 2, time.Second, time.Second}}}, - } - ap := &RatingPlan{} - ap.AddRateInterval("NAT", i1) - ap.AddRateInterval("NAT", i2) - ap.AddRateInterval("NAT", i3) - if len(ap.DestinationRates) != 1 { - t.Error("Wronfully appended interval ;)") - } - if len(ap.RateIntervalList("NAT")[0].Rating.Rates) != 1 { - t.Errorf("Group prices not formed: %#v", ap.RateIntervalList("NAT")[0].Rating.Rates[0]) - } -} - -func TestGetActiveForCall(t *testing.T) { - rpas := RatingPlanActivations{ - &RatingPlanActivation{ActivationTime: time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)}, - &RatingPlanActivation{ActivationTime: time.Date(2013, 11, 12, 11, 40, 0, 0, time.UTC)}, - &RatingPlanActivation{ActivationTime: time.Date(2013, 11, 13, 0, 0, 0, 0, time.UTC)}, - } - cd := &CallDescriptor{ - TimeStart: time.Date(2013, 11, 12, 11, 39, 0, 0, time.UTC), - TimeEnd: time.Date(2013, 11, 12, 11, 45, 0, 0, time.UTC), - } - active := rpas.GetActiveForCall(cd) - if len(active) != 2 { - t.Errorf("Error getting active rating plans: %+v", active) - } -} - -func TestRatingPlanIsContinousEmpty(t *testing.T) { - rpl := &RatingPlan{} - if rpl.isContinous() { - t.Errorf("Error determining rating plan's valididty: %+v", rpl) - } -} - -func TestRatingPlanIsContinousBlank(t *testing.T) { - rpl := &RatingPlan{ - Timings: map[string]*RITiming{ - "blank": {StartTime: "00:00:00"}, - "other": {WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"}, - }, - } - if !rpl.isContinous() { - t.Errorf("Error determining rating plan's valididty: %+v", rpl) - } -} - -func TestRatingPlanIsContinousGood(t *testing.T) { - rpl := &RatingPlan{ - Timings: map[string]*RITiming{ - "first": {WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"}, - "second": {WeekDays: utils.WeekDays{4, 5, 6}, StartTime: "00:00:00"}, - "third": {WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"}, - }, - } - if !rpl.isContinous() { - t.Errorf("Error determining rating plan's valididty: %+v", rpl) - } -} - -func TestRatingPlanisContinousBad(t *testing.T) { - rpl := &RatingPlan{ - Timings: map[string]*RITiming{ - "first": {WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"}, - "second": {WeekDays: utils.WeekDays{4, 5, 0}, StartTime: "00:00:00"}, - }, - } - if rpl.isContinous() { - t.Errorf("Error determining rating plan's valididty: %+v", rpl) - } -} - -func TestRatingPlanIsContinousSpecial(t *testing.T) { - rpl := &RatingPlan{ - Timings: map[string]*RITiming{ - "special": {Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"}, - "first": {WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"}, - "second": {WeekDays: utils.WeekDays{4, 5, 6}, StartTime: "00:00:00"}, - "third": {WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"}, - }, - } - if !rpl.isContinous() { - t.Errorf("Error determining rating plan's valididty: %+v", rpl) - } -} - -func TestRatingPlanIsContinousMultiple(t *testing.T) { - rpl := &RatingPlan{ - Timings: map[string]*RITiming{ - "special": {Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"}, - "first": {WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"}, - "first_08": {WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "08:00:00"}, - "second": {WeekDays: utils.WeekDays{4, 5, 6}, StartTime: "00:00:00"}, - "third": {WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"}, - }, - } - if !rpl.isContinous() { - t.Errorf("Error determining rating plan's valididty: %+v", rpl) - } -} - -func TestRatingPlanIsContinousMissing(t *testing.T) { - rpl := &RatingPlan{ - Timings: map[string]*RITiming{ - "special": {Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"}, - "first_08": {WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "08:00:00"}, - "second": {WeekDays: utils.WeekDays{4, 5, 6}, StartTime: "00:00:00"}, - "third": {WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"}, - }, - } - if rpl.isContinous() { - t.Errorf("Error determining rating plan's valididty: %+v", rpl) - } -} - -func TestRatingPlanSaneTimingsBad(t *testing.T) { - rpl := &RatingPlan{ - Timings: map[string]*RITiming{ - "one": {Years: utils.Years{2015}, WeekDays: utils.WeekDays{time.Monday}, tag: "first"}, - }, - } - if crazyTiming := rpl.getFirstUnsaneTiming(); crazyTiming == "" { - t.Errorf("Error detecting bad timings in rating profile: %+v", rpl) - } -} - -func TestRatingPlanSaneTimingsGood(t *testing.T) { - rpl := &RatingPlan{ - Timings: map[string]*RITiming{ - "one": {Years: utils.Years{2015}, tag: "first"}, - "two": {WeekDays: utils.WeekDays{0, 1, 2, 3, 4}, StartTime: "00:00:00", tag: "second"}, - }, - } - if crazyTiming := rpl.getFirstUnsaneTiming(); crazyTiming != "" { - t.Errorf("Error detecting bad timings in rating profile: %+v", rpl) - } -} - -func TestRatingPlanSaneRatingsEqual(t *testing.T) { - rpl := &RatingPlan{ - Ratings: map[string]*RIRate{ - "one": { - tag: "first", - Rates: RateGroups{ - &RGRate{ - GroupIntervalStart: 0, - RateIncrement: 30 * time.Second, - }, - &RGRate{ - GroupIntervalStart: 0, - RateIncrement: 30 * time.Second, - }, - }, - }, - }, - } - if crazyRating := rpl.getFirstUnsaneRating(); crazyRating == "" { - t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl) - } -} - -func TestRatingPlanSaneRatingsNotMultiple(t *testing.T) { - rpl := &RatingPlan{ - Ratings: map[string]*RIRate{ - "one": { - tag: "first", - Rates: RateGroups{ - &RGRate{ - GroupIntervalStart: 0, - RateIncrement: 30 * time.Second, - }, - &RGRate{ - GroupIntervalStart: 15 * time.Second, - RateIncrement: 30 * time.Second, - }, - }, - }, - }, - } - if crazyRating := rpl.getFirstUnsaneRating(); crazyRating == "" { - t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl) - } -} - -func TestRatingPlanSaneRatingsGoot(t *testing.T) { - rpl := &RatingPlan{ - Ratings: map[string]*RIRate{ - "one": { - tag: "first", - Rates: RateGroups{ - &RGRate{ - GroupIntervalStart: 60 * time.Second, - RateIncrement: 30 * time.Second, - RateUnit: time.Second, - }, - &RGRate{ - GroupIntervalStart: 0, - RateIncrement: 30 * time.Second, - RateUnit: time.Second, - }, - }, - }, - }, - } - if crazyRating := rpl.getFirstUnsaneRating(); crazyRating != "" { - t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl) - } -} - -/**************************** Benchmarks *************************************/ - -func BenchmarkRatingPlanMarshalJson(b *testing.B) { - b.StopTimer() - i := &RateInterval{ - Timing: &RITiming{ - Months: []time.Month{time.February}, - MonthDays: []int{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - ap := &RatingPlan{Id: "test"} - ap.AddRateInterval("NAT", i) - - ap1 := RatingPlan{} - b.StartTimer() - for i := 0; i < b.N; i++ { - result, _ := json.Marshal(ap) - json.Unmarshal(result, &ap1) - } -} - -func BenchmarkRatingPlanMarshal(b *testing.B) { - b.StopTimer() - i := &RateInterval{ - Timing: &RITiming{Months: []time.Month{time.February}, - MonthDays: []int{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - ap := &RatingPlan{Id: "test"} - ap.AddRateInterval("NAT", i) - - ap1 := &RatingPlan{} - b.StartTimer() - for i := 0; i < b.N; i++ { - result, _ := marsh.Marshal(ap) - marsh.Unmarshal(result, ap1) - } -} - -func BenchmarkRatingPlanRestore(b *testing.B) { - i := &RateInterval{ - Timing: &RITiming{Months: []time.Month{time.February}, - MonthDays: []int{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"}} - rp := &RatingPlan{Id: "test"} - rp.AddRateInterval("NAT", i) - dm.SetRatingPlan(rp, utils.NonTransactional) - b.ResetTimer() - for i := 0; i < b.N; i++ { - dm.GetRatingPlan(rp.Id, true, utils.NonTransactional) - } -} diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go index 155483099..2649759c0 100644 --- a/engine/ratingprofile.go +++ b/engine/ratingprofile.go @@ -20,71 +20,10 @@ package engine import ( "encoding/json" - "fmt" "sort" - "strings" "time" - - "github.com/cgrates/cgrates/utils" ) -type RatingProfile struct { - Id string - RatingPlanActivations RatingPlanActivations -} - -// RatingProfileWithAPIOpts is used in replicatorV1 for dispatcher -type RatingProfileWithAPIOpts struct { - *RatingProfile - Tenant string - APIOpts map[string]interface{} -} - -type RatingPlanActivation struct { - ActivationTime time.Time - RatingPlanId string - FallbackKeys []string -} - -func (rpa *RatingPlanActivation) Equal(orpa *RatingPlanActivation) bool { - return rpa.ActivationTime == orpa.ActivationTime && - rpa.RatingPlanId == orpa.RatingPlanId -} - -type RatingPlanActivations []*RatingPlanActivation - -func (rpas RatingPlanActivations) Len() int { - return len(rpas) -} - -func (rpas RatingPlanActivations) Swap(i, j int) { - rpas[i], rpas[j] = rpas[j], rpas[i] -} - -func (rpas RatingPlanActivations) Less(i, j int) bool { - return rpas[i].ActivationTime.Before(rpas[j].ActivationTime) -} - -func (rpas RatingPlanActivations) Sort() { - sort.Sort(rpas) -} - -func (rpas RatingPlanActivations) GetActiveForCall(cd *CallDescriptor) RatingPlanActivations { - rpas.Sort() - lastBeforeCallStart := 0 - firstAfterCallEnd := len(rpas) - for index, rpa := range rpas { - if rpa.ActivationTime.Before(cd.TimeStart) || rpa.ActivationTime.Equal(cd.TimeStart) { - lastBeforeCallStart = index - } - if rpa.ActivationTime.After(cd.TimeEnd) { - firstAfterCallEnd = index - break - } - } - return rpas[lastBeforeCallStart:firstAfterCallEnd] -} - type RatingInfo struct { MatchedSubject string RatingPlanId string @@ -157,124 +96,3 @@ func (ris RatingInfos) String() string { b, _ := json.MarshalIndent(ris, "", " ") return string(b) } - -func (rpf *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error) { - var ris RatingInfos - for index, rpa := range rpf.RatingPlanActivations.GetActiveForCall(cd) { - rpl, err := dm.GetRatingPlan(rpa.RatingPlanId, false, utils.NonTransactional) - if err != nil || rpl == nil { - utils.Logger.Err(fmt.Sprintf("Error checking destination: %v", err)) - continue - } - prefix := "" - destinationID := "" - var rps RateIntervalList - if cd.Destination == utils.MetaAny || cd.Destination == "" { - cd.Destination = utils.MetaAny - if _, ok := rpl.DestinationRates[utils.MetaAny]; ok { - rps = rpl.RateIntervalList(utils.MetaAny) - prefix = utils.MetaAny - destinationID = utils.MetaAny - } - } else { - for _, p := range utils.SplitPrefix(cd.Destination, MIN_PREFIX_MATCH) { - if destIDs, err := dm.GetReverseDestination(p, true, true, utils.NonTransactional); err == nil { - var bestWeight *float64 - for _, dID := range destIDs { - var timeChecker bool - if _, ok := rpl.DestinationRates[dID]; ok { - ril := rpl.RateIntervalList(dID) - //check if RateInverval is active for call descriptor time - for _, ri := range ril { - if !ri.Timing.IsActiveAt(cd.TimeStart) { - continue - } else { - timeChecker = true - break - } - } - currentWeight := ril.GetWeight() - if timeChecker && (bestWeight == nil || currentWeight > *bestWeight) { - bestWeight = utils.Float64Pointer(currentWeight) - rps = ril - prefix = p - destinationID = dID - } - } - } - } - if rps != nil { - break - } - } - if rps == nil { // fallback on *any destination - if _, ok := rpl.DestinationRates[utils.MetaAny]; ok { - rps = rpl.RateIntervalList(utils.MetaAny) - prefix = utils.MetaAny - destinationID = utils.MetaAny - } - } - } - // check if it's the first ri and add a blank one for the initial part not covered - if index == 0 && cd.TimeStart.Before(rpa.ActivationTime) { - ris = append(ris, &RatingInfo{ - MatchedSubject: "", - MatchedPrefix: "", - MatchedDestId: "", - ActivationTime: cd.TimeStart, - RateIntervals: nil, - FallbackKeys: []string{cd.GetKey(FALLBACK_SUBJECT)}}) - } - if len(prefix) > 0 { - ris = append(ris, &RatingInfo{ - MatchedSubject: rpf.Id, - RatingPlanId: rpl.Id, - MatchedPrefix: prefix, - MatchedDestId: destinationID, - ActivationTime: rpa.ActivationTime, - RateIntervals: rps, - FallbackKeys: rpa.FallbackKeys}) - } else { - // add for fallback information - if len(rpa.FallbackKeys) > 0 { - ris = append(ris, &RatingInfo{ - MatchedSubject: "", - MatchedPrefix: "", - MatchedDestId: "", - ActivationTime: rpa.ActivationTime, - RateIntervals: nil, - FallbackKeys: rpa.FallbackKeys, - }) - } - } - } - if len(ris) > 0 { - cd.addRatingInfos(ris) - return - } - return utils.ErrNotFound -} - -type TenantRatingSubject struct { - Tenant, Subject string -} - -func RatingProfileSubjectPrefixMatching(key string) (rp *RatingProfile, err error) { - if !getRpSubjectPrefixMatching() || strings.HasSuffix(key, utils.MetaAny) { - return dm.GetRatingProfile(key, false, utils.NonTransactional) - } - if rp, err = dm.GetRatingProfile(key, false, utils.NonTransactional); err == nil && rp != nil { // rp nil represents cached no-result - return - } - lastIndex := strings.LastIndex(key, utils.ConcatenatedKeySep) - baseKey := key[:lastIndex] - subject := key[lastIndex:] - lenSubject := len(subject) - for i := 1; i < lenSubject-1; i++ { - if rp, err = dm.GetRatingProfile(baseKey+subject[:lenSubject-i], - false, utils.NonTransactional); err == nil && rp != nil { - return - } - } - return -} diff --git a/engine/ratingprofile_test.go b/engine/ratingprofile_test.go deleted file mode 100644 index 0df479a81..000000000 --- a/engine/ratingprofile_test.go +++ /dev/null @@ -1,397 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package engine - -import ( - "testing" - "time" - - "github.com/cgrates/cgrates/utils" -) - -func TestGetRatingProfileForPrefix(t *testing.T) { - cd := &CallDescriptor{ - TimeStart: time.Date(2013, 11, 18, 13, 45, 1, 0, time.UTC), - TimeEnd: time.Date(2013, 11, 18, 13, 47, 30, 0, time.UTC), - Tenant: "vdf", - Category: "0", - Subject: "fallback1", - Destination: "0256098", - } - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 3 || !cd.continousRatingInfos() { - t.Logf("0: %+v", cd.RatingInfos[0]) - t.Logf("1: %+v", cd.RatingInfos[1]) - t.Logf("2: %+v", cd.RatingInfos[2]) - t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos()) - } -} - -func TestGetRatingProfileForPrefixFirstEmpty(t *testing.T) { - cd := &CallDescriptor{ - TimeStart: time.Date(2013, 11, 18, 13, 44, 1, 0, time.UTC), - TimeEnd: time.Date(2013, 11, 18, 13, 47, 30, 0, time.UTC), - Tenant: "vdf", - Category: "0", - Subject: "fallback1", - Destination: "0256098", - } - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 4 || !cd.continousRatingInfos() { - t.Logf("0: %+v", cd.RatingInfos[0]) - t.Logf("1: %+v", cd.RatingInfos[1]) - t.Logf("2: %+v", cd.RatingInfos[2]) - t.Logf("3: %+v", cd.RatingInfos[3]) - t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos()) - } -} - -func TestGetRatingProfileNotFound(t *testing.T) { - cd := &CallDescriptor{ - TimeStart: time.Date(2015, 8, 18, 22, 05, 0, 0, time.UTC), - TimeEnd: time.Date(2015, 8, 18, 22, 06, 30, 0, time.UTC), - Tenant: "vdf", - Category: "0", - Subject: "no_rating_profile", - Destination: "0256098", - } - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 1 || !cd.continousRatingInfos() { - t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos()) - } -} - -func TestGetRatingProfileFoundButNoDestination(t *testing.T) { - cd := &CallDescriptor{ - TimeStart: time.Date(2015, 8, 18, 22, 05, 0, 0, time.UTC), - TimeEnd: time.Date(2015, 8, 18, 22, 06, 30, 0, time.UTC), - Tenant: "cgrates.org", - Category: "call", - Subject: "nt", - Destination: "447956", - } - cd.LoadRatingPlans() - if len(cd.RatingInfos) != 0 { - t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos()) - } -} - -func TestRatingProfileRISorter(t *testing.T) { - ris := RateIntervalList{ - &RateInterval{ - Timing: &RITiming{ - StartTime: "09:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "00:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "19:00:00", - }, - }, - } - sorter := &RateIntervalTimeSorter{referenceTime: time.Date(2016, 1, 6, 19, 0, 0, 0, time.UTC), ris: ris} - rIntervals := sorter.Sort() - if len(rIntervals) != 3 || - rIntervals[0].Timing.StartTime != "00:00:00" || - rIntervals[1].Timing.StartTime != "09:00:00" || - rIntervals[2].Timing.StartTime != "19:00:00" { - t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) - } -} - -func TestRatingProfileRIforTSOne(t *testing.T) { - ri := &RatingInfo{ - RateIntervals: RateIntervalList{ - &RateInterval{ - Timing: &RITiming{ - StartTime: "09:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "00:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "19:00:00", - }, - }, - }, - } - ts := &TimeSpan{ - TimeStart: time.Date(2016, 1, 6, 19, 0, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 6, 19, 1, 30, 0, time.UTC), - } - rIntervals := ri.SelectRatingIntevalsForTimespan(ts) - if len(rIntervals) != 1 || rIntervals[0].Timing.StartTime != "19:00:00" { - t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) - } -} - -func TestRatingProfileRIforTSTwo(t *testing.T) { - ri := &RatingInfo{ - RateIntervals: RateIntervalList{ - &RateInterval{ - Timing: &RITiming{ - StartTime: "09:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "00:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "19:00:00", - }, - }, - }, - } - ts := &TimeSpan{ - TimeStart: time.Date(2016, 1, 6, 10, 0, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 6, 19, 1, 30, 0, time.UTC), - } - rIntervals := ri.SelectRatingIntevalsForTimespan(ts) - if len(rIntervals) != 2 || - rIntervals[0].Timing.StartTime != "09:00:00" || - rIntervals[1].Timing.StartTime != "19:00:00" { - t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) - } -} - -func TestRatingProfileRIforTSThree(t *testing.T) { - ri := &RatingInfo{ - RateIntervals: RateIntervalList{ - &RateInterval{ - Timing: &RITiming{ - StartTime: "09:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "00:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "19:00:00", - }, - }, - }, - } - ts := &TimeSpan{ - TimeStart: time.Date(2016, 1, 6, 8, 0, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 6, 19, 1, 30, 0, time.UTC), - } - rIntervals := ri.SelectRatingIntevalsForTimespan(ts) - if len(rIntervals) != 3 || - rIntervals[0].Timing.StartTime != "00:00:00" || - rIntervals[1].Timing.StartTime != "09:00:00" || - rIntervals[2].Timing.StartTime != "19:00:00" { - t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) - } -} - -func TestRatingProfileRIforTSMidnight(t *testing.T) { - ri := &RatingInfo{ - RateIntervals: RateIntervalList{ - &RateInterval{ - Timing: &RITiming{ - StartTime: "09:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "00:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "19:00:00", - }, - }, - }, - } - ts := &TimeSpan{ - TimeStart: time.Date(2016, 1, 6, 23, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 7, 1, 1, 30, 0, time.UTC), - } - rIntervals := ri.SelectRatingIntevalsForTimespan(ts) - if len(rIntervals) != 1 || - rIntervals[0].Timing.StartTime != "19:00:00" { - t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) - } -} - -func TestRatingProfileYearMonthDay(t *testing.T) { - ri := &RatingInfo{ - RateIntervals: RateIntervalList{ - &RateInterval{ - Timing: &RITiming{ - StartTime: "09:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "00:00:00", - }, - }, - &RateInterval{ - Timing: &RITiming{ - Years: utils.Years{2016}, - Months: utils.Months{1}, - MonthDays: utils.MonthDays{6, 7}, - WeekDays: utils.WeekDays{}, - StartTime: "19:00:00", - }, - }, - }, - } - ts := &TimeSpan{ - TimeStart: time.Date(2016, 1, 6, 23, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 7, 1, 1, 30, 0, time.UTC), - } - rIntervals := ri.SelectRatingIntevalsForTimespan(ts) - if len(rIntervals) != 1 || - rIntervals[0].Timing.StartTime != "19:00:00" { - t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) - } -} - -func TestRatingProfileWeighted(t *testing.T) { - ri := &RatingInfo{ - RateIntervals: RateIntervalList{ - &RateInterval{ - Timing: &RITiming{ - StartTime: "09:00:00", - }, - Weight: 10, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "00:00:00", - }, - Weight: 10, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "19:00:00", - }, - Weight: 10, - }, - &RateInterval{ - Timing: &RITiming{ - Years: utils.Years{2016}, - Months: utils.Months{1}, - MonthDays: utils.MonthDays{6}, - WeekDays: utils.WeekDays{}, - StartTime: "00:00:00", - }, - Weight: 11, - }, - }, - } - ts := &TimeSpan{ - TimeStart: time.Date(2016, 1, 6, 23, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 6, 23, 45, 30, 0, time.UTC), - } - rIntervals := ri.SelectRatingIntevalsForTimespan(ts) - if len(rIntervals) != 1 || - rIntervals[0].Timing.StartTime != "00:00:00" || - rIntervals[0].Weight != 11 { - t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) - } -} - -func TestRatingProfileWeightedMultiple(t *testing.T) { - ri := &RatingInfo{ - RateIntervals: RateIntervalList{ - &RateInterval{ - Timing: &RITiming{ - StartTime: "09:00:00", - }, - Weight: 10, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "00:00:00", - }, - Weight: 10, - }, - &RateInterval{ - Timing: &RITiming{ - StartTime: "19:00:00", - }, - Weight: 10, - }, - &RateInterval{ - Timing: &RITiming{ - Years: utils.Years{2016}, - Months: utils.Months{1}, - MonthDays: utils.MonthDays{6}, - WeekDays: utils.WeekDays{}, - StartTime: "00:00:00", - }, - Weight: 11, - }, - &RateInterval{ - Timing: &RITiming{ - Years: utils.Years{2016}, - Months: utils.Months{1}, - MonthDays: utils.MonthDays{6}, - WeekDays: utils.WeekDays{}, - StartTime: "18:00:00", - }, - Weight: 11, - }, - }, - } - ts := &TimeSpan{ - TimeStart: time.Date(2016, 1, 6, 17, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 6, 23, 45, 30, 0, time.UTC), - } - rIntervals := ri.SelectRatingIntevalsForTimespan(ts) - if len(rIntervals) != 2 || - rIntervals[0].Timing.StartTime != "00:00:00" || - rIntervals[0].Weight != 11 || - rIntervals[1].Timing.StartTime != "18:00:00" || - rIntervals[1].Weight != 11 { - t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals)) - } -} - -func TestRatingProfileSubjectPrefixMatching(t *testing.T) { - rpSubjectPrefixMatching = true - rp, err := RatingProfileSubjectPrefixMatching("*out:cgrates.org:data:rif") - if rp == nil || err != nil { - t.Errorf("Error getting rating profile by prefix: %+v (%v)", rp, err) - } - - rp, err = RatingProfileSubjectPrefixMatching("*out:cgrates.org:data:rifescu") - if rp == nil || err != nil { - t.Errorf("Error getting rating profile by prefix: %+v (%v)", rp, err) - } - rpSubjectPrefixMatching = false -} diff --git a/engine/routes.go b/engine/routes.go index dc8f3fb9c..4f00a3576 100644 --- a/engine/routes.go +++ b/engine/routes.go @@ -526,6 +526,7 @@ func (attr *ArgsGetRoutes) asOptsGetRoutes() (opts *optsGetRoutes, err error) { utils.Destination, utils.SetupTime, utils.Usage}); err != nil { return } + // rates.V1CostForEvent cd, err := NewCallDescriptorFromCGREvent(attr.CGREvent, config.CgrConfig().GeneralCfg().DefaultTimezone) if err != nil { diff --git a/engine/sharedgroup.go b/engine/sharedgroup.go deleted file mode 100644 index ae4f565d5..000000000 --- a/engine/sharedgroup.go +++ /dev/null @@ -1,196 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package engine - -import ( - "math/rand" - "sort" - "strings" - "time" - - "github.com/cgrates/cgrates/utils" -) - -const ( - MINE_PREFIX = "*mine_" - STRATEGY_MINE_LOWEST = "*mine_lowest" - STRATEGY_MINE_HIGHEST = "*mine_highest" - STRATEGY_MINE_RANDOM = "*mine_random" - STRATEGY_LOWEST = "*lowest" - STRATEGY_HIGHEST = "*highest" - STRATEGY_RANDOM = "*random" -) - -type SharedGroup struct { - Id string - AccountParameters map[string]*SharingParameters - MemberIds utils.StringMap - //members []*Account // accounts caching -} - -// SharedGroupWithOpts is used in replicatorV1 for dispatcher -type SharedGroupWithAPIOpts struct { - *SharedGroup - Tenant string - APIOpts map[string]interface{} -} - -type SharingParameters struct { - Strategy string - RatingSubject string -} - -// Clone clones *SharedGroup -func (sg *SharedGroup) Clone() (sharedGroup *SharedGroup) { - if sg == nil { - return - } - sharedGroup = &SharedGroup{ - Id: sg.Id, - } - if sg.AccountParameters != nil { - sharedGroup.AccountParameters = make(map[string]*SharingParameters, len(sg.AccountParameters)) - } - if sg.MemberIds != nil { - sharedGroup.MemberIds = sg.MemberIds.Clone() - } - for id := range sg.AccountParameters { - sharedGroup.AccountParameters[id] = sg.AccountParameters[id].Clone() - } - return -} - -//Clone clones *SharingParameters -func (sp *SharingParameters) Clone() *SharingParameters { - if sp == nil { - return nil - } - return &SharingParameters{ - Strategy: sp.Strategy, - RatingSubject: sp.RatingSubject, - } -} - -func (sg *SharedGroup) SortBalancesByStrategy(myBalance *Balance, bc Balances) Balances { - sharingParameters := sg.AccountParameters[utils.MetaAny] - if sp, hasParamsForAccount := sg.AccountParameters[myBalance.account.ID]; hasParamsForAccount { - sharingParameters = sp - } - - strategy := STRATEGY_MINE_RANDOM - if sharingParameters != nil && sharingParameters.Strategy != "" { - strategy = sharingParameters.Strategy - } - switch strategy { - case STRATEGY_LOWEST, STRATEGY_MINE_LOWEST: - sort.Sort(LowestBalancesSorter(bc)) - case STRATEGY_HIGHEST, STRATEGY_MINE_HIGHEST: - sort.Sort(HighestBalancesSorter(bc)) - case STRATEGY_RANDOM, STRATEGY_MINE_RANDOM: - rbc := RandomBalancesSorter(bc) - (&rbc).Sort() - bc = Balances(rbc) - default: // use mine random for anything else - strategy = STRATEGY_MINE_RANDOM - rbc := RandomBalancesSorter(bc) - (&rbc).Sort() - bc = Balances(rbc) - } - if strings.HasPrefix(strategy, MINE_PREFIX) { - // find index of my balance - index := 0 - for i, b := range bc { - if b.Uuid == myBalance.Uuid { - index = i - break - } - } - // move my balance first - bc[0], bc[index] = bc[index], bc[0] - } - return bc -} - -// Returns all shared group's balances collected from user accounts' -func (sg *SharedGroup) GetBalances(destination, category, balanceType string, ub *Account, aTime time.Time) (bc Balances) { - // if len(sg.members) == 0 { - for ubId := range sg.MemberIds { - var nUb *Account - if ubId == ub.ID { // skip the initiating user - nUb = ub - } else { - nUb, _ = dm.GetAccount(ubId) - if nUb == nil || nUb.Disabled { - continue - } - } - //sg.members = append(sg.members, nUb) - sb := nUb.getBalancesForPrefix(destination, category, balanceType, sg.Id, aTime) - bc = append(bc, sb...) - } - /* } else { - for _, m := range sg.members { - sb := m.getBalancesForPrefix(destination, m.BalanceMap[balanceType], sg.Id) - bc = append(bc, sb...) - } - }*/ - return -} - -type LowestBalancesSorter []*Balance - -func (lbcs LowestBalancesSorter) Len() int { - return len(lbcs) -} - -func (lbcs LowestBalancesSorter) Swap(i, j int) { - lbcs[i], lbcs[j] = lbcs[j], lbcs[i] -} - -func (lbcs LowestBalancesSorter) Less(i, j int) bool { - return lbcs[i].GetValue() < lbcs[j].GetValue() -} - -type HighestBalancesSorter []*Balance - -func (hbcs HighestBalancesSorter) Len() int { - return len(hbcs) -} - -func (hbcs HighestBalancesSorter) Swap(i, j int) { - hbcs[i], hbcs[j] = hbcs[j], hbcs[i] -} - -func (hbcs HighestBalancesSorter) Less(i, j int) bool { - return hbcs[i].GetValue() > hbcs[j].GetValue() -} - -type RandomBalancesSorter []*Balance - -func (rbcs *RandomBalancesSorter) Sort() { - src := *rbcs - // randomize balance chain - dest := make([]*Balance, len(src)) - rand.Seed(time.Now().UnixNano()) - perm := rand.Perm(len(src)) - for i, v := range perm { - dest[v] = src[i] - } - *rbcs = dest -} diff --git a/engine/sharedgroup_test.go b/engine/sharedgroup_test.go deleted file mode 100644 index d939c4184..000000000 --- a/engine/sharedgroup_test.go +++ /dev/null @@ -1,208 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package engine - -import ( - "reflect" - "testing" - - "github.com/cgrates/cgrates/utils" -) - -func TestSharedGroupClone(t *testing.T) { - //nil check - var sharedGroup *SharedGroup - if rcv := sharedGroup.Clone(); rcv != nil { - t.Errorf("Expecting: nil, received: %+v", utils.ToJSON(rcv)) - } - //empty check - sharedGroup = &SharedGroup{} - eOut := &SharedGroup{} - if rcv := sharedGroup.Clone(); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - //normal check - sharedGroup = &SharedGroup{ - Id: "testID", - AccountParameters: map[string]*SharingParameters{ - "string1": { - Strategy: "strategyTEST1", - RatingSubject: "RatingSubjectTEST1", - }, - "string2": { - Strategy: "strategyTEST2", - RatingSubject: "RatingSubjectTEST2", - }, - }, - MemberIds: utils.StringMap{ - "string1": true, - "string2": false, - }, - } - eOut = &SharedGroup{ - Id: "testID", - AccountParameters: map[string]*SharingParameters{ - "string1": { - Strategy: "strategyTEST1", - RatingSubject: "RatingSubjectTEST1", - }, - "string2": { - Strategy: "strategyTEST2", - RatingSubject: "RatingSubjectTEST2", - }, - }, - MemberIds: utils.StringMap{ - "string1": true, - "string2": false, - }, - } - rcv := sharedGroup.Clone() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - //double check - rcv.AccountParameters["string1"].Strategy = "updated" - if sharedGroup.AccountParameters["string1"].Strategy == "updated" { - t.Errorf("Original SharedGroup was modified") - } - -} - -func TestSharingParametersClone(t *testing.T) { - //nil check - var sharingParameters *SharingParameters - if rcv := sharingParameters.Clone(); rcv != nil { - t.Errorf("Expecting:nil, received: %+v", utils.ToJSON(rcv)) - } - //empty check - sharingParameters = &SharingParameters{} - eOut := &SharingParameters{} - if rcv := sharingParameters.Clone(); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } - //normal check - sharingParameters = &SharingParameters{ - Strategy: "StrategyTEST", - RatingSubject: "RatingSubjectTEST", - } - eOut = &SharingParameters{ - Strategy: "StrategyTEST", - RatingSubject: "RatingSubjectTEST", - } - if rcv := sharingParameters.Clone(); !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eOut), utils.ToJSON(rcv)) - } -} - -func TestSharedSetGet(t *testing.T) { - id := "TEST_SG100" - sg := &SharedGroup{ - Id: id, - AccountParameters: map[string]*SharingParameters{ - "test": {Strategy: STRATEGY_HIGHEST}, - }, - MemberIds: utils.NewStringMap("1", "2", "3"), - } - err := dm.SetSharedGroup(sg, utils.NonTransactional) - if err != nil { - t.Error("Error storing Shared groudp: ", err) - } - received, err := dm.GetSharedGroup(id, true, utils.NonTransactional) - if err != nil || received == nil || !reflect.DeepEqual(sg, received) { - t.Error("Error getting shared group: ", err, received) - } - received, err = dm.GetSharedGroup(id, false, utils.NonTransactional) - if err != nil || received == nil || !reflect.DeepEqual(sg, received) { - t.Error("Error getting cached shared group: ", err, received) - } - -} - -func TestSharedPopBalanceByStrategyLow(t *testing.T) { - bc := Balances{ - &Balance{Value: 2.0}, - &Balance{Uuid: "uuuu", Value: 1.0, account: &Account{ID: "test"}}, - &Balance{Value: 3.0}, - } - sg := &SharedGroup{AccountParameters: map[string]*SharingParameters{ - "test": {Strategy: STRATEGY_LOWEST}}, - } - sbc := sg.SortBalancesByStrategy(bc[1], bc) - if len(sbc) != 3 || - sbc[0].Value != 1.0 || - sbc[1].Value != 2.0 { - t.Error("Error sorting balance chain: ", sbc[0].GetValue()) - } -} - -func TestSharedPopBalanceByStrategyHigh(t *testing.T) { - bc := Balances{ - &Balance{Uuid: "uuuu", Value: 2.0, account: &Account{ID: "test"}}, - &Balance{Value: 1.0}, - &Balance{Value: 3.0}, - } - sg := &SharedGroup{AccountParameters: map[string]*SharingParameters{ - "test": {Strategy: STRATEGY_HIGHEST}}, - } - sbc := sg.SortBalancesByStrategy(bc[0], bc) - if len(sbc) != 3 || - sbc[0].Value != 3.0 || - sbc[1].Value != 2.0 { - t.Error("Error sorting balance chain: ", sbc) - } -} - -func TestSharedPopBalanceByStrategyMineHigh(t *testing.T) { - bc := Balances{ - &Balance{Uuid: "uuuu", Value: 2.0, account: &Account{ID: "test"}}, - &Balance{Value: 1.0}, - &Balance{Value: 3.0}, - } - sg := &SharedGroup{AccountParameters: map[string]*SharingParameters{ - "test": {Strategy: STRATEGY_MINE_HIGHEST}}, - } - sbc := sg.SortBalancesByStrategy(bc[0], bc) - if len(sbc) != 3 || - sbc[0].Value != 2.0 || - sbc[1].Value != 3.0 { - t.Error("Error sorting balance chain: ", sbc) - } -} - -/*func TestSharedPopBalanceByStrategyRandomHigh(t *testing.T) { - bc := Balances{ - &Balance{Uuid: "uuuu", Value: 2.0, account: &Account{Id: "test"}}, - &Balance{Value: 1.0}, - &Balance{Value: 3.0}, - } - sg := &SharedGroup{AccountParameters: map[string]*SharingParameters{ - "test": &SharingParameters{Strategy: STRATEGY_RANDOM}}, - } - x := bc[0] - sbc := sg.SortBalancesByStrategy(bc[0], bc) - firstTest := (sbc[0].Uuid == x.Uuid) - sbc = sg.SortBalancesByStrategy(bc[0], bc) - secondTest := (sbc[0].Uuid == x.Uuid) - sbc = sg.SortBalancesByStrategy(bc[0], bc) - thirdTest := (sbc[0].Uuid == x.Uuid) - sbc = sg.SortBalancesByStrategy(bc[0], bc) - fourthTest := (sbc[0].Uuid == x.Uuid) - if firstTest && secondTest && thirdTest && fourthTest { - t.Error("Something is wrong with balance randomizer") - } -}*/ diff --git a/engine/storage_csv.go b/engine/storage_csv.go index 021e5089c..a3c198f31 100644 --- a/engine/storage_csv.go +++ b/engine/storage_csv.go @@ -44,65 +44,47 @@ type CSVStorage struct { sep rune generator func() csvReaderCloser // file names - destinationsFn []string - ratesFn []string - destinationratesFn []string - timingsFn []string - destinationratetimingsFn []string - ratingprofilesFn []string - sharedgroupsFn []string - actionsFn []string - actiontimingsFn []string - actiontriggersFn []string - accountactionsFn []string - resProfilesFn []string - statsFn []string - thresholdsFn []string - filterFn []string - routeProfilesFn []string - attributeProfilesFn []string - chargerProfilesFn []string - dispatcherProfilesFn []string - dispatcherHostsFn []string - rateProfilesFn []string - actionProfilesFn []string - accountProfilesFn []string + destinationsFn []string + timingsFn []string + actionsFn []string + resProfilesFn []string + statsFn []string + thresholdsFn []string + filterFn []string + routeProfilesFn []string + attributeProfilesFn []string + chargerProfilesFn []string + dispatcherProfilesFn []string + dispatcherHostsFn []string + rateProfilesFn []string + actionProfilesFn []string + accountProfilesFn []string } // NewCSVStorage creates a CSV storege that takes the data from the paths specified func NewCSVStorage(sep rune, - destinationsFn, timingsFn, ratesFn, destinationratesFn, - destinationratetimingsFn, ratingprofilesFn, sharedgroupsFn, - actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, + destinationsFn, timingsFn, actionsFn, resProfilesFn, statsFn, thresholdsFn, filterFn, routeProfilesFn, attributeProfilesFn, chargerProfilesFn, dispatcherProfilesFn, dispatcherHostsFn, rateProfilesFn, actionProfilesFn, accountProfilesFn []string) *CSVStorage { return &CSVStorage{ - sep: sep, - generator: NewCsvFile, - destinationsFn: destinationsFn, - timingsFn: timingsFn, - ratesFn: ratesFn, - destinationratesFn: destinationratesFn, - destinationratetimingsFn: destinationratetimingsFn, - ratingprofilesFn: ratingprofilesFn, - sharedgroupsFn: sharedgroupsFn, - actionsFn: actionsFn, - actiontimingsFn: actiontimingsFn, - actiontriggersFn: actiontriggersFn, - accountactionsFn: accountactionsFn, - resProfilesFn: resProfilesFn, - statsFn: statsFn, - thresholdsFn: thresholdsFn, - filterFn: filterFn, - routeProfilesFn: routeProfilesFn, - attributeProfilesFn: attributeProfilesFn, - chargerProfilesFn: chargerProfilesFn, - dispatcherProfilesFn: dispatcherProfilesFn, - dispatcherHostsFn: dispatcherHostsFn, - rateProfilesFn: rateProfilesFn, - actionProfilesFn: actionProfilesFn, - accountProfilesFn: accountProfilesFn, + sep: sep, + generator: NewCsvFile, + destinationsFn: destinationsFn, + timingsFn: timingsFn, + actionsFn: actionsFn, + resProfilesFn: resProfilesFn, + statsFn: statsFn, + thresholdsFn: thresholdsFn, + filterFn: filterFn, + routeProfilesFn: routeProfilesFn, + attributeProfilesFn: attributeProfilesFn, + chargerProfilesFn: chargerProfilesFn, + dispatcherProfilesFn: dispatcherProfilesFn, + dispatcherHostsFn: dispatcherHostsFn, + rateProfilesFn: rateProfilesFn, + actionProfilesFn: actionProfilesFn, + accountProfilesFn: accountProfilesFn, } } @@ -114,15 +96,7 @@ func NewFileCSVStorage(sep rune, dataPath string) *CSVStorage { } destinationsPaths := appendName(allFoldersPath, utils.DestinationsCsv) timingsPaths := appendName(allFoldersPath, utils.TimingsCsv) - ratesPaths := appendName(allFoldersPath, utils.RatesCsv) - destinationRatesPaths := appendName(allFoldersPath, utils.DestinationRatesCsv) - ratingPlansPaths := appendName(allFoldersPath, utils.RatingPlansCsv) - ratingProfilesPaths := appendName(allFoldersPath, utils.RatingProfilesCsv) - sharedGroupsPaths := appendName(allFoldersPath, utils.SharedGroupsCsv) actionsPaths := appendName(allFoldersPath, utils.ActionsCsv) - actionPlansPaths := appendName(allFoldersPath, utils.ActionPlansCsv) - actionTriggersPaths := appendName(allFoldersPath, utils.ActionTriggersCsv) - accountActionsPaths := appendName(allFoldersPath, utils.AccountActionsCsv) resourcesPaths := appendName(allFoldersPath, utils.ResourcesCsv) statsPaths := appendName(allFoldersPath, utils.StatsCsv) thresholdsPaths := appendName(allFoldersPath, utils.ThresholdsCsv) @@ -138,15 +112,7 @@ func NewFileCSVStorage(sep rune, dataPath string) *CSVStorage { return NewCSVStorage(sep, destinationsPaths, timingsPaths, - ratesPaths, - destinationRatesPaths, - ratingPlansPaths, - ratingProfilesPaths, - sharedGroupsPaths, actionsPaths, - actionPlansPaths, - actionTriggersPaths, - accountActionsPaths, resourcesPaths, statsPaths, thresholdsPaths, @@ -164,16 +130,11 @@ func NewFileCSVStorage(sep rune, dataPath string) *CSVStorage { // NewStringCSVStorage creates a csv storage from strings func NewStringCSVStorage(sep rune, - destinationsFn, timingsFn, ratesFn, destinationratesFn, - destinationratetimingsFn, ratingprofilesFn, sharedgroupsFn, - actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, + destinationsFn, timingsFn, actionsFn, resProfilesFn, statsFn, thresholdsFn, filterFn, routeProfilesFn, attributeProfilesFn, chargerProfilesFn, dispatcherProfilesFn, dispatcherHostsFn, rateProfilesFn, actionProfilesFn, accountProfilesFn string) *CSVStorage { - c := NewCSVStorage(sep, []string{destinationsFn}, []string{timingsFn}, - []string{ratesFn}, []string{destinationratesFn}, []string{destinationratetimingsFn}, - []string{ratingprofilesFn}, []string{sharedgroupsFn}, []string{actionsFn}, - []string{actiontimingsFn}, []string{actiontriggersFn}, []string{accountactionsFn}, + c := NewCSVStorage(sep, []string{destinationsFn}, []string{timingsFn}, []string{actionsFn}, []string{resProfilesFn}, []string{statsFn}, []string{thresholdsFn}, []string{filterFn}, []string{routeProfilesFn}, []string{attributeProfilesFn}, []string{chargerProfilesFn}, []string{dispatcherProfilesFn}, []string{dispatcherHostsFn}, []string{rateProfilesFn}, @@ -201,15 +162,7 @@ func NewGoogleCSVStorage(sep rune, spreadsheetID string) (*CSVStorage, error) { c := NewCSVStorage(sep, getIfExist(utils.Destinations), getIfExist(utils.Timings), - getIfExist(utils.Rates), - getIfExist(utils.DestinationRates), - getIfExist(utils.RatingPlans), - getIfExist(utils.RatingProfiles), - getIfExist(utils.SharedGroups), getIfExist(utils.Actions), - getIfExist(utils.ActionPlans), - getIfExist(utils.ActionTriggers), - getIfExist(utils.AccountActions), getIfExist(utils.Resources), getIfExist(utils.Stats), getIfExist(utils.Thresholds), @@ -338,15 +291,7 @@ func NewURLCSVStorage(sep rune, dataPath string) *CSVStorage { c := NewCSVStorage(sep, destinationsPaths, timingsPaths, - ratesPaths, - destinationRatesPaths, - ratingPlansPaths, - ratingProfilesPaths, - sharedGroupsPaths, actionsPaths, - actionPlansPaths, - actionTriggersPaths, - accountActionsPaths, resourcesPaths, statsPaths, thresholdsPaths, @@ -451,69 +396,6 @@ func (csvs *CSVStorage) GetTPDestinations(tpid, id string) ([]*utils.TPDestinati return tpDests.AsTPDestinations(), nil } -func (csvs *CSVStorage) GetTPRates(tpid, id string) ([]*utils.TPRateRALs, error) { - var tpRates RateMdls - if err := csvs.proccesData(RateMdl{}, csvs.ratesFn, func(tp interface{}) { - r := tp.(RateMdl) - r.Tpid = tpid - tpRates = append(tpRates, r) - }); err != nil { - return nil, err - } - return tpRates.AsTPRates() -} - -func (csvs *CSVStorage) GetTPDestinationRates(tpid, id string, p *utils.Paginator) ([]*utils.TPDestinationRate, error) { - var tpDestinationRates DestinationRateMdls - if err := csvs.proccesData(DestinationRateMdl{}, csvs.destinationratesFn, func(tp interface{}) { - dr := tp.(DestinationRateMdl) - dr.Tpid = tpid - tpDestinationRates = append(tpDestinationRates, dr) - }); err != nil { - return nil, err - } - return tpDestinationRates.AsTPDestinationRates(), nil -} - -func (csvs *CSVStorage) GetTPRatingPlans(tpid, id string, p *utils.Paginator) ([]*utils.TPRatingPlan, error) { - var tpRatingPlans RatingPlanMdls - if err := csvs.proccesData(RatingPlanMdl{}, csvs.destinationratetimingsFn, func(tp interface{}) { - rp := tp.(RatingPlanMdl) - rp.Tpid = tpid - tpRatingPlans = append(tpRatingPlans, rp) - }); err != nil { - return nil, err - } - return tpRatingPlans.AsTPRatingPlans(), nil -} - -func (csvs *CSVStorage) GetTPRatingProfiles(filter *utils.TPRatingProfile) ([]*utils.TPRatingProfile, error) { - var tpRatingProfiles RatingProfileMdls - if err := csvs.proccesData(RatingProfileMdl{}, csvs.ratingprofilesFn, func(tp interface{}) { - rpf := tp.(RatingProfileMdl) - if filter != nil { - rpf.Tpid = filter.TPid - rpf.Loadid = filter.LoadId - } - tpRatingProfiles = append(tpRatingProfiles, rpf) - }); err != nil { - return nil, err - } - return tpRatingProfiles.AsTPRatingProfiles(), nil -} - -func (csvs *CSVStorage) GetTPSharedGroups(tpid, id string) ([]*utils.TPSharedGroups, error) { - var tpSharedGroups SharedGroupMdls - if err := csvs.proccesData(SharedGroupMdl{}, csvs.sharedgroupsFn, func(tp interface{}) { - sg := tp.(SharedGroupMdl) - sg.Tpid = tpid - tpSharedGroups = append(tpSharedGroups, sg) - }); err != nil { - return nil, err - } - return tpSharedGroups.AsTPSharedGroups(), nil -} - func (csvs *CSVStorage) GetTPActions(tpid, id string) ([]*utils.TPActions, error) { var tpActions ActionMdls if err := csvs.proccesData(ActionMdl{}, csvs.actionsFn, func(tp interface{}) { @@ -526,45 +408,6 @@ func (csvs *CSVStorage) GetTPActions(tpid, id string) ([]*utils.TPActions, error return tpActions.AsTPActions(), nil } -func (csvs *CSVStorage) GetTPActionPlans(tpid, id string) ([]*utils.TPActionPlan, error) { - var tpActionPlans ActionPlanMdls - if err := csvs.proccesData(ActionPlanMdl{}, csvs.actiontimingsFn, func(tp interface{}) { - ap := tp.(ActionPlanMdl) - ap.Tpid = tpid - tpActionPlans = append(tpActionPlans, ap) - }); err != nil { - return nil, err - } - return tpActionPlans.AsTPActionPlans(), nil -} - -func (csvs *CSVStorage) GetTPActionTriggers(tpid, id string) ([]*utils.TPActionTriggers, error) { - var tpActionTriggers ActionTriggerMdls - if err := csvs.proccesData(ActionTriggerMdl{}, csvs.actiontriggersFn, func(tp interface{}) { - at := tp.(ActionTriggerMdl) - at.Tpid = tpid - tpActionTriggers = append(tpActionTriggers, at) - }); err != nil { - return nil, err - } - return tpActionTriggers.AsTPActionTriggers(), nil -} - -func (csvs *CSVStorage) GetTPAccountActions(filter *utils.TPAccountActions) ([]*utils.TPAccountActions, error) { - var tpAccountActions AccountActionMdls - if err := csvs.proccesData(AccountActionMdl{}, csvs.accountactionsFn, func(tp interface{}) { - aa := tp.(AccountActionMdl) - if filter != nil { - aa.Tpid = filter.TPid - aa.Loadid = filter.LoadId - } - tpAccountActions = append(tpAccountActions, aa) - }); err != nil { - return nil, err - } - return tpAccountActions.AsTPAccountActions(), nil -} - func (csvs *CSVStorage) GetTPResources(tpid, tenant, id string) ([]*utils.TPResourceProfile, error) { var tpResLimits ResourceMdls if err := csvs.proccesData(ResourceMdl{}, csvs.resProfilesFn, func(tp interface{}) { diff --git a/engine/storage_interface.go b/engine/storage_interface.go index 7f9f15e1b..8468ccfb2 100644 --- a/engine/storage_interface.go +++ b/engine/storage_interface.go @@ -47,12 +47,6 @@ type Storage interface { type DataDB interface { Storage HasDataDrv(string, string, string) (bool, error) - GetRatingPlanDrv(string) (*RatingPlan, error) - SetRatingPlanDrv(*RatingPlan) error - RemoveRatingPlanDrv(key string) (err error) - GetRatingProfileDrv(string) (*RatingProfile, error) - SetRatingProfileDrv(*RatingProfile) error - RemoveRatingProfileDrv(string) error GetDestinationDrv(string, string) (*Destination, error) SetDestinationDrv(*Destination, string) error RemoveDestinationDrv(string, string) error @@ -62,25 +56,8 @@ type DataDB interface { GetActionsDrv(string) (Actions, error) SetActionsDrv(string, Actions) error RemoveActionsDrv(string) error - GetSharedGroupDrv(string) (*SharedGroup, error) - SetSharedGroupDrv(*SharedGroup) error - RemoveSharedGroupDrv(id string) (err error) - GetActionTriggersDrv(string) (ActionTriggers, error) - SetActionTriggersDrv(string, ActionTriggers) error - RemoveActionTriggersDrv(string) error - GetActionPlanDrv(string, bool, string) (*ActionPlan, error) - SetActionPlanDrv(string, *ActionPlan, bool, string) error - RemoveActionPlanDrv(key string, transactionID string) error - GetAllActionPlansDrv() (map[string]*ActionPlan, error) - GetAccountActionPlansDrv(acntID string, skipCache bool, - transactionID string) (apIDs []string, err error) - SetAccountActionPlansDrv(acntID string, apIDs []string, overwrite bool) (err error) - RemAccountActionPlansDrv(acntID string, apIDs []string) (err error) PushTask(*Task) error PopTask() (*Task, error) - GetAccountDrv(string) (*Account, error) - SetAccountDrv(*Account) error - RemoveAccountDrv(string) error GetResourceProfileDrv(string, string) (*ResourceProfile, error) SetResourceProfileDrv(*ResourceProfile) error RemoveResourceProfileDrv(string, string) error @@ -169,15 +146,7 @@ type LoadReader interface { map[string]string, *utils.PaginatorWithSearch) ([]string, error) GetTPTimings(string, string) ([]*utils.ApierTPTiming, error) GetTPDestinations(string, string) ([]*utils.TPDestination, error) - GetTPRates(string, string) ([]*utils.TPRateRALs, error) - GetTPDestinationRates(string, string, *utils.Paginator) ([]*utils.TPDestinationRate, error) - GetTPRatingPlans(string, string, *utils.Paginator) ([]*utils.TPRatingPlan, error) - GetTPRatingProfiles(*utils.TPRatingProfile) ([]*utils.TPRatingProfile, error) - GetTPSharedGroups(string, string) ([]*utils.TPSharedGroups, error) GetTPActions(string, string) ([]*utils.TPActions, error) - GetTPActionPlans(string, string) ([]*utils.TPActionPlan, error) - GetTPActionTriggers(string, string) ([]*utils.TPActionTriggers, error) - GetTPAccountActions(*utils.TPAccountActions) ([]*utils.TPAccountActions, error) GetTPResources(string, string, string) ([]*utils.TPResourceProfile, error) GetTPStats(string, string, string) ([]*utils.TPStatProfile, error) GetTPThresholds(string, string, string) ([]*utils.TPThresholdProfile, error) @@ -196,15 +165,7 @@ type LoadWriter interface { RemTpData(string, string, map[string]string) error SetTPTimings([]*utils.ApierTPTiming) error SetTPDestinations([]*utils.TPDestination) error - SetTPRates([]*utils.TPRateRALs) error - SetTPDestinationRates([]*utils.TPDestinationRate) error - SetTPRatingPlans([]*utils.TPRatingPlan) error - SetTPRatingProfiles([]*utils.TPRatingProfile) error - SetTPSharedGroups([]*utils.TPSharedGroups) error SetTPActions([]*utils.TPActions) error - SetTPActionPlans([]*utils.TPActionPlan) error - SetTPActionTriggers([]*utils.TPActionTriggers) error - SetTPAccountActions([]*utils.TPAccountActions) error SetTPResources([]*utils.TPResourceProfile) error SetTPStats([]*utils.TPStatProfile) error SetTPThresholds([]*utils.TPThresholdProfile) error diff --git a/engine/storage_internal_datadb.go b/engine/storage_internal_datadb.go index 428899c37..0442ada98 100644 --- a/engine/storage_internal_datadb.go +++ b/engine/storage_internal_datadb.go @@ -195,46 +195,6 @@ func (iDB *InternalDB) HasDataDrv(category, subject, tenant string) (bool, error return false, errors.New("Unsupported HasData category") } -func (iDB *InternalDB) GetRatingPlanDrv(id string) (rp *RatingPlan, err error) { - x, ok := Cache.Get(utils.CacheRatingPlans, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - return x.(*RatingPlan), nil -} - -func (iDB *InternalDB) SetRatingPlanDrv(rp *RatingPlan) (err error) { - Cache.SetWithoutReplicate(utils.CacheRatingPlans, rp.Id, rp, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) RemoveRatingPlanDrv(id string) (err error) { - Cache.RemoveWithoutReplicate(utils.CacheRatingPlans, id, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) GetRatingProfileDrv(id string) (rp *RatingProfile, err error) { - x, ok := Cache.Get(utils.CacheRatingProfiles, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - return x.(*RatingProfile), nil -} - -func (iDB *InternalDB) SetRatingProfileDrv(rp *RatingProfile) (err error) { - Cache.SetWithoutReplicate(utils.CacheRatingProfiles, rp.Id, rp, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) RemoveRatingProfileDrv(id string) (err error) { - Cache.RemoveWithoutReplicate(utils.CacheRatingProfiles, id, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - func (iDB *InternalDB) GetDestinationDrv(key, _ string) (dest *Destination, err error) { if x, ok := Cache.Get(utils.CacheDestinations, key); ok && x != nil { return x.(*Destination), nil @@ -320,155 +280,6 @@ func (iDB *InternalDB) RemoveActionsDrv(id string) (err error) { return } -func (iDB *InternalDB) GetSharedGroupDrv(id string) (sh *SharedGroup, err error) { - if x, ok := Cache.Get(utils.CacheSharedGroups, id); ok && x != nil { - return x.(*SharedGroup).Clone(), err - } - return nil, utils.ErrNotFound -} - -func (iDB *InternalDB) SetSharedGroupDrv(sh *SharedGroup) (err error) { - Cache.SetWithoutReplicate(utils.CacheSharedGroups, sh.Id, sh, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) RemoveSharedGroupDrv(id string) (err error) { - Cache.RemoveWithoutReplicate(utils.CacheSharedGroups, id, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) GetActionTriggersDrv(id string) (at ActionTriggers, err error) { - if x, ok := Cache.Get(utils.CacheActionTriggers, id); ok && x != nil { - return x.(ActionTriggers).Clone(), err - } - return nil, utils.ErrNotFound -} - -func (iDB *InternalDB) SetActionTriggersDrv(id string, at ActionTriggers) (err error) { - Cache.SetWithoutReplicate(utils.CacheActionTriggers, id, at, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) RemoveActionTriggersDrv(id string) (err error) { - Cache.RemoveWithoutReplicate(utils.CacheActionTriggers, id, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) GetActionPlanDrv(key string, skipCache bool, - transactionID string) (ats *ActionPlan, err error) { - if x, ok := Cache.Get(utils.CacheActionPlans, key); ok && x != nil { - return x.(*ActionPlan), nil - } - return nil, utils.ErrNotFound -} - -func (iDB *InternalDB) SetActionPlanDrv(key string, ats *ActionPlan, - overwrite bool, transactionID string) (err error) { - cCommit := cacheCommit(transactionID) - if len(ats.ActionTimings) == 0 { - Cache.RemoveWithoutReplicate(utils.CacheActionPlans, key, - cCommit, transactionID) - return - } - if !overwrite { - // get existing action plan to merge the account ids - if existingAts, _ := iDB.GetActionPlanDrv(key, true, - transactionID); existingAts != nil { - if ats.AccountIDs == nil && len(existingAts.AccountIDs) > 0 { - ats.AccountIDs = make(utils.StringMap) - } - for accID := range existingAts.AccountIDs { - ats.AccountIDs[accID] = true - } - } - } - Cache.SetWithoutReplicate(utils.CacheActionPlans, key, ats, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) RemoveActionPlanDrv(key string, transactionID string) (err error) { - Cache.RemoveWithoutReplicate(utils.CacheActionPlans, key, cacheCommit(transactionID), transactionID) - return -} - -func (iDB *InternalDB) GetAllActionPlansDrv() (ats map[string]*ActionPlan, err error) { - var keys []string - if keys, err = iDB.GetKeysForPrefix(utils.ActionPlanPrefix); err != nil { - return - } - - ats = make(map[string]*ActionPlan, len(keys)) - for _, key := range keys { - var ap *ActionPlan - if ap, err = iDB.GetActionPlanDrv(key[len(utils.ActionPlanPrefix):], false, utils.NonTransactional); err != nil { - ats = nil - return - } - ats[key[len(utils.ActionPlanPrefix):]] = ap - } - return -} - -func (iDB *InternalDB) GetAccountActionPlansDrv(acntID string, - skipCache bool, transactionID string) (apIDs []string, err error) { - if x, ok := Cache.Get(utils.CacheAccountActionPlans, acntID); ok && x != nil { - return x.([]string), nil - } - return nil, utils.ErrNotFound -} - -func (iDB *InternalDB) SetAccountActionPlansDrv(acntID string, apIDs []string, overwrite bool) (err error) { - if !overwrite { - var oldaPlIDs []string - if oldaPlIDs, err = iDB.GetAccountActionPlansDrv(acntID, - true, utils.NonTransactional); err != nil && err != utils.ErrNotFound { - return - } - err = nil - for _, oldAPid := range oldaPlIDs { - if !utils.IsSliceMember(apIDs, oldAPid) { - apIDs = append(apIDs, oldAPid) - } - } - } - Cache.SetWithoutReplicate(utils.CacheAccountActionPlans, acntID, apIDs, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - -func (iDB *InternalDB) RemAccountActionPlansDrv(acntID string, apIDs []string) (err error) { - if len(apIDs) == 0 { - Cache.RemoveWithoutReplicate(utils.CacheAccountActionPlans, acntID, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return - } - var oldaPlIDs []string - if oldaPlIDs, err = iDB.GetAccountActionPlansDrv(acntID, - true, utils.NonTransactional); err != nil { - return - } - for i := 0; i < len(oldaPlIDs); { - if utils.IsSliceMember(apIDs, oldaPlIDs[i]) { - oldaPlIDs = append(oldaPlIDs[:i], oldaPlIDs[i+1:]...) - continue - } - i++ - } - if len(oldaPlIDs) == 0 { - Cache.RemoveWithoutReplicate(utils.CacheAccountActionPlans, acntID, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return - } - Cache.SetWithoutReplicate(utils.CacheAccountActionPlans, acntID, oldaPlIDs, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - return -} - func (iDB *InternalDB) PushTask(t *Task) (err error) { iDB.mu.Lock() iDB.tasks = append(iDB.tasks, t) diff --git a/engine/storage_internal_stordb.go b/engine/storage_internal_stordb.go index b1e127e64..4701eb5f7 100644 --- a/engine/storage_internal_stordb.go +++ b/engine/storage_internal_stordb.go @@ -107,170 +107,6 @@ func (iDB *InternalDB) GetTPDestinations(tpid, id string) (dsts []*utils.TPDesti return } -func (iDB *InternalDB) GetTPRates(tpid, id string) (rates []*utils.TPRateRALs, err error) { - key := tpid - if id != utils.EmptyString { - key += utils.ConcatenatedKeySep + id - } - ids := Cache.GetItemIDs(utils.CacheTBLTPRates, key) - for _, id := range ids { - x, ok := Cache.Get(utils.CacheTBLTPRates, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - result := x.(*utils.TPRateRALs) - for _, rs := range result.RateSlots { - rs.SetDurations() - } - rates = append(rates, result) - } - - if len(rates) == 0 { - return nil, utils.ErrNotFound - } - return -} - -func (iDB *InternalDB) GetTPDestinationRates(tpid, id string, - paginator *utils.Paginator) (dRates []*utils.TPDestinationRate, err error) { - key := tpid - if id != utils.EmptyString { - key += utils.ConcatenatedKeySep + id - } - ids := Cache.GetItemIDs(utils.CacheTBLTPDestinationRates, key) - for _, id := range ids { - x, ok := Cache.Get(utils.CacheTBLTPDestinationRates, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - - dRates = append(dRates, x.(*utils.TPDestinationRate)) - } - - if len(dRates) == 0 { - return nil, utils.ErrNotFound - } - if paginator != nil { - var limit, offset int - if paginator.Limit != nil && *paginator.Limit > 0 { - limit = *paginator.Limit - } - if paginator.Offset != nil && *paginator.Offset > 0 { - offset = *paginator.Offset - } - if limit == 0 && offset == 0 { - return dRates, nil - } - if offset > len(dRates) { - return - } - if offset != 0 { - limit = limit + offset - } - if limit == 0 { - limit = len(dRates[offset:]) - } else if limit > len(dRates) { - limit = len(dRates) - } - dRates = dRates[offset:limit] - } - return -} - -func (iDB *InternalDB) GetTPRatingPlans(tpid, id string, paginator *utils.Paginator) (rPlans []*utils.TPRatingPlan, err error) { - key := tpid - if id != utils.EmptyString { - key += utils.ConcatenatedKeySep + id - } - ids := Cache.GetItemIDs(utils.CacheTBLTPRatingPlans, key) - for _, id := range ids { - x, ok := Cache.Get(utils.CacheTBLTPRatingPlans, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - rPlans = append(rPlans, x.(*utils.TPRatingPlan)) - } - - if len(rPlans) == 0 { - return nil, utils.ErrNotFound - } - if paginator != nil { - var limit, offset int - if paginator.Limit != nil && *paginator.Limit > 0 { - limit = *paginator.Limit - } - if paginator.Offset != nil && *paginator.Offset > 0 { - offset = *paginator.Offset - } - if limit == 0 && offset == 0 { - return rPlans, nil - } - if offset > len(rPlans) { - return - } - if offset != 0 { - limit = limit + offset - } - if limit == 0 { - limit = len(rPlans[offset:]) - } else if limit > len(rPlans) { - limit = len(rPlans) - } - rPlans = rPlans[offset:limit] - } - return -} - -func (iDB *InternalDB) GetTPRatingProfiles(filter *utils.TPRatingProfile) (rProfiles []*utils.TPRatingProfile, err error) { - key := filter.TPid - - if filter.LoadId != utils.EmptyString { - key += utils.ConcatenatedKeySep + filter.LoadId - } - if filter.Tenant != utils.EmptyString { - key += utils.ConcatenatedKeySep + filter.Tenant - } - if filter.Category != utils.EmptyString { - key += utils.ConcatenatedKeySep + filter.Category - } - if filter.Subject != utils.EmptyString { - key += utils.ConcatenatedKeySep + filter.Subject - } - ids := Cache.GetItemIDs(utils.CacheTBLTPRatingProfiles, key) - for _, id := range ids { - x, ok := Cache.Get(utils.CacheTBLTPRatingProfiles, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - rProfiles = append(rProfiles, x.(*utils.TPRatingProfile)) - } - - if len(rProfiles) == 0 { - return nil, utils.ErrNotFound - } - return -} - -func (iDB *InternalDB) GetTPSharedGroups(tpid, id string) (sGroups []*utils.TPSharedGroups, err error) { - key := tpid - if id != utils.EmptyString { - key += utils.ConcatenatedKeySep + id - } - ids := Cache.GetItemIDs(utils.CacheTBLTPSharedGroups, key) - for _, id := range ids { - x, ok := Cache.Get(utils.CacheTBLTPSharedGroups, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - sGroups = append(sGroups, x.(*utils.TPSharedGroups)) - } - - if len(sGroups) == 0 { - return nil, utils.ErrNotFound - } - return -} - func (iDB *InternalDB) GetTPActions(tpid, id string) (actions []*utils.TPActions, err error) { key := tpid if id != utils.EmptyString { @@ -291,71 +127,6 @@ func (iDB *InternalDB) GetTPActions(tpid, id string) (actions []*utils.TPActions return } -func (iDB *InternalDB) GetTPActionPlans(tpid, id string) (aPlans []*utils.TPActionPlan, err error) { - key := tpid - if id != utils.EmptyString { - key += utils.ConcatenatedKeySep + id - } - ids := Cache.GetItemIDs(utils.CacheTBLTPActionPlans, key) - for _, id := range ids { - x, ok := Cache.Get(utils.CacheTBLTPActionPlans, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - aPlans = append(aPlans, x.(*utils.TPActionPlan)) - - } - if len(aPlans) == 0 { - return nil, utils.ErrNotFound - } - return -} - -func (iDB *InternalDB) GetTPActionTriggers(tpid, id string) (aTriggers []*utils.TPActionTriggers, err error) { - key := tpid - if id != utils.EmptyString { - key += utils.ConcatenatedKeySep + id - } - ids := Cache.GetItemIDs(utils.CacheTBLTPActionTriggers, key) - for _, id := range ids { - x, ok := Cache.Get(utils.CacheTBLTPActionTriggers, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - aTriggers = append(aTriggers, x.(*utils.TPActionTriggers)) - } - if len(aTriggers) == 0 { - return nil, utils.ErrNotFound - } - return -} -func (iDB *InternalDB) GetTPAccountActions(filter *utils.TPAccountActions) (accounts []*utils.TPAccountActions, err error) { - key := filter.TPid - - if filter.LoadId != utils.EmptyString { - key += utils.ConcatenatedKeySep + filter.LoadId - } - if filter.Tenant != utils.EmptyString { - key += utils.ConcatenatedKeySep + filter.Tenant - } - if filter.Account != utils.EmptyString { - key += utils.ConcatenatedKeySep + filter.Account - } - ids := Cache.GetItemIDs(utils.CacheTBLTPAccountActions, key) - for _, id := range ids { - x, ok := Cache.Get(utils.CacheTBLTPAccountActions, id) - if !ok || x == nil { - return nil, utils.ErrNotFound - } - accounts = append(accounts, x.(*utils.TPAccountActions)) - } - - if len(accounts) == 0 { - return nil, utils.ErrNotFound - } - return -} - func (iDB *InternalDB) GetTPResources(tpid, tenant, id string) (resources []*utils.TPResourceProfile, err error) { key := tpid if tenant != utils.EmptyString { @@ -681,62 +452,6 @@ func (iDB *InternalDB) SetTPDestinations(dests []*utils.TPDestination) (err erro return } -func (iDB *InternalDB) SetTPRates(rates []*utils.TPRateRALs) (err error) { - if len(rates) == 0 { - return nil - } - for _, rate := range rates { - Cache.SetWithoutReplicate(utils.CacheTBLTPRates, utils.ConcatenatedKey(rate.TPid, rate.ID), rate, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - } - return -} - -func (iDB *InternalDB) SetTPDestinationRates(dRates []*utils.TPDestinationRate) (err error) { - if len(dRates) == 0 { - return nil - } - for _, dRate := range dRates { - Cache.SetWithoutReplicate(utils.CacheTBLTPDestinationRates, utils.ConcatenatedKey(dRate.TPid, dRate.ID), dRate, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - } - return -} - -func (iDB *InternalDB) SetTPRatingPlans(ratingPlans []*utils.TPRatingPlan) (err error) { - if len(ratingPlans) == 0 { - return nil - } - for _, rPlan := range ratingPlans { - Cache.SetWithoutReplicate(utils.CacheTBLTPRatingPlans, utils.ConcatenatedKey(rPlan.TPid, rPlan.ID), rPlan, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - } - return -} - -func (iDB *InternalDB) SetTPRatingProfiles(ratingProfiles []*utils.TPRatingProfile) (err error) { - if len(ratingProfiles) == 0 { - return nil - } - for _, rProfile := range ratingProfiles { - Cache.SetWithoutReplicate(utils.CacheTBLTPRatingProfiles, utils.ConcatenatedKey(rProfile.TPid, - rProfile.LoadId, rProfile.Tenant, rProfile.Category, rProfile.Subject), rProfile, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - } - return -} - -func (iDB *InternalDB) SetTPSharedGroups(groups []*utils.TPSharedGroups) (err error) { - if len(groups) == 0 { - return nil - } - for _, group := range groups { - Cache.SetWithoutReplicate(utils.CacheTBLTPSharedGroups, utils.ConcatenatedKey(group.TPid, group.ID), group, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - } - return -} - func (iDB *InternalDB) SetTPActions(acts []*utils.TPActions) (err error) { if len(acts) == 0 { return nil @@ -748,40 +463,6 @@ func (iDB *InternalDB) SetTPActions(acts []*utils.TPActions) (err error) { return } -func (iDB *InternalDB) SetTPActionPlans(aPlans []*utils.TPActionPlan) (err error) { - if len(aPlans) == 0 { - return nil - } - for _, aPlan := range aPlans { - Cache.SetWithoutReplicate(utils.CacheTBLTPActionPlans, utils.ConcatenatedKey(aPlan.TPid, aPlan.ID), aPlan, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - } - return -} - -func (iDB *InternalDB) SetTPActionTriggers(aTriggers []*utils.TPActionTriggers) (err error) { - if len(aTriggers) == 0 { - return nil - } - for _, aTrigger := range aTriggers { - Cache.SetWithoutReplicate(utils.CacheTBLTPActionTriggers, utils.ConcatenatedKey(aTrigger.TPid, aTrigger.ID), aTrigger, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - } - return -} - -func (iDB *InternalDB) SetTPAccountActions(accActions []*utils.TPAccountActions) (err error) { - if len(accActions) == 0 { - return nil - } - for _, accAction := range accActions { - Cache.SetWithoutReplicate(utils.CacheTBLTPAccountActions, utils.ConcatenatedKey(accAction.TPid, - accAction.LoadId, accAction.Tenant, accAction.Account), accAction, nil, - cacheCommit(utils.NonTransactional), utils.NonTransactional) - } - return -} - func (iDB *InternalDB) SetTPResources(resources []*utils.TPResourceProfile) (err error) { if len(resources) == 0 { return nil diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index 384c4a786..8927bd780 100644 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -34,7 +34,6 @@ import ( "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/guardian" "github.com/cgrates/cgrates/utils" - "github.com/cgrates/ltcache" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/bsoncodec" @@ -735,107 +734,6 @@ func (ms *MongoStorage) HasDataDrv(category, subject, tenant string) (has bool, return has, err } -func (ms *MongoStorage) GetRatingPlanDrv(key string) (rp *RatingPlan, err error) { - var kv struct { - Key string - Value []byte - } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColRpl).FindOne(sctx, bson.M{"key": key}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err - } - return nil - }); err != nil { - return nil, err - } - - b := bytes.NewBuffer(kv.Value) - r, err := zlib.NewReader(b) - if err != nil { - return nil, err - } - out, err := io.ReadAll(r) - if err != nil { - return nil, err - } - r.Close() - if err = ms.ms.Unmarshal(out, &rp); err != nil { - return nil, err - } - return -} - -func (ms *MongoStorage) SetRatingPlanDrv(rp *RatingPlan) error { - result, err := ms.ms.Marshal(rp) - if err != nil { - return err - } - var b bytes.Buffer - w := zlib.NewWriter(&b) - w.Write(result) - w.Close() - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRpl).UpdateOne(sctx, bson.M{"key": rp.Id}, - bson.M{"$set": struct { - Key string - Value []byte - }{Key: rp.Id, Value: b.Bytes()}}, - options.Update().SetUpsert(true), - ) - return err - }) -} - -func (ms *MongoStorage) RemoveRatingPlanDrv(key string) error { - return ms.query(func(sctx mongo.SessionContext) (err error) { - dr, err := ms.getCol(ColRpl).DeleteMany(sctx, bson.M{"key": key}) - if dr.DeletedCount == 0 { - return utils.ErrNotFound - } - return err - }) -} - -func (ms *MongoStorage) GetRatingProfileDrv(key string) (rp *RatingProfile, err error) { - rp = new(RatingProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColRpf).FindOne(sctx, bson.M{"id": key}) - if err := cur.Decode(rp); err != nil { - rp = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err - } - return nil - }) - return -} - -func (ms *MongoStorage) SetRatingProfileDrv(rp *RatingProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRpf).UpdateOne(sctx, bson.M{"id": rp.Id}, - bson.M{"$set": rp}, - options.Update().SetUpsert(true), - ) - return err - }) -} - -func (ms *MongoStorage) RemoveRatingProfileDrv(key string) error { - return ms.query(func(sctx mongo.SessionContext) (err error) { - dr, err := ms.getCol(ColRpf).DeleteMany(sctx, bson.M{"id": key}) - if dr.DeletedCount == 0 { - return utils.ErrNotFound - } - return err - }) -} - func (ms *MongoStorage) GetDestinationDrv(key, transactionID string) (result *Destination, err error) { var kv struct { Key string @@ -987,91 +885,6 @@ func (ms *MongoStorage) RemoveActionsDrv(key string) error { }) } -func (ms *MongoStorage) GetSharedGroupDrv(key string) (sg *SharedGroup, err error) { - sg = new(SharedGroup) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColShg).FindOne(sctx, bson.M{"id": key}) - if err := cur.Decode(sg); err != nil { - sg = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err - } - return nil - }) - return -} - -func (ms *MongoStorage) SetSharedGroupDrv(sg *SharedGroup) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColShg).UpdateOne(sctx, bson.M{"id": sg.Id}, - bson.M{"$set": sg}, - options.Update().SetUpsert(true), - ) - return err - }) -} - -func (ms *MongoStorage) RemoveSharedGroupDrv(id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - dr, err := ms.getCol(ColShg).DeleteOne(sctx, bson.M{"id": id}) - if dr.DeletedCount == 0 { - return utils.ErrNotFound - } - return err - }) -} - -func (ms *MongoStorage) GetAccountDrv(key string) (result *Account, err error) { - result = new(Account) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColAcc).FindOne(sctx, bson.M{"id": key}) - if err := cur.Decode(result); err != nil { - result = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err - } - return nil - }) - return -} - -func (ms *MongoStorage) SetAccountDrv(acc *Account) error { - // never override existing account with an empty one - // UPDATE: if all balances expired and were cleaned it makes - // sense to write empty balance map - if len(acc.BalanceMap) == 0 { - if ac, err := ms.GetAccountDrv(acc.ID); err == nil && !ac.allBalancesExpired() { - ac.ActionTriggers = acc.ActionTriggers - ac.UnitCounters = acc.UnitCounters - ac.AllowNegative = acc.AllowNegative - ac.Disabled = acc.Disabled - acc = ac - } - } - acc.UpdateTime = time.Now() - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAcc).UpdateOne(sctx, bson.M{"id": acc.ID}, - bson.M{"$set": acc}, - options.Update().SetUpsert(true), - ) - return err - }) -} - -func (ms *MongoStorage) RemoveAccountDrv(key string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - dr, err := ms.getCol(ColAcc).DeleteOne(sctx, bson.M{"id": key}) - if dr.DeletedCount == 0 { - return utils.ErrNotFound - } - return err - }) -} - // Limit will only retrieve the last n items out of history, newest first func (ms *MongoStorage) GetLoadHistory(limit int, skipCache bool, transactionID string) (loadInsts []*utils.LoadInstance, err error) { @@ -1177,291 +990,6 @@ func (ms *MongoStorage) AddLoadHistory(ldInst *utils.LoadInstance, return err } -func (ms *MongoStorage) GetActionTriggersDrv(key string) (atrs ActionTriggers, err error) { - var kv struct { - Key string - Value ActionTriggers - } - if err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColAtr).FindOne(sctx, bson.M{"key": key}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err - } - return nil - }); err != nil { - return nil, err - } - atrs = kv.Value - return -} - -func (ms *MongoStorage) SetActionTriggersDrv(key string, atrs ActionTriggers) (err error) { - if len(atrs) == 0 { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAtr).DeleteOne(sctx, bson.M{"key": key}) - return err - }) - } - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAtr).UpdateOne(sctx, bson.M{"key": key}, - bson.M{"$set": struct { - Key string - Value ActionTriggers - }{Key: key, Value: atrs}}, - options.Update().SetUpsert(true), - ) - return err - }) -} - -func (ms *MongoStorage) RemoveActionTriggersDrv(key string) error { - - return ms.query(func(sctx mongo.SessionContext) (err error) { - dr, err := ms.getCol(ColAtr).DeleteOne(sctx, bson.M{"key": key}) - if dr.DeletedCount == 0 { - return utils.ErrNotFound - } - return err - }) -} - -func (ms *MongoStorage) GetActionPlanDrv(key string, skipCache bool, - transactionID string) (ats *ActionPlan, err error) { - if !skipCache { - if x, err := Cache.GetCloned(utils.CacheActionPlans, key); err != nil { - if err != ltcache.ErrNotFound { // Only consider cache if item was found - return nil, err - } - } else if x == nil { // item was placed nil in cache - return nil, utils.ErrNotFound - } else { - return x.(*ActionPlan), nil - } - } - var kv struct { - Key string - Value []byte - } - if err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColApl).FindOne(sctx, bson.M{"key": key}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - if errCh := Cache.Set(utils.CacheActionPlans, key, nil, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return errCh - } - return utils.ErrNotFound - } - return err - } - return nil - }); err != nil { - return nil, err - } - b := bytes.NewBuffer(kv.Value) - r, err := zlib.NewReader(b) - if err != nil { - return nil, err - } - out, err := io.ReadAll(r) - if err != nil { - return nil, err - } - r.Close() - if err = ms.ms.Unmarshal(out, &ats); err != nil { - return nil, err - } - if errCh := Cache.Set(utils.CacheActionPlans, key, ats, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - return -} - -func (ms *MongoStorage) SetActionPlanDrv(key string, ats *ActionPlan, - overwrite bool, transactionID string) (err error) { - // clean dots from account ids map - cCommit := cacheCommit(transactionID) - if len(ats.ActionTimings) == 0 { - err = ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColApl).DeleteOne(sctx, bson.M{"key": key}) - return err - }) - if errCh := Cache.Remove(utils.CacheActionPlans, key, - cCommit, transactionID); errCh != nil { - return errCh - } - return - } - if !overwrite { - // get existing action plan to merge the account ids - if existingAts, _ := ms.GetActionPlanDrv(key, true, transactionID); existingAts != nil { - if ats.AccountIDs == nil && len(existingAts.AccountIDs) > 0 { - ats.AccountIDs = make(utils.StringMap) - } - for accID := range existingAts.AccountIDs { - ats.AccountIDs[accID] = true - } - } - } - result, err := ms.ms.Marshal(ats) - if err != nil { - return err - } - var b bytes.Buffer - w := zlib.NewWriter(&b) - w.Write(result) - w.Close() - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColApl).UpdateOne(sctx, bson.M{"key": key}, - bson.M{"$set": struct { - Key string - Value []byte - }{Key: key, Value: b.Bytes()}}, - options.Update().SetUpsert(true), - ) - return err - }) -} - -func (ms *MongoStorage) RemoveActionPlanDrv(key string, transactionID string) error { - cCommit := cacheCommit(transactionID) - if errCh := Cache.Remove(utils.CacheActionPlans, key, cCommit, transactionID); errCh != nil { - return errCh - } - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColApl).DeleteOne(sctx, bson.M{"key": key}) - return err - }) -} - -func (ms *MongoStorage) GetAllActionPlansDrv() (ats map[string]*ActionPlan, err error) { - keys, err := ms.GetKeysForPrefix(utils.ActionPlanPrefix) - if err != nil { - return nil, err - } - if len(keys) == 0 { - return nil, utils.ErrNotFound - } - ats = make(map[string]*ActionPlan, len(keys)) - for _, key := range keys { - ap, err := ms.GetActionPlanDrv(key[len(utils.ActionPlanPrefix):], - false, utils.NonTransactional) - if err != nil { - return nil, err - } - ats[key[len(utils.ActionPlanPrefix):]] = ap - } - return -} - -func (ms *MongoStorage) GetAccountActionPlansDrv(acntID string, skipCache bool, transactionID string) (aPlIDs []string, err error) { - if !skipCache { - if x, ok := Cache.Get(utils.CacheAccountActionPlans, acntID); ok { - if x == nil { - return nil, utils.ErrNotFound - } - return x.([]string), nil - } - } - var kv struct { - Key string - Value []string - } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColAAp).FindOne(sctx, bson.M{"key": acntID}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - if errCh := Cache.Set(utils.CacheAccountActionPlans, acntID, nil, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return errCh - } - return utils.ErrNotFound - } - return err - } - return nil - }); err != nil { - return nil, err - } - aPlIDs = kv.Value - if errCh := Cache.Set(utils.CacheAccountActionPlans, acntID, aPlIDs, nil, - cacheCommit(transactionID), transactionID); errCh != nil { - return nil, errCh - } - return -} - -func (ms *MongoStorage) SetAccountActionPlansDrv(acntID string, aPlIDs []string, overwrite bool) (err error) { - if !overwrite { - if oldaPlIDs, err := ms.GetAccountActionPlansDrv(acntID, false, utils.NonTransactional); err != nil && err != utils.ErrNotFound { - return err - } else { - for _, oldAPid := range oldaPlIDs { - if !utils.IsSliceMember(aPlIDs, oldAPid) { - aPlIDs = append(aPlIDs, oldAPid) - } - } - } - } - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAAp).UpdateOne(sctx, bson.M{"key": acntID}, - bson.M{"$set": struct { - Key string - Value []string - }{Key: acntID, Value: aPlIDs}}, - options.Update().SetUpsert(true), - ) - return err - }) -} - -// ToDo: check return len(aPlIDs) == 0 -func (ms *MongoStorage) RemAccountActionPlansDrv(acntID string, aPlIDs []string) (err error) { - if len(aPlIDs) == 0 { - return ms.query(func(sctx mongo.SessionContext) (err error) { - dr, err := ms.getCol(ColAAp).DeleteOne(sctx, bson.M{"key": acntID}) - if dr.DeletedCount == 0 { - return utils.ErrNotFound - } - return err - }) - } - oldAPlIDs, err := ms.GetAccountActionPlansDrv(acntID, true, utils.NonTransactional) - if err != nil { - return err - } - for i := 0; i < len(oldAPlIDs); { - if utils.IsSliceMember(aPlIDs, oldAPlIDs[i]) { - oldAPlIDs = append(oldAPlIDs[:i], oldAPlIDs[i+1:]...) - continue // if we have stripped, don't increase index so we can check next element by next run - } - i++ - } - if len(oldAPlIDs) == 0 { // no more elements, remove the reference - return ms.query(func(sctx mongo.SessionContext) (err error) { - dr, err := ms.getCol(ColAAp).DeleteOne(sctx, bson.M{"key": acntID}) - if dr.DeletedCount == 0 { - return utils.ErrNotFound - } - return err - }) - } - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAAp).UpdateOne(sctx, bson.M{"key": acntID}, - bson.M{"$set": struct { - Key string - Value []string - }{Key: acntID, Value: oldAPlIDs}}, - options.Update().SetUpsert(true), - ) - return err - }) -} - func (ms *MongoStorage) PushTask(t *Task) error { return ms.query(func(sctx mongo.SessionContext) error { _, err := ms.getCol(ColTsk).InsertOne(sctx, bson.M{"_id": primitive.NewObjectID(), "task": t}) diff --git a/engine/storage_mongo_stordb.go b/engine/storage_mongo_stordb.go index 086c214c5..fb716e3cc 100644 --- a/engine/storage_mongo_stordb.go +++ b/engine/storage_mongo_stordb.go @@ -207,171 +207,6 @@ func (ms *MongoStorage) GetTPDestinations(tpid, id string) ([]*utils.TPDestinati return results, err } -func (ms *MongoStorage) GetTPRates(tpid, id string) ([]*utils.TPRateRALs, error) { - filter := bson.M{"tpid": tpid} - if id != "" { - filter["id"] = id - } - var results []*utils.TPRateRALs - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPRates).Find(sctx, filter) - if err != nil { - return err - } - for cur.Next(sctx) { - var el utils.TPRateRALs - err := cur.Decode(&el) - if err != nil { - return err - } - for _, rs := range el.RateSlots { - rs.SetDurations() - } - results = append(results, &el) - } - if len(results) == 0 { - return utils.ErrNotFound - } - return cur.Close(sctx) - }) - return results, err -} - -func (ms *MongoStorage) GetTPDestinationRates(tpid, id string, pag *utils.Paginator) ([]*utils.TPDestinationRate, error) { - filter := bson.M{"tpid": tpid} - if id != "" { - filter["id"] = id - } - var results []*utils.TPDestinationRate - fop := options.Find() - if pag != nil { - if pag.Limit != nil { - fop = fop.SetLimit(int64(*pag.Limit)) - } - if pag.Offset != nil { - fop = fop.SetSkip(int64(*pag.Offset)) - } - } - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPDestinationRates).Find(sctx, filter, fop) - if err != nil { - return err - } - for cur.Next(sctx) { - var el utils.TPDestinationRate - err := cur.Decode(&el) - if err != nil { - return err - } - results = append(results, &el) - } - if len(results) == 0 { - return utils.ErrNotFound - } - return cur.Close(sctx) - }) - return results, err -} - -func (ms *MongoStorage) GetTPRatingPlans(tpid, id string, pag *utils.Paginator) ([]*utils.TPRatingPlan, error) { - filter := bson.M{"tpid": tpid} - if id != "" { - filter["id"] = id - } - var results []*utils.TPRatingPlan - fop := options.Find() - if pag != nil { - if pag.Limit != nil { - fop = fop.SetLimit(int64(*pag.Limit)) - } - if pag.Offset != nil { - fop = fop.SetSkip(int64(*pag.Offset)) - } - } - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPRatingPlans).Find(sctx, filter, fop) - if err != nil { - return err - } - for cur.Next(sctx) { - var el utils.TPRatingPlan - err := cur.Decode(&el) - if err != nil { - return err - } - results = append(results, &el) - } - if len(results) == 0 { - return utils.ErrNotFound - } - return cur.Close(sctx) - }) - return results, err -} - -func (ms *MongoStorage) GetTPRatingProfiles(tp *utils.TPRatingProfile) ([]*utils.TPRatingProfile, error) { - filter := bson.M{"tpid": tp.TPid} - if tp.Tenant != "" { - filter["tenant"] = tp.Tenant - } - if tp.Category != "" { - filter["category"] = tp.Category - } - if tp.Subject != "" { - filter["subject"] = tp.Subject - } - if tp.LoadId != "" { - filter["loadid"] = tp.LoadId - } - var results []*utils.TPRatingProfile - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPRatingProfiles).Find(sctx, filter) - if err != nil { - return err - } - for cur.Next(sctx) { - var el utils.TPRatingProfile - err := cur.Decode(&el) - if err != nil { - return err - } - results = append(results, &el) - } - if len(results) == 0 { - return utils.ErrNotFound - } - return cur.Close(sctx) - }) - return results, err -} - -func (ms *MongoStorage) GetTPSharedGroups(tpid, id string) ([]*utils.TPSharedGroups, error) { - filter := bson.M{"tpid": tpid} - if id != "" { - filter["id"] = id - } - var results []*utils.TPSharedGroups - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPSharedGroups).Find(sctx, filter) - if err != nil { - return err - } - for cur.Next(sctx) { - var el utils.TPSharedGroups - err := cur.Decode(&el) - if err != nil { - return err - } - results = append(results, &el) - } - if len(results) == 0 { - return utils.ErrNotFound - } - return cur.Close(sctx) - }) - return results, err -} - func (ms *MongoStorage) GetTPResources(tpid, tenant, id string) ([]*utils.TPResourceProfile, error) { filter := bson.M{"tpid": tpid} if id != "" { @@ -461,95 +296,6 @@ func (ms *MongoStorage) GetTPActions(tpid, id string) ([]*utils.TPActions, error return results, err } -func (ms *MongoStorage) GetTPActionPlans(tpid, id string) ([]*utils.TPActionPlan, error) { - filter := bson.M{"tpid": tpid} - if id != "" { - filter["id"] = id - } - var results []*utils.TPActionPlan - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPActionPlans).Find(sctx, filter) - if err != nil { - return err - } - for cur.Next(sctx) { - var el utils.TPActionPlan - err := cur.Decode(&el) - if err != nil { - return err - } - results = append(results, &el) - } - if len(results) == 0 { - return utils.ErrNotFound - } - return cur.Close(sctx) - }) - return results, err -} - -func (ms *MongoStorage) GetTPActionTriggers(tpid, id string) ([]*utils.TPActionTriggers, error) { - filter := bson.M{ - "tpid": tpid, - } - if id != "" { - filter["id"] = id - } - var results []*utils.TPActionTriggers - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPActionTriggers).Find(sctx, filter) - if err != nil { - return err - } - for cur.Next(sctx) { - var el utils.TPActionTriggers - err := cur.Decode(&el) - if err != nil { - return err - } - results = append(results, &el) - } - if len(results) == 0 { - return utils.ErrNotFound - } - return cur.Close(sctx) - }) - return results, err -} - -func (ms *MongoStorage) GetTPAccountActions(tp *utils.TPAccountActions) ([]*utils.TPAccountActions, error) { - filter := bson.M{"tpid": tp.TPid} - if tp.Tenant != "" { - filter["tenant"] = tp.Tenant - } - if tp.Account != "" { - filter["account"] = tp.Account - } - if tp.LoadId != "" { - filter["loadid"] = tp.LoadId - } - var results []*utils.TPAccountActions - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPAccountActions).Find(sctx, filter) - if err != nil { - return err - } - for cur.Next(sctx) { - var el utils.TPAccountActions - err := cur.Decode(&el) - if err != nil { - return err - } - results = append(results, &el) - } - if len(results) == 0 { - return utils.ErrNotFound - } - return cur.Close(sctx) - }) - return results, err -} - func (ms *MongoStorage) RemTpData(table, tpid string, args map[string]string) error { if len(table) == 0 { // Remove tpid out of all tables return ms.query(func(sctx mongo.SessionContext) error { @@ -629,119 +375,6 @@ func (ms *MongoStorage) SetTPDestinations(tpDsts []*utils.TPDestination) (err er }) } -func (ms *MongoStorage) SetTPRates(tps []*utils.TPRateRALs) error { - if len(tps) == 0 { - return nil - } - m := make(map[string]bool) - return ms.query(func(sctx mongo.SessionContext) (err error) { - for _, tp := range tps { - if !m[tp.ID] { - m[tp.ID] = true - _, err := ms.getCol(utils.TBLTPRates).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) - if err != nil { - return err - } - } - _, err := ms.getCol(utils.TBLTPRates).InsertOne(sctx, tp) - if err != nil { - return err - } - } - return nil - }) -} - -func (ms *MongoStorage) SetTPDestinationRates(tps []*utils.TPDestinationRate) error { - if len(tps) == 0 { - return nil - } - m := make(map[string]bool) - return ms.query(func(sctx mongo.SessionContext) (err error) { - for _, tp := range tps { - if !m[tp.ID] { - m[tp.ID] = true - _, err := ms.getCol(utils.TBLTPDestinationRates).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) - if err != nil { - return err - } - } - _, err := ms.getCol(utils.TBLTPDestinationRates).InsertOne(sctx, tp) - if err != nil { - return err - } - } - return nil - }) -} - -func (ms *MongoStorage) SetTPRatingPlans(tps []*utils.TPRatingPlan) error { - if len(tps) == 0 { - return nil - } - m := make(map[string]bool) - return ms.query(func(sctx mongo.SessionContext) (err error) { - for _, tp := range tps { - if !m[tp.ID] { - m[tp.ID] = true - _, err := ms.getCol(utils.TBLTPRatingPlans).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) - if err != nil { - return err - } - } - _, err := ms.getCol(utils.TBLTPRatingPlans).InsertOne(sctx, tp) - if err != nil { - return err - } - } - return nil - }) -} - -func (ms *MongoStorage) SetTPRatingProfiles(tps []*utils.TPRatingProfile) error { - if len(tps) == 0 { - return nil - } - return ms.query(func(sctx mongo.SessionContext) (err error) { - for _, tp := range tps { - _, err = ms.getCol(utils.TBLTPRatingProfiles).UpdateOne(sctx, bson.M{ - "tpid": tp.TPid, - "loadid": tp.LoadId, - "tenant": tp.Tenant, - "category": tp.Category, - "subject": tp.Subject, - }, bson.M{"$set": tp}, options.Update().SetUpsert(true)) - if err != nil { - return err - } - } - return nil - }) -} - -func (ms *MongoStorage) SetTPSharedGroups(tps []*utils.TPSharedGroups) error { - if len(tps) == 0 { - return nil - } - m := make(map[string]bool) - return ms.query(func(sctx mongo.SessionContext) (err error) { - for _, tp := range tps { - if !m[tp.ID] { - m[tp.ID] = true - _, err := ms.getCol(utils.TBLTPSharedGroups).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) - if err != nil { - return err - } - } - _, err := ms.getCol(utils.TBLTPSharedGroups).InsertOne(sctx, tp) - if err != nil { - return err - } - } - return nil - }) -} - func (ms *MongoStorage) SetTPActions(tps []*utils.TPActions) error { if len(tps) == 0 { return nil @@ -763,68 +396,6 @@ func (ms *MongoStorage) SetTPActions(tps []*utils.TPActions) error { }) } -func (ms *MongoStorage) SetTPActionPlans(tps []*utils.TPActionPlan) error { - if len(tps) == 0 { - return nil - } - m := make(map[string]bool) - return ms.query(func(sctx mongo.SessionContext) (err error) { - for _, tp := range tps { - if !m[tp.ID] { - m[tp.ID] = true - if _, err := ms.getCol(utils.TBLTPActionPlans).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}); err != nil { - return err - } - } - if _, err := ms.getCol(utils.TBLTPActionPlans).InsertOne(sctx, tp); err != nil { - return err - } - } - return nil - }) -} - -func (ms *MongoStorage) SetTPActionTriggers(tps []*utils.TPActionTriggers) error { - if len(tps) == 0 { - return nil - } - m := make(map[string]bool) - return ms.query(func(sctx mongo.SessionContext) (err error) { - for _, tp := range tps { - if !m[tp.ID] { - m[tp.ID] = true - if _, err := ms.getCol(utils.TBLTPActionTriggers).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}); err != nil { - return err - } - } - if _, err := ms.getCol(utils.TBLTPActionTriggers).InsertOne(sctx, tp); err != nil { - return err - } - } - return nil - }) -} - -func (ms *MongoStorage) SetTPAccountActions(tps []*utils.TPAccountActions) error { - if len(tps) == 0 { - return nil - } - return ms.query(func(sctx mongo.SessionContext) (err error) { - for _, tp := range tps { - _, err = ms.getCol(utils.TBLTPAccountActions).UpdateOne(sctx, bson.M{ - "tpid": tp.TPid, - "loadid": tp.LoadId, - "tenant": tp.Tenant, - "account": tp.Account, - }, bson.M{"$set": tp}, options.Update().SetUpsert(true)) - if err != nil { - return err - } - } - return nil - }) -} - func (ms *MongoStorage) SetTPResources(tpRLs []*utils.TPResourceProfile) (err error) { if len(tpRLs) == 0 { return diff --git a/engine/storage_sql.go b/engine/storage_sql.go index f30f2e731..b37e0f754 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -308,129 +308,6 @@ func (sqls *SQLStorage) SetTPDestinations(dests []*utils.TPDestination) error { return nil } -func (sqls *SQLStorage) SetTPRates(rs []*utils.TPRateRALs) error { - if len(rs) == 0 { - return nil //Nothing to set - } - m := make(map[string]bool) - tx := sqls.db.Begin() - for _, rate := range rs { - if !m[rate.ID] { - m[rate.ID] = true - if err := tx.Where(&RateMdl{Tpid: rate.TPid, Tag: rate.ID}).Delete(RateMdl{}).Error; err != nil { - tx.Rollback() - return err - } - } - for _, r := range APItoModelRate(rate) { - if err := tx.Create(&r).Error; err != nil { - tx.Rollback() - return err - } - } - } - tx.Commit() - return nil -} - -func (sqls *SQLStorage) SetTPDestinationRates(drs []*utils.TPDestinationRate) error { - if len(drs) == 0 { - return nil //Nothing to set - } - m := make(map[string]bool) - tx := sqls.db.Begin() - for _, dRate := range drs { - if !m[dRate.ID] { - m[dRate.ID] = true - if err := tx.Where(&DestinationRateMdl{Tpid: dRate.TPid, Tag: dRate.ID}).Delete(DestinationRateMdl{}).Error; err != nil { - tx.Rollback() - return err - } - } - for _, d := range APItoModelDestinationRate(dRate) { - if err := tx.Create(&d).Error; err != nil { - tx.Rollback() - return err - } - } - } - tx.Commit() - return nil -} - -func (sqls *SQLStorage) SetTPRatingPlans(rps []*utils.TPRatingPlan) error { - if len(rps) == 0 { - return nil //Nothing to set - } - m := make(map[string]bool) - tx := sqls.db.Begin() - for _, rPlan := range rps { - if !m[rPlan.ID] { - m[rPlan.ID] = true - if err := tx.Where(&RatingPlanMdl{Tpid: rPlan.TPid, Tag: rPlan.ID}).Delete(RatingPlanMdl{}).Error; err != nil { - tx.Rollback() - return err - } - } - for _, r := range APItoModelRatingPlan(rPlan) { - if err := tx.Create(&r).Error; err != nil { - tx.Rollback() - return err - } - } - } - tx.Commit() - return nil -} - -func (sqls *SQLStorage) SetTPRatingProfiles(rpfs []*utils.TPRatingProfile) error { - if len(rpfs) == 0 { - return nil //Nothing to set - } - tx := sqls.db.Begin() - for _, rpf := range rpfs { - if err := tx.Where(&RatingProfileMdl{Tpid: rpf.TPid, Loadid: rpf.LoadId, - Tenant: rpf.Tenant, Category: rpf.Category, - Subject: rpf.Subject}).Delete(RatingProfileMdl{}).Error; err != nil { - tx.Rollback() - return err - } - for _, r := range APItoModelRatingProfile(rpf) { - if err := tx.Create(&r).Error; err != nil { - tx.Rollback() - return err - } - } - } - tx.Commit() - return nil -} - -func (sqls *SQLStorage) SetTPSharedGroups(sgs []*utils.TPSharedGroups) error { - if len(sgs) == 0 { - return nil //Nothing to set - } - m := make(map[string]bool) - tx := sqls.db.Begin() - for _, sGroup := range sgs { - if !m[sGroup.ID] { - m[sGroup.ID] = true - if err := tx.Where(&SharedGroupMdl{Tpid: sGroup.TPid, Tag: sGroup.ID}).Delete(SharedGroupMdl{}).Error; err != nil { - tx.Rollback() - return err - } - } - for _, s := range APItoModelSharedGroup(sGroup) { - if err := tx.Create(&s).Error; err != nil { - tx.Rollback() - return err - } - } - } - tx.Commit() - return nil -} - func (sqls *SQLStorage) SetTPActions(acts []*utils.TPActions) error { if len(acts) == 0 { return nil //Nothing to set @@ -456,83 +333,6 @@ func (sqls *SQLStorage) SetTPActions(acts []*utils.TPActions) error { return nil } -func (sqls *SQLStorage) SetTPActionPlans(ats []*utils.TPActionPlan) error { - if len(ats) == 0 { - return nil //Nothing to set - } - m := make(map[string]bool) - - tx := sqls.db.Begin() - for _, aPlan := range ats { - if !m[aPlan.ID] { - m[aPlan.ID] = true - if err := tx.Where(&ActionPlanMdl{Tpid: aPlan.TPid, Tag: aPlan.ID}).Delete(ActionPlanMdl{}).Error; err != nil { - tx.Rollback() - return err - } - } - for _, a := range APItoModelActionPlan(aPlan) { - if err := tx.Create(&a).Error; err != nil { - tx.Rollback() - return err - } - } - } - r := tx.Commit() - return r.Error -} - -func (sqls *SQLStorage) SetTPActionTriggers(ats []*utils.TPActionTriggers) error { - if len(ats) == 0 { - return nil //Nothing to set - } - m := make(map[string]bool) - tx := sqls.db.Begin() - for _, aTrigger := range ats { - if !m[aTrigger.ID] { - m[aTrigger.ID] = true - if err := tx.Where(&ActionTriggerMdl{Tpid: aTrigger.TPid, Tag: aTrigger.ID}).Delete(ActionTriggerMdl{}).Error; err != nil { - tx.Rollback() - return err - } - } - for _, a := range APItoModelActionTrigger(aTrigger) { - if err := tx.Create(&a).Error; err != nil { - tx.Rollback() - return err - } - } - } - tx.Commit() - return nil -} - -// Sets a group of account actions. Map key has the role of grouping within a tpid -func (sqls *SQLStorage) SetTPAccountActions(aas []*utils.TPAccountActions) error { - if len(aas) == 0 { - return nil //Nothing to set - } - m := make(map[string]bool) - - tx := sqls.db.Begin() - for _, aa := range aas { - if !m[aa.GetId()] { - m[aa.GetId()] = true - if err := tx.Where(&AccountActionMdl{Tpid: aa.TPid, Loadid: aa.LoadId, Tenant: aa.Tenant, Account: aa.Account}).Delete(&AccountActionMdl{}).Error; err != nil { - tx.Rollback() - return err - } - } - sa := APItoModelAccountAction(aa) - if err := tx.Create(&sa).Error; err != nil { - tx.Rollback() - return err - } - } - tx.Commit() - return nil -} - func (sqls *SQLStorage) SetTPResources(rls []*utils.TPResourceProfile) error { if len(rls) == 0 { return nil @@ -1251,49 +1051,6 @@ func (sqls *SQLStorage) GetTPDestinations(tpid, id string) (uTPDsts []*utils.TPD return tpDests.AsTPDestinations(), nil } -func (sqls *SQLStorage) GetTPRates(tpid, id string) ([]*utils.TPRateRALs, error) { - var tpRates RateMdls - q := sqls.db.Where("tpid = ?", tpid).Order("id") - if len(id) != 0 { - q = q.Where("tag = ?", id) - } - if err := q.Find(&tpRates).Error; err != nil { - return nil, err - } - if rs, err := tpRates.AsTPRates(); err != nil { - return nil, err - } else { - if len(rs) == 0 { - return rs, utils.ErrNotFound - } - return rs, nil - } -} - -func (sqls *SQLStorage) GetTPDestinationRates(tpid, id string, pagination *utils.Paginator) ([]*utils.TPDestinationRate, error) { - var tpDestinationRates DestinationRateMdls - q := sqls.db.Where("tpid = ?", tpid) - if len(id) != 0 { - q = q.Where("tag = ?", id) - } - if pagination != nil { - if pagination.Limit != nil { - q = q.Limit(*pagination.Limit) - } - if pagination.Offset != nil { - q = q.Offset(*pagination.Offset) - } - } - if err := q.Find(&tpDestinationRates).Error; err != nil { - return nil, err - } - drs := tpDestinationRates.AsTPDestinationRates() - if len(drs) == 0 { - return drs, utils.ErrNotFound - } - return drs, nil -} - func (sqls *SQLStorage) GetTPTimings(tpid, id string) ([]*utils.ApierTPTiming, error) { var tpTimings TimingMdls q := sqls.db.Where("tpid = ?", tpid) @@ -1310,73 +1067,6 @@ func (sqls *SQLStorage) GetTPTimings(tpid, id string) ([]*utils.ApierTPTiming, e return ts, nil } -func (sqls *SQLStorage) GetTPRatingPlans(tpid, id string, pagination *utils.Paginator) ([]*utils.TPRatingPlan, error) { - var tpRatingPlans RatingPlanMdls - q := sqls.db.Where("tpid = ?", tpid) - if len(id) != 0 { - q = q.Where("tag = ?", id) - } - if err := q.Find(&tpRatingPlans).Error; err != nil { - return nil, err - } - if pagination != nil { - if pagination.Limit != nil { - q = q.Limit(*pagination.Limit) - } - if pagination.Offset != nil { - q = q.Offset(*pagination.Offset) - } - } - rps := tpRatingPlans.AsTPRatingPlans() - - if len(rps) == 0 { - return rps, utils.ErrNotFound - } - return rps, nil -} - -func (sqls *SQLStorage) GetTPRatingProfiles(filter *utils.TPRatingProfile) ([]*utils.TPRatingProfile, error) { - var tpRpfs RatingProfileMdls - q := sqls.db.Where("tpid = ?", filter.TPid) - if len(filter.LoadId) != 0 { - q = q.Where("loadid = ?", filter.LoadId) - } - if len(filter.Tenant) != 0 { - q = q.Where("tenant = ?", filter.Tenant) - } - if len(filter.Category) != 0 { - q = q.Where("category = ?", filter.Category) - } - if len(filter.Subject) != 0 { - q = q.Where("subject = ?", filter.Subject) - } - if err := q.Find(&tpRpfs).Error; err != nil { - return nil, err - } - rps := tpRpfs.AsTPRatingProfiles() - if len(rps) == 0 { - return rps, utils.ErrNotFound - } - return rps, nil -} - -func (sqls *SQLStorage) GetTPSharedGroups(tpid, id string) ([]*utils.TPSharedGroups, error) { - var tpShareGroups SharedGroupMdls - q := sqls.db.Where("tpid = ?", tpid) - if len(id) != 0 { - q = q.Where("tag = ?", id) - } - if err := q.Find(&tpShareGroups).Error; err != nil { - return nil, err - } - sgs := tpShareGroups.AsTPSharedGroups() - - if len(sgs) == 0 { - return sgs, utils.ErrNotFound - } - return sgs, nil -} - func (sqls *SQLStorage) GetTPActions(tpid, id string) ([]*utils.TPActions, error) { var tpActions ActionMdls q := sqls.db.Where("tpid = ?", tpid) @@ -1393,60 +1083,6 @@ func (sqls *SQLStorage) GetTPActions(tpid, id string) ([]*utils.TPActions, error return as, nil } -func (sqls *SQLStorage) GetTPActionTriggers(tpid, id string) ([]*utils.TPActionTriggers, error) { - var tpActionTriggers ActionTriggerMdls - q := sqls.db.Where("tpid = ?", tpid) - if len(id) != 0 { - q = q.Where("tag = ?", id) - } - if err := q.Find(&tpActionTriggers).Error; err != nil { - return nil, err - } - ats := tpActionTriggers.AsTPActionTriggers() - if len(ats) == 0 { - return ats, utils.ErrNotFound - } - return ats, nil -} - -func (sqls *SQLStorage) GetTPActionPlans(tpid, id string) ([]*utils.TPActionPlan, error) { - var tpActionPlans ActionPlanMdls - q := sqls.db.Where("tpid = ?", tpid) - if len(id) != 0 { - q = q.Where("tag = ?", id) - } - if err := q.Find(&tpActionPlans).Error; err != nil { - return nil, err - } - aps := tpActionPlans.AsTPActionPlans() - if len(aps) == 0 { - return aps, utils.ErrNotFound - } - return aps, nil -} - -func (sqls *SQLStorage) GetTPAccountActions(filter *utils.TPAccountActions) ([]*utils.TPAccountActions, error) { - var tpAccActs AccountActionMdls - q := sqls.db.Where("tpid = ?", filter.TPid) - if len(filter.LoadId) != 0 { - q = q.Where("loadid = ?", filter.LoadId) - } - if len(filter.Tenant) != 0 { - q = q.Where("tenant = ?", filter.Tenant) - } - if len(filter.Account) != 0 { - q = q.Where("account = ?", filter.Account) - } - if err := q.Find(&tpAccActs).Error; err != nil { - return nil, err - } - aas := tpAccActs.AsTPAccountActions() - if len(aas) == 0 { - return aas, utils.ErrNotFound - } - return aas, nil -} - func (sqls *SQLStorage) GetTPResources(tpid, tenant, id string) ([]*utils.TPResourceProfile, error) { var rls ResourceMdls q := sqls.db.Where("tpid = ?", tpid) diff --git a/engine/tpexporter.go b/engine/tpexporter.go index 722521140..a83d73ade 100644 --- a/engine/tpexporter.go +++ b/engine/tpexporter.go @@ -108,67 +108,6 @@ func (tpExp *TPExporter) Run() error { } } - storDataRates, err := tpExp.storDb.GetTPRates(tpExp.tpID, "") - if err != nil && err.Error() != utils.ErrNotFound.Error() { - utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpRates)) - withError = true - } - for _, sd := range storDataRates { - sdModels := APItoModelRate(sd) - for _, sdModel := range sdModels { - toExportMap[utils.RatesCsv] = append(toExportMap[utils.RatesCsv], sdModel) - } - } - - storDataDestinationRates, err := tpExp.storDb.GetTPDestinationRates(tpExp.tpID, "", nil) - if err != nil && err.Error() != utils.ErrNotFound.Error() { - utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpDestinationRates)) - withError = true - } - for _, sd := range storDataDestinationRates { - sdModels := APItoModelDestinationRate(sd) - for _, sdModel := range sdModels { - toExportMap[utils.DestinationRatesCsv] = append(toExportMap[utils.DestinationRatesCsv], sdModel) - } - } - - storDataRatingPlans, err := tpExp.storDb.GetTPRatingPlans(tpExp.tpID, "", nil) - if err != nil && err.Error() != utils.ErrNotFound.Error() { - utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpRatingPlans)) - withError = true - } - for _, sd := range storDataRatingPlans { - sdModels := APItoModelRatingPlan(sd) - for _, sdModel := range sdModels { - toExportMap[utils.RatingPlansCsv] = append(toExportMap[utils.RatingPlansCsv], sdModel) - } - } - - storDataRatingProfiles, err := tpExp.storDb.GetTPRatingProfiles(&utils.TPRatingProfile{TPid: tpExp.tpID}) - if err != nil && err.Error() != utils.ErrNotFound.Error() { - utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpRatingProfiles)) - withError = true - } - for _, sd := range storDataRatingProfiles { - sdModels := APItoModelRatingProfile(sd) - for _, sdModel := range sdModels { - toExportMap[utils.RatingProfilesCsv] = append(toExportMap[utils.RatingProfilesCsv], sdModel) - } - } - - storDataSharedGroups, err := tpExp.storDb.GetTPSharedGroups(tpExp.tpID, "") - if err != nil && err.Error() != utils.ErrNotFound.Error() { - utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpSharedGroups)) - withError = true - } - - for _, sd := range storDataSharedGroups { - sdModels := APItoModelSharedGroup(sd) - for _, sdModel := range sdModels { - toExportMap[utils.SharedGroupsCsv] = append(toExportMap[utils.SharedGroupsCsv], sdModel) - } - } - storDataActions, err := tpExp.storDb.GetTPActions(tpExp.tpID, "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpActions)) @@ -181,40 +120,6 @@ func (tpExp *TPExporter) Run() error { } } - storDataActionPlans, err := tpExp.storDb.GetTPActionPlans(tpExp.tpID, "") - if err != nil && err.Error() != utils.ErrNotFound.Error() { - utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpActionPlans)) - withError = true - } - for _, sd := range storDataActionPlans { - sdModels := APItoModelActionPlan(sd) - for _, sdModel := range sdModels { - toExportMap[utils.ActionPlansCsv] = append(toExportMap[utils.ActionPlansCsv], sdModel) - } - } - - storDataActionTriggers, err := tpExp.storDb.GetTPActionTriggers(tpExp.tpID, "") - if err != nil && err.Error() != utils.ErrNotFound.Error() { - utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpActionTriggers)) - withError = true - } - for _, sd := range storDataActionTriggers { - sdModels := APItoModelActionTrigger(sd) - for _, sdModel := range sdModels { - toExportMap[utils.ActionTriggersCsv] = append(toExportMap[utils.ActionTriggersCsv], sdModel) - } - } - - storDataAccountActions, err := tpExp.storDb.GetTPAccountActions(&utils.TPAccountActions{TPid: tpExp.tpID}) - if err != nil && err.Error() != utils.ErrNotFound.Error() { - utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpAccountActionsV)) - withError = true - } - for _, sd := range storDataAccountActions { - sdModel := APItoModelAccountAction(sd) - toExportMap[utils.AccountActionsCsv] = append(toExportMap[utils.AccountActionsCsv], sdModel) - } - storDataResources, err := tpExp.storDb.GetTPResources(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpResources)) diff --git a/engine/tpimporter_csv.go b/engine/tpimporter_csv.go index 4b25139b1..0ac83a5cd 100644 --- a/engine/tpimporter_csv.go +++ b/engine/tpimporter_csv.go @@ -42,15 +42,7 @@ type TPCSVImporter struct { var fileHandlers = map[string]func(*TPCSVImporter, string) error{ utils.TimingsCsv: (*TPCSVImporter).importTimings, utils.DestinationsCsv: (*TPCSVImporter).importDestinations, - utils.RatesCsv: (*TPCSVImporter).importRates, - utils.DestinationRatesCsv: (*TPCSVImporter).importDestinationRates, - utils.RatingPlansCsv: (*TPCSVImporter).importRatingPlans, - utils.RatingProfilesCsv: (*TPCSVImporter).importRatingProfiles, - utils.SharedGroupsCsv: (*TPCSVImporter).importSharedGroups, utils.ActionsCsv: (*TPCSVImporter).importActions, - utils.ActionPlansCsv: (*TPCSVImporter).importActionTimings, - utils.ActionTriggersCsv: (*TPCSVImporter).importActionTriggers, - utils.AccountActionsCsv: (*TPCSVImporter).importAccountActions, utils.ResourcesCsv: (*TPCSVImporter).importResources, utils.StatsCsv: (*TPCSVImporter).importStats, utils.ThresholdsCsv: (*TPCSVImporter).importThresholds, @@ -116,88 +108,6 @@ func (tpImp *TPCSVImporter) importDestinations(fn string) error { return tpImp.StorDb.SetTPDestinations(tps) } -func (tpImp *TPCSVImporter) importRates(fn string) error { - if tpImp.Verbose { - log.Printf("Processing file: <%s> ", fn) - } - tps, err := tpImp.csvr.GetTPRates(tpImp.TPid, "") - if err != nil { - return err - } - for i := 0; i < len(tps); i++ { - tps[i].TPid = tpImp.TPid - } - - return tpImp.StorDb.SetTPRates(tps) -} - -func (tpImp *TPCSVImporter) importDestinationRates(fn string) error { - if tpImp.Verbose { - log.Printf("Processing file: <%s> ", fn) - } - tps, err := tpImp.csvr.GetTPDestinationRates(tpImp.TPid, "", nil) - if err != nil { - return err - } - - for i := 0; i < len(tps); i++ { - tps[i].TPid = tpImp.TPid - } - - return tpImp.StorDb.SetTPDestinationRates(tps) -} - -func (tpImp *TPCSVImporter) importRatingPlans(fn string) error { - if tpImp.Verbose { - log.Printf("Processing file: <%s> ", fn) - } - tps, err := tpImp.csvr.GetTPRatingPlans(tpImp.TPid, "", nil) - if err != nil { - return err - } - for i := 0; i < len(tps); i++ { - tps[i].TPid = tpImp.TPid - } - - return tpImp.StorDb.SetTPRatingPlans(tps) -} - -func (tpImp *TPCSVImporter) importRatingProfiles(fn string) error { - if tpImp.Verbose { - log.Printf("Processing file: <%s> ", fn) - } - tps, err := tpImp.csvr.GetTPRatingProfiles(&utils.TPRatingProfile{TPid: tpImp.TPid}) - if err != nil { - return err - } - loadId := utils.CSVLoad //Autogenerate rating profile id - if tpImp.ImportId != "" { - loadId += "_" + tpImp.ImportId - } - - for i := 0; i < len(tps); i++ { - tps[i].TPid = tpImp.TPid - tps[i].LoadId = loadId - - } - return tpImp.StorDb.SetTPRatingProfiles(tps) -} - -func (tpImp *TPCSVImporter) importSharedGroups(fn string) error { - if tpImp.Verbose { - log.Printf("Processing file: <%s> ", fn) - } - tps, err := tpImp.csvr.GetTPSharedGroups(tpImp.TPid, "") - if err != nil { - return err - } - for i := 0; i < len(tps); i++ { - tps[i].TPid = tpImp.TPid - } - - return tpImp.StorDb.SetTPSharedGroups(tps) -} - func (tpImp *TPCSVImporter) importActions(fn string) error { if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) @@ -213,55 +123,6 @@ func (tpImp *TPCSVImporter) importActions(fn string) error { return tpImp.StorDb.SetTPActions(tps) } -func (tpImp *TPCSVImporter) importActionTimings(fn string) error { - if tpImp.Verbose { - log.Printf("Processing file: <%s> ", fn) - } - tps, err := tpImp.csvr.GetTPActionPlans(tpImp.TPid, "") - if err != nil { - return err - } - for i := 0; i < len(tps); i++ { - tps[i].TPid = tpImp.TPid - } - - return tpImp.StorDb.SetTPActionPlans(tps) -} - -func (tpImp *TPCSVImporter) importActionTriggers(fn string) error { - if tpImp.Verbose { - log.Printf("Processing file: <%s> ", fn) - } - tps, err := tpImp.csvr.GetTPActionTriggers(tpImp.TPid, "") - if err != nil { - return err - } - for i := 0; i < len(tps); i++ { - tps[i].TPid = tpImp.TPid - } - - return tpImp.StorDb.SetTPActionTriggers(tps) -} - -func (tpImp *TPCSVImporter) importAccountActions(fn string) error { - if tpImp.Verbose { - log.Printf("Processing file: <%s> ", fn) - } - tps, err := tpImp.csvr.GetTPAccountActions(&utils.TPAccountActions{TPid: tpImp.TPid}) - if err != nil { - return err - } - loadId := utils.CSVLoad //Autogenerate rating profile id - if tpImp.ImportId != "" { - loadId += "_" + tpImp.ImportId - } - for i := 0; i < len(tps); i++ { - tps[i].TPid = tpImp.TPid - tps[i].LoadId = loadId - } - return tpImp.StorDb.SetTPAccountActions(tps) -} - func (tpImp *TPCSVImporter) importResources(fn string) error { if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) diff --git a/engine/tpreader.go b/engine/tpreader.go index 646e1f858..412262f3c 100644 --- a/engine/tpreader.go +++ b/engine/tpreader.go @@ -37,16 +37,8 @@ type TpReader struct { dm *DataManager lr LoadReader actions map[string][]*Action - actionPlans map[string]*ActionPlan - actionsTriggers map[string]ActionTriggers - accountActions map[string]*Account destinations map[string]*Destination timings map[string]*utils.TPTiming - rates map[string]*utils.TPRateRALs - destinationRates map[string]*utils.TPDestinationRate - ratingPlans map[string]*RatingPlan - ratingProfiles map[string]*RatingProfile - sharedGroups map[string]*SharedGroup resProfiles map[utils.TenantID]*utils.TPResourceProfile sqProfiles map[utils.TenantID]*utils.TPStatProfile thProfiles map[utils.TenantID]*utils.TPThresholdProfile @@ -89,16 +81,8 @@ func NewTpReader(db DataDB, lr LoadReader, tpid, timezone string, func (tpr *TpReader) Init() { tpr.actions = make(map[string][]*Action) - tpr.actionPlans = make(map[string]*ActionPlan) - tpr.actionsTriggers = make(map[string]ActionTriggers) - tpr.rates = make(map[string]*utils.TPRateRALs) tpr.destinations = make(map[string]*Destination) - tpr.destinationRates = make(map[string]*utils.TPDestinationRate) tpr.timings = make(map[string]*utils.TPTiming) - tpr.ratingPlans = make(map[string]*RatingPlan) - tpr.ratingProfiles = make(map[string]*RatingProfile) - tpr.sharedGroups = make(map[string]*SharedGroup) - tpr.accountActions = make(map[string]*Account) tpr.resProfiles = make(map[utils.TenantID]*utils.TPResourceProfile) tpr.sqProfiles = make(map[utils.TenantID]*utils.TPStatProfile) tpr.thProfiles = make(map[utils.TenantID]*utils.TPThresholdProfile) @@ -165,278 +149,6 @@ func (tpr *TpReader) LoadTimings() (err error) { return err } -func (tpr *TpReader) LoadRates() (err error) { - tps, err := tpr.lr.GetTPRates(tpr.tpid, "") - if err != nil { - return err - } - tpr.rates, err = MapTPRates(tps) - return err -} - -func (tpr *TpReader) LoadDestinationRates() (err error) { - tps, err := tpr.lr.GetTPDestinationRates(tpr.tpid, "", nil) - if err != nil { - return err - } - tpr.destinationRates, err = MapTPDestinationRates(tps) - if err != nil { - return err - } - for _, drs := range tpr.destinationRates { - for _, dr := range drs.DestinationRates { - rate, exists := tpr.rates[dr.RateId] - if !exists { - return fmt.Errorf("could not find rate for tag %v", dr.RateId) - } - dr.Rate = rate - destinationExists := dr.DestinationId == utils.MetaAny - if !destinationExists { - _, destinationExists = tpr.destinations[dr.DestinationId] - } - if !destinationExists && tpr.dm.dataDB != nil { - if destinationExists, err = tpr.dm.HasData(utils.DestinationPrefix, dr.DestinationId, ""); err != nil { - return err - } - } - if !destinationExists { - return fmt.Errorf("could not get destination for tag %v", dr.DestinationId) - } - } - } - return nil -} - -// LoadRatingPlansFiltered returns true, nil in case of load success, false, nil in case of RatingPlan not found dataStorage -func (tpr *TpReader) LoadRatingPlansFiltered(tag string) (bool, error) { - mpRpls, err := tpr.lr.GetTPRatingPlans(tpr.tpid, tag, nil) - if err != nil { - return false, err - } else if len(mpRpls) == 0 { - return false, nil - } - - bindings := MapTPRatingPlanBindings(mpRpls) - - for tag, rplBnds := range bindings { - ratingPlan := &RatingPlan{Id: tag} - for _, rp := range rplBnds { - tm := tpr.timings - _, exists := tpr.timings[rp.TimingId] - if !exists { - tptm, err := tpr.lr.GetTPTimings(tpr.tpid, rp.TimingId) - if err != nil || len(tptm) == 0 { - return false, fmt.Errorf("no timing with id %s: %v", rp.TimingId, err) - } - tm, err = MapTPTimings(tptm) - if err != nil { - return false, err - } - } - - rp.SetTiming(tm[rp.TimingId]) - tpdrm, err := tpr.lr.GetTPDestinationRates(tpr.tpid, rp.DestinationRatesId, nil) - if err != nil || len(tpdrm) == 0 { - return false, fmt.Errorf("no DestinationRates profile with id %s: %v", rp.DestinationRatesId, err) - } - drm, err := MapTPDestinationRates(tpdrm) - if err != nil { - return false, err - } - for _, drate := range drm[rp.DestinationRatesId].DestinationRates { - tprt, err := tpr.lr.GetTPRates(tpr.tpid, drate.RateId) - if err != nil || len(tprt) == 0 { - return false, fmt.Errorf("no Rates profile with id %s: %v", drate.RateId, err) - } - rt, err := MapTPRates(tprt) - if err != nil { - return false, err - } - - drate.Rate = rt[drate.RateId] - ratingPlan.AddRateInterval(drate.DestinationId, GetRateInterval(rp, drate)) - if drate.DestinationId == utils.MetaAny { - continue // no need of loading the destinations in this case - } - - tpDests, err := tpr.lr.GetTPDestinations(tpr.tpid, drate.DestinationId) - if err != nil { - if err.Error() == utils.ErrNotFound.Error() { // if the destination doesn't exists in stordb check it in dataDB - if tpr.dm.dataDB != nil { - if dbExists, err := tpr.dm.HasData(utils.DestinationPrefix, drate.DestinationId, ""); err != nil { - return false, err - } else if dbExists { - continue - } else if !dbExists { // if the error doesn't exists in datadb return error - return false, fmt.Errorf("could not get destination for tag %v", drate.DestinationId) - } - } - } else { - return false, err - } - } - - for _, tpDst := range tpDests { - destination := NewDestinationFromTPDestination(tpDst) - tpr.dm.SetDestination(destination, utils.NonTransactional) - tpr.dm.SetReverseDestination(destination.Id, destination.Prefixes, utils.NonTransactional) - } - } - } - if err := tpr.dm.SetRatingPlan(ratingPlan, utils.NonTransactional); err != nil { - return false, err - } - } - return true, nil -} - -func (tpr *TpReader) LoadRatingPlans() (err error) { - tps, err := tpr.lr.GetTPRatingPlans(tpr.tpid, "", nil) - if err != nil { - return err - } - bindings := MapTPRatingPlanBindings(tps) - for tag, rplBnds := range bindings { - for _, rplBnd := range rplBnds { - t, exists := tpr.timings[rplBnd.TimingId] - if !exists { - return fmt.Errorf("could not get timing for tag %v", rplBnd.TimingId) - } - rplBnd.SetTiming(t) - drs, exists := tpr.destinationRates[rplBnd.DestinationRatesId] - if !exists { - return fmt.Errorf("could not find destination rate for tag %v", rplBnd.DestinationRatesId) - } - plan, exists := tpr.ratingPlans[tag] - if !exists { - plan = &RatingPlan{Id: tag} - tpr.ratingPlans[plan.Id] = plan - } - for _, dr := range drs.DestinationRates { - plan.AddRateInterval(dr.DestinationId, GetRateInterval(rplBnd, dr)) - } - } - } - return nil -} - -func (tpr *TpReader) LoadRatingProfilesFiltered(qriedRpf *utils.TPRatingProfile) error { - var resultRatingProfile *RatingProfile - mpTpRpfs, err := tpr.lr.GetTPRatingProfiles(qriedRpf) - if err != nil { - return fmt.Errorf("no RateProfile for filter %v, error: %v", qriedRpf, err) - } - - rpfs, err := MapTPRatingProfiles(mpTpRpfs) - if err != nil { - return err - } - for _, tpRpf := range rpfs { - resultRatingProfile = &RatingProfile{Id: tpRpf.KeyId()} - for _, tpRa := range tpRpf.RatingPlanActivations { - at, err := utils.ParseTimeDetectLayout(tpRa.ActivationTime, tpr.timezone) - if err != nil { - return fmt.Errorf("cannot parse activation time from %v", tpRa.ActivationTime) - } - _, exists := tpr.ratingPlans[tpRa.RatingPlanId] - if !exists && tpr.dm.dataDB != nil { - if exists, err = tpr.dm.HasData(utils.RatingPlanPrefix, tpRa.RatingPlanId, ""); err != nil { - return err - } - } - if !exists { - return fmt.Errorf("could not load rating plans for tag: %v", tpRa.RatingPlanId) - } - resultRatingProfile.RatingPlanActivations = append(resultRatingProfile.RatingPlanActivations, - &RatingPlanActivation{ - ActivationTime: at, - RatingPlanId: tpRa.RatingPlanId, - FallbackKeys: utils.FallbackSubjKeys(tpRpf.Tenant, - tpRpf.Category, tpRa.FallbackSubjects), - }) - } - if err := tpr.dm.SetRatingProfile(resultRatingProfile, utils.NonTransactional); err != nil { - return err - } - tpr.ratingProfiles[tpRpf.KeyId()] = resultRatingProfile - } - return nil -} - -func (tpr *TpReader) LoadRatingProfiles() (err error) { - tps, err := tpr.lr.GetTPRatingProfiles(&utils.TPRatingProfile{TPid: tpr.tpid}) - if err != nil { - return err - } - mpTpRpfs, err := MapTPRatingProfiles(tps) - if err != nil { - return err - } - for _, tpRpf := range mpTpRpfs { - rpf := &RatingProfile{Id: tpRpf.KeyId()} - for _, tpRa := range tpRpf.RatingPlanActivations { - at, err := utils.ParseTimeDetectLayout(tpRa.ActivationTime, tpr.timezone) - if err != nil { - return fmt.Errorf("cannot parse activation time from %v", tpRa.ActivationTime) - } - _, exists := tpr.ratingPlans[tpRa.RatingPlanId] - if !exists && tpr.dm.dataDB != nil { // Only query if there is a connection, eg on dry run there is none - if exists, err = tpr.dm.HasData(utils.RatingPlanPrefix, tpRa.RatingPlanId, ""); err != nil { - return err - } - } - if !exists { - return fmt.Errorf("could not load rating plans for tag: %v", tpRa.RatingPlanId) - } - rpf.RatingPlanActivations = append(rpf.RatingPlanActivations, - &RatingPlanActivation{ - ActivationTime: at, - RatingPlanId: tpRa.RatingPlanId, - FallbackKeys: utils.FallbackSubjKeys(tpRpf.Tenant, - tpRpf.Category, tpRa.FallbackSubjects), - }) - } - tpr.ratingProfiles[tpRpf.KeyId()] = rpf - } - return nil -} - -func (tpr *TpReader) LoadSharedGroupsFiltered(tag string, save bool) (err error) { - tps, err := tpr.lr.GetTPSharedGroups(tpr.tpid, "") - if err != nil { - return err - } - storSgs := MapTPSharedGroup(tps) - for tag, tpSgs := range storSgs { - sg, exists := tpr.sharedGroups[tag] - if !exists { - sg = &SharedGroup{ - Id: tag, - AccountParameters: make(map[string]*SharingParameters, len(tpSgs)), - } - } - for _, tpSg := range tpSgs { - sg.AccountParameters[tpSg.Account] = &SharingParameters{ - Strategy: tpSg.Strategy, - RatingSubject: tpSg.RatingSubject, - } - } - tpr.sharedGroups[tag] = sg - } - if save { - for _, sg := range tpr.sharedGroups { - if err := tpr.dm.SetSharedGroup(sg, utils.NonTransactional); err != nil { - return err - } - } - } - return nil -} - -func (tpr *TpReader) LoadSharedGroups() error { - return tpr.LoadSharedGroupsFiltered(tpr.tpid, false) -} - func (tpr *TpReader) LoadActions() (err error) { tps, err := tpr.lr.GetTPActions(tpr.tpid, "") if err != nil { @@ -545,566 +257,6 @@ func (tpr *TpReader) LoadActions() (err error) { return nil } -func (tpr *TpReader) LoadActionPlans() (err error) { - tps, err := tpr.lr.GetTPActionPlans(tpr.tpid, "") - if err != nil { - return err - } - storAps := MapTPActionTimings(tps) - for atID, ats := range storAps { - for _, at := range ats { - - _, exists := tpr.actions[at.ActionsId] - if !exists && tpr.dm.dataDB != nil { - if exists, err = tpr.dm.HasData(utils.ActionPrefix, at.ActionsId, ""); err != nil { - return fmt.Errorf("[ActionPlans] Error querying actions: %v - %s", at.ActionsId, err.Error()) - } - } - if !exists { - return fmt.Errorf("[ActionPlans] Could not load the action for tag: %v", at.ActionsId) - } - t, exists := tpr.timings[at.TimingId] - if !exists { - return fmt.Errorf("[ActionPlans] Could not load the timing for tag: %v", at.TimingId) - } - var actPln *ActionPlan - if actPln, exists = tpr.actionPlans[atID]; !exists { - actPln = &ActionPlan{ - Id: atID, - } - } - actPln.ActionTimings = append(actPln.ActionTimings, &ActionTiming{ - Uuid: utils.GenUUID(), - Weight: at.Weight, - Timing: &RateInterval{ - Timing: &RITiming{ - ID: at.TimingId, - Years: t.Years, - Months: t.Months, - MonthDays: t.MonthDays, - WeekDays: t.WeekDays, - StartTime: t.StartTime, - }, - }, - ActionsID: at.ActionsId, - }) - - tpr.actionPlans[atID] = actPln - } - } - return nil -} - -func (tpr *TpReader) LoadActionTriggers() (err error) { - tps, err := tpr.lr.GetTPActionTriggers(tpr.tpid, "") - if err != nil { - return err - } - storAts := MapTPActionTriggers(tps) - for key, atrsLst := range storAts { - atrs := make([]*ActionTrigger, len(atrsLst)) - for idx, atr := range atrsLst { - expirationDate, err := utils.ParseTimeDetectLayout(atr.ExpirationDate, tpr.timezone) - if err != nil { - return err - } - activationDate, err := utils.ParseTimeDetectLayout(atr.ActivationDate, tpr.timezone) - if err != nil { - return err - } - minSleep, err := utils.ParseDurationWithNanosecs(atr.MinSleep) - if err != nil { - return err - } - if atr.UniqueID == "" { - atr.UniqueID = utils.GenUUID() - } - atrs[idx] = &ActionTrigger{ - ID: key, - UniqueID: atr.UniqueID, - ThresholdType: atr.ThresholdType, - ThresholdValue: atr.ThresholdValue, - Recurrent: atr.Recurrent, - MinSleep: minSleep, - ExpirationDate: expirationDate, - ActivationDate: activationDate, - Balance: &BalanceFilter{}, - Weight: atr.Weight, - ActionsID: atr.ActionsId, - } - if atr.BalanceId != "" && atr.BalanceId != utils.MetaAny { - atrs[idx].Balance.ID = utils.StringPointer(atr.BalanceId) - } - - if atr.BalanceType != "" && atr.BalanceType != utils.MetaAny { - atrs[idx].Balance.Type = utils.StringPointer(atr.BalanceType) - } - - if atr.BalanceWeight != "" && atr.BalanceWeight != utils.MetaAny { - u, err := strconv.ParseFloat(atr.BalanceWeight, 64) - if err != nil { - return err - } - atrs[idx].Balance.Weight = utils.Float64Pointer(u) - } - if atr.BalanceExpirationDate != "" && atr.BalanceExpirationDate != utils.MetaAny && atr.ExpirationDate != utils.MetaUnlimited { - u, err := utils.ParseTimeDetectLayout(atr.BalanceExpirationDate, tpr.timezone) - if err != nil { - return err - } - atrs[idx].Balance.ExpirationDate = utils.TimePointer(u) - } - if atr.BalanceRatingSubject != "" && atr.BalanceRatingSubject != utils.MetaAny { - atrs[idx].Balance.RatingSubject = utils.StringPointer(atr.BalanceRatingSubject) - } - - if atr.BalanceCategories != "" && atr.BalanceCategories != utils.MetaAny { - atrs[idx].Balance.Categories = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceCategories)) - } - if atr.BalanceDestinationIds != "" && atr.BalanceDestinationIds != utils.MetaAny { - atrs[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDestinationIds)) - } - if atr.BalanceSharedGroups != "" && atr.BalanceSharedGroups != utils.MetaAny { - atrs[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceSharedGroups)) - } - if atr.BalanceTimingTags != "" && atr.BalanceTimingTags != utils.MetaAny { - atrs[idx].Balance.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceTimingTags)) - } - if atr.BalanceBlocker != "" && atr.BalanceBlocker != utils.MetaAny { - u, err := strconv.ParseBool(atr.BalanceBlocker) - if err != nil { - return err - } - atrs[idx].Balance.Blocker = utils.BoolPointer(u) - } - if atr.BalanceDisabled != "" && atr.BalanceDisabled != utils.MetaAny { - u, err := strconv.ParseBool(atr.BalanceDisabled) - if err != nil { - return err - } - atrs[idx].Balance.Disabled = utils.BoolPointer(u) - } - } - tpr.actionsTriggers[key] = atrs - } - - return nil -} - -func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions) error { - accountActions, err := tpr.lr.GetTPAccountActions(qriedAA) - if err != nil { - return errors.New(err.Error() + ": " + fmt.Sprintf("%+v", qriedAA)) - } - storAas, err := MapTPAccountActions(accountActions) - if err != nil { - return err - } - for _, accountAction := range storAas { - id := accountAction.KeyId() - var actionIDs []string // collects action ids - // action timings - if accountAction.ActionPlanId != "" { - // get old userBalanceIds - exitingAccountIds := make(utils.StringMap) - existingActionPlan, err := tpr.dm.GetActionPlan(accountAction.ActionPlanId, true, utils.NonTransactional) - if err == nil && existingActionPlan != nil { - exitingAccountIds = existingActionPlan.AccountIDs - } - - tpap, err := tpr.lr.GetTPActionPlans(tpr.tpid, accountAction.ActionPlanId) - if err != nil { - return errors.New(err.Error() + " (ActionPlan): " + accountAction.ActionPlanId) - } else if len(tpap) == 0 { - return fmt.Errorf("no action plan with id <%s>", accountAction.ActionPlanId) - } - aps := MapTPActionTimings(tpap) - var actionPlan *ActionPlan - ats := aps[accountAction.ActionPlanId] - for _, at := range ats { - // Check action exists before saving it inside actionTiming key - // ToDo: try saving the key after the actions was retrieved in order to save one query here. - if actions, err := tpr.lr.GetTPActions(tpr.tpid, at.ActionsId); err != nil { - return errors.New(err.Error() + " (Actions): " + at.ActionsId) - } else if len(actions) == 0 { - return fmt.Errorf("no action with id <%s>", at.ActionsId) - } - var t *utils.TPTiming - if at.TimingId != utils.MetaASAP { - tptm, err := tpr.lr.GetTPTimings(tpr.tpid, at.TimingId) - if err != nil { - return errors.New(err.Error() + " (Timing): " + at.TimingId) - } else if len(tptm) == 0 { - return fmt.Errorf("no timing with id <%s>", at.TimingId) - } - tm, err := MapTPTimings(tptm) - if err != nil { - return err - } - t = tm[at.TimingId] - } else { - t = tpr.timings[at.TimingId] // *asap - } - if actionPlan == nil { - actionPlan = &ActionPlan{ - Id: accountAction.ActionPlanId, - } - } - actionPlan.ActionTimings = append(actionPlan.ActionTimings, &ActionTiming{ - Uuid: utils.GenUUID(), - Weight: at.Weight, - Timing: &RateInterval{ - Timing: &RITiming{ - ID: at.TimingId, - Months: t.Months, - MonthDays: t.MonthDays, - WeekDays: t.WeekDays, - StartTime: t.StartTime, - }, - }, - ActionsID: at.ActionsId, - }) - // collect action ids from timings - actionIDs = append(actionIDs, at.ActionsId) - exitingAccountIds[id] = true - actionPlan.AccountIDs = exitingAccountIds - } - // write tasks - for _, at := range actionPlan.ActionTimings { - if at.IsASAP() { - for accID := range actionPlan.AccountIDs { - t := &Task{ - Uuid: utils.GenUUID(), - AccountID: accID, - ActionsID: at.ActionsID, - } - if err = tpr.dm.DataDB().PushTask(t); err != nil { - return err - } - } - } - } - // write action plan - if err = tpr.dm.SetActionPlan(accountAction.ActionPlanId, actionPlan, false, utils.NonTransactional); err != nil { - return errors.New(err.Error() + " (SetActionPlan): " + accountAction.ActionPlanId) - } - if err = tpr.dm.SetAccountActionPlans(id, []string{accountAction.ActionPlanId}, false); err != nil { - return err - } - var reply string - if err := connMgr.Call(tpr.cacheConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{ - utils.AccountActionPlanIDs: {id}, - utils.ActionPlanIDs: {accountAction.ActionPlanId}, - }, - }, &reply); err != nil { - return err - } - - } - // action triggers - var actionTriggers ActionTriggers - //ActionTriggerPriotityList []*ActionTrigger - if accountAction.ActionTriggersId != "" { - tpatrs, err := tpr.lr.GetTPActionTriggers(tpr.tpid, accountAction.ActionTriggersId) - if err != nil { - return errors.New(err.Error() + " (ActionTriggers): " + accountAction.ActionTriggersId) - } - atrs := MapTPActionTriggers(tpatrs) - atrsMap := make(map[string][]*ActionTrigger) - for key, atrsLst := range atrs { - atrs := make([]*ActionTrigger, len(atrsLst)) - for idx, atr := range atrsLst { - minSleep, _ := utils.ParseDurationWithNanosecs(atr.MinSleep) - expTime, _ := utils.ParseTimeDetectLayout(atr.ExpirationDate, tpr.timezone) - actTime, _ := utils.ParseTimeDetectLayout(atr.ActivationDate, tpr.timezone) - if atr.UniqueID == "" { - atr.UniqueID = utils.GenUUID() - } - atrs[idx] = &ActionTrigger{ - ID: key, - UniqueID: atr.UniqueID, - ThresholdType: atr.ThresholdType, - ThresholdValue: atr.ThresholdValue, - Recurrent: atr.Recurrent, - MinSleep: minSleep, - ExpirationDate: expTime, - ActivationDate: actTime, - Balance: &BalanceFilter{}, - Weight: atr.Weight, - ActionsID: atr.ActionsId, - } - if atr.BalanceId != "" && atr.BalanceId != utils.MetaAny { - atrs[idx].Balance.ID = utils.StringPointer(atr.BalanceId) - } - - if atr.BalanceType != "" && atr.BalanceType != utils.MetaAny { - atrs[idx].Balance.Type = utils.StringPointer(atr.BalanceType) - } - - if atr.BalanceWeight != "" && atr.BalanceWeight != utils.MetaAny { - u, err := strconv.ParseFloat(atr.BalanceWeight, 64) - if err != nil { - return err - } - atrs[idx].Balance.Weight = utils.Float64Pointer(u) - } - if atr.BalanceExpirationDate != "" && atr.BalanceExpirationDate != utils.MetaAny && atr.ExpirationDate != utils.MetaUnlimited { - u, err := utils.ParseTimeDetectLayout(atr.BalanceExpirationDate, tpr.timezone) - if err != nil { - return err - } - atrs[idx].Balance.ExpirationDate = utils.TimePointer(u) - } - if atr.BalanceRatingSubject != "" && atr.BalanceRatingSubject != utils.MetaAny { - atrs[idx].Balance.RatingSubject = utils.StringPointer(atr.BalanceRatingSubject) - } - - if atr.BalanceCategories != "" && atr.BalanceCategories != utils.MetaAny { - atrs[idx].Balance.Categories = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceCategories)) - } - if atr.BalanceDestinationIds != "" && atr.BalanceDestinationIds != utils.MetaAny { - atrs[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceDestinationIds)) - } - if atr.BalanceSharedGroups != "" && atr.BalanceSharedGroups != utils.MetaAny { - atrs[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceSharedGroups)) - } - if atr.BalanceTimingTags != "" && atr.BalanceTimingTags != utils.MetaAny { - atrs[idx].Balance.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(atr.BalanceTimingTags)) - } - if atr.BalanceBlocker != "" && atr.BalanceBlocker != utils.MetaAny { - u, err := strconv.ParseBool(atr.BalanceBlocker) - if err != nil { - return err - } - atrs[idx].Balance.Blocker = utils.BoolPointer(u) - } - if atr.BalanceDisabled != "" && atr.BalanceDisabled != utils.MetaAny { - u, err := strconv.ParseBool(atr.BalanceDisabled) - if err != nil { - return err - } - atrs[idx].Balance.Disabled = utils.BoolPointer(u) - } - } - atrsMap[key] = atrs - } - actionTriggers = atrsMap[accountAction.ActionTriggersId] - // collect action ids from triggers - for _, atr := range actionTriggers { - actionIDs = append(actionIDs, atr.ActionsID) - } - // write action triggers - if err = tpr.dm.SetActionTriggers(accountAction.ActionTriggersId, - actionTriggers, utils.NonTransactional); err != nil { - return errors.New(err.Error() + " (SetActionTriggers): " + accountAction.ActionTriggersId) - } - var reply string - if err := connMgr.Call(tpr.cacheConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{ - utils.ActionTriggerIDs: {accountAction.ActionTriggersId}, - }, - }, &reply); err != nil { - return err - } - } - - // actions - facts := make(map[string][]*Action) - for _, actID := range actionIDs { - tpas, err := tpr.lr.GetTPActions(tpr.tpid, actID) - if err != nil { - return err - } - as := MapTPActions(tpas) - for tag, tpacts := range as { - acts := make([]*Action, len(tpacts)) - for idx, tpact := range tpacts { - // check filter field - if len(tpact.Filter) > 0 { - if _, err := structmatcher.NewStructMatcher(tpact.Filter); err != nil { - return fmt.Errorf("error parsing action %s filter field: %v", tag, err) - } - } - acts[idx] = &Action{ - Id: tag, - ActionType: tpact.Identifier, - //BalanceType: tpact.BalanceType, - Weight: tpact.Weight, - ExtraParameters: tpact.ExtraParameters, - ExpirationString: tpact.ExpiryTime, - Filter: tpact.Filter, - Balance: &BalanceFilter{}, - } - if tpact.BalanceId != "" && tpact.BalanceId != utils.MetaAny { - acts[idx].Balance.ID = utils.StringPointer(tpact.BalanceId) - } - if tpact.BalanceType != "" && tpact.BalanceType != utils.MetaAny { - acts[idx].Balance.Type = utils.StringPointer(tpact.BalanceType) - } - - if tpact.Units != "" && tpact.Units != utils.MetaAny { - vf, err := utils.ParseBalanceFilterValue(tpact.BalanceType, tpact.Units) - if err != nil { - return err - } - acts[idx].Balance.Value = vf - } - - if tpact.BalanceWeight != "" && tpact.BalanceWeight != utils.MetaAny { - u, err := strconv.ParseFloat(tpact.BalanceWeight, 64) - if err != nil { - return err - } - acts[idx].Balance.Weight = utils.Float64Pointer(u) - } - if tpact.RatingSubject != "" && tpact.RatingSubject != utils.MetaAny { - acts[idx].Balance.RatingSubject = utils.StringPointer(tpact.RatingSubject) - } - - if tpact.Categories != "" && tpact.Categories != utils.MetaAny { - acts[idx].Balance.Categories = utils.StringMapPointer(utils.ParseStringMap(tpact.Categories)) - } - if tpact.DestinationIds != "" && tpact.DestinationIds != utils.MetaAny { - acts[idx].Balance.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(tpact.DestinationIds)) - } - if tpact.SharedGroups != "" && tpact.SharedGroups != utils.MetaAny { - acts[idx].Balance.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(tpact.SharedGroups)) - } - if tpact.TimingTags != "" && tpact.TimingTags != utils.MetaAny { - acts[idx].Balance.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(tpact.TimingTags)) - } - if tpact.BalanceBlocker != "" && tpact.BalanceBlocker != utils.MetaAny { - u, err := strconv.ParseBool(tpact.BalanceBlocker) - if err != nil { - return err - } - acts[idx].Balance.Blocker = utils.BoolPointer(u) - } - if tpact.BalanceDisabled != "" && tpact.BalanceDisabled != utils.MetaAny { - u, err := strconv.ParseBool(tpact.BalanceDisabled) - if err != nil { - return err - } - acts[idx].Balance.Disabled = utils.BoolPointer(u) - } - // load action timings from tags - if tpact.TimingTags != "" { - timingIds := strings.Split(tpact.TimingTags, utils.InfieldSep) - for _, timingID := range timingIds { - if timing, found := tpr.timings[timingID]; found { - acts[idx].Balance.Timings = append(acts[idx].Balance.Timings, &RITiming{ - ID: timingID, - Years: timing.Years, - Months: timing.Months, - MonthDays: timing.MonthDays, - WeekDays: timing.WeekDays, - StartTime: timing.StartTime, - EndTime: timing.EndTime, - }) - } else { - return fmt.Errorf("could not find timing: %v", timingID) - } - } - } - } - facts[tag] = acts - } - } - // write actions - for k, as := range facts { - if err = tpr.dm.SetActions(k, as, utils.NonTransactional); err != nil { - return err - } - var reply string - if err := connMgr.Call(tpr.cacheConns, nil, - utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithAPIOpts{ - ArgsCache: map[string][]string{ - utils.ActionIDs: {k}, - }, - }, &reply); err != nil { - return err - } - } - ub, err := tpr.dm.GetAccount(id) - if err != nil { - ub = &Account{ - ID: id, - } - } - ub.ActionTriggers = actionTriggers - // init counters - ub.InitCounters() - if err := tpr.dm.SetAccount(ub); err != nil { - return err - } - } - return nil -} - -func (tpr *TpReader) LoadAccountActions() (err error) { - tps, err := tpr.lr.GetTPAccountActions(&utils.TPAccountActions{TPid: tpr.tpid}) - if err != nil { - return err - } - storAts, err := MapTPAccountActions(tps) - if err != nil { - return err - } - - for _, aa := range storAts { - aaKeyID := aa.KeyId() - if _, alreadyDefined := tpr.accountActions[aa.KeyId()]; alreadyDefined { - return fmt.Errorf("duplicate account action found: %s", aaKeyID) - } - var aTriggers ActionTriggers - if aa.ActionTriggersId != "" { - var exists bool - if aTriggers, exists = tpr.actionsTriggers[aa.ActionTriggersId]; !exists { - return fmt.Errorf("could not get action triggers for tag %s", aa.ActionTriggersId) - } - } - ub := &Account{ - ID: aaKeyID, - ActionTriggers: aTriggers, - AllowNegative: aa.AllowNegative, - Disabled: aa.Disabled, - } - ub.InitCounters() - tpr.accountActions[aaKeyID] = ub - if aa.ActionPlanId != "" { - actionPlan, exists := tpr.actionPlans[aa.ActionPlanId] - if !exists { - if tpr.dm.dataDB != nil { - if actionPlan, err = tpr.dm.GetActionPlan(aa.ActionPlanId, true, utils.NonTransactional); err != nil { - if err.Error() == utils.ErrNotFound.Error() { - return fmt.Errorf("could not get action plan for tag %v", aa.ActionPlanId) - } - return err - } - exists = true - tpr.actionPlans[aa.ActionPlanId] = actionPlan - } - if !exists { - return fmt.Errorf("could not get action plan for tag %v", aa.ActionPlanId) - } - } - if actionPlan.AccountIDs == nil { - actionPlan.AccountIDs = make(utils.StringMap) - } - - actionPlan.AccountIDs[aaKeyID] = true - if _, hasKey := tpr.acntActionPlans[aaKeyID]; !hasKey { - tpr.acntActionPlans[aaKeyID] = make([]string, 0) - } - tpr.acntActionPlans[aaKeyID] = append(tpr.acntActionPlans[aaKeyID], aa.ActionPlanId) - } - } - return nil -} - func (tpr *TpReader) LoadResourceProfilesFiltered(tag string) (err error) { rls, err := tpr.lr.GetTPResources(tpr.tpid, "", tag) if err != nil { @@ -1358,33 +510,9 @@ func (tpr *TpReader) LoadAll() (err error) { if err = tpr.LoadTimings(); err != nil && err.Error() != utils.NotFoundCaps { return } - if err = tpr.LoadRates(); err != nil && err.Error() != utils.NotFoundCaps { - return - } - if err = tpr.LoadDestinationRates(); err != nil && err.Error() != utils.NotFoundCaps { - return - } - if err = tpr.LoadRatingPlans(); err != nil && err.Error() != utils.NotFoundCaps { - return - } - if err = tpr.LoadRatingProfiles(); err != nil && err.Error() != utils.NotFoundCaps { - return - } - if err = tpr.LoadSharedGroups(); err != nil && err.Error() != utils.NotFoundCaps { - return - } if err = tpr.LoadActions(); err != nil && err.Error() != utils.NotFoundCaps { return } - if err = tpr.LoadActionPlans(); err != nil && err.Error() != utils.NotFoundCaps { - return - } - if err = tpr.LoadActionTriggers(); err != nil && err.Error() != utils.NotFoundCaps { - return - } - if err = tpr.LoadAccountActions(); err != nil && err.Error() != utils.NotFoundCaps { - return - } if err = tpr.LoadFilters(); err != nil && err.Error() != utils.NotFoundCaps { return } @@ -1424,25 +552,6 @@ func (tpr *TpReader) LoadAll() (err error) { return nil } -func (tpr *TpReader) IsValid() (valid bool) { - valid = true - for rplTag, rpl := range tpr.ratingPlans { - if !rpl.isContinous() { - log.Printf("The rating plan %s is not covering all weekdays", rplTag) - valid = false - } - if crazyRate := rpl.getFirstUnsaneRating(); crazyRate != "" { - log.Printf("The rate %s is invalid", crazyRate) - valid = false - } - if crazyTiming := rpl.getFirstUnsaneTiming(); crazyTiming != "" { - log.Printf("The timing %s is invalid", crazyTiming) - valid = false - } - } - return -} - func (tpr *TpReader) WriteToDatabase(verbose, disableReverse bool) (err error) { if tpr.dm.dataDB == nil { return errors.New("no database connection") @@ -1465,118 +574,7 @@ func (tpr *TpReader) WriteToDatabase(verbose, disableReverse bool) (err error) { loadIDs[utils.CacheDestinations] = loadID loadIDs[utils.CacheReverseDestinations] = loadID } - if verbose { - log.Print("Rating Plans:") - } - for _, rp := range tpr.ratingPlans { - if err = tpr.dm.SetRatingPlan(rp, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Print("\t", rp.Id) - } - } - if len(tpr.ratingPlans) != 0 { - loadIDs[utils.CacheRatingPlans] = loadID - } - if verbose { - log.Print("Rating Profiles:") - } - for _, rp := range tpr.ratingProfiles { - if err = tpr.dm.SetRatingProfile(rp, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Print("\t", rp.Id) - } - } - if len(tpr.ratingProfiles) != 0 { - loadIDs[utils.CacheRatingProfiles] = loadID - } - if verbose { - log.Print("Action Plans:") - } - for k, ap := range tpr.actionPlans { - var hasScheduled bool - for _, at := range ap.ActionTimings { - if at.IsASAP() { - for accID := range ap.AccountIDs { - t := &Task{ - Uuid: utils.GenUUID(), - AccountID: accID, - ActionsID: at.ActionsID, - } - if verbose { - log.Println("\tTask: ", t) - } - if err = tpr.dm.DataDB().PushTask(t); err != nil { - return - } - } - if len(ap.AccountIDs) == 0 { - t := &Task{ - Uuid: utils.GenUUID(), - ActionsID: at.ActionsID, - } - if verbose { - log.Println("\tTask: ", t) - } - if err = tpr.dm.DataDB().PushTask(t); err != nil { - return - } - } - } else { - hasScheduled = true - } - } - if !hasScheduled { - ap.AccountIDs = utils.StringMap{} - } - if err = tpr.dm.SetActionPlan(k, ap, false, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Println("\t", k) - } - } - if len(tpr.actionPlans) != 0 { - loadIDs[utils.CacheActionPlans] = loadID - } - if len(tpr.acntActionPlans) != 0 { - loadIDs[utils.CacheAccountActionPlans] = loadID - } - if verbose { - log.Print("Account Action Plans:") - for id, vals := range tpr.acntActionPlans { - log.Printf("\t %s : %+v", id, vals) - } - log.Print("Action Triggers:") - } - for k, atrs := range tpr.actionsTriggers { - if err = tpr.dm.SetActionTriggers(k, atrs, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Println("\t", k) - } - } - if len(tpr.actionsTriggers) != 0 { - loadIDs[utils.CacheActionTriggers] = loadID - } - if verbose { - log.Print("Shared Groups:") - } - for k, sg := range tpr.sharedGroups { - if err = tpr.dm.SetSharedGroup(sg, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Println("\t", k) - } - } - if len(tpr.sharedGroups) != 0 { - loadIDs[utils.CacheSharedGroups] = loadID - } + if verbose { log.Print("Actions:") } @@ -1591,17 +589,7 @@ func (tpr *TpReader) WriteToDatabase(verbose, disableReverse bool) (err error) { if len(tpr.actions) != 0 { loadIDs[utils.CacheActions] = loadID } - if verbose { - log.Print("Account Actions:") - } - for _, ub := range tpr.accountActions { - if err = tpr.dm.SetAccount(ub); err != nil { - return - } - if verbose { - log.Println("\t", ub.ID) - } - } + if verbose { log.Print("Filters:") } @@ -1962,42 +950,8 @@ func (tpr *TpReader) ShowStatistics() { for k, v := range prefixDist { log.Printf("%d: %d", k, v) } - // rating plans - rplCount := len(tpr.ratingPlans) - log.Print("Rating plans: ", rplCount) - destRatesDist := make(map[int]int, 50) - destRatesCount := 0 - for _, rpl := range tpr.ratingPlans { - destRatesDist[len(rpl.DestinationRates)]++ - destRatesCount += len(rpl.DestinationRates) - } - log.Print("Avg Destination Rates: ", destRatesCount/rplCount) - log.Print("Destination Rates distribution:") - for k, v := range destRatesDist { - log.Printf("%d: %d", k, v) - } - // rating profiles - rpfCount := len(tpr.ratingProfiles) - log.Print("Rating profiles: ", rpfCount) - activDist := make(map[int]int, 50) - activCount := 0 - for _, rpf := range tpr.ratingProfiles { - activDist[len(rpf.RatingPlanActivations)]++ - activCount += len(rpf.RatingPlanActivations) - } - log.Print("Avg Activations: ", activCount/rpfCount) - log.Print("Activation distribution:") - for k, v := range activDist { - log.Printf("%d: %d", k, v) - } // actions log.Print("Actions: ", len(tpr.actions)) - // action plans - log.Print("Action plans: ", len(tpr.actionPlans)) - // action triggers - log.Print("Action triggers: ", len(tpr.actionsTriggers)) - // account actions - log.Print("Account actions: ", len(tpr.accountActions)) // resource profiles log.Print("ResourceProfiles: ", len(tpr.resProfiles)) // stats @@ -2041,22 +995,6 @@ func (tpr *TpReader) GetLoadedIds(categ string) ([]string, error) { } } return keys.AsSlice(), nil - case utils.RatingPlanPrefix: - keys := make([]string, len(tpr.ratingPlans)) - i := 0 - for k := range tpr.ratingPlans { - keys[i] = k - i++ - } - return keys, nil - case utils.RatingProfilePrefix: - keys := make([]string, len(tpr.ratingProfiles)) - i := 0 - for k := range tpr.ratingProfiles { - keys[i] = k - i++ - } - return keys, nil case utils.ActionPrefix: keys := make([]string, len(tpr.actions)) i := 0 @@ -2065,30 +1003,7 @@ func (tpr *TpReader) GetLoadedIds(categ string) ([]string, error) { i++ } return keys, nil - case utils.ActionPlanPrefix: // actionPlans - keys := make([]string, len(tpr.actionPlans)) - i := 0 - for k := range tpr.actionPlans { - keys[i] = k - i++ - } - return keys, nil - case utils.AccountActionPlansPrefix: - keys := make([]string, len(tpr.acntActionPlans)) - i := 0 - for k := range tpr.acntActionPlans { - keys[i] = k - i++ - } - return keys, nil - case utils.SharedGroupPrefix: - keys := make([]string, len(tpr.sharedGroups)) - i := 0 - for k := range tpr.sharedGroups { - keys[i] = k - i++ - } - return keys, nil + case utils.ResourceProfilesPrefix: keys := make([]string, len(tpr.resProfiles)) i := 0 @@ -2097,14 +1012,7 @@ func (tpr *TpReader) GetLoadedIds(categ string) ([]string, error) { i++ } return keys, nil - case utils.ActionTriggerPrefix: - keys := make([]string, len(tpr.actionsTriggers)) - i := 0 - for k := range tpr.actionsTriggers { - keys[i] = k - i++ - } - return keys, nil + case utils.StatQueueProfilePrefix: keys := make([]string, len(tpr.sqProfiles)) i := 0 @@ -2202,62 +1110,6 @@ func (tpr *TpReader) RemoveFromDatabase(verbose, disableReverse bool) (err error log.Print("\t", d.Id, " : ", d.Prefixes) } } - for _, rp := range tpr.ratingPlans { - if err = tpr.dm.RemoveRatingPlan(rp.Id, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Print("\t", rp.Id) - } - } - if verbose { - log.Print("Rating Profiles:") - } - for _, rp := range tpr.ratingProfiles { - if err = tpr.dm.RemoveRatingProfile(rp.Id, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Print("\t", rp.Id) - } - } - if verbose { - log.Print("Action Plans:") - } - for k := range tpr.actionPlans { - if err = tpr.dm.RemoveActionPlan(k, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Println("\t", k) - } - } - if verbose { - log.Print("Account Action Plans:") - for id, vals := range tpr.acntActionPlans { - log.Printf("\t %s : %+v", id, vals) - } - log.Print("Action Triggers:") - } - for k := range tpr.actionsTriggers { - if err = tpr.dm.RemoveActionTriggers(k, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Println("\t", k) - } - } - if verbose { - log.Print("Shared Groups:") - } - for k := range tpr.sharedGroups { - if err = tpr.dm.RemoveSharedGroup(k, utils.NonTransactional); err != nil { - return - } - if verbose { - log.Println("\t", k) - } - } if verbose { log.Print("Actions:") } @@ -2269,17 +1121,6 @@ func (tpr *TpReader) RemoveFromDatabase(verbose, disableReverse bool) (err error log.Println("\t", k) } } - if verbose { - log.Print("Account Actions:") - } - for _, ub := range tpr.accountActions { - if err = tpr.dm.RemoveAccount(ub.ID); err != nil { - return - } - if verbose { - log.Println("\t", ub.ID) - } - } if verbose { log.Print("ResourceProfiles:") } @@ -2495,24 +1336,9 @@ func (tpr *TpReader) RemoveFromDatabase(verbose, disableReverse bool) (err error loadIDs[utils.CacheDestinations] = loadID loadIDs[utils.CacheReverseDestinations] = loadID } - if len(tpr.ratingPlans) != 0 { - loadIDs[utils.CacheRatingPlans] = loadID - } - if len(tpr.ratingProfiles) != 0 { - loadIDs[utils.CacheRatingProfiles] = loadID - } - if len(tpr.actionPlans) != 0 { - loadIDs[utils.CacheActionPlans] = loadID - } if len(tpr.acntActionPlans) != 0 { loadIDs[utils.CacheAccountActionPlans] = loadID } - if len(tpr.actionsTriggers) != 0 { - loadIDs[utils.CacheActionTriggers] = loadID - } - if len(tpr.sharedGroups) != 0 { - loadIDs[utils.CacheSharedGroups] = loadID - } if len(tpr.actions) != 0 { loadIDs[utils.CacheActions] = loadID } diff --git a/engine/z_loader_it_test.go b/engine/z_loader_it_test.go index db19302f5..40da432c4 100644 --- a/engine/z_loader_it_test.go +++ b/engine/z_loader_it_test.go @@ -169,15 +169,6 @@ func testLoaderITRemoveLoad(t *testing.T) { if err = loader.LoadActions(); err != nil { t.Error("Failed loading actions: ", err.Error()) } - if err = loader.LoadActionPlans(); err != nil { - t.Error("Failed loading action timings: ", err.Error()) - } - if err = loader.LoadActionTriggers(); err != nil { - t.Error("Failed loading action triggers: ", err.Error()) - } - if err = loader.LoadAccountActions(); err != nil { - t.Error("Failed loading account actions: ", err.Error()) - } if err = loader.LoadFilters(); err != nil { t.Error("Failed loading filters: ", err.Error()) } @@ -248,15 +239,6 @@ func testLoaderITLoadFromCSV(t *testing.T) { if err = loader.LoadActions(); err != nil { t.Error("Failed loading actions: ", err.Error()) } - if err = loader.LoadActionPlans(); err != nil { - t.Error("Failed loading action timings: ", err.Error()) - } - if err = loader.LoadActionTriggers(); err != nil { - t.Error("Failed loading action triggers: ", err.Error()) - } - if err = loader.LoadAccountActions(); err != nil { - t.Error("Failed loading account actions: ", err.Error()) - } if err = loader.LoadFilters(); err != nil { t.Error("Failed loading filters: ", err.Error()) } @@ -548,15 +530,6 @@ func testLoaderITLoadFromStorDb(t *testing.T) { if err := loader.LoadActions(); err != nil && err.Error() != utils.NotFoundCaps { t.Error("Failed loading actions: ", err.Error()) } - if err := loader.LoadActionPlans(); err != nil && err.Error() != utils.NotFoundCaps { - t.Error("Failed loading action timings: ", err.Error()) - } - if err := loader.LoadActionTriggers(); err != nil && err.Error() != utils.NotFoundCaps { - t.Error("Failed loading action triggers: ", err.Error()) - } - if err := loader.LoadAccountActions(); err != nil && err.Error() != utils.NotFoundCaps { - t.Error("Failed loading account actions: ", err.Error()) - } } func testLoaderITLoadIndividualProfiles(t *testing.T) { @@ -587,19 +560,6 @@ func testLoaderITLoadIndividualProfiles(t *testing.T) { } } - // Load account actions - if aas, err := storDb.GetTPAccountActions(&utils.TPAccountActions{TPid: utils.TestSQL, LoadId: loadId}); err != nil { - t.Fatal("Could not retrieve account action profiles, error: ", err.Error()) - } else if len(aas) == 0 { - t.Error("No account actions") - } else { - - for _, a := range aas { - if err := loader.LoadAccountActionsFiltered(a); err != nil { - t.Fatalf("Could not load account actions with id: %s, error: %s", a.GetId(), err.Error()) - } - } - } } /* diff --git a/engine/z_stordb_it_test.go b/engine/z_stordb_it_test.go index f22652d4d..cd4d371f4 100644 --- a/engine/z_stordb_it_test.go +++ b/engine/z_stordb_it_test.go @@ -62,9 +62,6 @@ var sTestsStorDBit = []func(t *testing.T){ testStorDBitCRUDTpRatingProfiles, testStorDBitCRUDTpSharedGroups, testStorDBitCRUDTpActions, - testStorDBitCRUDTpActionPlans, - testStorDBitCRUDTpActionTriggers, - testStorDBitCRUDTpAccountActions, testStorDBitCRUDTpResources, testStorDBitCRUDTpStats, testStorDBitCRUDCDRs, @@ -1533,238 +1530,6 @@ func testStorDBitCRUDTpActions(t *testing.T) { } } -func testStorDBitCRUDTpActionPlans(t *testing.T) { - // READ - if _, err := storDB.GetTPActionPlans("testTPid", ""); err != utils.ErrNotFound { - t.Error(err) - } - // WRITE - var snd = []*utils.TPActionPlan{ - { - TPid: "testTPid", - ID: "1", - ActionPlan: []*utils.TPActionTiming{ - { - ActionsId: "1", - TimingId: "1", - Weight: 1, - }, - }, - }, - { - TPid: "testTPid", - ID: "2", - ActionPlan: []*utils.TPActionTiming{ - { - ActionsId: "1", - TimingId: "1", - Weight: 1, - }, - }, - }, - } - if err := storDB.SetTPActionPlans(snd); err != nil { - t.Error(err) - } - // READ - if rcv, err := storDB.GetTPActionPlans("testTPid", ""); err != nil { - t.Error(err) - } else { - if !(reflect.DeepEqual(snd[0], rcv[0]) || reflect.DeepEqual(snd[0], rcv[1])) { - t.Errorf("Expecting:\n%+v\nReceived:\n%+v\n||\n%+v", utils.ToJSON(snd[0]), utils.ToJSON(rcv[0]), utils.ToJSON(rcv[1])) - } - } - // UPDATE - snd[0].ActionPlan[0].TimingId = "test" - snd[1].ActionPlan[0].TimingId = "test" - if err := storDB.SetTPActionPlans(snd); err != nil { - t.Error(err) - } - // READ - if rcv, err := storDB.GetTPActionPlans("testTPid", ""); err != nil { - t.Error(err) - } else { - if !(reflect.DeepEqual(snd[0], rcv[0]) || reflect.DeepEqual(snd[0], rcv[1])) { - t.Errorf("Expecting:\n%+v\nReceived:\n%+v\n||\n%+v", utils.ToJSON(snd[0]), utils.ToJSON(rcv[0]), utils.ToJSON(rcv[1])) - } - } - // REMOVE - if err := storDB.RemTpData("", "testTPid", nil); err != nil { - t.Error(err) - } - // READ - if _, err := storDB.GetTPActionPlans("testTPid", ""); err != utils.ErrNotFound { - t.Error(err) - } -} - -func testStorDBitCRUDTpActionTriggers(t *testing.T) { - // READ - if _, err := storDB.GetTPActionTriggers("testTPid", ""); err != utils.ErrNotFound { - t.Error(err) - } - // WRITE - var snd = []*utils.TPActionTriggers{ - { - TPid: "testTPid", - ID: "1", - ActionTriggers: []*utils.TPActionTrigger{ - { - Id: "1", - UniqueID: "", - ThresholdType: "1", - ThresholdValue: 0, - Recurrent: true, - MinSleep: "", - ExpirationDate: "2014-07-29T15:00:00Z", - ActivationDate: "2014-07-29T15:00:00Z", - BalanceId: "test", - BalanceType: "*monetary", - BalanceDestinationIds: "call", - BalanceWeight: "0.0", - BalanceExpirationDate: "2014-07-29T15:00:00Z", - BalanceTimingTags: "T1", - BalanceRatingSubject: "test", - BalanceCategories: "", - BalanceSharedGroups: "SHARED_1", - BalanceBlocker: "false", - BalanceDisabled: "false", - ActionsId: "test", - Weight: 1.0, - }, - }, - }, - { - TPid: "testTPid", - ID: "2", - ActionTriggers: []*utils.TPActionTrigger{ - { - Id: "2", - UniqueID: "", - ThresholdType: "1", - ThresholdValue: 0, - Recurrent: true, - MinSleep: "", - ExpirationDate: "2014-07-29T15:00:00Z", - ActivationDate: "2014-07-29T15:00:00Z", - BalanceId: "test", - BalanceType: "*monetary", - BalanceDestinationIds: "call", - BalanceWeight: "0.0", - BalanceExpirationDate: "2014-07-29T15:00:00Z", - BalanceTimingTags: "T1", - BalanceRatingSubject: "test", - BalanceCategories: "", - BalanceSharedGroups: "SHARED_1", - BalanceBlocker: "false", - BalanceDisabled: "false", - ActionsId: "test", - Weight: 1.0, - }, - }, - }, - } - if err := storDB.SetTPActionTriggers(snd); err != nil { - t.Error(err) - } - // READ - if rcv, err := storDB.GetTPActionTriggers("testTPid", ""); err != nil { - t.Error(err) - } else { - if !(reflect.DeepEqual(snd[0], rcv[0]) || reflect.DeepEqual(snd[0], rcv[1])) { - t.Errorf("Expecting:\n%+v\nReceived:\n%+v\n||\n%+v", utils.ToJSON(snd[0]), utils.ToJSON(rcv[0]), utils.ToJSON(rcv[1])) - } - } - // UPDATE - snd[0].ActionTriggers[0].ActionsId = "test2" - snd[1].ActionTriggers[0].ActionsId = "test2" - if err := storDB.SetTPActionTriggers(snd); err != nil { - t.Error(err) - } - // READ - if rcv, err := storDB.GetTPActionTriggers("testTPid", ""); err != nil { - t.Error(err) - } else { - if !(reflect.DeepEqual(snd[0], rcv[0]) || reflect.DeepEqual(snd[0], rcv[1])) { - t.Errorf("Expecting:\n%+v\nReceived:\n%+v\n||\n%+v", utils.ToJSON(snd[0]), utils.ToJSON(rcv[0]), utils.ToJSON(rcv[1])) - } - } - // REMOVE - if err := storDB.RemTpData("", "testTPid", nil); err != nil { - t.Error(err) - } - // READ - if _, err := storDB.GetTPActionTriggers("testTPid", ""); err != utils.ErrNotFound { - t.Error(err) - } -} - -func testStorDBitCRUDTpAccountActions(t *testing.T) { - // READ - var filter = utils.TPAccountActions{ - TPid: "testTPid", - } - if _, err := storDB.GetTPAccountActions(&filter); err != utils.ErrNotFound { - t.Error(err) - } - // WRITE - var snd = []*utils.TPAccountActions{ - { - TPid: "testTPid", - LoadId: "TEST_LOADID", - Tenant: "cgrates.org", - Account: "1001", - ActionPlanId: "PACKAGE_10_SHARED_A_5", - ActionTriggersId: "STANDARD_TRIGGERS", - AllowNegative: true, - Disabled: true, - }, - { - TPid: "testTPid", - LoadId: "TEST_LOADID", - Tenant: "cgrates.org", - Account: "1002", - ActionPlanId: "PACKAGE_10_SHARED_A_5", - ActionTriggersId: "STANDARD_TRIGGERS", - AllowNegative: true, - Disabled: true, - }, - } - if err := storDB.SetTPAccountActions(snd); err != nil { - t.Error(err) - } - // READ - if rcv, err := storDB.GetTPAccountActions(&filter); err != nil { - t.Error(err) - } else { - if !(reflect.DeepEqual(snd[0], rcv[0]) || reflect.DeepEqual(snd[0], rcv[1])) { - t.Errorf("Expecting:\n%+v\nReceived:\n%+v\n||\n%+v", utils.ToJSON(snd[0]), utils.ToJSON(rcv[0]), utils.ToJSON(rcv[1])) - } - } - // UPDATE - snd[0].Disabled = false - snd[1].Disabled = false - if err := storDB.SetTPAccountActions(snd); err != nil { - t.Error(err) - } - // READ - if rcv, err := storDB.GetTPAccountActions(&filter); err != nil { - t.Error(err) - } else { - if !(reflect.DeepEqual(snd[0], rcv[0]) || reflect.DeepEqual(snd[0], rcv[1])) { - t.Errorf("Expecting:\n%+v\nReceived:\n%+v\n||\n%+v", utils.ToJSON(snd[0]), utils.ToJSON(rcv[0]), utils.ToJSON(rcv[1])) - } - } - // REMOVE - if err := storDB.RemTpData("", "testTPid", nil); err != nil { - t.Error(err) - } - // READ - if _, err := storDB.GetTPAccountActions(&filter); err != utils.ErrNotFound { - t.Error(err) - } -} - func testStorDBitCRUDTpResources(t *testing.T) { // READ if _, err := storDB.GetTPResources("testTPid", "", ""); err != utils.ErrNotFound { diff --git a/services/apiers_it_test.go b/services/apiers_it_test.go index c2e3f8a84..688924b6c 100644 --- a/services/apiers_it_test.go +++ b/services/apiers_it_test.go @@ -63,7 +63,7 @@ func TestApiersReload(t *testing.T) { schS := NewSchedulerService(cfg, db, chS, filterSChan, server, make(chan rpcclient.ClientConnector, 1), nil, anz, srvDep) tS := NewThresholdService(cfg, db, chS, filterSChan, server, make(chan rpcclient.ClientConnector, 1), anz, srvDep) rspd := NewResponderService(cfg, server, make(chan rpcclient.ClientConnector, 1), shdChan, anz, srvDep) - apiSv1 := NewAPIerSv1Service(cfg, db, stordb, filterSChan, server, schS, rspd, + apiSv1 := NewAPIerSv1Service(cfg, db, stordb, filterSChan, server, rspd, make(chan rpcclient.ClientConnector, 1), nil, anz, srvDep) apiSv2 := NewAPIerSv2Service(apiSv1, cfg, server, make(chan rpcclient.ClientConnector, 1), anz, srvDep) diff --git a/services/apierv1.go b/services/apierv1.go index 6d238b144..b27f83538 100644 --- a/services/apierv1.go +++ b/services/apierv1.go @@ -34,7 +34,6 @@ import ( func NewAPIerSv1Service(cfg *config.CGRConfig, dm *DataDBService, storDB *StorDBService, filterSChan chan *engine.FilterS, server *cores.Server, - actService *ActionService, responderService *ResponderService, internalAPIerSv1Chan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService, @@ -46,7 +45,6 @@ func NewAPIerSv1Service(cfg *config.CGRConfig, dm *DataDBService, storDB: storDB, filterSChan: filterSChan, server: server, - actService: actService, responderService: responderService, connMgr: connMgr, APIerSv1Chan: make(chan *v1.APIerSv1, 1), @@ -63,7 +61,6 @@ type APIerSv1Service struct { storDB *StorDBService filterSChan chan *engine.FilterS server *cores.Server - actService *ActionService responderService *ResponderService connMgr *engine.ConnManager @@ -101,14 +98,13 @@ func (apiService *APIerSv1Service) Start() (err error) { defer apiService.Unlock() apiService.api = &v1.APIerSv1{ - DataManager: datadb, - CdrDb: stordb, - StorDb: stordb, - Config: apiService.cfg, - ActionService: apiService.actService, - FilterS: filterS, - ConnMgr: apiService.connMgr, - StorDBChan: storDBChan, + DataManager: datadb, + CdrDb: stordb, + StorDb: stordb, + Config: apiService.cfg, + FilterS: filterS, + ConnMgr: apiService.connMgr, + StorDBChan: storDBChan, Responder: apiService.responderService.GetResponder(), // if already started use it ResponderChan: respChan, // if not wait in listenAndServe diff --git a/services/rals.go b/services/rals.go deleted file mode 100644 index 01da8527c..000000000 --- a/services/rals.go +++ /dev/null @@ -1,134 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package services - -import ( - "sync" - - v1 "github.com/cgrates/cgrates/apier/v1" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/cores" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" - "github.com/cgrates/rpcclient" -) - -// NewRalService returns the Ral Service -func NewRalService(cfg *config.CGRConfig, cacheS *engine.CacheS, server *cores.Server, - internalRALsChan, internalResponderChan chan rpcclient.ClientConnector, shdChan *utils.SyncedChan, - connMgr *engine.ConnManager, anz *AnalyzerService, - srvDep map[string]*sync.WaitGroup) *RalService { - resp := NewResponderService(cfg, server, internalResponderChan, shdChan, anz, srvDep) - - return &RalService{ - connChan: internalRALsChan, - cfg: cfg, - cacheS: cacheS, - server: server, - responder: resp, - connMgr: connMgr, - anz: anz, - srvDep: srvDep, - } -} - -// RalService implements Service interface -type RalService struct { - sync.RWMutex - cfg *config.CGRConfig - cacheS *engine.CacheS - server *cores.Server - rals *v1.RALsV1 - responder *ResponderService - connChan chan rpcclient.ClientConnector - connMgr *engine.ConnManager - anz *AnalyzerService - srvDep map[string]*sync.WaitGroup -} - -// Start should handle the sercive start -// For this service the start should be called from RAL Service -func (rals *RalService) Start() (err error) { - if rals.IsRunning() { - return utils.ErrServiceAlreadyRunning - } - engine.SetRpSubjectPrefixMatching(rals.cfg.RalsCfg().RpSubjectPrefixMatching) - rals.Lock() - defer rals.Unlock() - - <-rals.cacheS.GetPrecacheChannel(utils.CacheDestinations) - <-rals.cacheS.GetPrecacheChannel(utils.CacheReverseDestinations) - <-rals.cacheS.GetPrecacheChannel(utils.CacheRatingPlans) - <-rals.cacheS.GetPrecacheChannel(utils.CacheRatingProfiles) - <-rals.cacheS.GetPrecacheChannel(utils.CacheActions) - <-rals.cacheS.GetPrecacheChannel(utils.CacheActionPlans) - <-rals.cacheS.GetPrecacheChannel(utils.CacheAccountActionPlans) - <-rals.cacheS.GetPrecacheChannel(utils.CacheActionTriggers) - <-rals.cacheS.GetPrecacheChannel(utils.CacheSharedGroups) - <-rals.cacheS.GetPrecacheChannel(utils.CacheTimings) - rals.responder.Start() //we don't verify the error because responder.Start() always returns service already running - - rals.rals = v1.NewRALsV1() - - if !rals.cfg.DispatcherSCfg().Enabled { - rals.server.RpcRegister(rals.rals) - } - - rals.connChan <- rals.anz.GetInternalCodec(rals.rals, utils.RALService) - return -} - -// Reload handles the change of config -func (rals *RalService) Reload() (err error) { - engine.SetRpSubjectPrefixMatching(rals.cfg.RalsCfg().RpSubjectPrefixMatching) - rals.responder.Reload() //we don't verify the error because responder.Reload never returns an error - return -} - -// Shutdown stops the service -func (rals *RalService) Shutdown() (err error) { - rals.Lock() - defer rals.Unlock() - err = rals.responder.Shutdown() //we don't verify the error because responder.Reload never returns an error - rals.rals = nil - <-rals.connChan - return -} - -// IsRunning returns if the service is running -func (rals *RalService) IsRunning() bool { - rals.RLock() - defer rals.RUnlock() - return rals != nil && rals.rals != nil -} - -// ServiceName returns the service name -func (rals *RalService) ServiceName() string { - return utils.RALService -} - -// ShouldRun returns if the service should be running -func (rals *RalService) ShouldRun() bool { - return rals.cfg.RalsCfg().Enabled -} - -// GetResponder returns the responder service -func (rals *RalService) GetResponder() *ResponderService { - return rals.responder -} diff --git a/services/rals_it_test.go b/services/rals_it_test.go deleted file mode 100644 index ae714809c..000000000 --- a/services/rals_it_test.go +++ /dev/null @@ -1,175 +0,0 @@ -// +build integration - -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package services - -import ( - "path" - "sync" - "testing" - "time" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/cores" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/servmanager" - "github.com/cgrates/cgrates/utils" - "github.com/cgrates/rpcclient" -) - -func TestRalsReload(t *testing.T) { - cfg := config.NewDefaultCGRConfig() - - utils.Logger, _ = utils.Newlogger(utils.MetaSysLog, cfg.GeneralCfg().NodeID) - utils.Logger.SetLogLevel(7) - filterSChan := make(chan *engine.FilterS, 1) - filterSChan <- nil - shdChan := utils.NewSyncedChan() - shdWg := new(sync.WaitGroup) - chS := engine.NewCacheS(cfg, nil, nil) - close(chS.GetPrecacheChannel(utils.CacheThresholdProfiles)) - close(chS.GetPrecacheChannel(utils.CacheThresholds)) - close(chS.GetPrecacheChannel(utils.CacheThresholdFilterIndexes)) - - close(chS.GetPrecacheChannel(utils.CacheDestinations)) - close(chS.GetPrecacheChannel(utils.CacheReverseDestinations)) - close(chS.GetPrecacheChannel(utils.CacheRatingPlans)) - close(chS.GetPrecacheChannel(utils.CacheRatingProfiles)) - close(chS.GetPrecacheChannel(utils.CacheActions)) - close(chS.GetPrecacheChannel(utils.CacheActionPlans)) - close(chS.GetPrecacheChannel(utils.CacheAccountActionPlans)) - close(chS.GetPrecacheChannel(utils.CacheActionTriggers)) - close(chS.GetPrecacheChannel(utils.CacheSharedGroups)) - close(chS.GetPrecacheChannel(utils.CacheTimings)) - - cfg.ThresholdSCfg().Enabled = true - server := cores.NewServer(nil) - srvMngr := servmanager.NewServiceManager(cfg, shdChan, shdWg, nil) - srvDep := map[string]*sync.WaitGroup{utils.DataDB: new(sync.WaitGroup)} - db := NewDataDBService(cfg, nil, srvDep) - cfg.StorDbCfg().Type = utils.INTERNAL - anz := NewAnalyzerService(cfg, server, filterSChan, shdChan, make(chan rpcclient.ClientConnector, 1), srvDep) - stordb := NewStorDBService(cfg, srvDep) - schS := NewSchedulerService(cfg, db, chS, filterSChan, server, make(chan rpcclient.ClientConnector, 1), nil, anz, srvDep) - tS := NewThresholdService(cfg, db, chS, filterSChan, server, make(chan rpcclient.ClientConnector, 1), anz, srvDep) - ralS := NewRalService(cfg, chS, server, - make(chan rpcclient.ClientConnector, 1), - make(chan rpcclient.ClientConnector, 1), - shdChan, nil, anz, srvDep) - srvMngr.AddServices(ralS, schS, tS, - NewLoaderService(cfg, db, filterSChan, server, make(chan rpcclient.ClientConnector, 1), nil, anz, srvDep), db, stordb) - if err := srvMngr.StartServices(); err != nil { - t.Error(err) - } - if ralS.IsRunning() { - t.Errorf("Expected service to be down") - } - if db.IsRunning() { - t.Errorf("Expected service to be down") - } - if stordb.IsRunning() { - t.Errorf("Expected service to be down") - } - var reply string - if err := cfg.V1ReloadConfig(&config.ReloadArgs{ - Path: path.Join("/usr", "share", "cgrates", "conf", "samples", "tutmongo"), - Section: config.RALS_JSN, - }, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Errorf("Expecting OK ,received %s", reply) - } - time.Sleep(10 * time.Millisecond) //need to switch to gorutine - if !ralS.IsRunning() { - t.Errorf("Expected service to be running") - } - - if resp := ralS.GetResponder(); !resp.IsRunning() { - t.Errorf("Expected service to be running") - } - - if !db.IsRunning() { - t.Errorf("Expected service to be running") - } - if !stordb.IsRunning() { - t.Errorf("Expected service to be running") - } - err := ralS.Start() - if err == nil || err != utils.ErrServiceAlreadyRunning { - t.Errorf("\nExpecting <%+v>,\n Received <%+v>", utils.ErrServiceAlreadyRunning, err) - } - err = ralS.Reload() - if err != nil { - t.Errorf("\nExpecting ,\n Received <%+v>", err) - } - cfg.RalsCfg().Enabled = false - cfg.GetReloadChan(config.RALS_JSN) <- struct{}{} - time.Sleep(10 * time.Millisecond) - if ralS.IsRunning() { - t.Errorf("Expected service to be down") - } - if resp := ralS.GetResponder(); resp.IsRunning() { - t.Errorf("Expected service to be down") - } - shdChan.CloseOnce() - time.Sleep(10 * time.Millisecond) -} -func TestRalsReload2(t *testing.T) { - cfg := config.NewDefaultCGRConfig() - - utils.Logger, _ = utils.Newlogger(utils.MetaSysLog, cfg.GeneralCfg().NodeID) - utils.Logger.SetLogLevel(7) - filterSChan := make(chan *engine.FilterS, 1) - filterSChan <- nil - shdChan := utils.NewSyncedChan() - chS := engine.NewCacheS(cfg, nil, nil) - close(chS.GetPrecacheChannel(utils.CacheThresholdProfiles)) - close(chS.GetPrecacheChannel(utils.CacheThresholds)) - close(chS.GetPrecacheChannel(utils.CacheThresholdFilterIndexes)) - close(chS.GetPrecacheChannel(utils.CacheDestinations)) - close(chS.GetPrecacheChannel(utils.CacheReverseDestinations)) - close(chS.GetPrecacheChannel(utils.CacheRatingPlans)) - close(chS.GetPrecacheChannel(utils.CacheRatingProfiles)) - close(chS.GetPrecacheChannel(utils.CacheActions)) - close(chS.GetPrecacheChannel(utils.CacheActionPlans)) - close(chS.GetPrecacheChannel(utils.CacheAccountActionPlans)) - close(chS.GetPrecacheChannel(utils.CacheActionTriggers)) - close(chS.GetPrecacheChannel(utils.CacheSharedGroups)) - close(chS.GetPrecacheChannel(utils.CacheTimings)) - - cfg.ThresholdSCfg().Enabled = true - server := cores.NewServer(nil) - srvDep := map[string]*sync.WaitGroup{utils.DataDB: new(sync.WaitGroup)} - cfg.StorDbCfg().Type = utils.INTERNAL - anz := NewAnalyzerService(cfg, server, filterSChan, shdChan, make(chan rpcclient.ClientConnector, 1), srvDep) - ralS := NewRalService(cfg, chS, server, - make(chan rpcclient.ClientConnector, 1), - make(chan rpcclient.ClientConnector, 1), - shdChan, nil, anz, srvDep) - ralS.responder.resp = &engine.Responder{ - ShdChan: shdChan, - Timeout: 0, - Timezone: "", - MaxComputedUsage: nil, - } - err := ralS.Start() - if err != nil { - t.Fatalf("\nExpecting <%+v>,\n Received <%+v>", nil, err) - } -} diff --git a/services/rals_test.go b/services/rals_test.go deleted file mode 100644 index 614b3be60..000000000 --- a/services/rals_test.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package services - -import ( - "reflect" - "sync" - "testing" - - v1 "github.com/cgrates/cgrates/apier/v1" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/cores" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" - "github.com/cgrates/rpcclient" -) - -//TestRalsCoverage for cover testing -func TestRalsCoverage(t *testing.T) { - cfg := config.NewDefaultCGRConfig() - filterSChan := make(chan *engine.FilterS, 1) - filterSChan <- nil - shdChan := utils.NewSyncedChan() - chS := engine.NewCacheS(cfg, nil, nil) - cfg.ThresholdSCfg().Enabled = true - server := cores.NewServer(nil) - srvDep := map[string]*sync.WaitGroup{utils.DataDB: new(sync.WaitGroup)} - cfg.StorDbCfg().Type = utils.INTERNAL - anz := NewAnalyzerService(cfg, server, filterSChan, shdChan, make(chan rpcclient.ClientConnector, 1), srvDep) - ralS := NewRalService(cfg, chS, server, - make(chan rpcclient.ClientConnector, 1), - make(chan rpcclient.ClientConnector, 1), - shdChan, nil, anz, srvDep) - if ralS.IsRunning() { - t.Errorf("Expected service to be down") - } - ralS2 := RalService{ - responder: &ResponderService{ - cfg: cfg, - server: server, - shdChan: shdChan, - resp: &engine.Responder{}, - connChan: make(chan rpcclient.ClientConnector, 1), - anz: anz, - srvDep: srvDep, - }, - cfg: cfg, - cacheS: chS, - server: server, - rals: &v1.RALsV1{}, - connChan: make(chan rpcclient.ClientConnector, 1), - } - ralS2.responder.connChan <- chS - if !ralS2.IsRunning() { - t.Errorf("Expected service to be running") - } - serviceName := ralS2.ServiceName() - if !reflect.DeepEqual(serviceName, utils.RALService) { - t.Errorf("\nExpecting <%+v>,\n Received <%+v>", utils.RALService, serviceName) - } - shouldRun := ralS2.ShouldRun() - if !reflect.DeepEqual(shouldRun, false) { - t.Errorf("\nExpecting ,\n Received <%+v>", shouldRun) - } - if !reflect.DeepEqual(ralS2.GetResponder(), ralS2.responder) { - t.Errorf("\nExpecting <%+v>,\n Received <%+v>", ralS2.responder, ralS2.GetResponder()) - } - ralS2.connChan <- chS - ralS2.Shutdown() - if ralS.IsRunning() { - t.Errorf("Expected service to be down") - } -} diff --git a/services/sessions_it_test.go b/services/sessions_it_test.go index c386ac4e9..1a91169d3 100644 --- a/services/sessions_it_test.go +++ b/services/sessions_it_test.go @@ -153,13 +153,7 @@ func TestSessionSReload2(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheChargerFilterIndexes)) close(chS.GetPrecacheChannel(utils.CacheDestinations)) close(chS.GetPrecacheChannel(utils.CacheReverseDestinations)) - close(chS.GetPrecacheChannel(utils.CacheRatingPlans)) - close(chS.GetPrecacheChannel(utils.CacheRatingProfiles)) close(chS.GetPrecacheChannel(utils.CacheActions)) - close(chS.GetPrecacheChannel(utils.CacheActionPlans)) - close(chS.GetPrecacheChannel(utils.CacheAccountActionPlans)) - close(chS.GetPrecacheChannel(utils.CacheActionTriggers)) - close(chS.GetPrecacheChannel(utils.CacheSharedGroups)) close(chS.GetPrecacheChannel(utils.CacheTimings)) internalChan := make(chan rpcclient.ClientConnector, 1) @@ -215,13 +209,7 @@ func TestSessionSReload3(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheChargerFilterIndexes)) close(chS.GetPrecacheChannel(utils.CacheDestinations)) close(chS.GetPrecacheChannel(utils.CacheReverseDestinations)) - close(chS.GetPrecacheChannel(utils.CacheRatingPlans)) - close(chS.GetPrecacheChannel(utils.CacheRatingProfiles)) close(chS.GetPrecacheChannel(utils.CacheActions)) - close(chS.GetPrecacheChannel(utils.CacheActionPlans)) - close(chS.GetPrecacheChannel(utils.CacheAccountActionPlans)) - close(chS.GetPrecacheChannel(utils.CacheActionTriggers)) - close(chS.GetPrecacheChannel(utils.CacheSharedGroups)) close(chS.GetPrecacheChannel(utils.CacheTimings)) internalChan := make(chan rpcclient.ClientConnector, 1) diff --git a/services/stordb_it_test.go b/services/stordb_it_test.go index 367fd1a50..2e1b8a982 100644 --- a/services/stordb_it_test.go +++ b/services/stordb_it_test.go @@ -51,7 +51,6 @@ func TestStorDBReload(t *testing.T) { stordb := NewStorDBService(cfg, srvDep) anz := NewAnalyzerService(cfg, server, filterSChan, shdChan, make(chan rpcclient.ClientConnector, 1), srvDep) chrS := NewChargerService(cfg, db, chS, filterSChan, server, make(chan rpcclient.ClientConnector, 1), nil, anz, srvDep) - schS := NewSchedulerService(cfg, db, chS, filterSChan, server, make(chan rpcclient.ClientConnector, 1), nil, anz, srvDep) ralS := NewRalService(cfg, chS, server, make(chan rpcclient.ClientConnector, 1), make(chan rpcclient.ClientConnector, 1), @@ -59,7 +58,7 @@ func TestStorDBReload(t *testing.T) { cdrsRPC := make(chan rpcclient.ClientConnector, 1) cdrS := NewCDRServer(cfg, db, stordb, filterSChan, server, cdrsRPC, nil, anz, srvDep) - srvMngr.AddServices(cdrS, ralS, schS, chrS, + srvMngr.AddServices(cdrS, ralS, chrS, NewLoaderService(cfg, db, filterSChan, server, make(chan rpcclient.ClientConnector, 1), nil, anz, srvDep), db, stordb) if err := srvMngr.StartServices(); err != nil { diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 0852ab00b..3e13dc22e 100755 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -98,81 +98,6 @@ type TPDestination struct { Prefixes []string // Prefixes attached to this destination } -// This file deals with tp_* data definition -// TPRateRALs -> TPRateRALs -type TPRateRALs struct { - TPid string // Tariff plan id - ID string // Rate id - RateSlots []*RateSlot // One or more RateSlots -} - -// Needed so we make sure we always use SetDurations() on a newly created value -func NewRateSlot(connectFee, rate float64, rateUnit, rateIncrement, grpInterval string) (*RateSlot, error) { - rs := &RateSlot{ - ConnectFee: connectFee, - Rate: rate, - RateUnit: rateUnit, - RateIncrement: rateIncrement, - GroupIntervalStart: grpInterval, - } - if err := rs.SetDurations(); err != nil { - return nil, err - } - return rs, nil -} - -type RateSlot struct { - ConnectFee float64 // ConnectFee applied once the call is answered - Rate float64 // Rate applied - RateUnit string // Number of billing units this rate applies to - RateIncrement string // This rate will apply in increments of duration - GroupIntervalStart string // Group position - rateUnitDur time.Duration - rateIncrementDur time.Duration - groupIntervalStartDur time.Duration - tag string // load validation only -} - -// Used to set the durations we need out of strings -func (rs *RateSlot) SetDurations() error { - var err error - if rs.rateUnitDur, err = ParseDurationWithNanosecs(rs.RateUnit); err != nil { - return err - } - if rs.rateIncrementDur, err = ParseDurationWithNanosecs(rs.RateIncrement); err != nil { - return err - } - if rs.groupIntervalStartDur, err = ParseDurationWithNanosecs(rs.GroupIntervalStart); err != nil { - return err - } - return nil -} -func (rs *RateSlot) RateUnitDuration() time.Duration { - return rs.rateUnitDur -} -func (rs *RateSlot) RateIncrementDuration() time.Duration { - return rs.rateIncrementDur -} -func (rs *RateSlot) GroupIntervalStartDuration() time.Duration { - return rs.groupIntervalStartDur -} - -type TPDestinationRate struct { - TPid string // Tariff plan id - ID string // DestinationRate profile id - DestinationRates []*DestinationRate // Set of destinationid-rateid bindings -} - -type DestinationRate struct { - DestinationId string // The destination identity - RateId string // The rate identity - Rate *TPRateRALs - RoundingMethod string - RoundingDecimals int - MaxCost float64 - MaxCostStrategy string -} - type ApierTPTiming struct { TPid string // Tariff plan id ID string // Timing id @@ -215,117 +140,12 @@ func NewTiming(ID, years, mounths, mounthdays, weekdays, time string) (rt *TPTim return } -type TPRatingPlan struct { - TPid string // Tariff plan id - ID string // RatingPlan profile id - RatingPlanBindings []*TPRatingPlanBinding // Set of destinationid-rateid bindings -} - -type TPRatingPlanBinding struct { - DestinationRatesId string // The DestinationRate identity - TimingId string // The timing identity - Weight float64 // Binding priority taken into consideration when more DestinationRates are active on a time slot - timing *TPTiming // Not exporting it via JSON -} - -func (self *TPRatingPlanBinding) SetTiming(tm *TPTiming) { - self.timing = tm -} - -func (self *TPRatingPlanBinding) Timing() *TPTiming { - return self.timing -} - -type TPRatingProfile struct { - TPid string // Tariff plan id - LoadId string // Gives ability to load specific RatingProfile based on load identifier, hence being able to keep history also in stordb - Tenant string // Tenant's Id - Category string // TypeOfRecord - Subject string // Rating subject, usually the same as account - RatingPlanActivations []*TPRatingActivation // Activate rate profiles at specific time -} - -// Used as key in nosql db (eg: redis) -func (rpf *TPRatingProfile) KeyId() string { - return ConcatenatedKey(MetaOut, - rpf.Tenant, rpf.Category, rpf.Subject) -} - -func (rpf *TPRatingProfile) GetId() string { - return ConcatenatedKey(rpf.LoadId, MetaOut, - rpf.Tenant, rpf.Category, rpf.Subject) -} - -func (rpf *TPRatingProfile) SetRatingProfileID(id string) error { - ids := strings.Split(id, ConcatenatedKeySep) - if len(ids) != 4 { - return fmt.Errorf("Wrong TPRatingProfileId: %s", id) - } - rpf.LoadId = ids[0] - rpf.Tenant = ids[1] - rpf.Category = ids[2] - rpf.Subject = ids[3] - return nil -} - -type AttrSetRatingProfile struct { - Tenant string // Tenant's Id - Category string // TypeOfRecord - Subject string // Rating subject, usually the same as account - Overwrite bool // Overwrite if exists - RatingPlanActivations []*TPRatingActivation // Activate rating plans at specific time -} - -type AttrGetRatingProfile struct { - Tenant string // Tenant's Id - Category string // TypeOfRecord - Subject string // Rating subject, usually the same as account -} - -func (self *AttrGetRatingProfile) GetID() string { - return ConcatenatedKey(MetaOut, self.Tenant, self.Category, self.Subject) -} - -type TPRatingActivation struct { - ActivationTime string // Time when this profile will become active, defined as unix epoch time - RatingPlanId string // Id of RatingPlan profile - FallbackSubjects string // So we follow the api -} - -// Helper to return the subject fallback keys we need in dataDb -func FallbackSubjKeys(tenant, tor, fallbackSubjects string) []string { - var sslice sort.StringSlice - if len(fallbackSubjects) != 0 { - for _, fbs := range strings.Split(fallbackSubjects, string(FallbackSep)) { - newKey := ConcatenatedKey(MetaOut, tenant, tor, fbs) - i := sslice.Search(newKey) - if i < len(sslice) && sslice[i] != newKey { - // not found so insert it - sslice = append(sslice, "") - copy(sslice[i+1:], sslice[i:]) - sslice[i] = newKey - } else if i == len(sslice) { - // not found and at the end - sslice = append(sslice, newKey) - } // newKey was found - } - } - return sslice -} - type AttrSetDestination struct { Id string Prefixes []string Overwrite bool } -type AttrTPRatingProfileIds struct { - TPid string // Tariff plan id - Tenant string // Tenant's Id - Category string // TypeOfRecord - Subject string // Rating subject, usually the same as account -} - type TPActions struct { TPid string // Tariff plan id ID string // Actions id @@ -352,91 +172,6 @@ type TPAction struct { Weight float64 // Action's weight } -type TPSharedGroups struct { - TPid string - ID string - SharedGroups []*TPSharedGroup -} - -type TPSharedGroup struct { - Account string - Strategy string - RatingSubject string -} - -type TPActionPlan struct { - TPid string // Tariff plan id - ID string // ActionPlan id - ActionPlan []*TPActionTiming // Set of ActionTiming bindings this profile will group -} - -type TPActionTiming struct { - ActionsId string // Actions id - TimingId string // Timing profile id - Weight float64 // Binding's weight -} - -type TPActionTriggers struct { - TPid string // Tariff plan id - ID string // action trigger id - ActionTriggers []*TPActionTrigger // Set of triggers grouped in this profile -} - -type TPActionTrigger struct { - Id string // group id - UniqueID string // individual id - ThresholdType string // This threshold type - ThresholdValue float64 // Threshold - Recurrent bool // reset executed flag each run - MinSleep string // Minimum duration between two executions in case of recurrent triggers - ExpirationDate string // Trigger expiration - ActivationDate string // Trigger activation - BalanceId string // The id of the balance in the account - BalanceType string // Type of balance this trigger monitors - BalanceDestinationIds string // filter for balance - BalanceWeight string // filter for balance - BalanceExpirationDate string // filter for balance - BalanceTimingTags string // filter for balance - BalanceRatingSubject string // filter for balance - BalanceCategories string // filter for balance - BalanceSharedGroups string // filter for balance - BalanceBlocker string // filter for balance - BalanceDisabled string // filter for balance - ActionsId string // Actions which will execute on threshold reached - Weight float64 // weight -} - -type TPAccountActions struct { - TPid string // Tariff plan id - LoadId string // LoadId, used to group actions on a load - Tenant string // Tenant's Id - Account string // Account name - ActionPlanId string // Id of ActionPlan profile to use - ActionTriggersId string // Id of ActionTriggers profile to use - AllowNegative bool - Disabled bool -} - -// Returns the id used in some nosql dbs (eg: redis) -func (aa *TPAccountActions) KeyId() string { - return ConcatenatedKey(aa.Tenant, aa.Account) -} - -func (aa *TPAccountActions) GetId() string { - return aa.LoadId + ConcatenatedKeySep + aa.Tenant + ConcatenatedKeySep + aa.Account -} - -func (aa *TPAccountActions) SetAccountActionsId(id string) error { - ids := strings.Split(id, ConcatenatedKeySep) - if len(ids) != 3 { - return fmt.Errorf("Wrong TP Account Action Id: %s", id) - } - aa.LoadId = ids[0] - aa.Tenant = ids[1] - aa.Account = ids[2] - return nil -} - type AttrGetAccount struct { Tenant string Account string diff --git a/utils/apitpdata_test.go b/utils/apitpdata_test.go index 1ec45df56..e527aa905 100644 --- a/utils/apitpdata_test.go +++ b/utils/apitpdata_test.go @@ -90,34 +90,6 @@ func TestPaginatorPaginateStringSlice(t *testing.T) { } } -func TestNewRateSlot(t *testing.T) { - var err error - eOut := &RateSlot{ - ConnectFee: 1, - Rate: 1.01, - RateUnit: "1", - RateIncrement: "1", - GroupIntervalStart: "1", - rateUnitDur: 1, - rateIncrementDur: 1, - groupIntervalStartDur: 1, - tag: "", - } - rcv, err := NewRateSlot(eOut.ConnectFee, eOut.Rate, eOut.RateUnit, eOut.RateIncrement, eOut.GroupIntervalStart) - if err != nil { - t.Error(err) - } - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected: %+v ,received: %+v ", eOut, rcv) - } - eOut.RateUnit = "a" - _, err = NewRateSlot(eOut.ConnectFee, eOut.Rate, eOut.RateUnit, eOut.RateIncrement, eOut.GroupIntervalStart) - //must receive from time an error: "invalid duration a" - if err == nil || err.Error() != "time: invalid duration \"a\"" { - t.Error(err) - } -} - func TestClonePaginator(t *testing.T) { expectedPaginator := Paginator{ Limit: IntPointer(2), @@ -129,55 +101,6 @@ func TestClonePaginator(t *testing.T) { } } -func TestSetDurations(t *testing.T) { - rs := &RateSlot{ - RateUnit: "1", - RateIncrement: "1", - GroupIntervalStart: "1", - } - //must receive "nil" with - if err := rs.SetDurations(); err != nil { - t.Error(err) - } - rs.RateUnit = "a" - //at RateUnit if, must receive from time an error: "invalid duration a" - if err := rs.SetDurations(); err == nil || err.Error() != "time: invalid duration \"a\"" { - t.Error(err) - } - rs.RateUnit = "1" - rs.RateIncrement = "a" - //at RateIncrement, must receive from time an error: "invalid duration a" - if err := rs.SetDurations(); err == nil || err.Error() != "time: invalid duration \"a\"" { - t.Error(err) - } - rs.RateIncrement = "1" - rs.GroupIntervalStart = "a" - //at GroupIntervalStart, must receive from time an error: "invalid duration a" - if err := rs.SetDurations(); err == nil || err.Error() != "time: invalid duration \"a\"" { - t.Error(err) - } -} - -func TestRateUnitDuration(t *testing.T) { - eOut := &RateSlot{ - rateUnitDur: 1, - rateIncrementDur: 1, - groupIntervalStartDur: 1, - } - rcv := eOut.RateUnitDuration() - if rcv != eOut.rateUnitDur { - t.Errorf("Expected %+v, received %+v", eOut.rateUnitDur, rcv) - } - rcv = eOut.RateIncrementDuration() - if rcv != eOut.rateIncrementDur { - t.Errorf("Expected %+v, received %+v", eOut.rateIncrementDur, rcv) - } - rcv = eOut.GroupIntervalStartDuration() - if rcv != eOut.groupIntervalStartDur { - t.Errorf("Expected %+v, received %+v", eOut.groupIntervalStartDur, rcv) - } -} - func TestNewTiming(t *testing.T) { eOut := &TPTiming{ ID: "1", @@ -206,170 +129,6 @@ func TestNewTiming(t *testing.T) { } } -func TestTPTimingSetTiming(t *testing.T) { - tpTiming := &TPTiming{ - ID: "1", - Years: Years{2020}, - Months: []time.Month{time.April}, - MonthDays: MonthDays{18}, - WeekDays: WeekDays{06}, - StartTime: "00:00:00", - EndTime: "11:11:11", - } - tpRatingPlanBinding := new(TPRatingPlanBinding) - tpRatingPlanBinding.SetTiming(tpTiming) - if !reflect.DeepEqual(tpTiming, tpRatingPlanBinding.timing) { - t.Errorf("Expected %+v, received %+v", tpTiming, tpRatingPlanBinding.timing) - } - rcv := tpRatingPlanBinding.Timing() - if !reflect.DeepEqual(tpTiming, rcv) { - t.Errorf("Expected %+v, received %+v", tpTiming, rcv) - } -} - -func TestTPRatingProfileKeys(t *testing.T) { - //empty check -> KeyId - tpRatingProfile := new(TPRatingProfile) - eOut := "*out:::" - rcv := tpRatingProfile.KeyId() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } - //empty check -> GetId - eOut = ":*out:::" - rcv = tpRatingProfile.GetId() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } - // test check -> KeyId - tpRatingProfile.Tenant = "test" - tpRatingProfile.Category = "test" - tpRatingProfile.Subject = "test" - eOut = "*out:test:test:test" - rcv = tpRatingProfile.KeyId() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } - //test check -> GetId - eOut = "test:*out:test:test:test" - tpRatingProfile.TPid = "test" - tpRatingProfile.LoadId = "test" - - rcv = tpRatingProfile.GetId() - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } -} - -func TestTPRatingProfileSetRatingProfilesId(t *testing.T) { - //empty check - tpRatingProfile := new(TPRatingProfile) - tpRatingProfile.SetRatingProfileID("") - eOut := new(TPRatingProfile) - if !reflect.DeepEqual(eOut, tpRatingProfile) { - t.Errorf("Expected %+v, received %+v", eOut, tpRatingProfile) - } - //test check - tpRatingProfile.SetRatingProfileID("1:3:4:5") - eOut.LoadId = "1" - eOut.Tenant = "3" - eOut.Category = "4" - eOut.Subject = "5" - if !reflect.DeepEqual(eOut, tpRatingProfile) { - t.Errorf("Expected %+v, received %+v", eOut, tpRatingProfile) - } - //wrong TPRatingProfile sent - err := tpRatingProfile.SetRatingProfileID("1:2:3:4:5:6") - if err == nil { - t.Error("Wrong TPRatingProfileId sent and no error received") - } - -} - -func TestAttrGetRatingProfileGetID(t *testing.T) { - //empty check - attrGetRatingProfile := &AttrGetRatingProfile{ - Tenant: "", - Category: "", - Subject: "", - } - rcv := attrGetRatingProfile.GetID() - eOut := "*out:::" - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } - //test check - attrGetRatingProfile.Tenant = "cgrates" - attrGetRatingProfile.Category = "cgrates" - attrGetRatingProfile.Subject = "cgrates" - rcv = attrGetRatingProfile.GetID() - eOut = "*out:cgrates:cgrates:cgrates" - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } -} - -func TestFallbackSubjKeys(t *testing.T) { - //call with empty slice -> expect an empty slice - rcv := FallbackSubjKeys("", "", "") - if rcv != nil { - t.Errorf("Expected an empty slice") - } - //check with test vars - eOut := []string{"*out:cgrates.org:*voice:1001", "*out:cgrates.org:*voice:1002", "*out:cgrates.org:*voice:1003"} - rcv = FallbackSubjKeys("cgrates.org", MetaVoice, "1001;1003;1002") - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } -} - -func TestTPAccountActionsKeyId(t *testing.T) { - //empty check KeyIs() - tPAccountActions := new(TPAccountActions) - rcv := tPAccountActions.KeyId() - eOut := ":" - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } - //empty check GetId() - rcv = tPAccountActions.GetId() - eOut = "::" - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } - //empty check SetAccountActionsId() - err := tPAccountActions.SetAccountActionsId("") - if err == nil { - t.Errorf("Wrong TP Account Action Id not received") - } - //test check SetAccountActionsId() - err = tPAccountActions.SetAccountActionsId("loadID:cgrates.org:cgrates") - if err != nil { - t.Errorf("Expected nil") - } - expectedOut := &TPAccountActions{ - LoadId: "loadID", - Tenant: "cgrates.org", - Account: "cgrates", - } - if !reflect.DeepEqual(expectedOut, tPAccountActions) { - t.Errorf("Expected %+v, received %+v", ToJSON(expectedOut), ToJSON(tPAccountActions)) - } - //test check KeyIs() *Tenant, Account setted above via SetAccountActionsId - rcv = tPAccountActions.KeyId() - eOut = "cgrates.org:cgrates" - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } - //tect check GetID() *LoadId, tenant, account setted above via SetAccountActionsId - rcv = tPAccountActions.GetId() - eOut = "loadID:cgrates.org:cgrates" - if !reflect.DeepEqual(eOut, rcv) { - t.Errorf("Expected %+v, received %+v", eOut, rcv) - } - -} - //now working here func TestAttrGetCdrsAsCDRsFilter(t *testing.T) { attrGetCdrs := &AttrGetCdrs{ diff --git a/utils/consts.go b/utils/consts.go index edb4aae0f..0fb52c401 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -47,21 +47,19 @@ var ( CacheCDRIDs, CacheRPCConnections, CacheUCH, CacheSTIR, CacheEventCharges, MetaAPIBan, CacheCapsEvents, CacheVersions, CacheReplicationHosts}) - dataDBPartition = NewStringSet([]string{CacheDestinations, CacheReverseDestinations, CacheRatingPlans, - CacheRatingProfiles, CacheActions, CacheActionTriggers, CacheSharedGroups, CacheTimings, + dataDBPartition = NewStringSet([]string{CacheDestinations, CacheReverseDestinations, + CacheActions, CacheTimings, CacheResourceProfiles, CacheResources, CacheEventResources, CacheStatQueueProfiles, CacheStatQueues, CacheThresholdProfiles, CacheThresholds, CacheFilters, CacheRouteProfiles, CacheAttributeProfiles, CacheChargerProfiles, CacheActionProfiles, CacheDispatcherProfiles, CacheDispatcherHosts, CacheResourceFilterIndexes, CacheStatFilterIndexes, CacheThresholdFilterIndexes, CacheRouteFilterIndexes, CacheAttributeFilterIndexes, CacheChargerFilterIndexes, CacheDispatcherFilterIndexes, CacheLoadIDs, - CacheRatingProfilesTmp, CacheRateProfiles, CacheRateProfilesFilterIndexes, CacheRateFilterIndexes, + CacheRateProfiles, CacheRateProfilesFilterIndexes, CacheRateFilterIndexes, CacheActionProfilesFilterIndexes, CacheAccountProfilesFilterIndexes, CacheReverseFilterIndexes, - CacheActionPlans, CacheAccountActionPlans, CacheAccountProfiles, CacheAccounts}) + CacheAccountProfiles}) - storDBPartition = NewStringSet([]string{CacheTBLTPTimings, CacheTBLTPDestinations, CacheTBLTPRates, CacheTBLTPDestinationRates, - CacheTBLTPRatingPlans, CacheTBLTPRatingProfiles, CacheTBLTPSharedGroups, CacheTBLTPActions, - CacheTBLTPActionPlans, CacheTBLTPActionTriggers, CacheTBLTPAccountActions, CacheTBLTPResources, - CacheTBLTPStats, CacheTBLTPThresholds, CacheTBLTPFilters, CacheSessionCostsTBL, CacheCDRsTBL, + storDBPartition = NewStringSet([]string{CacheTBLTPTimings, CacheTBLTPDestinations, CacheTBLTPActions, + CacheTBLTPResources, CacheTBLTPStats, CacheTBLTPThresholds, CacheTBLTPFilters, CacheSessionCostsTBL, CacheCDRsTBL, CacheTBLTPRoutes, CacheTBLTPAttributes, CacheTBLTPChargers, CacheTBLTPDispatchers, CacheTBLTPDispatcherHosts, CacheTBLTPRateProfiles, CacheTBLTPActionProfiles, CacheTBLTPAccountProfiles}) @@ -71,13 +69,7 @@ var ( CacheInstanceToPrefix = map[string]string{ CacheDestinations: DestinationPrefix, CacheReverseDestinations: ReverseDestinationPrefix, - CacheRatingPlans: RatingPlanPrefix, - CacheRatingProfiles: RatingProfilePrefix, CacheActions: ActionPrefix, - CacheActionPlans: ActionPlanPrefix, - CacheAccountActionPlans: AccountActionPlansPrefix, - CacheActionTriggers: ActionTriggerPrefix, - CacheSharedGroups: SharedGroupPrefix, CacheResourceProfiles: ResourceProfilesPrefix, CacheResources: ResourcesPrefix, CacheTimings: TimingsPrefix, @@ -106,7 +98,6 @@ var ( CacheAccountProfilesFilterIndexes: AccountProfileFilterIndexPrfx, CacheLoadIDs: LoadIDPrefix, - CacheAccounts: AccountPrefix, CacheRateFilterIndexes: RateFilterIndexPrfx, CacheReverseFilterIndexes: FilterIndexPrfx, MetaAPIBan: MetaAPIBan, // special case as it is not in a DB @@ -148,44 +139,30 @@ var ( AccountableRequestTypes = NewStringSet([]string{MetaPrepaid, MetaPostpaid, MetaPseudoPrepaid}) CacheStorDBPartitions = map[string]string{ - TBLTPTimings: CacheTBLTPTimings, - TBLTPDestinations: CacheTBLTPDestinations, - TBLTPRates: CacheTBLTPRates, - TBLTPDestinationRates: CacheTBLTPDestinationRates, - TBLTPRatingPlans: CacheTBLTPRatingPlans, - TBLTPRatingProfiles: CacheTBLTPRatingProfiles, - TBLTPSharedGroups: CacheTBLTPSharedGroups, - TBLTPActions: CacheTBLTPActions, - TBLTPActionPlans: CacheTBLTPActionPlans, - TBLTPActionTriggers: CacheTBLTPActionTriggers, - TBLTPAccountActions: CacheTBLTPAccountActions, - TBLTPResources: CacheTBLTPResources, - TBLTPStats: CacheTBLTPStats, - TBLTPThresholds: CacheTBLTPThresholds, - TBLTPFilters: CacheTBLTPFilters, - SessionCostsTBL: CacheSessionCostsTBL, - CDRsTBL: CacheCDRsTBL, - TBLTPRoutes: CacheTBLTPRoutes, - TBLTPAttributes: CacheTBLTPAttributes, - TBLTPChargers: CacheTBLTPChargers, - TBLTPDispatchers: CacheTBLTPDispatchers, - TBLTPDispatcherHosts: CacheTBLTPDispatcherHosts, - TBLTPRateProfiles: CacheTBLTPRateProfiles, - TBLTPActionProfiles: CacheTBLTPActionProfiles, - TBLTPAccountProfiles: CacheTBLTPAccountProfiles, + TBLTPTimings: CacheTBLTPTimings, + TBLTPDestinations: CacheTBLTPDestinations, + TBLTPActions: CacheTBLTPActions, + TBLTPResources: CacheTBLTPResources, + TBLTPStats: CacheTBLTPStats, + TBLTPThresholds: CacheTBLTPThresholds, + TBLTPFilters: CacheTBLTPFilters, + SessionCostsTBL: CacheSessionCostsTBL, + CDRsTBL: CacheCDRsTBL, + TBLTPRoutes: CacheTBLTPRoutes, + TBLTPAttributes: CacheTBLTPAttributes, + TBLTPChargers: CacheTBLTPChargers, + TBLTPDispatchers: CacheTBLTPDispatchers, + TBLTPDispatcherHosts: CacheTBLTPDispatcherHosts, + TBLTPRateProfiles: CacheTBLTPRateProfiles, + TBLTPActionProfiles: CacheTBLTPActionProfiles, + TBLTPAccountProfiles: CacheTBLTPAccountProfiles, } // ProtectedSFlds are the fields that sessions should not alter ProtectedSFlds = NewStringSet([]string{CGRID, OriginHost, OriginID, Usage}) ArgCacheToPrefix = map[string]string{ DestinationIDs: DestinationPrefix, ReverseDestinationIDs: ReverseDestinationPrefix, - RatingPlanIDs: RatingPlanPrefix, - RatingProfileIDs: RatingProfilePrefix, ActionIDs: ActionPrefix, - ActionPlanIDs: ActionPlanPrefix, - AccountActionPlanIDs: AccountActionPlansPrefix, - ActionTriggerIDs: ActionTriggerPrefix, - SharedGroupIDs: SharedGroupPrefix, ResourceProfileIDs: ResourceProfilesPrefix, ResourceIDs: ResourcesPrefix, StatsQueueIDs: StatQueuePrefix, @@ -219,13 +196,7 @@ var ( ArgCacheToInstance = map[string]string{ DestinationIDs: CacheDestinations, ReverseDestinationIDs: CacheReverseDestinations, - RatingPlanIDs: CacheRatingPlans, - RatingProfileIDs: CacheRatingProfiles, ActionIDs: CacheActions, - ActionPlanIDs: CacheActionPlans, - AccountActionPlanIDs: CacheAccountActionPlans, - ActionTriggerIDs: CacheActionTriggers, - SharedGroupIDs: CacheSharedGroups, ResourceProfileIDs: CacheResourceProfiles, ResourceIDs: CacheResources, StatsQueueIDs: CacheStatQueues, @@ -378,18 +349,9 @@ const ( MetaVoice = "*voice" ACD = "ACD" TasksKey = "tasks" - ActionPlanPrefix = "apl_" - AccountActionPlansPrefix = "aap_" - ActionTriggerPrefix = "atr_" - RatingPlanPrefix = "rpl_" - RatingProfilePrefix = "rpf_" ActionPrefix = "act_" - SharedGroupPrefix = "shg_" - AccountPrefix = "acc_" DestinationPrefix = "dst_" ReverseDestinationPrefix = "rds_" - DerivedChargersPrefix = "dcs_" - UsersPrefix = "usr_" ResourcesPrefix = "res_" ResourceProfilesPrefix = "rsp_" ThresholdPrefix = "thd_" @@ -1242,7 +1204,6 @@ const ( const ( ReplicatorSv1 = "ReplicatorSv1" ReplicatorSv1Ping = "ReplicatorSv1.Ping" - ReplicatorSv1GetAccount = "ReplicatorSv1.GetAccount" ReplicatorSv1GetDestination = "ReplicatorSv1.GetDestination" ReplicatorSv1GetReverseDestination = "ReplicatorSv1.GetReverseDestination" ReplicatorSv1GetStatQueue = "ReplicatorSv1.GetStatQueue" @@ -1253,14 +1214,7 @@ const ( ReplicatorSv1GetTiming = "ReplicatorSv1.GetTiming" ReplicatorSv1GetResource = "ReplicatorSv1.GetResource" ReplicatorSv1GetResourceProfile = "ReplicatorSv1.GetResourceProfile" - ReplicatorSv1GetActionTriggers = "ReplicatorSv1.GetActionTriggers" - ReplicatorSv1GetSharedGroup = "ReplicatorSv1.GetSharedGroup" ReplicatorSv1GetActions = "ReplicatorSv1.GetActions" - ReplicatorSv1GetActionPlan = "ReplicatorSv1.GetActionPlan" - ReplicatorSv1GetAllActionPlans = "ReplicatorSv1.GetAllActionPlans" - ReplicatorSv1GetAccountActionPlans = "ReplicatorSv1.GetAccountActionPlans" - ReplicatorSv1GetRatingPlan = "ReplicatorSv1.GetRatingPlan" - ReplicatorSv1GetRatingProfile = "ReplicatorSv1.GetRatingProfile" ReplicatorSv1GetRouteProfile = "ReplicatorSv1.GetRouteProfile" ReplicatorSv1GetAttributeProfile = "ReplicatorSv1.GetAttributeProfile" ReplicatorSv1GetChargerProfile = "ReplicatorSv1.GetChargerProfile" @@ -1272,7 +1226,6 @@ const ( ReplicatorSv1GetItemLoadIDs = "ReplicatorSv1.GetItemLoadIDs" ReplicatorSv1SetThresholdProfile = "ReplicatorSv1.SetThresholdProfile" ReplicatorSv1SetThreshold = "ReplicatorSv1.SetThreshold" - ReplicatorSv1SetAccount = "ReplicatorSv1.SetAccount" ReplicatorSv1SetDestination = "ReplicatorSv1.SetDestination" ReplicatorSv1SetReverseDestination = "ReplicatorSv1.SetReverseDestination" ReplicatorSv1SetStatQueue = "ReplicatorSv1.SetStatQueue" @@ -1281,13 +1234,7 @@ const ( ReplicatorSv1SetTiming = "ReplicatorSv1.SetTiming" ReplicatorSv1SetResource = "ReplicatorSv1.SetResource" ReplicatorSv1SetResourceProfile = "ReplicatorSv1.SetResourceProfile" - ReplicatorSv1SetActionTriggers = "ReplicatorSv1.SetActionTriggers" - ReplicatorSv1SetSharedGroup = "ReplicatorSv1.SetSharedGroup" ReplicatorSv1SetActions = "ReplicatorSv1.SetActions" - ReplicatorSv1SetActionPlan = "ReplicatorSv1.SetActionPlan" - ReplicatorSv1SetAccountActionPlans = "ReplicatorSv1.SetAccountActionPlans" - ReplicatorSv1SetRatingPlan = "ReplicatorSv1.SetRatingPlan" - ReplicatorSv1SetRatingProfile = "ReplicatorSv1.SetRatingProfile" ReplicatorSv1SetRouteProfile = "ReplicatorSv1.SetRouteProfile" ReplicatorSv1SetAttributeProfile = "ReplicatorSv1.SetAttributeProfile" ReplicatorSv1SetChargerProfile = "ReplicatorSv1.SetChargerProfile" @@ -1299,7 +1246,6 @@ const ( ReplicatorSv1SetLoadIDs = "ReplicatorSv1.SetLoadIDs" ReplicatorSv1RemoveThreshold = "ReplicatorSv1.RemoveThreshold" ReplicatorSv1RemoveDestination = "ReplicatorSv1.RemoveDestination" - ReplicatorSv1RemoveAccount = "ReplicatorSv1.RemoveAccount" ReplicatorSv1RemoveStatQueue = "ReplicatorSv1.RemoveStatQueue" ReplicatorSv1RemoveFilter = "ReplicatorSv1.RemoveFilter" ReplicatorSv1RemoveThresholdProfile = "ReplicatorSv1.RemoveThresholdProfile" @@ -1307,13 +1253,7 @@ const ( ReplicatorSv1RemoveTiming = "ReplicatorSv1.RemoveTiming" ReplicatorSv1RemoveResource = "ReplicatorSv1.RemoveResource" ReplicatorSv1RemoveResourceProfile = "ReplicatorSv1.RemoveResourceProfile" - ReplicatorSv1RemoveActionTriggers = "ReplicatorSv1.RemoveActionTriggers" - ReplicatorSv1RemoveSharedGroup = "ReplicatorSv1.RemoveSharedGroup" ReplicatorSv1RemoveActions = "ReplicatorSv1.RemoveActions" - ReplicatorSv1RemoveActionPlan = "ReplicatorSv1.RemoveActionPlan" - ReplicatorSv1RemAccountActionPlans = "ReplicatorSv1.RemAccountActionPlans" - ReplicatorSv1RemoveRatingPlan = "ReplicatorSv1.RemoveRatingPlan" - ReplicatorSv1RemoveRatingProfile = "ReplicatorSv1.RemoveRatingProfile" ReplicatorSv1RemoveRouteProfile = "ReplicatorSv1.RemoveRouteProfile" ReplicatorSv1RemoveAttributeProfile = "ReplicatorSv1.RemoveAttributeProfile" ReplicatorSv1RemoveChargerProfile = "ReplicatorSv1.RemoveChargerProfile" @@ -1361,39 +1301,14 @@ const ( APIerSv1GetRatingProfileIDs = "APIerSv1.GetRatingProfileIDs" APIerSv1SetDataDBVersions = "APIerSv1.SetDataDBVersions" APIerSv1SetStorDBVersions = "APIerSv1.SetStorDBVersions" - APIerSv1GetAccountActionPlan = "APIerSv1.GetAccountActionPlan" - APIerSv1ComputeActionPlanIndexes = "APIerSv1.ComputeActionPlanIndexes" APIerSv1GetActions = "APIerSv1.GetActions" - APIerSv1GetActionPlan = "APIerSv1.GetActionPlan" - APIerSv1GetActionPlanIDs = "APIerSv1.GetActionPlanIDs" - APIerSv1GetRatingPlanIDs = "APIerSv1.GetRatingPlanIDs" - APIerSv1GetRatingPlan = "APIerSv1.GetRatingPlan" - APIerSv1RemoveRatingPlan = "APIerSv1.RemoveRatingPlan" APIerSv1GetDestination = "APIerSv1.GetDestination" APIerSv1RemoveDestination = "APIerSv1.RemoveDestination" APIerSv1GetReverseDestination = "APIerSv1.GetReverseDestination" - APIerSv1AddBalance = "APIerSv1.AddBalance" - APIerSv1DebitBalance = "APIerSv1.DebitBalance" - APIerSv1SetAccount = "APIerSv1.SetAccount" - APIerSv1GetAccountsCount = "APIerSv1.GetAccountsCount" APIerSv1GetDataDBVersions = "APIerSv1.GetDataDBVersions" APIerSv1GetStorDBVersions = "APIerSv1.GetStorDBVersions" APIerSv1GetCDRs = "APIerSv1.GetCDRs" - APIerSv1GetTPAccountActions = "APIerSv1.GetTPAccountActions" - APIerSv1SetTPAccountActions = "APIerSv1.SetTPAccountActions" - APIerSv1GetTPAccountActionsByLoadId = "APIerSv1.GetTPAccountActionsByLoadId" - APIerSv1GetTPAccountActionLoadIds = "APIerSv1.GetTPAccountActionLoadIds" - APIerSv1GetTPAccountActionIds = "APIerSv1.GetTPAccountActionIds" - APIerSv1RemoveTPAccountActions = "APIerSv1.RemoveTPAccountActions" - APIerSv1GetTPActionPlan = "APIerSv1.GetTPActionPlan" - APIerSv1SetTPActionPlan = "APIerSv1.SetTPActionPlan" - APIerSv1GetTPActionPlanIds = "APIerSv1.GetTPActionPlanIds" - APIerSv1SetTPActionTriggers = "APIerSv1.SetTPActionTriggers" - APIerSv1GetTPActionTriggers = "APIerSv1.GetTPActionTriggers" - APIerSv1RemoveTPActionTriggers = "APIerSv1.RemoveTPActionTriggers" - APIerSv1GetTPActionTriggerIds = "APIerSv1.GetTPActionTriggerIds" APIerSv1GetTPActions = "APIerSv1.GetTPActions" - APIerSv1RemoveTPActionPlan = "APIerSv1.RemoveTPActionPlan" APIerSv1GetTPAttributeProfile = "APIerSv1.GetTPAttributeProfile" APIerSv1SetTPAttributeProfile = "APIerSv1.SetTPAttributeProfile" APIerSv1GetTPAttributeProfileIds = "APIerSv1.GetTPAttributeProfileIds" @@ -1896,46 +1811,32 @@ const ( // Table Name const ( - TBLTPTimings = "tp_timings" - TBLTPDestinations = "tp_destinations" - TBLTPRates = "tp_rates" - TBLTPDestinationRates = "tp_destination_rates" - TBLTPRatingPlans = "tp_rating_plans" - TBLTPRatingProfiles = "tp_rating_profiles" - TBLTPSharedGroups = "tp_shared_groups" - TBLTPActions = "tp_actions" - TBLTPActionPlans = "tp_action_plans" - TBLTPActionTriggers = "tp_action_triggers" - TBLTPAccountActions = "tp_account_actions" - TBLTPResources = "tp_resources" - TBLTPStats = "tp_stats" - TBLTPThresholds = "tp_thresholds" - TBLTPFilters = "tp_filters" - SessionCostsTBL = "session_costs" - CDRsTBL = "cdrs" - TBLTPRoutes = "tp_routes" - TBLTPAttributes = "tp_attributes" - TBLTPChargers = "tp_chargers" - TBLVersions = "versions" - OldSMCosts = "sm_costs" - TBLTPDispatchers = "tp_dispatcher_profiles" - TBLTPDispatcherHosts = "tp_dispatcher_hosts" - TBLTPRateProfiles = "tp_rate_profiles" - TBLTPActionProfiles = "tp_action_profiles" - TBLTPAccountProfiles = "tp_account_profiles" + TBLTPTimings = "tp_timings" + TBLTPDestinations = "tp_destinations" + TBLTPActions = "tp_actions" + TBLTPResources = "tp_resources" + TBLTPStats = "tp_stats" + TBLTPThresholds = "tp_thresholds" + TBLTPFilters = "tp_filters" + SessionCostsTBL = "session_costs" + CDRsTBL = "cdrs" + TBLTPRoutes = "tp_routes" + TBLTPAttributes = "tp_attributes" + TBLTPChargers = "tp_chargers" + TBLVersions = "versions" + OldSMCosts = "sm_costs" + TBLTPDispatchers = "tp_dispatcher_profiles" + TBLTPDispatcherHosts = "tp_dispatcher_hosts" + TBLTPRateProfiles = "tp_rate_profiles" + TBLTPActionProfiles = "tp_action_profiles" + TBLTPAccountProfiles = "tp_account_profiles" ) // Cache Name const ( CacheDestinations = "*destinations" CacheReverseDestinations = "*reverse_destinations" - CacheRatingPlans = "*rating_plans" - CacheRatingProfiles = "*rating_profiles" CacheActions = "*actions" - CacheActionPlans = "*action_plans" - CacheAccountActionPlans = "*account_action_plans" - CacheActionTriggers = "*action_triggers" - CacheSharedGroups = "*shared_groups" CacheResources = "*resources" CacheResourceProfiles = "*resource_profiles" CacheTimings = "*timings" @@ -1975,42 +1876,32 @@ const ( CacheLoadIDs = "*load_ids" CacheRPCConnections = "*rpc_connections" CacheCDRIDs = "*cdr_ids" - CacheRatingProfilesTmp = "*tmp_rating_profiles" CacheUCH = "*uch" CacheSTIR = "*stir" CacheEventCharges = "*event_charges" CacheReverseFilterIndexes = "*reverse_filter_indexes" - CacheAccounts = "*accounts" CacheVersions = "*versions" CacheCapsEvents = "*caps_events" CacheReplicationHosts = "*replication_hosts" // storDB - CacheTBLTPTimings = "*tp_timings" - CacheTBLTPDestinations = "*tp_destinations" - CacheTBLTPRates = "*tp_rates" - CacheTBLTPDestinationRates = "*tp_destination_rates" - CacheTBLTPRatingPlans = "*tp_rating_plans" - CacheTBLTPRatingProfiles = "*tp_rating_profiles" - CacheTBLTPSharedGroups = "*tp_shared_groups" - CacheTBLTPActions = "*tp_actions" - CacheTBLTPActionPlans = "*tp_action_plans" - CacheTBLTPActionTriggers = "*tp_action_triggers" - CacheTBLTPAccountActions = "*tp_account_actions" - CacheTBLTPResources = "*tp_resources" - CacheTBLTPStats = "*tp_stats" - CacheTBLTPThresholds = "*tp_thresholds" - CacheTBLTPFilters = "*tp_filters" - CacheSessionCostsTBL = "*session_costs" - CacheCDRsTBL = "*cdrs" - CacheTBLTPRoutes = "*tp_routes" - CacheTBLTPAttributes = "*tp_attributes" - CacheTBLTPChargers = "*tp_chargers" - CacheTBLTPDispatchers = "*tp_dispatcher_profiles" - CacheTBLTPDispatcherHosts = "*tp_dispatcher_hosts" - CacheTBLTPRateProfiles = "*tp_rate_profiles" - CacheTBLTPActionProfiles = "*tp_action_profiles" - CacheTBLTPAccountProfiles = "*tp_account_profiles" + CacheTBLTPTimings = "*tp_timings" + CacheTBLTPDestinations = "*tp_destinations" + CacheTBLTPActions = "*tp_actions" + CacheTBLTPResources = "*tp_resources" + CacheTBLTPStats = "*tp_stats" + CacheTBLTPThresholds = "*tp_thresholds" + CacheTBLTPFilters = "*tp_filters" + CacheSessionCostsTBL = "*session_costs" + CacheCDRsTBL = "*cdrs" + CacheTBLTPRoutes = "*tp_routes" + CacheTBLTPAttributes = "*tp_attributes" + CacheTBLTPChargers = "*tp_chargers" + CacheTBLTPDispatchers = "*tp_dispatcher_profiles" + CacheTBLTPDispatcherHosts = "*tp_dispatcher_hosts" + CacheTBLTPRateProfiles = "*tp_rate_profiles" + CacheTBLTPActionProfiles = "*tp_action_profiles" + CacheTBLTPAccountProfiles = "*tp_account_profiles" ) // Prefix for indexing