diff --git a/apier/v1/tpfilters.go b/apier/v1/tpfilters.go
new file mode 100644
index 000000000..f7fa1d7e8
--- /dev/null
+++ b/apier/v1/tpfilters.go
@@ -0,0 +1,96 @@
+/*
+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 (
+ "github.com/cgrates/cgrates/utils"
+)
+
+// Creates a new Filter within a tariff plan
+func (self *ApierV1) SetTPFilter(attrs utils.TPFilter, reply *string) error {
+ if missing := utils.MissingStructFields(&attrs, []string{"TPid", "Tenant", "ID"}); len(missing) != 0 {
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if err := self.StorDb.SetTPFilter([]*utils.TPFilter{&attrs}); err != nil {
+ return utils.NewErrServerError(err)
+ }
+ *reply = utils.OK
+ return nil
+}
+
+type AttrGetTPFilter struct {
+ TPid string // Tariff plan id
+ ID string // Filter id
+}
+
+// Queries specific Filter on tariff plan
+func (self *ApierV1) GetTPFilter(attr AttrGetTPFilter, reply *utils.TPFilter) error {
+ if missing := utils.MissingStructFields(&attr, []string{"TPid", "ID"}); len(missing) != 0 { //Params missing
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if filter, err := self.StorDb.GetTPFilter(attr.TPid, attr.ID); err != nil {
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
+ } else {
+ *reply = *filter[0]
+ }
+ return nil
+}
+
+type AttrGetTPFilterIds struct {
+ TPid string // Tariff plan id
+ utils.Paginator
+}
+
+// Queries Filter identities on specific tariff plan.
+func (self *ApierV1) GetTPFilterIds(attrs AttrGetTPFilterIds, reply *[]string) error {
+ if missing := utils.MissingStructFields(&attrs, []string{"TPid"}); len(missing) != 0 { //Params missing
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if ids, err := self.StorDb.GetTpTableIds(attrs.TPid, utils.TBLTPFilters, utils.TPDistinctIds{"id"}, nil, &attrs.Paginator); err != nil {
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
+ } else {
+ *reply = ids
+ }
+ return nil
+}
+
+type AttrRemTPFilter struct {
+ TPid string // Tariff plan id
+ Tenant string
+ ID string // Filter id
+}
+
+// Removes specific Filter on Tariff plan
+func (self *ApierV1) RemTPFilter(attrs AttrRemTPFilter, reply *string) error {
+ if missing := utils.MissingStructFields(&attrs, []string{"TPid", "Tenant", "ID"}); len(missing) != 0 { //Params missing
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if err := self.StorDb.RemTpData(utils.TBLTPFilters, attrs.TPid, map[string]string{"tenant": attrs.Tenant, "id": attrs.ID}); err != nil {
+ return utils.NewErrServerError(err)
+ } else {
+ *reply = utils.OK
+ }
+ return nil
+}
diff --git a/apier/v1/tpfilters_it_test.go b/apier/v1/tpfilters_it_test.go
new file mode 100644
index 000000000..b302c2a03
--- /dev/null
+++ b/apier/v1/tpfilters_it_test.go
@@ -0,0 +1,215 @@
+// +build offline_tp
+
+/*
+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 (
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+ "net/rpc"
+ "net/rpc/jsonrpc"
+ "path"
+ "reflect"
+ "testing"
+)
+
+var (
+ tpFilterCfgPath string
+ tpFilterCfg *config.CGRConfig
+ tpFilterRPC *rpc.Client
+ tpFilterDataDir = "/usr/share/cgrates"
+ tpFilter *utils.TPFilter
+ tpFilterDelay int
+ tpFilterConfigDIR string //run tests for specific configuration
+)
+
+var sTestsTPFilters = []func(t *testing.T){
+ testTPFilterInitCfg,
+ testTPFilterResetStorDb,
+ testTPFilterStartEngine,
+ testTPFilterRpcConn,
+ ttestTPFilterGetTPFilterBeforeSet,
+ testTPFilterSetTPFilter,
+ testTPFilterGetTPFilterAfterSet,
+ testTPFilterGetFilterIds,
+ testTPFilterUpdateTPFilter,
+ testTPFilterGetTPFilterAfterUpdate,
+ testTPFilterRemTPFilter,
+ testTPFilterGetTPFilterAfterRemove,
+ testTPFilterKillEngine,
+}
+
+//Test start here
+func TestTPFilterITMySql(t *testing.T) {
+ tpFilterConfigDIR = "tutmysql"
+ for _, stest := range sTestsTPFilters {
+ t.Run(tpFilterConfigDIR, stest)
+ }
+}
+
+func TestTPFilterITMongo(t *testing.T) {
+ tpFilterConfigDIR = "tutmongo"
+ for _, stest := range sTestsTPFilters {
+ t.Run(tpFilterConfigDIR, stest)
+ }
+}
+
+func TestTPFilterITPG(t *testing.T) {
+ tpFilterConfigDIR = "tutpostgres"
+ for _, stest := range sTestsTPFilters {
+ t.Run(tpFilterConfigDIR, stest)
+ }
+}
+
+func testTPFilterInitCfg(t *testing.T) {
+ var err error
+ tpFilterCfgPath = path.Join(tpFilterDataDir, "conf", "samples", tpFilterConfigDIR)
+ tpFilterCfg, err = config.NewCGRConfigFromFolder(tpFilterCfgPath)
+ if err != nil {
+ t.Error(err)
+ }
+ tpFilterCfg.DataFolderPath = tpFilterDataDir // Share DataFolderPath through config towards StoreDb for Flush()
+ config.SetCgrConfig(tpFilterCfg)
+ switch tpFilterConfigDIR {
+ case "tutmongo": // Mongo needs more time to reset db, need to investigate
+ tpFilterDelay = 2000
+ default:
+ tpFilterDelay = 1000
+ }
+}
+
+// Wipe out the cdr database
+func testTPFilterResetStorDb(t *testing.T) {
+ if err := engine.InitStorDb(tpFilterCfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Start CGR Engine
+func testTPFilterStartEngine(t *testing.T) {
+ if _, err := engine.StopStartEngine(tpFilterCfgPath, tpFilterDelay); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Connect rpc client to rater
+func testTPFilterRpcConn(t *testing.T) {
+ var err error
+ tpFilterRPC, err = jsonrpc.Dial("tcp", tpFilterCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func ttestTPFilterGetTPFilterBeforeSet(t *testing.T) {
+ var reply *utils.TPFilter
+ if err := tpFilterRPC.Call("ApierV1.GetTPFilter", &AttrGetTPFilter{TPid: "TP1", ID: "Filter"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testTPFilterSetTPFilter(t *testing.T) {
+ tpFilter = &utils.TPFilter{
+ TPid: "TP1",
+ Tenant: "cgrates.org",
+ ID: "Filter",
+ FilterType: "*string",
+ FilterFieldName: "Account",
+ FilterFielValues: []string{"1001", "1002"},
+ }
+
+ var result string
+ if err := tpFilterRPC.Call("ApierV1.SetTPFilter", tpFilter, &result); err != nil {
+ t.Error(err)
+ } else if result != utils.OK {
+ t.Error("Unexpected reply returned", result)
+ }
+}
+
+func testTPFilterGetTPFilterAfterSet(t *testing.T) {
+ var reply *utils.TPFilter
+ if err := tpFilterRPC.Call("ApierV1.GetTPFilter", &AttrGetTPFilter{TPid: "TP1", ID: "Filter"}, &reply); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(tpFilter, reply) {
+ t.Errorf("Expecting : %+v, received: %+v", tpFilter, reply)
+ }
+
+}
+
+func testTPFilterGetFilterIds(t *testing.T) {
+ var result []string
+ expectedTPID := []string{"Filter"}
+ if err := tpFilterRPC.Call("ApierV1.GetTPFilterIds", &AttrGetTPFilterIds{TPid: "TP1"}, &result); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(expectedTPID, result) {
+ t.Errorf("Expecting: %+v, received: %+v", expectedTPID, result)
+ }
+
+}
+
+func testTPFilterUpdateTPFilter(t *testing.T) {
+ tpFilter = &utils.TPFilter{
+ TPid: "TP1",
+ Tenant: "cgrates.org",
+ ID: "Filter",
+ FilterType: "*string_prefix",
+ FilterFieldName: "Account",
+ FilterFielValues: []string{"10", "20"},
+ }
+
+ var result string
+ if err := tpFilterRPC.Call("ApierV1.SetTPFilter", tpFilter, &result); err != nil {
+ t.Error(err)
+ } else if result != utils.OK {
+ t.Error("Unexpected reply returned", result)
+ }
+}
+
+func testTPFilterGetTPFilterAfterUpdate(t *testing.T) {
+ var reply *utils.TPFilter
+ if err := tpFilterRPC.Call("ApierV1.GetTPFilter", &AttrGetTPFilter{TPid: "TP1", ID: "Filter"}, &reply); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(tpFilter, reply) {
+ t.Errorf("Expecting : %+v, received: %+v", tpFilter, reply)
+ }
+}
+
+func testTPFilterRemTPFilter(t *testing.T) {
+ var resp string
+ if err := tpFilterRPC.Call("ApierV1.RemTPFilter", &AttrRemTPFilter{TPid: "TP1", Tenant: "cgrates.org", ID: "Filter"}, &resp); err != nil {
+ t.Error(err)
+ } else if resp != utils.OK {
+ t.Error("Unexpected reply returned", resp)
+ }
+}
+
+func testTPFilterGetTPFilterAfterRemove(t *testing.T) {
+ var reply *utils.TPFilter
+ if err := tpFilterRPC.Call("ApierV1.GetTPFilter", &AttrGetTPFilter{TPid: "TP1", ID: "Filter"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testTPFilterKillEngine(t *testing.T) {
+ if err := engine.KillEngine(tpFilterDelay); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/apier/v1/tplcrrules_it_test.go b/apier/v1/tplcrrules_it_test.go
index 135902c07..cf0363eb9 100644
--- a/apier/v1/tplcrrules_it_test.go
+++ b/apier/v1/tplcrrules_it_test.go
@@ -50,7 +50,7 @@ var sTestsTPLcrRules = []func(t *testing.T){
testTPLcrRulesGetTPLcrRulesBeforeSet,
testTPLcrRulesSetTPLcrRules,
testTPLcrRulesGetTPLcrRulesAfterSet,
- testTPLcrRulesGetTPDestinationIds,
+ testTPLcrRulesGetTPLcrRuleIds,
testTPLcrRulesUpdateTPLcrRules,
testTPLcrRulesGetTPLcrRulesAfterUpdate,
testTPLcrRulesRemTPLcrRules,
@@ -176,7 +176,7 @@ func testTPLcrRulesGetTPLcrRulesAfterSet(t *testing.T) {
}
-func testTPLcrRulesGetTPDestinationIds(t *testing.T) {
+func testTPLcrRulesGetTPLcrRuleIds(t *testing.T) {
var result []string
expectedTPID := []string{"*out:cgrates.org:call:1001:*any"}
if err := tpLcrRuleRPC.Call("ApierV1.GetTPLcrRuleIds", &AttrGetTPLcrIds{TPid: "TPLRC1"}, &result); err != nil {