diff --git a/apier/v1/apier.go b/apier/v1/apier.go
index 9afe5cf63..b6abf47f0 100644
--- a/apier/v1/apier.go
+++ b/apier/v1/apier.go
@@ -824,7 +824,7 @@ func (self *ApierV1) GetCacheStats(attrs utils.AttrCacheStats, reply *utils.Cach
}
if loadHistInsts, err := self.AccountDb.GetLoadHistory(1, false); err != nil || len(loadHistInsts) == 0 {
if err != nil { // Not really an error here since we only count in cache
- utils.Logger.Err(fmt.Sprintf("ApierV1.GetCacheStats, error on GetLoadHistory: %s", err.Error()))
+ utils.Logger.Warning(fmt.Sprintf("ApierV1.GetCacheStats, error on GetLoadHistory: %s", err.Error()))
}
cs.LastLoadId = utils.NOT_AVAILABLE
cs.LastLoadTime = utils.NOT_AVAILABLE
diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go
index cfa76e271..002d95e43 100644
--- a/apier/v1/apier_local_test.go
+++ b/apier/v1/apier_local_test.go
@@ -1295,8 +1295,8 @@ func TestApierResetDataAfterLoadFromFolder(t *testing.T) {
t.Error("Got error on ApierV1.GetCacheStats: ", err.Error())
} else {
if rcvStats.Destinations != 5 ||
- rcvStats.RatingPlans != 4 ||
- rcvStats.RatingProfiles != 4 ||
+ rcvStats.RatingPlans != 5 ||
+ rcvStats.RatingProfiles != 5 ||
rcvStats.Actions != 8 ||
rcvStats.DerivedChargers != 3 {
t.Errorf("Calling ApierV1.GetCacheStats received: %+v", rcvStats)
diff --git a/apier/v1/triggers.go b/apier/v1/triggers.go
index 642c137c7..b6c6a3f5f 100644
--- a/apier/v1/triggers.go
+++ b/apier/v1/triggers.go
@@ -175,7 +175,7 @@ type AttrSetAccountActionTriggers struct {
MinSleep *string
ExpirationDate *string
ActivationDate *string
- BalanceId *string
+ BalanceID *string
BalanceType *string
BalanceDirections *[]string
BalanceDestinationIds *[]string
@@ -188,7 +188,7 @@ type AttrSetAccountActionTriggers struct {
BalanceBlocker *bool
BalanceDisabled *bool
MinQueuedItems *int
- ActionsId *string
+ ActionsID *string
}
func (self *ApierV1) SetAccountActionTriggers(attr AttrSetAccountActionTriggers, reply *string) error {
@@ -238,8 +238,9 @@ func (self *ApierV1) SetAccountActionTriggers(attr AttrSetAccountActionTriggers,
}
at.ActivationDate = actTime
}
- if attr.BalanceId != nil {
- at.Balance.ID = attr.BalanceId
+ at.Balance = &engine.BalanceFilter{}
+ if attr.BalanceID != nil {
+ at.Balance.ID = attr.BalanceID
}
if attr.BalanceType != nil {
at.Balance.Type = attr.BalanceType
@@ -281,8 +282,8 @@ func (self *ApierV1) SetAccountActionTriggers(attr AttrSetAccountActionTriggers,
if attr.MinQueuedItems != nil {
at.MinQueuedItems = *attr.MinQueuedItems
}
- if attr.ActionsId != nil {
- at.ActionsID = *attr.ActionsId
+ if attr.ActionsID != nil {
+ at.ActionsID = *attr.ActionsID
}
}
@@ -300,3 +301,180 @@ func (self *ApierV1) SetAccountActionTriggers(attr AttrSetAccountActionTriggers,
*reply = utils.OK
return nil
}
+
+type AttrSetActionTrigger struct {
+ 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) SetActionTrigger(attr AttrSetActionTrigger, reply *string) error {
+
+ if missing := utils.MissingStructFields(&attr, []string{"GroupID"}); len(missing) != 0 {
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+
+ atrs, _ := self.RatingDb.GetActionTriggers(attr.GroupID)
+ var newAtr *engine.ActionTrigger
+ if attr.UniqueID != "" {
+ //search for exiting one
+ for _, atr := range atrs {
+ if atr.UniqueID == attr.UniqueID {
+ newAtr = atr
+ break
+ }
+ }
+ }
+
+ if newAtr == nil {
+ newAtr = &engine.ActionTrigger{}
+ atrs = append(atrs, newAtr)
+ }
+ newAtr.ID = attr.GroupID
+ if attr.UniqueID != "" {
+ newAtr.UniqueID = attr.UniqueID
+ } else {
+ newAtr.UniqueID = utils.GenUUID()
+ }
+
+ if attr.ThresholdType != nil {
+ newAtr.ThresholdType = *attr.ThresholdType
+ }
+ if attr.ThresholdValue != nil {
+ newAtr.ThresholdValue = *attr.ThresholdValue
+ }
+ if attr.Recurrent != nil {
+ newAtr.Recurrent = *attr.Recurrent
+ }
+ if attr.MinSleep != nil {
+ minSleep, err := utils.ParseDurationWithSecs(*attr.MinSleep)
+ if err != nil {
+ *reply = err.Error()
+ return err
+ }
+ newAtr.MinSleep = minSleep
+ }
+ if attr.ExpirationDate != nil {
+ expTime, err := utils.ParseTimeDetectLayout(*attr.ExpirationDate, self.Config.DefaultTimezone)
+ if err != nil {
+ *reply = err.Error()
+ return err
+ }
+ newAtr.ExpirationDate = expTime
+ }
+ if attr.ActivationDate != nil {
+ actTime, err := utils.ParseTimeDetectLayout(*attr.ActivationDate, self.Config.DefaultTimezone)
+ if err != nil {
+ *reply = err.Error()
+ return err
+ }
+ newAtr.ActivationDate = actTime
+ }
+ newAtr.Balance = &engine.BalanceFilter{}
+ if attr.BalanceID != nil {
+ newAtr.Balance.ID = attr.BalanceID
+ }
+ if attr.BalanceType != nil {
+ newAtr.Balance.Type = attr.BalanceType
+ }
+ if attr.BalanceDirections != nil {
+ newAtr.Balance.Directions = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceDirections...))
+ }
+ if attr.BalanceDestinationIds != nil {
+ newAtr.Balance.DestinationIDs = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceDestinationIds...))
+ }
+ if attr.BalanceWeight != nil {
+ newAtr.Balance.Weight = attr.BalanceWeight
+ }
+ if attr.BalanceExpirationDate != nil {
+ balanceExpTime, err := utils.ParseDate(*attr.BalanceExpirationDate)
+ if err != nil {
+ *reply = err.Error()
+ return err
+ }
+ newAtr.Balance.ExpirationDate = &balanceExpTime
+ }
+ if attr.BalanceTimingTags != nil {
+ newAtr.Balance.TimingIDs = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceTimingTags...))
+ }
+ if attr.BalanceRatingSubject != nil {
+ newAtr.Balance.RatingSubject = attr.BalanceRatingSubject
+ }
+ if attr.BalanceCategories != nil {
+ newAtr.Balance.Categories = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceCategories...))
+ }
+ if attr.BalanceSharedGroups != nil {
+ newAtr.Balance.SharedGroups = utils.StringMapPointer(utils.NewStringMap(*attr.BalanceSharedGroups...))
+ }
+ if attr.BalanceBlocker != nil {
+ newAtr.Balance.Blocker = attr.BalanceBlocker
+ }
+ if attr.BalanceDisabled != nil {
+ newAtr.Balance.Disabled = attr.BalanceDisabled
+ }
+ if attr.MinQueuedItems != nil {
+ newAtr.MinQueuedItems = *attr.MinQueuedItems
+ }
+ if attr.ActionsID != nil {
+ newAtr.ActionsID = *attr.ActionsID
+ }
+
+ if err := self.RatingDb.SetActionTriggers(attr.GroupID, atrs); err != nil {
+ *reply = err.Error()
+ return err
+ }
+ //no cache for action triggers
+ *reply = utils.OK
+ return nil
+}
+
+type AttrGetActionTriggers struct {
+ GroupIDs []string
+}
+
+func (self *ApierV1) GetActionTriggers(attr AttrGetActionTriggers, atrs *engine.ActionTriggers) error {
+ var allAttrs engine.ActionTriggers
+ if len(attr.GroupIDs) > 0 {
+ for _, key := range attr.GroupIDs {
+ getAttrs, err := self.RatingDb.GetActionTriggers(key)
+ if err != nil {
+ return err
+ }
+ allAttrs = append(allAttrs, getAttrs...)
+ }
+
+ } else {
+ keys, err := self.RatingDb.GetKeysForPrefix(utils.ACTION_TRIGGER_PREFIX, true)
+ if err != nil {
+ return err
+ }
+ for _, key := range keys {
+ getAttrs, err := self.RatingDb.GetActionTriggers(key[len(utils.ACTION_TRIGGER_PREFIX):])
+ if err != nil {
+ return err
+ }
+ allAttrs = append(allAttrs, getAttrs...)
+ }
+ }
+ *atrs = allAttrs
+ return nil
+}
diff --git a/console/trigger_add.go b/console/account_trigger_add.go
similarity index 76%
rename from console/trigger_add.go
rename to console/account_trigger_add.go
index bef41f910..3577aee9f 100644
--- a/console/trigger_add.go
+++ b/console/account_trigger_add.go
@@ -21,8 +21,8 @@ package console
import "github.com/cgrates/cgrates/apier/v1"
func init() {
- c := &CmdAddTriggers{
- name: "triggers_add",
+ c := &CmdAccountAddTriggers{
+ name: "account_triggers_add",
rpcMethod: "ApierV1.AddAccountActionTriggers",
rpcParams: &v1.AttrAddAccountActionTriggers{},
}
@@ -31,33 +31,33 @@ func init() {
}
// Commander implementation
-type CmdAddTriggers struct {
+type CmdAccountAddTriggers struct {
name string
rpcMethod string
rpcParams *v1.AttrAddAccountActionTriggers
*CommandExecuter
}
-func (self *CmdAddTriggers) Name() string {
+func (self *CmdAccountAddTriggers) Name() string {
return self.name
}
-func (self *CmdAddTriggers) RpcMethod() string {
+func (self *CmdAccountAddTriggers) RpcMethod() string {
return self.rpcMethod
}
-func (self *CmdAddTriggers) RpcParams(reset bool) interface{} {
+func (self *CmdAccountAddTriggers) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.AttrAddAccountActionTriggers{}
}
return self.rpcParams
}
-func (self *CmdAddTriggers) PostprocessRpcParams() error {
+func (self *CmdAccountAddTriggers) PostprocessRpcParams() error {
return nil
}
-func (self *CmdAddTriggers) RpcResult() interface{} {
+func (self *CmdAccountAddTriggers) RpcResult() interface{} {
var s string
return &s
}
diff --git a/console/trigger_remove.go b/console/account_trigger_remove.go
similarity index 75%
rename from console/trigger_remove.go
rename to console/account_trigger_remove.go
index a460d8528..5d2739692 100644
--- a/console/trigger_remove.go
+++ b/console/account_trigger_remove.go
@@ -21,8 +21,8 @@ package console
import "github.com/cgrates/cgrates/apier/v1"
func init() {
- c := &CmdRemoveTriggers{
- name: "triggers_remove",
+ c := &CmdAccountRemoveTriggers{
+ name: "account_triggers_remove",
rpcMethod: "ApierV1.RemoveAccountActionTriggers",
rpcParams: &v1.AttrRemoveAccountActionTriggers{},
}
@@ -31,33 +31,33 @@ func init() {
}
// Commander implementation
-type CmdRemoveTriggers struct {
+type CmdAccountRemoveTriggers struct {
name string
rpcMethod string
rpcParams *v1.AttrRemoveAccountActionTriggers
*CommandExecuter
}
-func (self *CmdRemoveTriggers) Name() string {
+func (self *CmdAccountRemoveTriggers) Name() string {
return self.name
}
-func (self *CmdRemoveTriggers) RpcMethod() string {
+func (self *CmdAccountRemoveTriggers) RpcMethod() string {
return self.rpcMethod
}
-func (self *CmdRemoveTriggers) RpcParams(reset bool) interface{} {
+func (self *CmdAccountRemoveTriggers) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.AttrRemoveAccountActionTriggers{}
}
return self.rpcParams
}
-func (self *CmdRemoveTriggers) PostprocessRpcParams() error {
+func (self *CmdAccountRemoveTriggers) PostprocessRpcParams() error {
return nil
}
-func (self *CmdRemoveTriggers) RpcResult() interface{} {
+func (self *CmdAccountRemoveTriggers) RpcResult() interface{} {
var s string
return &s
}
diff --git a/console/trigger_reset.go b/console/account_trigger_reset.go
similarity index 75%
rename from console/trigger_reset.go
rename to console/account_trigger_reset.go
index 0d5be9f24..d545361db 100644
--- a/console/trigger_reset.go
+++ b/console/account_trigger_reset.go
@@ -21,8 +21,8 @@ package console
import "github.com/cgrates/cgrates/apier/v1"
func init() {
- c := &CmdResetTriggers{
- name: "triggers_reset",
+ c := &CmdAccountResetTriggers{
+ name: "account_triggers_reset",
rpcMethod: "ApierV1.ResetAccountActionTriggers",
rpcParams: &v1.AttrRemoveAccountActionTriggers{},
}
@@ -31,33 +31,33 @@ func init() {
}
// Commander implementation
-type CmdResetTriggers struct {
+type CmdAccountResetTriggers struct {
name string
rpcMethod string
rpcParams *v1.AttrRemoveAccountActionTriggers
*CommandExecuter
}
-func (self *CmdResetTriggers) Name() string {
+func (self *CmdAccountResetTriggers) Name() string {
return self.name
}
-func (self *CmdResetTriggers) RpcMethod() string {
+func (self *CmdAccountResetTriggers) RpcMethod() string {
return self.rpcMethod
}
-func (self *CmdResetTriggers) RpcParams(reset bool) interface{} {
+func (self *CmdAccountResetTriggers) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.AttrRemoveAccountActionTriggers{}
}
return self.rpcParams
}
-func (self *CmdResetTriggers) PostprocessRpcParams() error {
+func (self *CmdAccountResetTriggers) PostprocessRpcParams() error {
return nil
}
-func (self *CmdResetTriggers) RpcResult() interface{} {
+func (self *CmdAccountResetTriggers) RpcResult() interface{} {
var s string
return &s
}
diff --git a/console/account_trigger_set.go b/console/account_trigger_set.go
new file mode 100644
index 000000000..84ed47079
--- /dev/null
+++ b/console/account_trigger_set.go
@@ -0,0 +1,63 @@
+/*
+Rating system designed to be used in VoIP Carriers World
+Copyright (C) 2012-2015 ITsysCOM
+
+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 console
+
+import "github.com/cgrates/cgrates/apier/v1"
+
+func init() {
+ c := &CmdAccountSetTriggers{
+ name: "account_triggers_set",
+ rpcMethod: "ApierV1.SetAccountActionTriggers",
+ rpcParams: &v1.AttrSetAccountActionTriggers{},
+ }
+ commands[c.Name()] = c
+ c.CommandExecuter = &CommandExecuter{c}
+}
+
+// Commander implementation
+type CmdAccountSetTriggers struct {
+ name string
+ rpcMethod string
+ rpcParams *v1.AttrSetAccountActionTriggers
+ *CommandExecuter
+}
+
+func (self *CmdAccountSetTriggers) Name() string {
+ return self.name
+}
+
+func (self *CmdAccountSetTriggers) RpcMethod() string {
+ return self.rpcMethod
+}
+
+func (self *CmdAccountSetTriggers) RpcParams(reset bool) interface{} {
+ if reset || self.rpcParams == nil {
+ self.rpcParams = &v1.AttrSetAccountActionTriggers{}
+ }
+ return self.rpcParams
+}
+
+func (self *CmdAccountSetTriggers) PostprocessRpcParams() error {
+ return nil
+}
+
+func (self *CmdAccountSetTriggers) RpcResult() interface{} {
+ var s string
+ return &s
+}
diff --git a/console/trigger_set.go b/console/trigger_set.go
index 2e9095d95..e1a72dd67 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.SetActionTrigger",
+ rpcParams: &v1.AttrSetActionTrigger{},
}
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.AttrSetActionTrigger
*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.AttrSetActionTrigger{}
}
return self.rpcParams
}
diff --git a/console/triggers.go b/console/triggers.go
new file mode 100644
index 000000000..454d4994c
--- /dev/null
+++ b/console/triggers.go
@@ -0,0 +1,66 @@
+/*
+Rating system designed to be used in VoIP Carriers World
+Copyright (C) 2012-2015 ITsysCOM
+
+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 console
+
+import (
+ "github.com/cgrates/cgrates/apier/v1"
+ "github.com/cgrates/cgrates/engine"
+)
+
+func init() {
+ c := &CmdGetTriggers{
+ name: "triggers",
+ rpcMethod: "ApierV1.GetActionTriggers",
+ rpcParams: &v1.AttrGetActionTriggers{},
+ }
+ commands[c.Name()] = c
+ c.CommandExecuter = &CommandExecuter{c}
+}
+
+// Commander implementation
+type CmdGetTriggers struct {
+ name string
+ rpcMethod string
+ rpcParams *v1.AttrGetActionTriggers
+ *CommandExecuter
+}
+
+func (self *CmdGetTriggers) Name() string {
+ return self.name
+}
+
+func (self *CmdGetTriggers) RpcMethod() string {
+ return self.rpcMethod
+}
+
+func (self *CmdGetTriggers) RpcParams(reset bool) interface{} {
+ if reset || self.rpcParams == nil {
+ self.rpcParams = &v1.AttrGetActionTriggers{}
+ }
+ return self.rpcParams
+}
+
+func (self *CmdGetTriggers) PostprocessRpcParams() error {
+ return nil
+}
+
+func (self *CmdGetTriggers) RpcResult() interface{} {
+ atr := engine.ActionTriggers{}
+ return &atr
+}
diff --git a/data/docker/devel/Dockerfile b/data/docker/devel/Dockerfile
index 47e251317..ea0a8b803 100644
--- a/data/docker/devel/Dockerfile
+++ b/data/docker/devel/Dockerfile
@@ -17,7 +17,7 @@ RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
RUN echo 'deb http://repo.mongodb.org/apt/debian wheezy/mongodb-org/3.2 main' | tee '/etc/apt/sources.list.d/mongodb-org-3.2.list'
# install dependencies
-RUN apt-get -y update && apt-get -y install git bzr mercurial redis-server mysql-server python-pycurl python-mysqldb postgresql postgresql-client sudo wget freeswitch-meta-vanilla vim zsh mongodb-org
+RUN apt-get -y update && apt-get -y install git bzr mercurial redis-server mysql-server python-pycurl python-mysqldb postgresql postgresql-client sudo wget freeswitch-meta-vanilla vim zsh mongodb-org tmux rsyslog
# add mongo conf
COPY mongod.conf /etc/mongod.conf
@@ -34,6 +34,9 @@ RUN GOROOT=/root/go GOPATH=/root/code /root/go/bin/go get github.com/Masterminds
#install oh-my-zsh
RUN TERM=xterm sh -c "$(wget https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"; exit 0
+# change shell for tmux
+RUN chsh -s /usr/bin/zsh
+
# cleanup
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
diff --git a/data/docker/devel/start.sh b/data/docker/devel/start.sh
index ac7992663..0a4a75591 100755
--- a/data/docker/devel/start.sh
+++ b/data/docker/devel/start.sh
@@ -2,6 +2,7 @@
sed -i 's/127.0.0.1/0.0.0.0/g' /etc/redis/redis.conf /etc/mysql/my.cnf
echo 'host all all 0.0.0.0/32 md5'>>/etc/postgresql/9.4/main/pg_hba.conf
+/etc/init.d/rsyslog start
/etc/init.d/mysql start
/etc/init.d/postgresql start
/etc/init.d/redis-server start
diff --git a/data/tariffplans/testtp/AccountActions.csv b/data/tariffplans/testtp/AccountActions.csv
index d04a5bde4..fc5722aa3 100644
--- a/data/tariffplans/testtp/AccountActions.csv
+++ b/data/tariffplans/testtp/AccountActions.csv
@@ -7,3 +7,4 @@ cgrates.org,1005,PREPAID_10,STANDARD_TRIGGERS,,
cgrates.org,1009,TEST_EXE,,,
cgrates.org,1010,TEST_DATA_r,,true,
cgrates.org,1011,TEST_VOICE,,,
+cgrates.org,1012,PREPAID_10,,,
diff --git a/data/tariffplans/testtp/DestinationRates.csv b/data/tariffplans/testtp/DestinationRates.csv
index 9be903aef..2f51c5c18 100644
--- a/data/tariffplans/testtp/DestinationRates.csv
+++ b/data/tariffplans/testtp/DestinationRates.csv
@@ -3,4 +3,5 @@ DR_RETAIL,GERMANY,RT_1CENT,*up,4,0,
DR_RETAIL,GERMANY_MOBILE,RT_1CENT,*up,4,0,
DR_DATA_1,*any,RT_DATA_2c,*up,4,0,
DR_SMS_1,*any,RT_SMS_5c,*up,4,0,
-DR_DATA_r,DATA_DEST,RT_DATA_r,*up,5,0,
\ No newline at end of file
+DR_DATA_r,DATA_DEST,RT_DATA_r,*up,5,0,
+DR_FREE,GERMANY,RT_ZERO,*middle,2,0,
diff --git a/data/tariffplans/testtp/Rates.csv b/data/tariffplans/testtp/Rates.csv
index 21c9abc4a..b8860104b 100644
--- a/data/tariffplans/testtp/Rates.csv
+++ b/data/tariffplans/testtp/Rates.csv
@@ -3,3 +3,4 @@ RT_1CENT,0,1,1s,1s,0s
RT_DATA_2c,0,0.002,10,10,0
RT_SMS_5c,0,0.005,1,1,0
RT_DATA_r,0,0.1,1048576,10240,0
+RT_ZERO,0,0,1,1,0
diff --git a/data/tariffplans/testtp/RatingPlans.csv b/data/tariffplans/testtp/RatingPlans.csv
index f7003dcf4..5be68df5d 100644
--- a/data/tariffplans/testtp/RatingPlans.csv
+++ b/data/tariffplans/testtp/RatingPlans.csv
@@ -3,3 +3,4 @@ RP_RETAIL,DR_RETAIL,ALWAYS,10
RP_DATA1,DR_DATA_1,ALWAYS,10
RP_SMS1,DR_SMS_1,ALWAYS,10
RP_DATAr,DR_DATA_r,ALWAYS,10
+RP_FREE,DR_FREE,ALWAYS,10
diff --git a/data/tariffplans/testtp/RatingProfiles.csv b/data/tariffplans/testtp/RatingProfiles.csv
index ffa6bf2f6..3a6a28222 100644
--- a/data/tariffplans/testtp/RatingProfiles.csv
+++ b/data/tariffplans/testtp/RatingProfiles.csv
@@ -3,3 +3,4 @@
*out,cgrates.org,data,*any,2012-01-01T00:00:00Z,RP_DATA1,,
*out,cgrates.org,sms,*any,2012-01-01T00:00:00Z,RP_SMS1,,
*out,cgrates.org,data,datar,2016-01-01T00:00:00Z,RP_DATAr,,
+*out,cgrates.org,call,free,2016-01-01T00:00:00Z,RP_FREE,,
diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go
index 84503d7a1..51abc1989 100644
--- a/engine/storage_mongo_datadb.go
+++ b/engine/storage_mongo_datadb.go
@@ -310,6 +310,12 @@ func (ms *MongoStorage) GetKeysForPrefix(prefix string, skipCache bool) ([]strin
result = append(result, utils.ACTION_PLAN_PREFIX+keyResult.Key)
}
return result, nil
+ case utils.ACTION_TRIGGER_PREFIX:
+ iter := ms.db.C(colAtr).Find(bson.M{"key": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"key": 1}).Iter()
+ for iter.Next(&keyResult) {
+ result = append(result, utils.ACTION_TRIGGER_PREFIX+keyResult.Key)
+ }
+ return result, nil
case utils.ACCOUNT_PREFIX:
iter := ms.db.C(colAcc).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter()
for iter.Next(&idResult) {
diff --git a/general_tests/tp_it_test.go b/general_tests/tp_it_test.go
index 3eef405e1..cbea917f3 100644
--- a/general_tests/tp_it_test.go
+++ b/general_tests/tp_it_test.go
@@ -7,6 +7,7 @@ import (
"testing"
"time"
+ "github.com/cgrates/cgrates/apier/v1"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/utils"
@@ -106,7 +107,7 @@ func TestTpBalanceCounter(t *testing.T) {
var cc engine.CallCost
if err := tpRPC.Call("Responder.Debit", cd, &cc); err != nil {
t.Error("Got error on Responder.GetCost: ", err.Error())
- } else if cc.GetDuration() == 20 {
+ } else if cc.GetDuration() != 20*time.Second {
t.Errorf("Calling Responder.MaxDebit got callcost: %v", cc.GetDuration())
}
var acnt *engine.Account
@@ -117,3 +118,72 @@ func TestTpBalanceCounter(t *testing.T) {
t.Errorf("Calling ApierV2.GetBalance received: %s", utils.ToIJSON(acnt))
}
}
+
+func TestTpActionTriggers(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ var atrs engine.ActionTriggers
+ if err := tpRPC.Call("ApierV1.GetActionTriggers", v1.AttrGetActionTriggers{GroupIDs: []string{}}, &atrs); err != nil {
+ t.Error("Got error on ApierV1.GetActionTriggers: ", err.Error())
+ } else if len(atrs) != 9 {
+ t.Errorf("Calling v1.GetActionTriggers got: %v", atrs)
+ }
+ var reply string
+ if err := tpRPC.Call("ApierV1.SetActionTrigger", v1.AttrSetActionTrigger{
+ GroupID: "TestATR",
+ UniqueID: "Unique atr id",
+ BalanceID: utils.StringPointer("BID1"),
+ }, &reply); err != nil {
+ t.Error("Got error on ApierV1.SetActionTrigger: ", err.Error())
+ } else if reply != utils.OK {
+ t.Errorf("Calling v1.SetActionTrigger got: %v", reply)
+ }
+
+ if err := tpRPC.Call("ApierV1.GetActionTriggers", v1.AttrGetActionTriggers{GroupIDs: []string{}}, &atrs); err != nil {
+ t.Error("Got error on ApierV1.GetActionTriggers: ", err.Error())
+ } else if len(atrs) != 10 {
+ t.Errorf("Calling v1.GetActionTriggers got: %v", atrs)
+ }
+ if err := tpRPC.Call("ApierV1.GetActionTriggers", v1.AttrGetActionTriggers{GroupIDs: []string{"TestATR"}}, &atrs); err != nil {
+ t.Error("Got error on ApierV1.GetActionTriggers: ", err.Error())
+ } else if len(atrs) != 1 {
+ t.Errorf("Calling v1.GetActionTriggers got: %v", atrs)
+ }
+ if atrs[0].ID != "TestATR" ||
+ atrs[0].UniqueID != "Unique atr id" ||
+ *atrs[0].Balance.ID != "BID1" {
+ t.Error("Wrong action trigger set: ", utils.ToIJSON(atrs[0]))
+ }
+}
+
+func TestTpZeroCost(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ tStart := time.Date(2016, 3, 31, 0, 0, 0, 0, time.UTC)
+ cd := engine.CallDescriptor{
+ Direction: "*out",
+ Category: "call",
+ Tenant: "cgrates.org",
+ Subject: "free",
+ Account: "1012",
+ Destination: "+49",
+ DurationIndex: 0,
+ TimeStart: tStart,
+ TimeEnd: tStart.Add(time.Duration(20) * time.Second),
+ }
+ var cc engine.CallCost
+ if err := tpRPC.Call("Responder.Debit", cd, &cc); err != nil {
+ t.Error("Got error on Responder.GetCost: ", err.Error())
+ } else if cc.GetDuration() != 20*time.Second {
+ t.Errorf("Calling Responder.MaxDebit got callcost: %v", utils.ToIJSON(cc))
+ }
+ var acnt *engine.Account
+ attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1012"}
+ if err := tpRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil {
+ t.Error("Got error on ApierV2.GetAccount: ", err.Error())
+ } else if acnt.BalanceMap[utils.MONETARY][0].Value != 11.0 {
+ t.Errorf("Calling ApierV2.GetAccount received: %s", utils.ToIJSON(acnt))
+ }
+}
diff --git a/packages/squeeze/rules b/packages/squeeze/rules
index b813db9c6..34115a611 100755
--- a/packages/squeeze/rules
+++ b/packages/squeeze/rules
@@ -5,7 +5,6 @@
export DH_VERBOSE=1
export GOPATH=$(CURDIR)
-export GO15VENDOREXPERIMENT=1
PKGDIR=debian/cgrates
SRCDIR=src/github.com/cgrates/cgrates
@@ -24,8 +23,8 @@ binary-arch: clean
dh_installdirs
mkdir -p src/github.com/cgrates
ln -sf $(CURDIR) src/github.com/cgrates
- go get -v github.com/Masterminds/glide
- $(GOPATH)/bin/glide install
+ go get -u -v github.com/Masterminds/glide
+ $(GOPATH)/bin/glide install --force
exec $(CURDIR)/build.sh
mkdir -p $(PKGDIR)/usr/bin
cp $(GOPATH)/bin/cgr-* $(PKGDIR)/usr/bin/