diff --git a/apier/apier.go b/apier/apier.go index 3c3e959aa..03ac21319 100644 --- a/apier/apier.go +++ b/apier/apier.go @@ -19,6 +19,7 @@ along with this program. If not, see package apier import ( + "encoding/json" "errors" "fmt" "path" @@ -433,6 +434,54 @@ func (self *ApierV1) AddTriggeredAction(attr AttrAddActionTrigger, reply *string return nil } +type AttrResetTriggeredAction struct { + Tenant string + Account string + Direction string + BalanceType string + ThresholdType string + ThresholdValue float64 +} + +func (self *ApierV1) ResetTriggeredActions(attr AttrResetTriggeredAction, reply *string) error { + if attr.Direction == "" { + attr.Direction = engine.OUTBOUND + } + extraParameters, err := json.Marshal(struct { + ThresholdType string + ThresholdValue float64 + }{attr.ThresholdType, attr.ThresholdValue}) + if err != nil { + *reply = err.Error() + return err + } + a := &engine.Action{ + BalanceType: attr.BalanceType, + Direction: attr.Direction, + ExtraParameters: string(extraParameters), + } + accID := utils.BalanceKey(attr.Tenant, attr.Account, attr.Direction) + _, err = engine.AccLock.Guard(accID, func() (float64, error) { + acc, err := self.AccountDb.GetAccount(accID) + if err != nil { + return 0, err + } + + acc.ResetActionTriggers(a) + + if err = self.AccountDb.SetAccount(acc); err != nil { + return 0, err + } + return 0, nil + }) + if err != nil { + *reply = err.Error() + return err + } + *reply = OK + return nil +} + // Process dependencies and load a specific AccountActions profile from storDb into dataDb. func (self *ApierV1) LoadAccountActions(attrs utils.TPAccountActions, reply *string) error { if missing := utils.MissingStructFields(&attrs, []string{"TPid", "LoadId", "Tenant", "Account", "Direction"}); len(missing) != 0 { diff --git a/engine/account.go b/engine/account.go index 1fb8e04d4..463181cbb 100644 --- a/engine/account.go +++ b/engine/account.go @@ -381,7 +381,7 @@ func (ub *Account) executeActionTriggers(a *Action) { // Mark all action trigers as ready for execution // If the action is not nil it acts like a filter -func (ub *Account) resetActionTriggers(a *Action) { +func (ub *Account) ResetActionTriggers(a *Action) { for _, at := range ub.ActionTriggers { if !at.Match(a) { continue diff --git a/engine/account_test.go b/engine/account_test.go index 36ea975af..547b464cb 100644 --- a/engine/account_test.go +++ b/engine/account_test.go @@ -830,7 +830,7 @@ func TestAccountExecuteTriggeredActions(t *testing.T) { t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES+OUTBOUND][0].Value) } // we can reset them - ub.resetActionTriggers(nil) + ub.ResetActionTriggers(nil) ub.countUnits(&Action{BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}}) if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 120 || ub.BalanceMap[MINUTES+OUTBOUND][0].Value != 30 { t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES+OUTBOUND][0].Value) diff --git a/engine/action.go b/engine/action.go index 00ed811e6..84a016429 100644 --- a/engine/action.go +++ b/engine/action.go @@ -111,7 +111,7 @@ func logAction(ub *Account, a *Action) (err error) { } func resetTriggersAction(ub *Account, a *Action) (err error) { - ub.resetActionTriggers(a) + ub.ResetActionTriggers(a) return } @@ -194,7 +194,7 @@ func genericReset(ub *Account) error { ub.BalanceMap[k] = BalanceChain{&Balance{Value: 0}} } ub.UnitCounters = make([]*UnitsCounter, 0) - ub.resetActionTriggers(nil) + ub.ResetActionTriggers(nil) return nil } diff --git a/engine/action_trigger.go b/engine/action_trigger.go index 3effe16af..676b08a02 100644 --- a/engine/action_trigger.go +++ b/engine/action_trigger.go @@ -21,8 +21,9 @@ package engine import ( "encoding/json" "fmt" - "github.com/cgrates/cgrates/utils" "sort" + + "github.com/cgrates/cgrates/utils" ) type ActionTrigger struct {