From fcb98adcf727e37c327767f93552ba370fbf8696 Mon Sep 17 00:00:00 2001 From: DanB Date: Sun, 24 Nov 2013 16:31:42 +0100 Subject: [PATCH] Buffer writter for multiple values in sql queries, finished storage interface cleanup --- apier/v1/apier_local_test.go | 313 ++++++++++++++++----------------- apier/v1/tpactions.go | 6 +- apier/v1/tpdestinationrates.go | 6 +- apier/v1/tpdestinations.go | 6 +- apier/v1/tprates.go | 6 +- apier/v1/tpratingplans.go | 6 +- apier/v1/tptimings.go | 5 +- engine/loader_db.go | 61 ++++++- engine/loader_local_test.go | 9 +- engine/storage_interface.go | 38 ++-- engine/storage_sql.go | 263 ++++++++------------------- utils/apitpdata.go | 10 +- utils/consts.go | 1 - 13 files changed, 329 insertions(+), 401 deletions(-) diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go index be187863f..aacb33861 100644 --- a/apier/v1/apier_local_test.go +++ b/apier/v1/apier_local_test.go @@ -20,17 +20,17 @@ package apier import ( "flag" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/utils" - "github.com/cgrates/cgrates/engine" - "os/exec" - "path" "fmt" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" "net/rpc" "net/rpc/jsonrpc" - "time" + "os/exec" + "path" "reflect" "testing" + "time" ) // ToDo: Replace rpc.Client with internal rpc server and Apier using internal map as both data and stor so we can run the tests non-local @@ -91,11 +91,11 @@ func TestStartEngine(t *testing.T) { t.Fatal("Cannot find cgr-engine executable") } exec.Command("pkill", "cgr-engine").Run() // Just to make sure another one is not running, bit brutal maybe we can fine tune it - engine := exec.Command(enginePath, "-rater", "-config", path.Join(*dataDir,"conf","cgrates.cfg")) + engine := exec.Command(enginePath, "-rater", "-config", path.Join(*dataDir, "conf", "cgrates.cfg")) if err := engine.Start(); err != nil { t.Fatal("Cannot start cgr-engine: ", err.Error()) } - time.Sleep(time.Duration(*waitRater)*time.Millisecond) // Give time to rater to fire up + time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time to rater to fire up } // Connect rpc client to rater @@ -121,63 +121,63 @@ func TestApierTPTiming(t *testing.T) { } // ALWAYS,*any,*any,*any,*any,00:00:00 tmAlways := &utils.ApierTPTiming{TPid: engine.TEST_SQL, - TimingId: "ALWAYS", - Years: "*any", - Months: "*any", - MonthDays: "*any", - WeekDays: "*any", - Time: "00:00:00", - } + TimingId: "ALWAYS", + Years: "*any", + Months: "*any", + MonthDays: "*any", + WeekDays: "*any", + Time: "00:00:00", + } tmAlways2 := new(utils.ApierTPTiming) *tmAlways2 = *tmAlways tmAlways2.TimingId = "ALWAYS2" tmAsap := &utils.ApierTPTiming{TPid: engine.TEST_SQL, - TimingId: "ASAP", - Years: "*any", - Months: "*any", - MonthDays: "*any", - WeekDays: "*any", - Time: "*asap", - } + TimingId: "ASAP", + Years: "*any", + Months: "*any", + MonthDays: "*any", + WeekDays: "*any", + Time: "*asap", + } reply := "" for _, tm := range []*utils.ApierTPTiming{tmAlways, tmAsap, tmAlways2} { - if err := rater.Call("ApierV1.SetTPTiming", tm, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPTiming", tm, &reply); err != nil { t.Error("Got error on ApierV1.SetTPTiming: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPTiming: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPTiming", tmAlways, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPTiming", tmAlways, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPTiming: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPTiming got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPTiming", new(utils.ApierTPTiming), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPTiming", new(utils.ApierTPTiming), &reply); err == nil { t.Error("Calling ApierV1.SetTPTiming, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid TimingId Years Months MonthDays WeekDays Time]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid TimingId Years Months MonthDays WeekDays Time]" { t.Error("Calling ApierV1.SetTPTiming got unexpected error: ", err.Error()) } // Test get var rplyTmAlways2 *utils.ApierTPTiming - if err := rater.Call("ApierV1.GetTPTiming", AttrGetTPTiming{tmAlways2.TPid, tmAlways2.TimingId}, &rplyTmAlways2); err!=nil { + if err := rater.Call("ApierV1.GetTPTiming", AttrGetTPTiming{tmAlways2.TPid, tmAlways2.TimingId}, &rplyTmAlways2); err != nil { t.Error("Calling ApierV1.GetTPTiming, got error: ", err.Error()) - } else if !reflect.DeepEqual(tmAlways2, rplyTmAlways2) { + } else if !reflect.DeepEqual(tmAlways2, rplyTmAlways2) { t.Errorf("Calling ApierV1.GetTPTiming expected: %v, received: %v", tmAlways, rplyTmAlways2) } // Test remove - if err := rater.Call("ApierV1.RemTPTiming", AttrGetTPTiming{tmAlways2.TPid, tmAlways2.TimingId}, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPTiming", AttrGetTPTiming{tmAlways2.TPid, tmAlways2.TimingId}, &reply); err != nil { t.Error("Calling ApierV1.RemTPTiming, got error: ", err.Error()) - } else if reply != "OK" { + } else if reply != "OK" { t.Error("Calling ApierV1.RemTPTiming received: ", reply) } // Test getIds var rplyTmIds []string expectedTmIds := []string{"ALWAYS", "ASAP"} - if err := rater.Call("ApierV1.GetTPTimingIds", AttrGetTPTimingIds{tmAlways.TPid}, &rplyTmIds); err!=nil { + if err := rater.Call("ApierV1.GetTPTimingIds", AttrGetTPTimingIds{tmAlways.TPid}, &rplyTmIds); err != nil { t.Error("Calling ApierV1.GetTPTimingIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedTmIds, rplyTmIds) { + } else if !reflect.DeepEqual(expectedTmIds, rplyTmIds) { t.Errorf("Calling ApierV1.GetTPTimingIds expected: %v, received: %v", expectedTmIds, rplyTmIds) } } @@ -188,50 +188,50 @@ func TestApierTPDestination(t *testing.T) { return } reply := "" - dstDe := &utils.TPDestination{TPid:engine.TEST_SQL, DestinationId: "GERMANY", Prefixes: []string{"+49"}} - dstDeMobile := &utils.TPDestination{TPid:engine.TEST_SQL, DestinationId: "GERMANY_MOBILE", Prefixes: []string{"+4915", "+4916", "+4917"}} - dstFs := &utils.TPDestination{TPid:engine.TEST_SQL, DestinationId: "FS_USERS", Prefixes: []string{"10"}} + dstDe := &utils.TPDestination{TPid: engine.TEST_SQL, DestinationId: "GERMANY", Prefixes: []string{"+49"}} + dstDeMobile := &utils.TPDestination{TPid: engine.TEST_SQL, DestinationId: "GERMANY_MOBILE", Prefixes: []string{"+4915", "+4916", "+4917"}} + dstFs := &utils.TPDestination{TPid: engine.TEST_SQL, DestinationId: "FS_USERS", Prefixes: []string{"10"}} dstDe2 := new(utils.TPDestination) *dstDe2 = *dstDe // Data which we use for remove, still keeping the sample data to check proper loading dstDe2.DestinationId = "GERMANY2" for _, dst := range []*utils.TPDestination{dstDe, dstDeMobile, dstFs, dstDe2} { - if err := rater.Call("ApierV1.SetTPDestination", dst, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPDestination", dst, &reply); err != nil { t.Error("Got error on ApierV1.SetTPDestination: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPDestination: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPDestination", dstDe2, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPDestination", dstDe2, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPDestination: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPDestination got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPDestination", new(utils.TPDestination), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPDestination", new(utils.TPDestination), &reply); err == nil { t.Error("Calling ApierV1.SetTPDestination, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid DestinationId Prefixes]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid DestinationId Prefixes]" { t.Error("Calling ApierV1.SetTPDestination got unexpected error: ", err.Error()) } // Test get var rplyDstDe2 *utils.TPDestination - if err := rater.Call("ApierV1.GetTPDestination", AttrGetTPDestination{dstDe2.TPid, dstDe2.DestinationId}, &rplyDstDe2); err!=nil { + if err := rater.Call("ApierV1.GetTPDestination", AttrGetTPDestination{dstDe2.TPid, dstDe2.DestinationId}, &rplyDstDe2); err != nil { t.Error("Calling ApierV1.GetTPDestination, got error: ", err.Error()) - } else if !reflect.DeepEqual(dstDe2, rplyDstDe2) { + } else if !reflect.DeepEqual(dstDe2, rplyDstDe2) { t.Errorf("Calling ApierV1.GetTPDestination expected: %v, received: %v", dstDe2, rplyDstDe2) } // Test remove - if err := rater.Call("ApierV1.RemTPDestination", AttrGetTPDestination{dstDe2.TPid, dstDe2.DestinationId}, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPDestination", AttrGetTPDestination{dstDe2.TPid, dstDe2.DestinationId}, &reply); err != nil { t.Error("Calling ApierV1.RemTPTiming, got error: ", err.Error()) - } else if reply != "OK" { + } else if reply != "OK" { t.Error("Calling ApierV1.RemTPTiming received: ", reply) } // Test getIds var rplyDstIds []string expectedDstIds := []string{"FS_USERS", "GERMANY", "GERMANY_MOBILE"} - if err := rater.Call("ApierV1.GetTPDestinationIds", AttrGetTPDestinationIds{dstDe.TPid}, &rplyDstIds); err!=nil { + if err := rater.Call("ApierV1.GetTPDestinationIds", AttrGetTPDestinationIds{dstDe.TPid}, &rplyDstIds); err != nil { t.Error("Calling ApierV1.GetTPDestinationIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedDstIds, rplyDstIds) { + } else if !reflect.DeepEqual(expectedDstIds, rplyDstIds) { t.Errorf("Calling ApierV1.GetTPDestinationIds expected: %v, received: %v", expectedDstIds, rplyDstIds) } } @@ -243,104 +243,103 @@ func TestApierTPRate(t *testing.T) { } reply := "" rt := &utils.TPRate{TPid: engine.TEST_SQL, RateId: "RT_FS_USERS", RateSlots: []*utils.RateSlot{ - &utils.RateSlot{ConnectFee:0, Rate:0, RateUnit:"60s", RateIncrement:"60s", GroupIntervalStart:"0s", RoundingMethod:"*up", RoundingDecimals: 0}, - }} + &utils.RateSlot{ConnectFee: 0, Rate: 0, RateUnit: "60s", RateIncrement: "60s", GroupIntervalStart: "0s", RoundingMethod: "*up", RoundingDecimals: 0}, + }} rt2 := new(utils.TPRate) *rt2 = *rt rt2.RateId = "RT_FS_USERS2" for _, r := range []*utils.TPRate{rt, rt2} { - if err := rater.Call("ApierV1.SetTPRate", r, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPRate", r, &reply); err != nil { t.Error("Got error on ApierV1.SetTPRate: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPRate: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPRate", rt2, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPRate", rt2, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPRate: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPRate got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPRate", new(utils.TPRate), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPRate", new(utils.TPRate), &reply); err == nil { t.Error("Calling ApierV1.SetTPDestination, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid RateId RateSlots]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid RateId RateSlots]" { t.Error("Calling ApierV1.SetTPRate got unexpected error: ", err.Error()) } // Test get var rplyRt2 *utils.TPRate - if err := rater.Call("ApierV1.GetTPRate", AttrGetTPRate{rt2.TPid, rt2.RateId}, &rplyRt2); err!=nil { + if err := rater.Call("ApierV1.GetTPRate", AttrGetTPRate{rt2.TPid, rt2.RateId}, &rplyRt2); err != nil { t.Error("Calling ApierV1.GetTPRate, got error: ", err.Error()) - } else if !reflect.DeepEqual(rt2, rplyRt2) { + } else if !reflect.DeepEqual(rt2, rplyRt2) { t.Errorf("Calling ApierV1.GetTPRate expected: %v, received: %v", rt2, rplyRt2) } // Test remove - if err := rater.Call("ApierV1.RemTPRate", AttrGetTPRate{rt2.TPid, rt2.RateId}, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPRate", AttrGetTPRate{rt2.TPid, rt2.RateId}, &reply); err != nil { t.Error("Calling ApierV1.RemTPRate, got error: ", err.Error()) - } else if reply != "OK" { + } else if reply != "OK" { t.Error("Calling ApierV1.RemTPRate received: ", reply) } // Test getIds var rplyRtIds []string expectedRtIds := []string{"RT_FS_USERS"} - if err := rater.Call("ApierV1.GetTPRateIds", AttrGetTPRateIds{rt.TPid}, &rplyRtIds); err!=nil { + if err := rater.Call("ApierV1.GetTPRateIds", AttrGetTPRateIds{rt.TPid}, &rplyRtIds); err != nil { t.Error("Calling ApierV1.GetTPRateIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedRtIds, rplyRtIds) { + } else if !reflect.DeepEqual(expectedRtIds, rplyRtIds) { t.Errorf("Calling ApierV1.GetTPDestinationIds expected: %v, received: %v", expectedRtIds, rplyRtIds) } } - // Test here TPDestinationRate APIs func TestApierTPDestinationRate(t *testing.T) { if !*testLocal { return } reply := "" - dr := &utils.TPDestinationRate{TPid:engine.TEST_SQL, DestinationRateId: "DR_FREESWITCH_USERS", DestinationRates: []*utils.DestinationRate{ - &utils.DestinationRate{DestinationId: "FS_USERS", RateId: "RT_FS_USERS"}, - }} + dr := &utils.TPDestinationRate{TPid: engine.TEST_SQL, DestinationRateId: "DR_FREESWITCH_USERS", DestinationRates: []*utils.DestinationRate{ + &utils.DestinationRate{DestinationId: "FS_USERS", RateId: "RT_FS_USERS"}, + }} dr2 := new(utils.TPDestinationRate) *dr2 = *dr dr2.DestinationRateId = engine.TEST_SQL for _, d := range []*utils.TPDestinationRate{dr, dr2} { - if err := rater.Call("ApierV1.SetTPDestinationRate", d, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPDestinationRate", d, &reply); err != nil { t.Error("Got error on ApierV1.SetTPDestinationRate: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPDestinationRate: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPDestinationRate", dr2, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPDestinationRate", dr2, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPDestinationRate: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPDestinationRate got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPDestinationRate", new(utils.TPDestinationRate), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPDestinationRate", new(utils.TPDestinationRate), &reply); err == nil { t.Error("Calling ApierV1.SetTPDestination, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid DestinationRateId DestinationRates]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid DestinationRateId DestinationRates]" { t.Error("Calling ApierV1.SetTPDestinationRate got unexpected error: ", err.Error()) } // Test get var rplyDr2 *utils.TPDestinationRate - if err := rater.Call("ApierV1.GetTPDestinationRate", AttrGetTPDestinationRate{dr2.TPid, dr2.DestinationRateId}, &rplyDr2); err!=nil { + if err := rater.Call("ApierV1.GetTPDestinationRate", AttrGetTPDestinationRate{dr2.TPid, dr2.DestinationRateId}, &rplyDr2); err != nil { t.Error("Calling ApierV1.GetTPDestinationRate, got error: ", err.Error()) - } else if !reflect.DeepEqual(dr2, rplyDr2) { + } else if !reflect.DeepEqual(dr2, rplyDr2) { t.Errorf("Calling ApierV1.GetTPDestinationRate expected: %v, received: %v", dr2, rplyDr2) } // Test remove - if err := rater.Call("ApierV1.RemTPDestinationRate", AttrGetTPDestinationRate{dr2.TPid, dr2.DestinationRateId}, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPDestinationRate", AttrGetTPDestinationRate{dr2.TPid, dr2.DestinationRateId}, &reply); err != nil { t.Error("Calling ApierV1.RemTPRate, got error: ", err.Error()) - } else if reply != "OK" { + } else if reply != "OK" { t.Error("Calling ApierV1.RemTPRate received: ", reply) } // Test getIds var rplyDrIds []string expectedDrIds := []string{"DR_FREESWITCH_USERS"} - if err := rater.Call("ApierV1.GetTPDestinationRateIds", AttrTPDestinationRateIds{dr.TPid}, &rplyDrIds); err!=nil { + if err := rater.Call("ApierV1.GetTPDestinationRateIds", AttrTPDestinationRateIds{dr.TPid}, &rplyDrIds); err != nil { t.Error("Calling ApierV1.GetTPDestinationRateIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedDrIds, rplyDrIds) { + } else if !reflect.DeepEqual(expectedDrIds, rplyDrIds) { t.Errorf("Calling ApierV1.GetTPDestinationRateIds expected: %v, received: %v", expectedDrIds, rplyDrIds) } } @@ -351,106 +350,105 @@ func TestApierTPRatingPlan(t *testing.T) { return } reply := "" - rp := &utils.TPRatingPlan{ TPid:engine.TEST_SQL, RatingPlanId: "RETAIL1", RatingPlanBindings: []*utils.TPRatingPlanBinding{ - &utils.TPRatingPlanBinding{ DestinationRatesId: "DR_FREESWITCH_USERS", TimingId: "ALWAYS", Weight: 10}, - }} + rp := &utils.TPRatingPlan{TPid: engine.TEST_SQL, RatingPlanId: "RETAIL1", RatingPlanBindings: []*utils.TPRatingPlanBinding{ + &utils.TPRatingPlanBinding{DestinationRatesId: "DR_FREESWITCH_USERS", TimingId: "ALWAYS", Weight: 10}, + }} rpTst := new(utils.TPRatingPlan) *rpTst = *rp rpTst.RatingPlanId = engine.TEST_SQL for _, rpl := range []*utils.TPRatingPlan{rp, rpTst} { - if err := rater.Call("ApierV1.SetTPRatingPlan", rpl, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPRatingPlan", rpl, &reply); err != nil { t.Error("Got error on ApierV1.SetTPRatingPlan: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPRatingPlan: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPRatingPlan", rpTst, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPRatingPlan", rpTst, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPRatingPlan: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPRatingPlan got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPRatingPlan", new(utils.TPRatingPlan), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPRatingPlan", new(utils.TPRatingPlan), &reply); err == nil { t.Error("Calling ApierV1.SetTPRatingPlan, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid RatingPlanId RatingPlanBindings]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid RatingPlanId RatingPlanBindings]" { t.Error("Calling ApierV1.SetTPRatingPlan got unexpected error: ", err.Error()) } // Test get var rplyRpTst *utils.TPRatingPlan - if err := rater.Call("ApierV1.GetTPRatingPlan", AttrGetTPRatingPlan{rpTst.TPid, rpTst.RatingPlanId}, &rplyRpTst); err!=nil { + if err := rater.Call("ApierV1.GetTPRatingPlan", AttrGetTPRatingPlan{rpTst.TPid, rpTst.RatingPlanId}, &rplyRpTst); err != nil { t.Error("Calling ApierV1.GetTPRatingPlan, got error: ", err.Error()) - } else if !reflect.DeepEqual(rpTst, rplyRpTst) { + } else if !reflect.DeepEqual(rpTst, rplyRpTst) { t.Errorf("Calling ApierV1.GetTPRatingPlan expected: %v, received: %v", rpTst, rplyRpTst) } // Test remove - if err := rater.Call("ApierV1.RemTPRatingPlan", AttrGetTPRatingPlan{rpTst.TPid, rpTst.RatingPlanId}, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPRatingPlan", AttrGetTPRatingPlan{rpTst.TPid, rpTst.RatingPlanId}, &reply); err != nil { t.Error("Calling ApierV1.RemTPRatingPlan, got error: ", err.Error()) - } else if reply != "OK" { + } else if reply != "OK" { t.Error("Calling ApierV1.RemTPRatingPlan received: ", reply) } // Test getIds var rplyRpIds []string expectedRpIds := []string{"RETAIL1"} - if err := rater.Call("ApierV1.GetTPRatingPlanIds", AttrGetTPRatingPlanIds{rp.TPid}, &rplyRpIds); err!=nil { + if err := rater.Call("ApierV1.GetTPRatingPlanIds", AttrGetTPRatingPlanIds{rp.TPid}, &rplyRpIds); err != nil { t.Error("Calling ApierV1.GetTPRatingPlanIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedRpIds, rplyRpIds) { + } else if !reflect.DeepEqual(expectedRpIds, rplyRpIds) { t.Errorf("Calling ApierV1.GetTPRatingPlanIds expected: %v, received: %v", expectedRpIds, rplyRpIds) } } - // Test here TPRatingPlan APIs func TestApierTPRatingProfile(t *testing.T) { if !*testLocal { return } reply := "" - rpf := &utils.TPRatingProfile{ TPid:engine.TEST_SQL, LoadId:engine.TEST_SQL, Tenant:"cgrates.org", TOR:"call", Direction:"*out", Subject:"*any", + rpf := &utils.TPRatingProfile{TPid: engine.TEST_SQL, LoadId: engine.TEST_SQL, Tenant: "cgrates.org", TOR: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: []*utils.TPRatingActivation{ - &utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId:"RETAIL1", FallbackSubjects:""}, + &utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1", FallbackSubjects: ""}, }} rpfTst := new(utils.TPRatingProfile) *rpfTst = *rpf rpfTst.Subject = engine.TEST_SQL for _, rp := range []*utils.TPRatingProfile{rpf, rpfTst} { - if err := rater.Call("ApierV1.SetTPRatingProfile", rp, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPRatingProfile", rp, &reply); err != nil { t.Error("Got error on ApierV1.SetTPRatingProfile: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPRatingProfile: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPRatingProfile", rpfTst, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPRatingProfile", rpfTst, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPRatingProfile: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPRatingProfile got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPRatingProfile", new(utils.TPRatingProfile), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPRatingProfile", new(utils.TPRatingProfile), &reply); err == nil { t.Error("Calling ApierV1.SetTPRatingProfile, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid LoadId Tenant TOR Direction Subject RatingPlanActivations]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid LoadId Tenant TOR Direction Subject RatingPlanActivations]" { t.Error("Calling ApierV1.SetTPRatingProfile got unexpected error: ", err.Error()) } // Test get var rplyRpfs []*utils.TPRatingProfile - if err := rater.Call("ApierV1.GetTPRatingProfiles", rpfTst, &rplyRpfs); err!=nil { + if err := rater.Call("ApierV1.GetTPRatingProfiles", rpfTst, &rplyRpfs); err != nil { t.Error("Calling ApierV1.GetTPRatingProfiles, got error: ", err.Error()) - } else if !reflect.DeepEqual(rpfTst, rplyRpfs[0]) { + } else if !reflect.DeepEqual(rpfTst, rplyRpfs[0]) { t.Errorf("Calling ApierV1.GetTPRatingProfiles expected: %v, received: %v", rpfTst, rplyRpfs[0]) } // Test remove - if err := rater.Call("ApierV1.RemTPRatingProfile", rpfTst, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPRatingProfile", rpfTst, &reply); err != nil { t.Error("Calling ApierV1.RemTPRatingProfile, got error: ", err.Error()) - } else if reply != "OK" { + } else if reply != "OK" { t.Error("Calling ApierV1.RemTPRatingProfile received: ", reply) } // Test getLoadIds var rplyRpIds []string expectedRpIds := []string{engine.TEST_SQL} - if err := rater.Call("ApierV1.GetTPRatingProfileLoadIds", utils.AttrTPRatingProfileIds{TPid:rpf.TPid}, &rplyRpIds); err!=nil { + if err := rater.Call("ApierV1.GetTPRatingProfileLoadIds", utils.AttrTPRatingProfileIds{TPid: rpf.TPid}, &rplyRpIds); err != nil { t.Error("Calling ApierV1.GetTPRatingProfileLoadIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedRpIds, rplyRpIds) { + } else if !reflect.DeepEqual(expectedRpIds, rplyRpIds) { t.Errorf("Calling ApierV1.GetTPRatingProfileLoadIds expected: %v, received: %v", expectedRpIds, rplyRpIds) } } @@ -461,40 +459,40 @@ func TestApierTPActions(t *testing.T) { } reply := "" act := &utils.TPActions{TPid: engine.TEST_SQL, ActionsId: "PREPAID_10", Actions: []*utils.TPAction{ - &utils.TPAction{Identifier:"*topup_reset", BalanceType:"*monetary", Direction: "*out", Units: 10, ExpiryTime: "*unlimited", - DestinationId: "*any", BalanceWeight:10, Weight:10}, - }} + &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Direction: "*out", Units: 10, ExpiryTime: "*unlimited", + DestinationId: "*any", BalanceWeight: 10, Weight: 10}, + }} actTst := new(utils.TPActions) *actTst = *act actTst.ActionsId = engine.TEST_SQL for _, ac := range []*utils.TPActions{act, actTst} { - if err := rater.Call("ApierV1.SetTPActions", ac, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPActions", ac, &reply); err != nil { t.Error("Got error on ApierV1.SetTPActions: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPActions: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPActions", actTst, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPActions", actTst, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPActions: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPActions got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPActions", new(utils.TPActions), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPActions", new(utils.TPActions), &reply); err == nil { t.Error("Calling ApierV1.SetTPActions, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid ActionsId Actions]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid ActionsId Actions]" { t.Error("Calling ApierV1.SetTPActions got unexpected error: ", err.Error()) } // Test get var rplyActs *utils.TPActions - if err := rater.Call("ApierV1.GetTPActions", AttrGetTPActions{TPid:actTst.TPid, ActionsId:actTst.ActionsId}, &rplyActs); err!=nil { + if err := rater.Call("ApierV1.GetTPActions", AttrGetTPActions{TPid: actTst.TPid, ActionsId: actTst.ActionsId}, &rplyActs); err != nil { t.Error("Calling ApierV1.GetTPActions, got error: ", err.Error()) - } else if !reflect.DeepEqual(actTst, rplyActs) { + } else if !reflect.DeepEqual(actTst, rplyActs) { t.Errorf("Calling ApierV1.GetTPActions expected: %v, received: %v", actTst, rplyActs) } // Test remove - if err := rater.Call("ApierV1.RemTPActions", AttrGetTPActions{TPid:actTst.TPid, ActionsId:actTst.ActionsId}, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPActions", AttrGetTPActions{TPid: actTst.TPid, ActionsId: actTst.ActionsId}, &reply); err != nil { t.Error("Calling ApierV1.RemTPActions, got error: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.RemTPActions received: ", reply) @@ -502,9 +500,9 @@ func TestApierTPActions(t *testing.T) { // Test getIds var rplyIds []string expectedIds := []string{"PREPAID_10"} - if err := rater.Call("ApierV1.GetTPActionIds", AttrGetTPActionIds{TPid: actTst.TPid}, &rplyIds); err!=nil { + if err := rater.Call("ApierV1.GetTPActionIds", AttrGetTPActionIds{TPid: actTst.TPid}, &rplyIds); err != nil { t.Error("Calling ApierV1.GetTPActionIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedIds, rplyIds) { + } else if !reflect.DeepEqual(expectedIds, rplyIds) { t.Errorf("Calling ApierV1.GetTPActionIds expected: %v, received: %v", expectedIds, rplyIds) } } @@ -515,39 +513,39 @@ func TestApierTPActionTimings(t *testing.T) { } reply := "" at := &utils.TPActionTimings{TPid: engine.TEST_SQL, ActionTimingsId: "PREPAID_10", ActionTimings: []*utils.TPActionTiming{ - &utils.TPActionTiming{ActionsId:"PREPAID_10",TimingId:"ASAP", Weight:10}, - }} + &utils.TPActionTiming{ActionsId: "PREPAID_10", TimingId: "ASAP", Weight: 10}, + }} atTst := new(utils.TPActionTimings) *atTst = *at atTst.ActionTimingsId = engine.TEST_SQL for _, act := range []*utils.TPActionTimings{at, atTst} { - if err := rater.Call("ApierV1.SetTPActionTimings", act, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPActionTimings", act, &reply); err != nil { t.Error("Got error on ApierV1.SetTPActionTimings: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPActionTimings: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPActionTimings", atTst, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPActionTimings", atTst, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPActionTimings: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPActionTimings got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPActionTimings", new(utils.TPActionTimings), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPActionTimings", new(utils.TPActionTimings), &reply); err == nil { t.Error("Calling ApierV1.SetTPActionTimings, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid ActionTimingsId ActionTimings]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid ActionTimingsId ActionTimings]" { t.Error("Calling ApierV1.SetTPActionTimings got unexpected error: ", err.Error()) } // Test get var rplyActs *utils.TPActionTimings - if err := rater.Call("ApierV1.GetTPActionTimings", AttrGetTPActionTimings{TPid:atTst.TPid, ActionTimingsId:atTst.ActionTimingsId}, &rplyActs); err!=nil { + if err := rater.Call("ApierV1.GetTPActionTimings", AttrGetTPActionTimings{TPid: atTst.TPid, ActionTimingsId: atTst.ActionTimingsId}, &rplyActs); err != nil { t.Error("Calling ApierV1.GetTPActionTimings, got error: ", err.Error()) - } else if !reflect.DeepEqual(atTst, rplyActs) { + } else if !reflect.DeepEqual(atTst, rplyActs) { t.Errorf("Calling ApierV1.GetTPActionTimings expected: %v, received: %v", atTst, rplyActs) } // Test remove - if err := rater.Call("ApierV1.RemTPActionTimings", AttrGetTPActionTimings{TPid:atTst.TPid, ActionTimingsId:atTst.ActionTimingsId}, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPActionTimings", AttrGetTPActionTimings{TPid: atTst.TPid, ActionTimingsId: atTst.ActionTimingsId}, &reply); err != nil { t.Error("Calling ApierV1.RemTPActionTimings, got error: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.RemTPActionTimings received: ", reply) @@ -555,9 +553,9 @@ func TestApierTPActionTimings(t *testing.T) { // Test getIds var rplyIds []string expectedIds := []string{"PREPAID_10"} - if err := rater.Call("ApierV1.GetTPActionTimingIds", AttrGetTPActionTimingIds{TPid: atTst.TPid}, &rplyIds); err!=nil { + if err := rater.Call("ApierV1.GetTPActionTimingIds", AttrGetTPActionTimingIds{TPid: atTst.TPid}, &rplyIds); err != nil { t.Error("Calling ApierV1.GetTPActionTimingIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedIds, rplyIds) { + } else if !reflect.DeepEqual(expectedIds, rplyIds) { t.Errorf("Calling ApierV1.GetTPActionTimingIds expected: %v, received: %v", expectedIds, rplyIds) } } @@ -568,39 +566,39 @@ func TestApierTPActionTriggers(t *testing.T) { } reply := "" at := &utils.TPActionTriggers{TPid: engine.TEST_SQL, ActionTriggersId: "STANDARD_TRIGGERS", ActionTriggers: []*utils.TPActionTrigger{ - &utils.TPActionTrigger{BalanceType:"*monetary",Direction:"*out", ThresholdType:"*min_balance", ThresholdValue:2, ActionsId:"LOG_BALANCE", Weight:10}, - }} + &utils.TPActionTrigger{BalanceType: "*monetary", Direction: "*out", ThresholdType: "*min_balance", ThresholdValue: 2, ActionsId: "LOG_BALANCE", Weight: 10}, + }} atTst := new(utils.TPActionTriggers) *atTst = *at atTst.ActionTriggersId = engine.TEST_SQL for _, act := range []*utils.TPActionTriggers{at, atTst} { - if err := rater.Call("ApierV1.SetTPActionTriggers", act, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPActionTriggers", act, &reply); err != nil { t.Error("Got error on ApierV1.SetTPActionTriggers: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPActionTriggers: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPActionTriggers", atTst, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPActionTriggers", atTst, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPActionTriggers: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPActionTriggers got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPActionTriggers", new(utils.TPActionTriggers), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPActionTriggers", new(utils.TPActionTriggers), &reply); err == nil { t.Error("Calling ApierV1.SetTPActionTriggers, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid ActionTriggersId]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid ActionTriggersId]" { t.Error("Calling ApierV1.SetTPActionTriggers got unexpected error: ", err.Error()) } // Test get var rplyActs *utils.TPActionTriggers - if err := rater.Call("ApierV1.GetTPActionTriggers", AttrGetTPActionTriggers{TPid:atTst.TPid, ActionTriggersId:atTst.ActionTriggersId}, &rplyActs); err!=nil { + if err := rater.Call("ApierV1.GetTPActionTriggers", AttrGetTPActionTriggers{TPid: atTst.TPid, ActionTriggersId: atTst.ActionTriggersId}, &rplyActs); err != nil { t.Error("Calling ApierV1.GetTPActionTriggers, got error: ", err.Error()) - } else if !reflect.DeepEqual(atTst, rplyActs) { + } else if !reflect.DeepEqual(atTst, rplyActs) { t.Errorf("Calling ApierV1.GetTPActionTriggers expected: %v, received: %v", atTst, rplyActs) } // Test remove - if err := rater.Call("ApierV1.RemTPActionTriggers", AttrGetTPActionTriggers{TPid:atTst.TPid, ActionTriggersId:atTst.ActionTriggersId}, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPActionTriggers", AttrGetTPActionTriggers{TPid: atTst.TPid, ActionTriggersId: atTst.ActionTriggersId}, &reply); err != nil { t.Error("Calling ApierV1.RemTPActionTriggers, got error: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.RemTPActionTriggers received: ", reply) @@ -608,9 +606,9 @@ func TestApierTPActionTriggers(t *testing.T) { // Test getIds var rplyIds []string expectedIds := []string{"STANDARD_TRIGGERS"} - if err := rater.Call("ApierV1.GetTPActionTriggerIds", AttrGetTPActionTriggerIds{TPid: atTst.TPid}, &rplyIds); err!=nil { + if err := rater.Call("ApierV1.GetTPActionTriggerIds", AttrGetTPActionTriggerIds{TPid: atTst.TPid}, &rplyIds); err != nil { t.Error("Calling ApierV1.GetTPActionTriggerIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedIds, rplyIds) { + } else if !reflect.DeepEqual(expectedIds, rplyIds) { t.Errorf("Calling ApierV1.GetTPActionTriggerIds expected: %v, received: %v", expectedIds, rplyIds) } } @@ -621,57 +619,57 @@ func TestApierTPAccountActions(t *testing.T) { return } reply := "" - aa1 := &utils.TPAccountActions{ TPid:engine.TEST_SQL, LoadId:engine.TEST_SQL, Tenant:"cgrates.org", - Account:"1001", Direction:"*out", ActionTimingsId:"PREPAID_10",ActionTriggersId:"STANDARD_TRIGGERS" } - aa2 := &utils.TPAccountActions{ TPid:engine.TEST_SQL, LoadId:engine.TEST_SQL, Tenant:"cgrates.org", - Account:"1002", Direction:"*out", ActionTimingsId:"PREPAID_10",ActionTriggersId:"STANDARD_TRIGGERS" } - aa3 := &utils.TPAccountActions{ TPid:engine.TEST_SQL, LoadId:engine.TEST_SQL, Tenant:"cgrates.org", - Account:"1003", Direction:"*out", ActionTimingsId:"PREPAID_10",ActionTriggersId:"STANDARD_TRIGGERS" } - aa4 := &utils.TPAccountActions{ TPid:engine.TEST_SQL, LoadId:engine.TEST_SQL, Tenant:"cgrates.org", - Account:"1004", Direction:"*out", ActionTimingsId:"PREPAID_10",ActionTriggersId:"STANDARD_TRIGGERS" } - aa5 := &utils.TPAccountActions{ TPid:engine.TEST_SQL, LoadId:engine.TEST_SQL, Tenant:"cgrates.org", - Account:"1005", Direction:"*out", ActionTimingsId:"PREPAID_10",ActionTriggersId:"STANDARD_TRIGGERS" } + aa1 := &utils.TPAccountActions{TPid: engine.TEST_SQL, LoadId: engine.TEST_SQL, Tenant: "cgrates.org", + Account: "1001", Direction: "*out", ActionTimingsId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} + aa2 := &utils.TPAccountActions{TPid: engine.TEST_SQL, LoadId: engine.TEST_SQL, Tenant: "cgrates.org", + Account: "1002", Direction: "*out", ActionTimingsId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} + aa3 := &utils.TPAccountActions{TPid: engine.TEST_SQL, LoadId: engine.TEST_SQL, Tenant: "cgrates.org", + Account: "1003", Direction: "*out", ActionTimingsId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} + aa4 := &utils.TPAccountActions{TPid: engine.TEST_SQL, LoadId: engine.TEST_SQL, Tenant: "cgrates.org", + Account: "1004", Direction: "*out", ActionTimingsId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} + aa5 := &utils.TPAccountActions{TPid: engine.TEST_SQL, LoadId: engine.TEST_SQL, Tenant: "cgrates.org", + Account: "1005", Direction: "*out", ActionTimingsId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} aaTst := new(utils.TPAccountActions) *aaTst = *aa1 aaTst.Account = engine.TEST_SQL for _, aact := range []*utils.TPAccountActions{aa1, aa2, aa3, aa4, aa5, aaTst} { - if err := rater.Call("ApierV1.SetTPAccountActions", aact, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPAccountActions", aact, &reply); err != nil { t.Error("Got error on ApierV1.SetTPAccountActions: ", err.Error()) } else if reply != "OK" { t.Error("Unexpected reply received when calling ApierV1.SetTPAccountActions: ", reply) } } // Check second set - if err := rater.Call("ApierV1.SetTPAccountActions", aaTst, &reply); err!=nil { + if err := rater.Call("ApierV1.SetTPAccountActions", aaTst, &reply); err != nil { t.Error("Got error on second ApierV1.SetTPAccountActions: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetTPAccountActions got reply: ", reply) } // Check missing params - if err := rater.Call("ApierV1.SetTPAccountActions", new(utils.TPAccountActions), &reply); err==nil { + if err := rater.Call("ApierV1.SetTPAccountActions", new(utils.TPAccountActions), &reply); err == nil { t.Error("Calling ApierV1.SetTPAccountActions, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING:[TPid LoadId Tenant Account Direction ActionTimingsId ActionTriggersId]" { + } else if err.Error() != "MANDATORY_IE_MISSING:[TPid LoadId Tenant Account Direction ActionTimingsId ActionTriggersId]" { t.Error("Calling ApierV1.SetTPAccountActions got unexpected error: ", err.Error()) } // Test get var rplyaas []*utils.TPAccountActions - if err := rater.Call("ApierV1.GetTPAccountActions", aaTst, &rplyaas); err!=nil { + if err := rater.Call("ApierV1.GetTPAccountActions", aaTst, &rplyaas); err != nil { t.Error("Calling ApierV1.GetTPAccountActions, got error: ", err.Error()) - } else if !reflect.DeepEqual(aaTst, rplyaas[0]) { + } else if !reflect.DeepEqual(aaTst, rplyaas[0]) { t.Errorf("Calling ApierV1.GetTPAccountActions expected: %v, received: %v", aaTst, rplyaas[0]) } // Test remove - if err := rater.Call("ApierV1.RemTPAccountActions", aaTst, &reply); err!=nil { + if err := rater.Call("ApierV1.RemTPAccountActions", aaTst, &reply); err != nil { t.Error("Calling ApierV1.RemTPAccountActions, got error: ", err.Error()) - } else if reply != "OK" { + } else if reply != "OK" { t.Error("Calling ApierV1.RemTPAccountActions received: ", reply) } // Test getLoadIds var rplyRpIds []string expectedRpIds := []string{engine.TEST_SQL} - if err := rater.Call("ApierV1.GetTPAccountActionLoadIds", AttrGetTPAccountActionIds{TPid:aaTst.TPid}, &rplyRpIds); err!=nil { + if err := rater.Call("ApierV1.GetTPAccountActionLoadIds", AttrGetTPAccountActionIds{TPid: aaTst.TPid}, &rplyRpIds); err != nil { t.Error("Calling ApierV1.GetTPAccountActionLoadIds, got error: ", err.Error()) - } else if !reflect.DeepEqual(expectedRpIds, rplyRpIds) { + } else if !reflect.DeepEqual(expectedRpIds, rplyRpIds) { t.Errorf("Calling ApierV1.GetTPAccountActionLoadIds expected: %v, received: %v", expectedRpIds, rplyRpIds) } } @@ -683,7 +681,7 @@ func TestApierSetRatingPlan(t *testing.T) { } reply := "" //SetRatingPlan(attrs AttrSetRatingPlan - if err := rater.Call("ApierV1.SetRatingPlan", AttrSetRatingPlan{TPid:engine.TEST_SQL,RatingPlanId:"RETAIL1"}, &reply); err!=nil { + if err := rater.Call("ApierV1.SetRatingPlan", AttrSetRatingPlan{TPid: engine.TEST_SQL, RatingPlanId: "RETAIL1"}, &reply); err != nil { t.Error("Got error on second ApierV1.SetRatingPlan: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetRatingPlan got reply: ", reply) @@ -696,8 +694,8 @@ func TestApierSetRatingProfile(t *testing.T) { return } reply := "" - rpf := &utils.TPRatingProfile{TPid:engine.TEST_SQL, LoadId:engine.TEST_SQL, Tenant:"cgrates.org", TOR:"call", Direction:"*out", Subject:"*any"} - if err := rater.Call("ApierV1.SetRatingProfile", rpf, &reply); err!=nil { + rpf := &utils.TPRatingProfile{TPid: engine.TEST_SQL, LoadId: engine.TEST_SQL, Tenant: "cgrates.org", TOR: "call", Direction: "*out", Subject: "*any"} + if err := rater.Call("ApierV1.SetRatingProfile", rpf, &reply); err != nil { t.Error("Got error on second ApierV1.SetRatingProfile: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetRatingProfile got reply: ", reply) @@ -710,13 +708,10 @@ func TestApierSetAccountActions(t *testing.T) { return } reply := "" - aa1 := &utils.TPAccountActions{ TPid:engine.TEST_SQL, LoadId:engine.TEST_SQL, Tenant:"cgrates.org", Account:"1001", Direction:"*out"} - if err := rater.Call("ApierV1.SetAccountActions", aa1, &reply); err!=nil { + aa1 := &utils.TPAccountActions{TPid: engine.TEST_SQL, LoadId: engine.TEST_SQL, Tenant: "cgrates.org", Account: "1001", Direction: "*out"} + if err := rater.Call("ApierV1.SetAccountActions", aa1, &reply); err != nil { t.Error("Got error on second ApierV1.SetAccountActions: ", err.Error()) } else if reply != "OK" { t.Error("Calling ApierV1.SetAccountActions got reply: ", reply) } } - - - diff --git a/apier/v1/tpactions.go b/apier/v1/tpactions.go index 389811e40..4b99b2a9e 100644 --- a/apier/v1/tpactions.go +++ b/apier/v1/tpactions.go @@ -55,12 +55,12 @@ func (self *ApierV1) GetTPActions(attrs AttrGetTPActions, reply *utils.TPActions if missing := utils.MissingStructFields(&attrs, []string{"TPid", "ActionsId"}); len(missing) != 0 { //Params missing return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) } - if acts, err := self.StorDb.GetTPActions(attrs.TPid, attrs.ActionsId); err != nil { + if acts, err := self.StorDb.GetTpActions(attrs.TPid, attrs.ActionsId); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) - } else if acts == nil { + } else if len(acts) == 0 { return errors.New(utils.ERR_NOT_FOUND) } else { - *reply = *acts + *reply = utils.TPActions{TPid: attrs.TPid, ActionsId: attrs.ActionsId, Actions: acts[attrs.ActionsId]} } return nil } diff --git a/apier/v1/tpdestinationrates.go b/apier/v1/tpdestinationrates.go index cdecc7151..599f61217 100644 --- a/apier/v1/tpdestinationrates.go +++ b/apier/v1/tpdestinationrates.go @@ -48,12 +48,12 @@ func (self *ApierV1) GetTPDestinationRate(attrs AttrGetTPDestinationRate, reply if missing := utils.MissingStructFields(&attrs, []string{"TPid", "DestinationRateId"}); len(missing) != 0 { //Params missing return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) } - if dr, err := self.StorDb.GetTPDestinationRate(attrs.TPid, attrs.DestinationRateId); err != nil { + if drs, err := self.StorDb.GetTpDestinationRates(attrs.TPid, attrs.DestinationRateId); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) - } else if dr == nil { + } else if len(drs) == 0 { return errors.New(utils.ERR_NOT_FOUND) } else { - *reply = *dr + *reply = *drs[attrs.DestinationRateId] } return nil } diff --git a/apier/v1/tpdestinations.go b/apier/v1/tpdestinations.go index 2efe3c9b7..14a27181f 100644 --- a/apier/v1/tpdestinations.go +++ b/apier/v1/tpdestinations.go @@ -47,12 +47,12 @@ func (self *ApierV1) GetTPDestination(attrs AttrGetTPDestination, reply *utils.T if missing := utils.MissingStructFields(&attrs, []string{"TPid", "DestinationId"}); len(missing) != 0 { //Params missing return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) } - if dst, err := self.StorDb.GetTPDestination(attrs.TPid, attrs.DestinationId); err != nil { + if dsts, err := self.StorDb.GetTpDestinations(attrs.TPid, attrs.DestinationId); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) - } else if dst == nil { + } else if len(dsts) == 0 { return errors.New(utils.ERR_NOT_FOUND) } else { - *reply = utils.TPDestination{attrs.TPid, dst.Id, dst.Prefixes} + *reply = utils.TPDestination{attrs.TPid, dsts[0].Id, dsts[0].Prefixes} } return nil } diff --git a/apier/v1/tprates.go b/apier/v1/tprates.go index f446e0a6c..1a2229f29 100644 --- a/apier/v1/tprates.go +++ b/apier/v1/tprates.go @@ -48,12 +48,12 @@ func (self *ApierV1) GetTPRate(attrs AttrGetTPRate, reply *utils.TPRate) error { if missing := utils.MissingStructFields(&attrs, []string{"TPid", "RateId"}); len(missing) != 0 { //Params missing return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) } - if rt, err := self.StorDb.GetTPRate(attrs.TPid, attrs.RateId); err != nil { + if rts, err := self.StorDb.GetTpRates(attrs.TPid, attrs.RateId); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) - } else if rt == nil { + } else if len(rts) == 0 { return errors.New(utils.ERR_NOT_FOUND) } else { - *reply = *rt + *reply = *rts[attrs.RateId] } return nil } diff --git a/apier/v1/tpratingplans.go b/apier/v1/tpratingplans.go index fdb3e076c..b74711dd9 100644 --- a/apier/v1/tpratingplans.go +++ b/apier/v1/tpratingplans.go @@ -48,12 +48,12 @@ func (self *ApierV1) GetTPRatingPlan(attrs AttrGetTPRatingPlan, reply *utils.TPR if missing := utils.MissingStructFields(&attrs, []string{"TPid", "RatingPlanId"}); len(missing) != 0 { //Params missing return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) } - if dr, err := self.StorDb.GetTPRatingPlan(attrs.TPid, attrs.RatingPlanId); err != nil { + if rps, err := self.StorDb.GetTpRatingPlans(attrs.TPid, attrs.RatingPlanId); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) - } else if dr == nil { + } else if len(rps) == 0 { return errors.New(utils.ERR_NOT_FOUND) } else { - *reply = *dr + *reply = utils.TPRatingPlan{TPid: attrs.TPid, RatingPlanId: attrs.RatingPlanId, RatingPlanBindings: rps[attrs.RatingPlanId]} } return nil } diff --git a/apier/v1/tptimings.go b/apier/v1/tptimings.go index e1f5ac76e..a38794579 100644 --- a/apier/v1/tptimings.go +++ b/apier/v1/tptimings.go @@ -48,11 +48,12 @@ func (self *ApierV1) GetTPTiming(attrs AttrGetTPTiming, reply *utils.ApierTPTimi if missing := utils.MissingStructFields(&attrs, []string{"TPid", "TimingId"}); len(missing) != 0 { //Params missing return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) } - if tm, err := self.StorDb.GetTPTiming(attrs.TPid, attrs.TimingId); err != nil { + if tms, err := self.StorDb.GetTpTimings(attrs.TPid, attrs.TimingId); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) - } else if tm == nil { + } else if len(tms) == 0 { return errors.New(utils.ERR_NOT_FOUND) } else { + tm := tms[attrs.TimingId] *reply = utils.ApierTPTiming{attrs.TPid, tm.Id, tm.Years.Serialize(";"), tm.Months.Serialize(";"), tm.MonthDays.Serialize(";"), tm.WeekDays.Serialize(";"), tm.StartTime} } diff --git a/engine/loader_db.go b/engine/loader_db.go index b4bda8aab..ed4d70393 100644 --- a/engine/loader_db.go +++ b/engine/loader_db.go @@ -328,12 +328,38 @@ func (dbr *DbReader) LoadRatingProfileFiltered(qriedRpf *utils.TPRatingProfile) } func (dbr *DbReader) LoadActions() (err error) { - dbr.actions, err = dbr.storDb.GetTpActions(dbr.tpid, "") - return err + storActs, err := dbr.storDb.GetTpActions(dbr.tpid, "") + if err != nil { + return err + } + // map[string][]*Action + for tag, tpacts := range storActs { + acts := make([]*Action, len(tpacts)) + for idx, tpact := range tpacts { + acts[idx] = &Action{ + Id: utils.GenUUID(), + ActionType: tpact.Identifier, + BalanceId: tpact.BalanceType, + Direction: tpact.Direction, + Weight: tpact.Weight, + ExtraParameters: tpact.ExtraParameters, + ExpirationString: tpact.ExpiryTime, + Balance: &Balance{ + Uuid: utils.GenUUID(), + Value: tpact.Units, + Weight: tpact.BalanceWeight, + RateSubject: tpact.RatingSubject, + DestinationId: tpact.DestinationId, + }, + } + } + dbr.actions[tag] = acts + } + return nil } func (dbr *DbReader) LoadActionTimings() (err error) { - atsMap, err := dbr.storDb.GetTpActionTimings(dbr.tpid, "") + atsMap, err := dbr.storDb.GetTPActionTimings(dbr.tpid, "") if err != nil { return err } @@ -437,7 +463,7 @@ func (dbr *DbReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions) exitingUserBalanceIds = existingActionTimings[0].UserBalanceIds } - actionTimingsMap, err := dbr.storDb.GetTpActionTimings(dbr.tpid, accountAction.ActionTimingsId) + actionTimingsMap, err := dbr.storDb.GetTPActionTimings(dbr.tpid, accountAction.ActionTimingsId) if err != nil { return err } else if len(actionTimingsMap) == 0 { @@ -524,18 +550,37 @@ func (dbr *DbReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions) // collect action ids from triggers for _, atr := range actionTriggers { actionsIds = append(actionsIds, atr.ActionsId) - } + } } // actions acts := make(map[string][]*Action) for _, actId := range actionsIds { - actions, err := dbr.storDb.GetTpActions(dbr.tpid, actId) + storActs, err := dbr.storDb.GetTpActions(dbr.tpid, actId) if err != nil { return err } - for id, act := range actions { - acts[id] = act + for tag, tpacts := range storActs { + enacts := make([]*Action, len(tpacts)) + for idx, tpact := range tpacts { + enacts[idx] = &Action{ + Id: utils.GenUUID(), + ActionType: tpact.Identifier, + BalanceId: tpact.BalanceType, + Direction: tpact.Direction, + Weight: tpact.Weight, + ExtraParameters: tpact.ExtraParameters, + ExpirationString: tpact.ExpiryTime, + Balance: &Balance{ + Uuid: utils.GenUUID(), + Value: tpact.Units, + Weight: tpact.BalanceWeight, + RateSubject: tpact.RatingSubject, + DestinationId: tpact.DestinationId, + }, + } + } + acts[tag] = enacts } } // writee actions diff --git a/engine/loader_local_test.go b/engine/loader_local_test.go index 578265b07..e5bf87eee 100644 --- a/engine/loader_local_test.go +++ b/engine/loader_local_test.go @@ -66,7 +66,7 @@ func TestConnDataDbs(t *testing.T) { if dataDbApier, err = ConfigureDataStorage(cfg.DataDBType, cfg.DataDBHost, cfg.DataDBPort, "15", cfg.DataDBUser, cfg.DataDBPass, cfg.DBDataEncoding); err != nil { t.Fatal("Error on dataDb connection: ", err.Error()) } - for _,db := range []DataStorage{dataDbCsv, dataDbStor, dataDbApier} { + for _, db := range []DataStorage{dataDbCsv, dataDbStor, dataDbApier} { if err = db.Flush(); err != nil { t.Fatal("Error when flushing datadb") } @@ -225,8 +225,8 @@ func TestLoadIndividualProfiles(t *testing.T) { } } // Load rating profiles - loadId := utils.CSV_LOAD+"_"+TEST_SQL - if ratingProfiles, err := storDb.GetTpRatingProfiles(&utils.TPRatingProfile{TPid:TEST_SQL, LoadId: loadId}); err != nil { + loadId := utils.CSV_LOAD + "_" + TEST_SQL + if ratingProfiles, err := storDb.GetTpRatingProfiles(&utils.TPRatingProfile{TPid: TEST_SQL, LoadId: loadId}); err != nil { t.Fatal("Could not retrieve rating profiles, error: ", err.Error()) } else if len(ratingProfiles) == 0 { t.Fatal("Could not retrieve rating profiles") @@ -239,7 +239,7 @@ func TestLoadIndividualProfiles(t *testing.T) { } } // Load account actions - if aas, err := storDb.GetTpAccountActions(&utils.TPAccountActions{TPid:TEST_SQL, LoadId: loadId}); err != nil { + if aas, err := storDb.GetTpAccountActions(&utils.TPAccountActions{TPid: TEST_SQL, LoadId: loadId}); err != nil { t.Fatal("Could not retrieve account action profiles, error: ", err.Error()) } else if len(aas) == 0 { t.Error("No account actions") @@ -252,7 +252,6 @@ func TestLoadIndividualProfiles(t *testing.T) { } } } - // Compares previously loaded data from csv and stor to be identical, redis specific tests func TestMatchLoadCsvWithStor(t *testing.T) { diff --git a/engine/storage_interface.go b/engine/storage_interface.go index 2e06fa397..63b453b0a 100644 --- a/engine/storage_interface.go +++ b/engine/storage_interface.go @@ -108,44 +108,46 @@ type LoadStorage interface { // Apier functions RemTPData(string, string, ...string) error GetTPIds() ([]string, error) + SetTPTiming(string, *utils.TPTiming) error - GetTPTiming(string, string) (*utils.TPTiming, error) + GetTpTimings(string, string) (map[string]*utils.TPTiming, error) GetTPTimingIds(string) ([]string, error) + SetTPDestination(string, *Destination) error - GetTPDestination(string, string) (*Destination, error) + GetTpDestinations(string, string) ([]*Destination, error) GetTPDestinationIds(string) ([]string, error) + SetTPRates(string, map[string][]*utils.RateSlot) error - GetTPRate(string, string) (*utils.TPRate, error) + GetTpRates(string, string) (map[string]*utils.TPRate, error) GetTPRateIds(string) ([]string, error) + SetTPDestinationRates(string, map[string][]*utils.DestinationRate) error - GetTPDestinationRate(string, string) (*utils.TPDestinationRate, error) + GetTpDestinationRates(string, string) (map[string]*utils.TPDestinationRate, error) GetTPDestinationRateIds(string) ([]string, error) + SetTPRatingPlans(string, map[string][]*utils.TPRatingPlanBinding) error - GetTPRatingPlan(string, string) (*utils.TPRatingPlan, error) + GetTpRatingPlans(string, string) (map[string][]*utils.TPRatingPlanBinding, error) GetTPRatingPlanIds(string) ([]string, error) + SetTPRatingProfiles(string, map[string]*utils.TPRatingProfile) error + GetTpRatingProfiles(*utils.TPRatingProfile) (map[string]*utils.TPRatingProfile, error) GetTPRatingProfileIds(*utils.AttrTPRatingProfileIds) ([]string, error) + SetTPActions(string, map[string][]*utils.TPAction) error - GetTPActions(string, string) (*utils.TPActions, error) + GetTpActions(string, string) (map[string][]*utils.TPAction, error) GetTPActionIds(string) ([]string, error) + SetTPActionTimings(string, map[string][]*utils.TPActionTiming) error GetTPActionTimings(string, string) (map[string][]*utils.TPActionTiming, error) GetTPActionTimingIds(string) ([]string, error) + SetTPActionTriggers(string, map[string][]*utils.TPActionTrigger) error - GetTPActionTriggerIds(string) ([]string, error) - SetTPAccountActions(string, map[string]*utils.TPAccountActions) error - GetTPAccountActionIds(string) ([]string, error) - // loader functions - GetTpDestinations(string, string) ([]*Destination, error) - GetTpTimings(string, string) (map[string]*utils.TPTiming, error) - GetTpRates(string, string) (map[string]*utils.TPRate, error) - GetTpDestinationRates(string, string) (map[string]*utils.TPDestinationRate, error) - GetTpRatingPlans(string, string) (map[string][]*utils.TPRatingPlanBinding, error) - GetTpRatingProfiles(*utils.TPRatingProfile) (map[string]*utils.TPRatingProfile, error) - GetTpActions(string, string) (map[string][]*Action, error) - GetTpActionTimings(string, string) (map[string][]*utils.TPActionTiming, error) GetTpActionTriggers(string, string) (map[string][]*utils.TPActionTrigger, error) + GetTPActionTriggerIds(string) ([]string, error) + + SetTPAccountActions(string, map[string]*utils.TPAccountActions) error GetTpAccountActions(*utils.TPAccountActions) (map[string]*utils.TPAccountActions, error) + GetTPAccountActionIds(string) ([]string, error) } type Marshaler interface { diff --git a/engine/storage_sql.go b/engine/storage_sql.go index 9d13c57e6..096670365 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -19,6 +19,7 @@ along with this program. If not, see package engine import ( + "bytes" "database/sql" "encoding/json" "fmt" @@ -92,19 +93,6 @@ func (self *SQLStorage) SetTPTiming(tpid string, tm *utils.TPTiming) error { return nil } -func (self *SQLStorage) GetTPTiming(tpid, tmId string) (*utils.TPTiming, error) { - var years, months, monthDays, weekDays, time string - err := self.Db.QueryRow(fmt.Sprintf("SELECT years, months, month_days, week_days, time FROM %s WHERE tpid='%s' AND tag='%s' LIMIT 1", - utils.TBL_TP_TIMINGS, tpid, tmId)).Scan(&years, &months, &monthDays, &weekDays, &time) - switch { - case err == sql.ErrNoRows: - return nil, nil - case err != nil: - return nil, err - } - return NewTiming(tmId, years, months, monthDays, weekDays, time), nil -} - func (self *SQLStorage) GetTPTimingIds(tpid string) ([]string, error) { rows, err := self.Db.Query(fmt.Sprintf("SELECT DISTINCT tag FROM %s where tpid='%s'", utils.TBL_TP_TIMINGS, tpid)) if err != nil { @@ -196,16 +184,16 @@ func (self *SQLStorage) SetTPDestination(tpid string, dest *Destination) error { if len(dest.Prefixes) == 0 { return nil } - vals := "" + var buffer bytes.Buffer // Use bytes buffer istead of string concatenation since that becomes quite heavy on large prefixes + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid, tag, prefix) VALUES ", utils.TBL_TP_DESTINATIONS)) for idx, prefix := range dest.Prefixes { if idx != 0 { - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s','%s','%s')", tpid, dest.Id, prefix) + buffer.WriteString(fmt.Sprintf("('%s','%s','%s')", tpid, dest.Id, prefix)) } - q := fmt.Sprintf("INSERT INTO %s (tpid, tag, prefix) VALUES %s ON DUPLICATE KEY UPDATE prefix=values(prefix)", - utils.TBL_TP_DESTINATIONS, vals) - if _, err := self.Db.Exec(q); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE prefix=values(prefix)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil @@ -215,55 +203,28 @@ func (self *SQLStorage) SetTPRates(tpid string, rts map[string][]*utils.RateSlot if len(rts) == 0 { return nil //Nothing to set } - vals := "" + var buffer bytes.Buffer + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid, tag, connect_fee, rate, rate_unit, rate_increment, group_interval_start, rounding_method, rounding_decimals) VALUES ", + utils.TBL_TP_RATES)) i := 0 for rtId, rtRows := range rts { for _, rt := range rtRows { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s', '%s', %f, %f, '%s', '%s','%s','%s', %d)", + buffer.WriteString(fmt.Sprintf("('%s', '%s', %f, %f, '%s', '%s','%s','%s', %d)", tpid, rtId, rt.ConnectFee, rt.Rate, rt.RateUnit, rt.RateIncrement, rt.GroupIntervalStart, - rt.RoundingMethod, rt.RoundingDecimals) + rt.RoundingMethod, rt.RoundingDecimals)) i++ } } - qry := fmt.Sprintf("INSERT INTO %s (tpid, tag, connect_fee, rate, rate_unit, rate_increment, group_interval_start, rounding_method, rounding_decimals) VALUES %s ON DUPLICATE KEY UPDATE connect_fee=values(connect_fee), rate=values(rate), rate_increment=values(rate_increment), group_interval_start=values(group_interval_start), rounding_method=values(rounding_method), rounding_decimals=values(rounding_decimals)", utils.TBL_TP_RATES, vals) - if _, err := self.Db.Exec(qry); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE connect_fee=values(connect_fee), rate=values(rate), rate_increment=values(rate_increment), group_interval_start=values(group_interval_start), rounding_method=values(rounding_method), rounding_decimals=values(rounding_decimals)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil } -func (self *SQLStorage) GetTPRate(tpid, rtId string) (*utils.TPRate, error) { - rows, err := self.Db.Query(fmt.Sprintf("SELECT connect_fee, rate, rate_unit, rate_increment, group_interval_start, rounding_method, rounding_decimals FROM %s WHERE tpid='%s' AND tag='%s'", utils.TBL_TP_RATES, tpid, rtId)) - if err != nil { - return nil, err - } - defer rows.Close() - rt := &utils.TPRate{TPid: tpid, RateId: rtId} - i := 0 - for rows.Next() { - i++ //Keep here a reference so we know we got at least one prefix - var connectFee, rate float64 - var roundingDecimals int - var rateUnit, rateIncrement, groupIntervalStart, roundingMethod string - err = rows.Scan(&connectFee, &rate, &rateUnit, &rateIncrement, &groupIntervalStart, &roundingMethod, &roundingDecimals) - if err != nil { - return nil, err - } - if rs, err := utils.NewRateSlot(connectFee, rate, rateUnit, rateIncrement, groupIntervalStart, roundingMethod, roundingDecimals); err != nil { - return nil, err - } else { - rt.RateSlots = append(rt.RateSlots, rs) - } - } - if i == 0 { - return nil, nil - } - return rt, nil -} - func (self *SQLStorage) GetTPRateIds(tpid string) ([]string, error) { rows, err := self.Db.Query(fmt.Sprintf("SELECT DISTINCT tag FROM %s where tpid='%s'", utils.TBL_TP_RATES, tpid)) if err != nil { @@ -291,48 +252,25 @@ func (self *SQLStorage) SetTPDestinationRates(tpid string, drs map[string][]*uti if len(drs) == 0 { return nil //Nothing to set } - vals := "" + var buffer bytes.Buffer + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid,tag,destinations_tag,rates_tag) VALUES ", utils.TBL_TP_DESTINATION_RATES)) i := 0 for drId, drRows := range drs { for _, dr := range drRows { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s','%s','%s','%s')", - tpid, drId, dr.DestinationId, dr.RateId) + buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s')", tpid, drId, dr.DestinationId, dr.RateId)) i++ } } - qry := fmt.Sprintf("INSERT INTO %s (tpid,tag,destinations_tag,rates_tag) VALUES %s ON DUPLICATE KEY UPDATE destinations_tag=values(destinations_tag),rates_tag=values(rates_tag)", utils.TBL_TP_DESTINATION_RATES, vals) - if _, err := self.Db.Exec(qry); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE destinations_tag=values(destinations_tag),rates_tag=values(rates_tag)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil } -func (self *SQLStorage) GetTPDestinationRate(tpid, drId string) (*utils.TPDestinationRate, error) { - rows, err := self.Db.Query(fmt.Sprintf("SELECT destinations_tag, rates_tag FROM %s WHERE tpid='%s' AND tag='%s'", utils.TBL_TP_DESTINATION_RATES, tpid, drId)) - if err != nil { - return nil, err - } - defer rows.Close() - dr := &utils.TPDestinationRate{TPid: tpid, DestinationRateId: drId} - i := 0 - for rows.Next() { - i++ //Keep here a reference so we know we got at least one prefix - var dstTag, ratesTag string - err = rows.Scan(&dstTag, &ratesTag) - if err != nil { - return nil, err - } - dr.DestinationRates = append(dr.DestinationRates, &utils.DestinationRate{dstTag, ratesTag, nil}) - } - if i == 0 { - return nil, nil - } - return dr, nil -} - func (self *SQLStorage) GetTPDestinationRateIds(tpid string) ([]string, error) { rows, err := self.Db.Query(fmt.Sprintf("SELECT DISTINCT tag FROM %s where tpid='%s'", utils.TBL_TP_DESTINATION_RATES, tpid)) if err != nil { @@ -360,49 +298,25 @@ func (self *SQLStorage) SetTPRatingPlans(tpid string, drts map[string][]*utils.T if len(drts) == 0 { return nil //Nothing to set } - vals := "" + var buffer bytes.Buffer + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid, tag, destrates_tag, timing_tag, weight) VALUES ", utils.TBL_TP_RATING_PLANS)) i := 0 for drtId, drtRows := range drts { for _, drt := range drtRows { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s','%s','%s','%s',%f)", - tpid, drtId, drt.DestinationRatesId, drt.TimingId, drt.Weight) + buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s',%f)", tpid, drtId, drt.DestinationRatesId, drt.TimingId, drt.Weight)) i++ } } - qry := fmt.Sprintf("INSERT INTO %s (tpid, tag, destrates_tag, timing_tag, weight) VALUES %s ON DUPLICATE KEY UPDATE weight=values(weight)", utils.TBL_TP_RATING_PLANS, vals) - if _, err := self.Db.Exec(qry); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE weight=values(weight)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil } -func (self *SQLStorage) GetTPRatingPlan(tpid, drtId string) (*utils.TPRatingPlan, error) { - rows, err := self.Db.Query(fmt.Sprintf("SELECT destrates_tag, timing_tag, weight from %s where tpid='%s' and tag='%s'", utils.TBL_TP_RATING_PLANS, tpid, drtId)) - if err != nil { - return nil, err - } - defer rows.Close() - drt := &utils.TPRatingPlan{TPid: tpid, RatingPlanId: drtId} - i := 0 - for rows.Next() { - i++ //Keep here a reference so we know we got at least one result - var drTag, timingTag string - var weight float64 - err = rows.Scan(&drTag, &timingTag, &weight) - if err != nil { - return nil, err - } - drt.RatingPlanBindings = append(drt.RatingPlanBindings, &utils.TPRatingPlanBinding{DestinationRatesId: drTag, TimingId: timingTag, Weight: weight}) - } - if i == 0 { - return nil, nil - } - return drt, nil -} - func (self *SQLStorage) GetTPRatingPlanIds(tpid string) ([]string, error) { rows, err := self.Db.Query(fmt.Sprintf("SELECT DISTINCT tag FROM %s where tpid='%s'", utils.TBL_TP_RATING_PLANS, tpid)) if err != nil { @@ -430,20 +344,22 @@ func (self *SQLStorage) SetTPRatingProfiles(tpid string, rps map[string]*utils.T if len(rps) == 0 { return nil //Nothing to set } - vals := "" + var buffer bytes.Buffer + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid,loadid,tenant,tor,direction,subject,activation_time,rating_plan_tag,fallback_subjects) VALUES ", + utils.TBL_TP_RATE_PROFILES)) i := 0 for _, rp := range rps { for _, rpa := range rp.RatingPlanActivations { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s')", tpid, rp.LoadId, rp.Tenant, rp.TOR, rp.Direction, - rp.Subject, rpa.ActivationTime, rpa.RatingPlanId, rpa.FallbackSubjects) + buffer.WriteString(fmt.Sprintf("('%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s')", tpid, rp.LoadId, rp.Tenant, rp.TOR, rp.Direction, + rp.Subject, rpa.ActivationTime, rpa.RatingPlanId, rpa.FallbackSubjects)) i++ } } - qry := fmt.Sprintf("INSERT INTO %s (tpid,loadid,tenant,tor,direction,subject,activation_time,rating_plan_tag,fallback_subjects) VALUES %s ON DUPLICATE KEY UPDATE fallback_subjects=values(fallback_subjects)", utils.TBL_TP_RATE_PROFILES, vals) - if _, err := self.Db.Exec(qry); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE fallback_subjects=values(fallback_subjects)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil @@ -489,21 +405,22 @@ func (self *SQLStorage) SetTPActions(tpid string, acts map[string][]*utils.TPAct if len(acts) == 0 { return nil //Nothing to set } - vals := "" + var buffer bytes.Buffer + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid,tag,action,balance_type,direction,units,expiry_time,destination_tag,rating_subject,balance_weight,extra_parameters,weight) VALUES ", utils.TBL_TP_ACTIONS)) i := 0 for actId, actRows := range acts { for _, act := range actRows { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s','%s','%s','%s','%s',%f,'%s','%s','%s',%f,'%s',%f)", + buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s','%s',%f,'%s','%s','%s',%f,'%s',%f)", tpid, actId, act.Identifier, act.BalanceType, act.Direction, act.Units, act.ExpiryTime, - act.DestinationId, act.RatingSubject, act.BalanceWeight, act.ExtraParameters, act.Weight) + act.DestinationId, act.RatingSubject, act.BalanceWeight, act.ExtraParameters, act.Weight)) i++ } } - qry := fmt.Sprintf("INSERT INTO %s (tpid,tag,action,balance_type,direction,units,expiry_time,destination_tag,rating_subject,balance_weight,extra_parameters,weight) VALUES %s ON DUPLICATE KEY UPDATE action=values(action),balance_type=values(balance_type),direction=values(direction),units=values(units),expiry_time=values(expiry_time),destination_tag=values(destination_tag),rating_subject=values(rating_subject),balance_weight=values(balance_weight),extra_parameters=values(extra_parameters),weight=values(weight)", utils.TBL_TP_ACTIONS, vals) - if _, err := self.Db.Exec(qry); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE action=values(action),balance_type=values(balance_type),direction=values(direction),units=values(units),expiry_time=values(expiry_time),destination_tag=values(destination_tag),rating_subject=values(rating_subject),balance_weight=values(balance_weight),extra_parameters=values(extra_parameters),weight=values(weight)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil @@ -559,20 +476,20 @@ func (self *SQLStorage) SetTPActionTimings(tpid string, ats map[string][]*utils. if len(ats) == 0 { return nil //Nothing to set } - vals := "" + var buffer bytes.Buffer + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid,tag,actions_tag,timing_tag,weight) VALUES ", utils.TBL_TP_ACTION_TIMINGS)) i := 0 for atId, atRows := range ats { for _, at := range atRows { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s','%s','%s','%s',%f)", - tpid, atId, at.ActionsId, at.TimingId, at.Weight) + buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s',%f)", tpid, atId, at.ActionsId, at.TimingId, at.Weight)) i++ } } - qry := fmt.Sprintf("INSERT INTO %s (tpid,tag,actions_tag,timing_tag,weight) VALUES %s ON DUPLICATE KEY UPDATE timing_tag=values(timing_tag),weight=values(weight)", utils.TBL_TP_ACTION_TIMINGS, vals) - if _, err := self.Db.Exec(qry); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE timing_tag=values(timing_tag),weight=values(weight)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil @@ -628,21 +545,23 @@ func (self *SQLStorage) SetTPActionTriggers(tpid string, ats map[string][]*utils if len(ats) == 0 { return nil //Nothing to set } - vals := "" + var buffer bytes.Buffer + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid,tag,balance_type,direction,threshold_type,threshold_value,destination_tag,actions_tag,weight) VALUES ", + utils.TBL_TP_ACTION_TRIGGERS)) i := 0 for atId, atRows := range ats { for _, atsRow := range atRows { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s','%s','%s','%s','%s', %f, '%s','%s',%f)", + buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s','%s', %f, '%s','%s',%f)", tpid, atId, atsRow.BalanceType, atsRow.Direction, atsRow.ThresholdType, - atsRow.ThresholdValue, atsRow.DestinationId, atsRow.ActionsId, atsRow.Weight) + atsRow.ThresholdValue, atsRow.DestinationId, atsRow.ActionsId, atsRow.Weight)) i++ } } - qry := fmt.Sprintf("INSERT INTO %s (tpid,tag,balance_type,direction,threshold_type,threshold_value,destination_tag,actions_tag,weight) VALUES %s ON DUPLICATE KEY UPDATE weight=values(weight)", utils.TBL_TP_ACTION_TRIGGERS, vals) - if _, err := self.Db.Exec(qry); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE weight=values(weight)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil @@ -675,18 +594,19 @@ func (self *SQLStorage) SetTPAccountActions(tpid string, aa map[string]*utils.TP if len(aa) == 0 { return nil //Nothing to set } - vals := "" + var buffer bytes.Buffer + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid, loadid, tenant, account, direction, action_timings_tag, action_triggers_tag) VALUES ", utils.TBL_TP_ACCOUNT_ACTIONS)) i := 0 for _, aActs := range aa { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator - vals += "," + buffer.WriteRune(',') } - vals += fmt.Sprintf("('%s','%s','%s','%s','%s','%s','%s')", - tpid, aActs.LoadId, aActs.Tenant, aActs.Account, aActs.Direction, aActs.ActionTimingsId, aActs.ActionTriggersId) + buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s','%s','%s','%s')", + tpid, aActs.LoadId, aActs.Tenant, aActs.Account, aActs.Direction, aActs.ActionTimingsId, aActs.ActionTriggersId)) i++ } - qry := fmt.Sprintf("INSERT INTO %s (tpid, loadid, tenant, account, direction, action_timings_tag, action_triggers_tag) VALUES %s ON DUPLICATE KEY UPDATE action_timings_tag=values(action_timings_tag), action_triggers_tag=values(action_triggers_tag)", utils.TBL_TP_ACCOUNT_ACTIONS, vals) - if _, err := self.Db.Exec(qry); err != nil { + buffer.WriteString(" ON DUPLICATE KEY UPDATE action_timings_tag=values(action_timings_tag), action_triggers_tag=values(action_triggers_tag)") + if _, err := self.Db.Exec(buffer.String()); err != nil { return err } return nil @@ -1066,8 +986,8 @@ func (self *SQLStorage) GetTpRatingProfiles(qryRpf *utils.TPRatingProfile) (map[ return rpfs, nil } -func (self *SQLStorage) GetTpActions(tpid, tag string) (map[string][]*Action, error) { - as := make(map[string][]*Action) +func (self *SQLStorage) GetTpActions(tpid, tag string) (map[string][]*utils.TPAction, error) { + as := make(map[string][]*utils.TPAction) q := fmt.Sprintf("SELECT * FROM %s WHERE tpid='%s'", utils.TBL_TP_ACTIONS, tpid) if tag != "" { q += fmt.Sprintf(" AND tag='%s'", tag) @@ -1084,54 +1004,23 @@ func (self *SQLStorage) GetTpActions(tpid, tag string) (map[string][]*Action, er if err := rows.Scan(&id, &tpid, &tag, &action, &balance_type, &direction, &units, &expirationDate, &destinations_tag, &rating_subject, &balance_weight, &extra_parameters, &weight); err != nil { return nil, err } - a := &Action{ - Id: utils.GenUUID(), - ActionType: action, - BalanceId: balance_type, - Direction: direction, - Weight: weight, - ExtraParameters: extra_parameters, - ExpirationString: expirationDate, - Balance: &Balance{ - Uuid: utils.GenUUID(), - Value: units, - Weight: balance_weight, - RateSubject: rating_subject, - DestinationId: destinations_tag, - }, + a := &utils.TPAction{ + Identifier: action, + BalanceType: balance_type, + Direction: direction, + Units: units, + ExpiryTime: expirationDate, + DestinationId: destinations_tag, + RatingSubject: rating_subject, + BalanceWeight: balance_weight, + ExtraParameters: extra_parameters, + Weight: weight, } as[tag] = append(as[tag], a) } return as, nil } -func (self *SQLStorage) GetTpActionTimings(tpid, tag string) (map[string][]*utils.TPActionTiming, error) { - q := fmt.Sprintf("SELECT tag,actions_tag,timing_tag,weight FROM %s WHERE tpid='%s'", utils.TBL_TP_ACTION_TIMINGS, tpid) - if tag != "" { - q += fmt.Sprintf(" AND tag='%s'", tag) - } - rows, err := self.Db.Query(q) - if err != nil { - return nil, err - } - defer rows.Close() - ats := make(map[string][]*utils.TPActionTiming) - for rows.Next() { - var weight float64 - var tag, actions_tag, timing_tag string - if err := rows.Scan(&tag, &actions_tag, &timing_tag, &weight); err != nil { - return nil, err - } - at := &utils.TPActionTiming{ - ActionsId: tag, - TimingId: timing_tag, - Weight: weight, - } - ats[tag] = append(ats[tag], at) - } - return ats, nil -} - func (self *SQLStorage) GetTpActionTriggers(tpid, tag string) (map[string][]*utils.TPActionTrigger, error) { ats := make(map[string][]*utils.TPActionTrigger) q := fmt.Sprintf("SELECT tpid,tag,balance_type,direction,threshold_type,threshold_value,destination_tag,actions_tag,weight FROM %s WHERE tpid='%s'", diff --git a/utils/apitpdata.go b/utils/apitpdata.go index f35535cb2..620e3371f 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -30,7 +30,6 @@ type TPDestination struct { Prefixes []string // Prefixes attached to this destination } - // This file deals with tp_* data definition type TPRate struct { @@ -138,16 +137,15 @@ func (self *TPRatingPlanBinding) Timing() *TPTiming { return self.timing } - // Used to rebuild a TPRatingProfile (empty RatingPlanActivations) out of it's key in nosqldb -func NewTPRatingProfileFromKeyId( tpid, loadId, keyId string ) (*TPRatingProfile, error) { +func NewTPRatingProfileFromKeyId(tpid, loadId, keyId string) (*TPRatingProfile, error) { // *out:cgrates.org:call:*any s := strings.Split(keyId, ":") // [*out cgrates.org call *any] if len(s) != 4 { return nil, fmt.Errorf("Cannot parse key %s into RatingProfile", keyId) } - return &TPRatingProfile{TPid: tpid, LoadId: loadId, Tenant:s[1], TOR:s[2], Direction:s[0], Subject:s[3]}, nil + return &TPRatingProfile{TPid: tpid, LoadId: loadId, Tenant: s[1], TOR: s[2], Direction: s[0], Subject: s[3]}, nil } type TPRatingProfile struct { @@ -243,14 +241,14 @@ type TPActionTrigger struct { } // Used to rebuild a TPAccountActions (empty ActionTimingsId and ActionTriggersId) out of it's key in nosqldb -func NewTPAccountActionsFromKeyId( tpid, loadId, keyId string ) (*TPAccountActions, error) { +func NewTPAccountActionsFromKeyId(tpid, loadId, keyId string) (*TPAccountActions, error) { // *out:cgrates.org:1001 s := strings.Split(keyId, ":") // [*out cgrates.org 1001] if len(s) != 3 { return nil, fmt.Errorf("Cannot parse key %s into AccountActions", keyId) } - return &TPAccountActions{TPid: tpid, LoadId: loadId, Tenant:s[1], Account: s[2], Direction:s[0]}, nil + return &TPAccountActions{TPid: tpid, LoadId: loadId, Tenant: s[1], Account: s[2], Direction: s[0]}, nil } type TPAccountActions struct { diff --git a/utils/consts.go b/utils/consts.go index 1237e030b..7ec99d678 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -62,5 +62,4 @@ const ( JSON = "json" MSGPACK = "msgpack" CSV_LOAD = "CSVLOAD" - )