From b2a39ed8671e0c5f91ea2c9f77c8f99b3ef4b56d Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 4 Feb 2016 18:46:06 +0200 Subject: [PATCH] action triggers expiration and activation times --- apier/v1/apier_local_test.go | 14 +- apier/v1/triggers.go | 141 +++++++++++++++++- console/trigger_set.go | 8 +- .../mysql/create_tariffplan_tables.sql | 2 + .../postgres/create_tariffplan_tables.sql | 2 + data/tariffplans/cdrstats/ActionTriggers.csv | 12 +- data/tariffplans/testtp/ActionTriggers.csv | 18 +-- data/tariffplans/tutorial/ActionTriggers.csv | 24 +-- engine/account.go | 15 +- engine/account_test.go | 2 +- engine/action_trigger.go | 10 ++ engine/loader_csv_test.go | 20 +-- engine/model_converters.go | 2 + engine/model_helpers.go | 2 + engine/model_helpers_test.go | 4 +- engine/models.go | 32 ++-- engine/tp_reader.go | 31 +++- utils/apitpdata.go | 2 + 18 files changed, 266 insertions(+), 75 deletions(-) diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go index e78886dee..4f7211162 100644 --- a/apier/v1/apier_local_test.go +++ b/apier/v1/apier_local_test.go @@ -1009,19 +1009,19 @@ func TestApierAddTriggeredAction(t *testing.T) { } reply := "" // Add balance to a previously known account - attrs := &AttrSetAccountActionTriggers{ActionTriggerIDs: &[]string{"STANDARD_TRIGGERS"}, Tenant: "cgrates.org", Account: "dan2"} - if err := rater.Call("ApierV1.SetAccountActionTriggers", attrs, &reply); err != nil { - t.Error("Got error on ApierV1.SetAccountActionTriggers: ", err.Error()) + attrs := &AttrAddAccountActionTriggers{ActionTriggerIDs: &[]string{"STANDARD_TRIGGERS"}, Tenant: "cgrates.org", Account: "dan2"} + if err := rater.Call("ApierV1.AddAccountActionTriggers", attrs, &reply); err != nil { + t.Error("Got error on ApierV1.AddAccountActionTriggers: ", err.Error()) } else if reply != "OK" { - t.Errorf("Calling ApierV1.SetAccountActionTriggers received: %s", reply) + t.Errorf("Calling ApierV1.AddAccountActionTriggers received: %s", reply) } reply2 := "" - attrs2 := new(AttrSetAccountActionTriggers) + attrs2 := new(AttrAddAccountActionTriggers) *attrs2 = *attrs attrs2.Account = "dan10" // Does not exist so it should error when adding triggers on it // Add trigger to an account which does n exist - if err := rater.Call("ApierV1.SetAccountActionTriggers", attrs2, &reply2); err == nil || reply2 == "OK" { - t.Error("Expecting error on ApierV1.SetAccountActionTriggers.", err, reply2) + if err := rater.Call("ApierV1.AddAccountActionTriggers", attrs2, &reply2); err == nil || reply2 == "OK" { + t.Error("Expecting error on ApierV1.AddAccountActionTriggers.", err, reply2) } } diff --git a/apier/v1/triggers.go b/apier/v1/triggers.go index 908a315c4..37b2b89b4 100644 --- a/apier/v1/triggers.go +++ b/apier/v1/triggers.go @@ -22,14 +22,14 @@ func (self *ApierV1) GetAccountActionTriggers(attrs AttrAcntAction, reply *engin return nil } -type AttrSetAccountActionTriggers struct { +type AttrAddAccountActionTriggers struct { Tenant string Account string ActionTriggerIDs *[]string ActionTriggerOverwrite bool } -func (self *ApierV1) SetAccountActionTriggers(attr AttrSetAccountActionTriggers, reply *string) error { +func (self *ApierV1) AddAccountActionTriggers(attr AttrAddAccountActionTriggers, reply *string) error { if missing := utils.MissingStructFields(&attr, []string{"Tenant", "Account"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } @@ -156,3 +156,140 @@ func (self *ApierV1) ResetAccountActionTriggers(attr AttrRemoveAccountActionTrig *reply = utils.OK return nil } + +type AttrSetAccountActionTriggers struct { + Tenant string + Account string + GroupID string + UniqueID string + ThresholdType *string + ThresholdValue *float64 + Recurrent *bool + MinSleep *string + ExpirationDate *string + ActivationDate *string + BalanceId *string + BalanceType *string + BalanceDirections *[]string + BalanceDestinationIds *[]string + BalanceWeight *float64 + BalanceExpirationDate *string + BalanceTimingTags *[]string + BalanceRatingSubject *string + BalanceCategories *[]string + BalanceSharedGroups *[]string + BalanceBlocker *bool + BalanceDisabled *bool + MinQueuedItems *int + ActionsId *string +} + +func (self *ApierV1) SetAccountActionTriggers(attr AttrSetAccountActionTriggers, reply *string) error { + + if missing := utils.MissingStructFields(&attr, []string{"Tenant", "Account"}); len(missing) != 0 { + return utils.NewErrMandatoryIeMissing(missing...) + } + accID := utils.AccountKey(attr.Tenant, attr.Account) + var account *engine.Account + _, err := engine.Guardian.Guard(func() (interface{}, error) { + if acc, err := self.AccountDb.GetAccount(accID); err == nil { + account = acc + } else { + return 0, err + } + for _, at := range account.ActionTriggers { + if (attr.UniqueID == "" || at.UniqueID == attr.UniqueID) && + (attr.GroupID == "" || at.ID == attr.GroupID) { + // we have a winner + if attr.ThresholdType != nil { + at.ThresholdType = *attr.ThresholdType + } + if attr.ThresholdValue != nil { + at.ThresholdValue = *attr.ThresholdValue + } + if attr.Recurrent != nil { + at.Recurrent = *attr.Recurrent + } + if attr.MinSleep != nil { + minSleep, err := utils.ParseDurationWithSecs(*attr.MinSleep) + if err != nil { + return 0, err + } + at.MinSleep = minSleep + } + if attr.ExpirationDate != nil { + expTime, err := utils.ParseDate(*attr.ExpirationDate) + if err != nil { + return 0, err + } + at.ExpirationDate = expTime + } + if attr.ActivationDate != nil { + actTime, err := utils.ParseDate(*attr.ActivationDate) + if err != nil { + return 0, err + } + at.ActivationDate = actTime + } + if attr.BalanceId != nil { + at.BalanceId = *attr.BalanceId + } + if attr.BalanceType != nil { + at.BalanceType = *attr.BalanceType + } + if attr.BalanceDirections != nil { + at.BalanceDirections = utils.NewStringMap(*attr.BalanceDirections...) + } + if attr.BalanceDestinationIds != nil { + at.BalanceDestinationIds = utils.NewStringMap(*attr.BalanceDestinationIds...) + } + if attr.BalanceWeight != nil { + at.BalanceWeight = *attr.BalanceWeight + } + if attr.BalanceExpirationDate != nil { + balanceExpTime, err := utils.ParseDate(*attr.BalanceExpirationDate) + if err != nil { + return 0, err + } + at.BalanceExpirationDate = balanceExpTime + } + if attr.BalanceTimingTags != nil { + at.BalanceTimingTags = utils.NewStringMap(*attr.BalanceTimingTags...) + } + if attr.BalanceRatingSubject != nil { + at.BalanceRatingSubject = *attr.BalanceRatingSubject + } + if attr.BalanceCategories != nil { + at.BalanceCategories = utils.NewStringMap(*attr.BalanceCategories...) + } + if attr.BalanceSharedGroups != nil { + at.BalanceSharedGroups = utils.NewStringMap(*attr.BalanceSharedGroups...) + } + if attr.BalanceBlocker != nil { + at.BalanceBlocker = *attr.BalanceBlocker + } + if attr.BalanceDisabled != nil { + at.BalanceDisabled = *attr.BalanceDisabled + } + if attr.MinQueuedItems != nil { + at.MinQueuedItems = *attr.MinQueuedItems + } + if attr.ActionsId != nil { + at.ActionsId = *attr.ActionsId + } + } + + } + account.ExecuteActionTriggers(nil) + if err := self.AccountDb.SetAccount(account); err != nil { + return 0, err + } + return 0, nil + }, 0, accID) + if err != nil { + *reply = err.Error() + return err + } + *reply = utils.OK + return nil +} diff --git a/console/trigger_set.go b/console/trigger_set.go index 2e9095d95..fa7944eb7 100644 --- a/console/trigger_set.go +++ b/console/trigger_set.go @@ -23,8 +23,8 @@ import "github.com/cgrates/cgrates/apier/v1" func init() { c := &CmdSetTriggers{ name: "triggers_set", - rpcMethod: "ApierV1.SetAccountActionTriggers", - rpcParams: &v1.AttrSetAccountActionTriggers{}, + rpcMethod: "ApierV1.AddAccountActionTriggers", + rpcParams: &v1.AttrAddAccountActionTriggers{}, } commands[c.Name()] = c c.CommandExecuter = &CommandExecuter{c} @@ -34,7 +34,7 @@ func init() { type CmdSetTriggers struct { name string rpcMethod string - rpcParams *v1.AttrSetAccountActionTriggers + rpcParams *v1.AttrAddAccountActionTriggers *CommandExecuter } @@ -48,7 +48,7 @@ func (self *CmdSetTriggers) RpcMethod() string { func (self *CmdSetTriggers) RpcParams(reset bool) interface{} { if reset || self.rpcParams == nil { - self.rpcParams = &v1.AttrSetAccountActionTriggers{} + self.rpcParams = &v1.AttrAddAccountActionTriggers{} } return self.rpcParams } diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql index 15783c927..0a640135a 100644 --- a/data/storage/mysql/create_tariffplan_tables.sql +++ b/data/storage/mysql/create_tariffplan_tables.sql @@ -203,6 +203,8 @@ CREATE TABLE `tp_action_triggers` ( `threshold_value` DECIMAL(20,4) NOT NULL, `recurrent` BOOLEAN NOT NULL, `min_sleep` varchar(16) NOT NULL, + `expiry_time` varchar(24) NOT NULL, + `activation_time` varchar(24) NOT NULL, `balance_tag` varchar(64) NOT NULL, `balance_type` varchar(24) NOT NULL, `balance_directions` varchar(8) NOT NULL, diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql index 857fb956f..e4d3aaee8 100644 --- a/data/storage/postgres/create_tariffplan_tables.sql +++ b/data/storage/postgres/create_tariffplan_tables.sql @@ -198,6 +198,8 @@ CREATE TABLE tp_action_triggers ( threshold_value NUMERIC(20,4) NOT NULL, recurrent BOOLEAN NOT NULL, min_sleep VARCHAR(16) NOT NULL, + expiry_time VARCHAR(24) NOT NULL, + activation_time VARCHAR(24) NOT NULL, balance_tag VARCHAR(64) NOT NULL, balance_type VARCHAR(24) NOT NULL, balance_directions VARCHAR(8) NOT NULL, diff --git a/data/tariffplans/cdrstats/ActionTriggers.csv b/data/tariffplans/cdrstats/ActionTriggers.csv index 6081b9d67..153da6ceb 100644 --- a/data/tariffplans/cdrstats/ActionTriggers.csv +++ b/data/tariffplans/cdrstats/ActionTriggers.csv @@ -1,6 +1,6 @@ -#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirections[8],BalanceCategories[9],BalanceDestinationTags[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingTags[14],BalanceWeight[15],BalanceBlocker[16],BalanceDisabled[17],StatsMinQueuedItems[18],ActionsTag[19],Weight[20] -CDRST3_WARN_ASR,,*min_asr,45,true,1h,,,,,,,,,,,,,3,CDRST_LOG,10 -CDRST3_WARN_ACD,,*min_acd,10,true,1h,,,,,,,,,,,,,5,CDRST_LOG,10 -CDRST3_WARN_ACC,,*max_acc,10,true,10m,,,,,,,,,,,,,5,CDRST_LOG,10 -CDRST4_WARN_ASR,,*min_asr,30,true,0,,,,,,,,,,,,,5,CDRST_LOG,10 -CDRST4_WARN_ACD,,*min_acd,3,true,0,,,,,,,,,,,,,2,CDRST_LOG,10 +#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],ExpiryTime[6],ActivationTime[7],BalanceTag[8],BalanceType[9],BalanceDirections[10],BalanceCategories[11],BalanceDestinationIds[12],BalanceRatingSubject[13],BalanceSharedGroup[14],BalanceExpiryTime[15],BalanceTimingIds[16],BalanceWeight[17],BalanceBlocker[18],BalanceDisabled[19],StatsMinQueuedItems[20],ActionsId[21],Weight[22] +CDRST3_WARN_ASR,,*min_asr,45,true,1h,,,,,,,,,,,,,,,3,CDRST_LOG,10 +CDRST3_WARN_ACD,,*min_acd,10,true,1h,,,,,,,,,,,,,,,5,CDRST_LOG,10 +CDRST3_WARN_ACC,,*max_acc,10,true,10m,,,,,,,,,,,,,,,5,CDRST_LOG,10 +CDRST4_WARN_ASR,,*min_asr,30,true,0,,,,,,,,,,,,,,,5,CDRST_LOG,10 +CDRST4_WARN_ACD,,*min_acd,3,true,0,,,,,,,,,,,,,,,2,CDRST_LOG,10 diff --git a/data/tariffplans/testtp/ActionTriggers.csv b/data/tariffplans/testtp/ActionTriggers.csv index c50ff9a7c..795ef6ab8 100644 --- a/data/tariffplans/testtp/ActionTriggers.csv +++ b/data/tariffplans/testtp/ActionTriggers.csv @@ -1,9 +1,9 @@ -#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirections[8],BalanceCategories[9],BalanceDestinationTags[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingTags[14],BalanceWeight[15],BalanceBlocker[16],BalanceDisabled[17],StatsMinQueuedItems[18],ActionsTag[19],Weight[20] -STANDARD_TRIGGERS,,*min_balance,2,false,0,,*monetary,*out,,,,,,,,,,,LOG_BALANCE,10 -STANDARD_TRIGGERS,,*max_balance,20,false,0,,*monetary,*out,,,,,,,,,,,LOG_BALANCE,10 -STANDARD_TRIGGERS,,*max_event_counter,15,false,0,,*monetary,*out,,FS_USERS,,,,,,,,,LOG_BALANCE,10 -CDRST1_WARN_ASR,,*min_asr,45,true,1h,,,,,,,,,,,,,3,CDRST_WARN_HTTP,10 -CDRST1_WARN_ACD,,*min_acd,10,true,1h,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 -CDRST1_WARN_ACC,,*max_acc,10,true,10m,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 -CDRST2_WARN_ASR,,*min_asr,30,true,0,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 -CDRST2_WARN_ACD,,*min_acd,3,true,0,,,,,,,,,,,,,2,CDRST_LOG,10 +#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],ExpiryTime[6],ActivationTime[7],BalanceTag[8],BalanceType[9],BalanceDirections[10],BalanceCategories[11],BalanceDestinationIds[12],BalanceRatingSubject[13],BalanceSharedGroup[14],BalanceExpiryTime[15],BalanceTimingIds[16],BalanceWeight[17],BalanceBlocker[18],BalanceDisabled[19],StatsMinQueuedItems[20],ActionsId[21],Weight[22] +STANDARD_TRIGGERS,,*min_balance,2,false,0,,,,*monetary,*out,,,,,,,,,,,LOG_BALANCE,10 +STANDARD_TRIGGERS,,*max_balance,20,false,0,,,,*monetary,*out,,,,,,,,,,,LOG_BALANCE,10 +STANDARD_TRIGGERS,,*max_event_counter,15,false,0,,,,*monetary,*out,,FS_USERS,,,,,,,,,LOG_BALANCE,10 +CDRST1_WARN_ASR,,*min_asr,45,true,1h,,,,,,,,,,,,,,,3,CDRST_WARN_HTTP,10 +CDRST1_WARN_ACD,,*min_acd,10,true,1h,,,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 +CDRST1_WARN_ACC,,*max_acc,10,true,10m,,,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 +CDRST2_WARN_ASR,,*min_asr,30,true,0,,,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 +CDRST2_WARN_ACD,,*min_acd,3,true,0,,,,,,,,,,,,,,,2,CDRST_LOG,10 diff --git a/data/tariffplans/tutorial/ActionTriggers.csv b/data/tariffplans/tutorial/ActionTriggers.csv index e68fbdf34..2036c0ad2 100644 --- a/data/tariffplans/tutorial/ActionTriggers.csv +++ b/data/tariffplans/tutorial/ActionTriggers.csv @@ -1,12 +1,12 @@ -#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],BalanceTag[6],BalanceType[7],BalanceDirections[8],BalanceCategories[9],BalanceDestinationIds[10],BalanceRatingSubject[11],BalanceSharedGroup[12],BalanceExpiryTime[13],BalanceTimingIds[14],BalanceWeight[15],BalanceBlocker[16],BalanceDisabled[17],StatsMinQueuedItems[18],ActionsId[19],Weight[20] -STANDARD_TRIGGERS,,*min_balance,2,false,0,,*monetary,*out,,,,,,,,,,,LOG_WARNING,10 -STANDARD_TRIGGERS,,*max_event_counter,5,false,0,,*monetary,*out,,FS_USERS,,,,,,,,,LOG_WARNING,10 -STANDARD_TRIGGERS,,*max_balance,20,false,0,,*monetary,*out,,,,,,,,,,,LOG_WARNING,10 -STANDARD_TRIGGERS,,*max_balance,100,false,0,,*monetary,*out,,,,,,,,,,,DISABLE_AND_LOG,10 -CDRST1_WARN,,*min_asr,45,true,1m,,,,,,,,,,,,,3,LOG_WARNING,10 -CDRST1_WARN,,*min_acd,10,true,1m,,,,,,,,,,,,,5,LOG_WARNING,10 -CDRST1_WARN,,*max_acc,10,true,1m,,,,,,,,,,,,,5,LOG_WARNING,10 -CDRST1001_WARN,,*min_asr,65,true,1m,,,,,,,,,,,,,3,LOG_WARNING,10 -CDRST1001_WARN,,*min_acd,10,true,1m,,,,,,,,,,,,,5,LOG_WARNING,10 -CDRST1001_WARN,,*max_acc,5,true,1m,,,,,,,,,,,,,5,LOG_WARNING,10 -CDRST3_WARN,,*min_acd,60,false,1m,,,,,,,,,,,,,5,LOG_WARNING,10 +#Tag[0],UniqueId[1],ThresholdType[2],ThresholdValue[3],Recurrent[4],MinSleep[5],ExpiryTime[6],ActivationTime[7],BalanceTag[8],BalanceType[9],BalanceDirections[10],BalanceCategories[11],BalanceDestinationIds[12],BalanceRatingSubject[13],BalanceSharedGroup[14],BalanceExpiryTime[15],BalanceTimingIds[16],BalanceWeight[17],BalanceBlocker[18],BalanceDisabled[19],StatsMinQueuedItems[20],ActionsId[21],Weight[22] +STANDARD_TRIGGERS,,*min_balance,2,false,0,,,,*monetary,*out,,,,,,,,,,,LOG_WARNING,10 +STANDARD_TRIGGERS,,*max_event_counter,5,false,0,,,,*monetary,*out,,FS_USERS,,,,,,,,,LOG_WARNING,10 +STANDARD_TRIGGERS,,*max_balance,20,false,0,,,,*monetary,*out,,,,,,,,,,,LOG_WARNING,10 +STANDARD_TRIGGERS,,*max_balance,100,false,0,,,,*monetary,*out,,,,,,,,,,,DISABLE_AND_LOG,10 +CDRST1_WARN,,*min_asr,45,true,1m,,,,,,,,,,,,,,,3,LOG_WARNING,10 +CDRST1_WARN,,*min_acd,10,true,1m,,,,,,,,,,,,,,,5,LOG_WARNING,10 +CDRST1_WARN,,*max_acc,10,true,1m,,,,,,,,,,,,,,,5,LOG_WARNING,10 +CDRST1001_WARN,,*min_asr,65,true,1m,,,,,,,,,,,,,,,3,LOG_WARNING,10 +CDRST1001_WARN,,*min_acd,10,true,1m,,,,,,,,,,,,,,,5,LOG_WARNING,10 +CDRST1001_WARN,,*max_acc,5,true,1m,,,,,,,,,,,,,,,5,LOG_WARNING,10 +CDRST3_WARN,,*min_acd,60,false,1m,,,,,,,,,,,,,,,5,LOG_WARNING,10 diff --git a/engine/account.go b/engine/account.go index 99875285b..287c3ab3a 100644 --- a/engine/account.go +++ b/engine/account.go @@ -572,6 +572,11 @@ func (ub *Account) refundIncrement(increment *Increment, cd *CallDescriptor, cou func (acc *Account) ExecuteActionTriggers(a *Action) { acc.ActionTriggers.Sort() for _, at := range acc.ActionTriggers { + // check is effective + if at.IsExpired(time.Now()) || !at.IsActive(time.Now()) { + continue + } + // sanity check if !strings.Contains(at.ThresholdType, "counter") && !strings.Contains(at.ThresholdType, "balance") { continue @@ -623,7 +628,7 @@ func (acc *Account) ExecuteActionTriggers(a *Action) { } } } - acc.CleanExpiredBalances() + acc.CleanExpiredStuff() } // Mark all action trigers as ready for execution @@ -693,7 +698,7 @@ func (acc *Account) InitCounters() { } } -func (acc *Account) CleanExpiredBalances() { +func (acc *Account) CleanExpiredStuff() { for key, bm := range acc.BalanceMap { for i := 0; i < len(bm); i++ { if bm[i].IsExpired() { @@ -703,6 +708,12 @@ func (acc *Account) CleanExpiredBalances() { } acc.BalanceMap[key] = bm } + + for i := 0; i < len(acc.ActionTriggers); i++ { + if acc.ActionTriggers[i].IsExpired(time.Now()) { + acc.ActionTriggers = append(acc.ActionTriggers[:i], acc.ActionTriggers[i+1:]...) + } + } } func (acc *Account) allBalancesExpired() bool { diff --git a/engine/account_test.go b/engine/account_test.go index 577dfc0b8..885a23c7d 100644 --- a/engine/account_test.go +++ b/engine/account_test.go @@ -997,7 +997,7 @@ func TestCleanExpired(t *testing.T) { &Balance{ExpirationDate: time.Now().Add(10 * time.Second)}, }}, } - ub.CleanExpiredBalances() + ub.CleanExpiredStuff() if len(ub.BalanceMap[utils.MONETARY]) != 2 { t.Error("Error cleaning expired balances!") } diff --git a/engine/action_trigger.go b/engine/action_trigger.go index 3e2dc7ea1..71c8aed6d 100644 --- a/engine/action_trigger.go +++ b/engine/action_trigger.go @@ -36,6 +36,8 @@ type ActionTrigger struct { 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 BalanceId string BalanceType string // *monetary/*voice etc BalanceDirections utils.StringMap // filter for balance @@ -188,6 +190,14 @@ func (at *ActionTrigger) Equals(oat *ActionTrigger) bool { 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 diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 885cca250..ffb85bbae 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -189,16 +189,16 @@ BLOCK_AT,BLOCK,*asap,10 ` actionTriggers = ` -STANDARD_TRIGGER,st0,*min_event_counter,10,false,0,,*voice,*out,,GERMANY_O2,,,,,,,,,SOME_1,10 -STANDARD_TRIGGER,st1,*max_balance,200,false,0,,*voice,*out,,GERMANY,,,,,,,,,SOME_2,10 -STANDARD_TRIGGERS,,*min_balance,2,false,0,,*monetary,*out,,,,,,,,,,,LOG_WARNING,10 -STANDARD_TRIGGERS,,*max_balance,20,false,0,,*monetary,*out,,,,,,,,,,,LOG_WARNING,10 -STANDARD_TRIGGERS,,*max_event_counter,5,false,0,,*monetary,*out,,FS_USERS,,,,,,,,,LOG_WARNING,10 -CDRST1_WARN_ASR,,*min_asr,45,true,1h,,,,,,,,,,,,,3,CDRST_WARN_HTTP,10 -CDRST1_WARN_ACD,,*min_acd,10,true,1h,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 -CDRST1_WARN_ACC,,*max_acc,10,true,10m,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 -CDRST2_WARN_ASR,,*min_asr,30,true,0,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 -CDRST2_WARN_ACD,,*min_acd,3,true,0,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 +STANDARD_TRIGGER,st0,*min_event_counter,10,false,0,,,,*voice,*out,,GERMANY_O2,,,,,,,,,SOME_1,10 +STANDARD_TRIGGER,st1,*max_balance,200,false,0,,,,*voice,*out,,GERMANY,,,,,,,,,SOME_2,10 +STANDARD_TRIGGERS,,*min_balance,2,false,0,,,,*monetary,*out,,,,,,,,,,,LOG_WARNING,10 +STANDARD_TRIGGERS,,*max_balance,20,false,0,,,,*monetary,*out,,,,,,,,,,,LOG_WARNING,10 +STANDARD_TRIGGERS,,*max_event_counter,5,false,0,,,,*monetary,*out,,FS_USERS,,,,,,,,,LOG_WARNING,10 +CDRST1_WARN_ASR,,*min_asr,45,true,1h,,,,,,,,,,,,,,,3,CDRST_WARN_HTTP,10 +CDRST1_WARN_ACD,,*min_acd,10,true,1h,,,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 +CDRST1_WARN_ACC,,*max_acc,10,true,10m,,,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 +CDRST2_WARN_ASR,,*min_asr,30,true,0,,,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 +CDRST2_WARN_ACD,,*min_acd,3,true,0,,,,,,,,,,,,,,,5,CDRST_WARN_HTTP,10 ` accountActions = ` vdf,minitsboy,MORE_MINUTES,STANDARD_TRIGGER,, diff --git a/engine/model_converters.go b/engine/model_converters.go index d3035772e..f15e99abd 100644 --- a/engine/model_converters.go +++ b/engine/model_converters.go @@ -224,6 +224,8 @@ func APItoModelActionTrigger(ats *utils.TPActionTriggers) (result []TpActionTrig ThresholdValue: at.ThresholdValue, Recurrent: at.Recurrent, MinSleep: at.MinSleep, + ExpiryTime: at.ExpirationDate, + ActivationTime: at.ActivationDate, BalanceTag: at.BalanceId, BalanceType: at.BalanceType, BalanceDirections: at.BalanceDirections, diff --git a/engine/model_helpers.go b/engine/model_helpers.go index 0d2d0a648..3d29e2d47 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -430,6 +430,8 @@ func (tps TpActionTriggers) GetActionTriggers() (map[string][]*utils.TPActionTri ThresholdValue: tpAt.ThresholdValue, Recurrent: tpAt.Recurrent, MinSleep: tpAt.MinSleep, + ExpirationDate: tpAt.ExpiryTime, + ActivationDate: tpAt.ActivationTime, BalanceId: tpAt.BalanceTag, BalanceType: tpAt.BalanceType, BalanceDirections: tpAt.BalanceDirections, diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index 7d0413c9a..90f1986c3 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -597,8 +597,8 @@ func TestTPActionPlanAsExportSlice(t *testing.T) { }, } expectedSlc := [][]string{ - []string{"STANDARD_TRIGGERS", "1", "*min_balance", "2", "false", "0", "b1", "*monetary", "*out", "call", "", "special1", "SHARED_1", "*never", "T1", "0", "false", "false", "0", "LOG_WARNING", "10"}, - []string{"STANDARD_TRIGGERS", "2", "*max_event_counter", "5", "false", "0", "b2", "*monetary", "*out", "call", "FS_USERS", "special1", "SHARED_1", "*never", "T1", "0", "false", "false", "0", "LOG_WARNING", "10"}, + []string{"STANDARD_TRIGGERS", "1", "*min_balance", "2", "false", "0", "", "", "b1", "*monetary", "*out", "call", "", "special1", "SHARED_1", "*never", "T1", "0", "false", "false", "0", "LOG_WARNING", "10"}, + []string{"STANDARD_TRIGGERS", "2", "*max_event_counter", "5", "false", "0", "", "", "b2", "*monetary", "*out", "call", "FS_USERS", "special1", "SHARED_1", "*never", "T1", "0", "false", "false", "0", "LOG_WARNING", "10"}, } ms := APItoModelActionTrigger(at) var slc [][]string diff --git a/engine/models.go b/engine/models.go index 2fb2ffc56..d16916891 100644 --- a/engine/models.go +++ b/engine/models.go @@ -193,21 +193,23 @@ type TpActionTrigger struct { ThresholdValue float64 `index:"3" re:"\d+\.?\d*"` Recurrent bool `index:"4" re:"true|false"` MinSleep string `index:"5" re:"\d+[smh]?"` - BalanceTag string `index:"6" re:"\w+\s*"` - BalanceType string `index:"7" re:"\*\w+"` - BalanceDirections string `index:"8" re:"\*out"` - BalanceCategories string `index:"9" re:""` - BalanceDestinationTags string `index:"10" re:"\w+|\*any"` - BalanceRatingSubject string `index:"11" re:"\w+|\*any"` - BalanceSharedGroups string `index:"12" re:"\w+|\*any"` - BalanceExpiryTime string `index:"13" re:"\*\w+\s*|\+\d+[smh]\s*|\d+\s*"` - BalanceTimingTags string `index:"14" re:"[0-9A-Za-z_;]*|\*any"` - BalanceWeight float64 `index:"15" re:"\d+\.?\d*"` - BalanceBlocker bool `index:"16" re:""` - BalanceDisabled bool `index:"17" re:""` - MinQueuedItems int `index:"18" re:"\d+"` - ActionsTag string `index:"19" re:"\w+"` - Weight float64 `index:"20" re:"\d+\.?\d*"` + ExpiryTime string `index:"6" re:""` + ActivationTime string `index:"7" re:""` + BalanceTag string `index:"8" re:"\w+\s*"` + BalanceType string `index:"9" re:"\*\w+"` + BalanceDirections string `index:"10" re:"\*out"` + BalanceCategories string `index:"11" re:""` + BalanceDestinationTags string `index:"12" re:"\w+|\*any"` + BalanceRatingSubject string `index:"13" re:"\w+|\*any"` + BalanceSharedGroups string `index:"14" re:"\w+|\*any"` + BalanceExpiryTime string `index:"15" re:"\*\w+\s*|\+\d+[smh]\s*|\d+\s*"` + BalanceTimingTags string `index:"16" re:"[0-9A-Za-z_;]*|\*any"` + BalanceWeight float64 `index:"17" re:"\d+\.?\d*"` + BalanceBlocker bool `index:"18" re:""` + BalanceDisabled bool `index:"19" re:""` + MinQueuedItems int `index:"20" re:"\d+"` + ActionsTag string `index:"21" re:"\w+"` + Weight float64 `index:"22" re:"\d+\.?\d*"` CreatedAt time.Time } diff --git a/engine/tp_reader.go b/engine/tp_reader.go index 444a9bc57..af4cae816 100644 --- a/engine/tp_reader.go +++ b/engine/tp_reader.go @@ -625,7 +625,18 @@ func (tpr *TpReader) LoadActionTriggers() (err error) { for key, atrsLst := range storAts { atrs := make([]*ActionTrigger, len(atrsLst)) for idx, atr := range atrsLst { - balanceExpirationDate, _ := utils.ParseTimeDetectLayout(atr.BalanceExpirationDate, tpr.timezone) + balanceExpirationDate, err := utils.ParseTimeDetectLayout(atr.BalanceExpirationDate, tpr.timezone) + if err != nil { + return err + } + 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.ParseDurationWithSecs(atr.MinSleep) if err != nil { return err @@ -640,6 +651,8 @@ func (tpr *TpReader) LoadActionTriggers() (err error) { ThresholdValue: atr.ThresholdValue, Recurrent: atr.Recurrent, MinSleep: minSleep, + ExpirationDate: expirationDate, + ActivationDate: activationDate, BalanceId: atr.BalanceId, BalanceType: atr.BalanceType, BalanceDirections: utils.ParseStringMap(atr.BalanceDirections), @@ -783,7 +796,9 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error atrs := make([]*ActionTrigger, len(atrsLst)) for idx, apiAtr := range atrsLst { minSleep, _ := utils.ParseDurationWithSecs(apiAtr.MinSleep) - expTime, _ := utils.ParseDate(apiAtr.BalanceExpirationDate) + balanceExpTime, _ := utils.ParseDate(apiAtr.BalanceExpirationDate) + expTime, _ := utils.ParseDate(apiAtr.ExpirationDate) + actTime, _ := utils.ParseDate(apiAtr.ActivationDate) if apiAtr.UniqueID == "" { apiAtr.UniqueID = utils.GenUUID() } @@ -794,12 +809,14 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error ThresholdValue: apiAtr.ThresholdValue, Recurrent: apiAtr.Recurrent, MinSleep: minSleep, + ExpirationDate: expTime, + ActivationDate: actTime, BalanceId: apiAtr.BalanceId, BalanceType: apiAtr.BalanceType, BalanceDirections: utils.ParseStringMap(apiAtr.BalanceDirections), BalanceDestinationIds: utils.ParseStringMap(apiAtr.BalanceDestinationIds), BalanceWeight: apiAtr.BalanceWeight, - BalanceExpirationDate: expTime, + BalanceExpirationDate: balanceExpTime, BalanceTimingTags: utils.ParseStringMap(apiAtr.BalanceTimingTags), BalanceRatingSubject: apiAtr.BalanceRatingSubject, BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories), @@ -1012,7 +1029,9 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) { atrs := make([]*ActionTrigger, len(atrsLst)) for idx, apiAtr := range atrsLst { minSleep, _ := utils.ParseDurationWithSecs(apiAtr.MinSleep) - expTime, _ := utils.ParseDate(apiAtr.BalanceExpirationDate) + balanceExpTime, _ := utils.ParseDate(apiAtr.BalanceExpirationDate) + expTime, _ := utils.ParseDate(apiAtr.ExpirationDate) + actTime, _ := utils.ParseDate(apiAtr.ActivationDate) if apiAtr.UniqueID == "" { apiAtr.UniqueID = utils.GenUUID() } @@ -1023,12 +1042,14 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) { ThresholdValue: apiAtr.ThresholdValue, Recurrent: apiAtr.Recurrent, MinSleep: minSleep, + ExpirationDate: expTime, + ActivationDate: actTime, BalanceId: apiAtr.BalanceId, BalanceType: apiAtr.BalanceType, BalanceDirections: utils.ParseStringMap(apiAtr.BalanceDirections), BalanceDestinationIds: utils.ParseStringMap(apiAtr.BalanceDestinationIds), BalanceWeight: apiAtr.BalanceWeight, - BalanceExpirationDate: expTime, + BalanceExpirationDate: balanceExpTime, BalanceRatingSubject: apiAtr.BalanceRatingSubject, BalanceCategories: utils.ParseStringMap(apiAtr.BalanceCategories), BalanceSharedGroups: utils.ParseStringMap(apiAtr.BalanceSharedGroups), diff --git a/utils/apitpdata.go b/utils/apitpdata.go index f235c33ed..9fdabdc9a 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -480,6 +480,8 @@ type TPActionTrigger struct { 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 BalanceDirections string // Traffic direction