diff --git a/apier/v2/accounts.go b/apier/v2/accounts.go index bc7b85208..89e342172 100644 --- a/apier/v2/accounts.go +++ b/apier/v2/accounts.go @@ -117,18 +117,7 @@ func (apiv2 *APIerSv2) GetAccount(ctx *context.Context, attr *utils.AttrGetAccou 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(ctx *context.Context, attr *AttrSetAccount, reply *string) error { +func (apiv2 *APIerSv2) SetAccount(ctx *context.Context, attr *engine.AttrSetAccount, reply *string) error { if missing := utils.MissingStructFields(attr, []string{utils.AccountField}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } diff --git a/console/account_set.go b/console/account_set.go index 42a04a6e1..d05c32296 100644 --- a/console/account_set.go +++ b/console/account_set.go @@ -19,7 +19,7 @@ along with this program. If not, see package console import ( - v2 "github.com/cgrates/cgrates/apier/v2" + "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) @@ -36,7 +36,7 @@ func init() { type CmdAddAccount struct { name string rpcMethod string - rpcParams *v2.AttrSetAccount + rpcParams *engine.AttrSetAccount *CommandExecuter } @@ -50,7 +50,7 @@ func (self *CmdAddAccount) RpcMethod() string { func (self *CmdAddAccount) RpcParams(reset bool) any { if reset || self.rpcParams == nil { - self.rpcParams = &v2.AttrSetAccount{} + self.rpcParams = &engine.AttrSetAccount{} } return self.rpcParams } diff --git a/engine/account.go b/engine/account.go index 1d166ce0a..d3672ab48 100644 --- a/engine/account.go +++ b/engine/account.go @@ -33,6 +33,17 @@ import ( "github.com/cgrates/cgrates/utils" ) +type AttrSetAccount struct { + Tenant string + Account string + ActionPlanIDs []string + ActionPlansOverwrite bool + ActionTriggerIDs []string + ActionTriggerOverwrite bool + ExtraOptions map[string]bool + ReloadScheduler bool +} + // Account structure containing information about user's credit (minutes, cents, sms...).' // This can represent a user or a shared group. type Account struct { diff --git a/engine/action.go b/engine/action.go index 263e32066..1a72610e8 100644 --- a/engine/action.go +++ b/engine/action.go @@ -193,6 +193,7 @@ func init() { actionFuncMap[utils.MetaDynamicStats] = dynamicStats actionFuncMap[utils.MetaDynamicAttribute] = dynamicAttribute actionFuncMap[utils.MetaDynamicActionPlan] = dynamicActionPlan + actionFuncMap[utils.MetaDynamicAccountAction] = dynamicAccountAction } func getActionFunc(typ string) (f actionTypeFunc, exists bool) { @@ -1910,3 +1911,74 @@ func dynamicActionPlan(_ *Account, act *Action, _ Actions, _ *FilterS, ev any, var reply string return connMgr.Call(context.Background(), connCfg.ConnIDs, utils.APIerSv1SetActionPlan, ap, &reply) } + +// dynamicAccountAction processes the `ExtraParameters` field from the action to +// populate action plans and action triggers for account +// +// The ExtraParameters field format is expected as follows: +// +// 0 Tenant: string +// 1 Account: string +// 2 ActionPlanIds: strings separated by "&". +// 3 ActionTriggersIds: strings separated by "&". +// 4 AllowNegative: bool +// 5 Disabled: bool +// +// Parameters are separated by ";" and must be provided in the specified order. +func dynamicAccountAction(_ *Account, act *Action, _ Actions, _ *FilterS, ev any, + _ SharedActionsData, connCfg ActionConnCfg) (err error) { + cgrEv, canCast := ev.(*utils.CGREvent) + if !canCast { + return errors.New("Couldn't cast event to CGREvent") + } + dP := utils.MapStorage{ // create DataProvider from event + utils.MetaReq: cgrEv.Event, + utils.MetaTenant: cgrEv.Tenant, + utils.MetaOpts: cgrEv.APIOpts, + } + // Parse Account parameters based on the predefined format. + params := strings.Split(act.ExtraParameters, utils.InfieldSep) + if len(params) != 6 { + return errors.New(fmt.Sprintf("invalid number of parameters <%d> expected 6", len(params))) + } + // parse dynamic parameters + for i := range params { + if params[i], err = utils.ParseParamForDataProvider(params[i], dP); err != nil { + return err + } + } + // populate Account's parameters + acc := &AttrSetAccount{ + Tenant: params[0], + Account: params[1], + ReloadScheduler: true, + ExtraOptions: make(map[string]bool), + } + // populate Account's ActionPlanIDs + if params[2] != utils.EmptyString { + acc.ActionPlanIDs = strings.Split(params[2], utils.ANDSep) + } + // populate Account's ActionTriggerIDs + if params[3] != utils.EmptyString { + acc.ActionTriggerIDs = strings.Split(params[3], utils.ANDSep) + } + // populate Account's AllowNegative ExtraParams + if params[4] != utils.EmptyString { + allNeg, err := strconv.ParseBool(params[4]) + if err != nil { + return err + } + acc.ExtraOptions[utils.AllowNegative] = allNeg + } + // populate Account's Disabled ExtraParams + if params[5] != utils.EmptyString { + disable, err := strconv.ParseBool(params[5]) + if err != nil { + return err + } + acc.ExtraOptions[utils.Disabled] = disable + } + // create the Account based on the populated parameters + var reply string + return connMgr.Call(context.Background(), connCfg.ConnIDs, utils.APIerSv2SetAccount, acc, &reply) +} diff --git a/utils/consts.go b/utils/consts.go index 7461dfe1a..5586313fd 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -1185,6 +1185,7 @@ const ( MetaDynamicStats = "*dynamic_stats" MetaDynamicAttribute = "*dynamic_attribute" MetaDynamicActionPlan = "*dynamic_action_plan" + MetaDynamicAccountAction = "*dynamic_account_action" ActionID = "ActionID" ActionType = "ActionType" ActionValue = "ActionValue"