From 979a2818a74cba7bada1aebb65d938aa98832bdd Mon Sep 17 00:00:00 2001 From: TeoV Date: Tue, 17 Nov 2020 17:23:57 +0200 Subject: [PATCH] Calculate cost from routes with rateS and move ArgsCostForEvent in utils --- apier/v1/rateprofiles.go | 2 +- apier/v1/rateprofiles_it_test.go | 23 ++++++------- engine/routes.go | 57 +++++++++++++++++++++++--------- rates/rates.go | 28 ++-------------- rates/rates_test.go | 14 ++++---- utils/apitpdata.go | 22 ++++++++++++ utils/consts.go | 1 + 7 files changed, 86 insertions(+), 61 deletions(-) diff --git a/apier/v1/rateprofiles.go b/apier/v1/rateprofiles.go index 0f70438a6..db8a9a713 100644 --- a/apier/v1/rateprofiles.go +++ b/apier/v1/rateprofiles.go @@ -211,7 +211,7 @@ func (rSv1 *RateSv1) Call(serviceMethod string, return utils.APIerRPCCall(rSv1, serviceMethod, args, reply) } -func (rSv1 *RateSv1) CostForEvent(args *rates.ArgsCostForEvent, rpCost *engine.RateProfileCost) (err error) { +func (rSv1 *RateSv1) CostForEvent(args *utils.ArgsCostForEvent, rpCost *engine.RateProfileCost) (err error) { return rSv1.rS.V1CostForEvent(args, rpCost) } diff --git a/apier/v1/rateprofiles_it_test.go b/apier/v1/rateprofiles_it_test.go index 6418521e7..0d6fbfb01 100644 --- a/apier/v1/rateprofiles_it_test.go +++ b/apier/v1/rateprofiles_it_test.go @@ -29,7 +29,6 @@ import ( "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/rates" "github.com/cgrates/cgrates/utils" ) @@ -823,7 +822,7 @@ func testV1RateCostForEventWithDefault(t *testing.T) { } var rply *engine.RateProfileCost - argsRt := &rates.ArgsCostForEvent{ + argsRt := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", @@ -863,7 +862,7 @@ func testV1RateCostForEventWithDefault(t *testing.T) { func testV1RateCostForEventWithUsage(t *testing.T) { var rply *engine.RateProfileCost - argsRt := &rates.ArgsCostForEvent{ + argsRt := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesUsage: "2m10s", @@ -929,7 +928,7 @@ func testV1RateCostForEventWithUsage(t *testing.T) { t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(exp), utils.ToJSON(rply)) } - argsRt2 := &rates.ArgsCostForEvent{ + argsRt2 := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesUsage: "4h10m15s", @@ -978,7 +977,7 @@ func testV1RateCostForEventWithUsage(t *testing.T) { func testV1RateCostForEventWithWrongUsage(t *testing.T) { var rply *engine.RateProfileCost - argsRt := &rates.ArgsCostForEvent{ + argsRt := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesUsage: "wrongUsage", @@ -1020,7 +1019,7 @@ func testV1RateCostForEventWithStartTime(t *testing.T) { } var rply *engine.RateProfileCost - argsRt := &rates.ArgsCostForEvent{ + argsRt := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesStartTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC), @@ -1059,7 +1058,7 @@ func testV1RateCostForEventWithStartTime(t *testing.T) { t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(exp), utils.ToJSON(rply)) } - argsRt2 := &rates.ArgsCostForEvent{ + argsRt2 := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesStartTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC).String(), @@ -1082,7 +1081,7 @@ func testV1RateCostForEventWithStartTime(t *testing.T) { func testV1RateCostForEventWithWrongStartTime(t *testing.T) { var rply *engine.RateProfileCost - argsRt := &rates.ArgsCostForEvent{ + argsRt := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesStartTime: "wrongTime", @@ -1104,7 +1103,7 @@ func testV1RateCostForEventWithWrongStartTime(t *testing.T) { func testV1RateCostForEventWithOpts(t *testing.T) { var rply *engine.RateProfileCost - argsRt := &rates.ArgsCostForEvent{ + argsRt := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesStartTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC), @@ -1171,7 +1170,7 @@ func testV1RateCostForEventWithOpts(t *testing.T) { t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(exp), utils.ToJSON(rply)) } - argsRt2 := &rates.ArgsCostForEvent{ + argsRt2 := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesStartTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC), @@ -1269,7 +1268,7 @@ func testV1RateCostForEventSpecial(t *testing.T) { } var rply *engine.RateProfileCost - argsRt := &rates.ArgsCostForEvent{ + argsRt := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesStartTime: time.Date(2020, 12, 23, 23, 0, 0, 0, time.UTC), @@ -1409,7 +1408,7 @@ func testV1RateCostForEventThreeRates(t *testing.T) { } var rply *engine.RateProfileCost - argsRt := &rates.ArgsCostForEvent{ + argsRt := &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ Opts: map[string]interface{}{ utils.OptsRatesStartTime: time.Date(2020, 12, 31, 10, 0, 0, 0, time.UTC), diff --git a/engine/routes.go b/engine/routes.go index 885e30b09..5bd035317 100644 --- a/engine/routes.go +++ b/engine/routes.go @@ -276,24 +276,49 @@ func (rpS *RouteService) costForEvent(ev *utils.CGREvent, } if accountMaxUsage == 0 || accountMaxUsage < initialUsage { - var rpCost map[string]interface{} - if err := rpS.connMgr.Call(rpS.cgrcfg.RouteSCfg().RALsConns, nil, utils.ResponderGetCostOnRatingPlans, - &utils.GetCostOnRatingPlansArgs{ - Tenant: ev.Tenant, - Account: acnt, - Subject: subj, - Destination: dst, - SetupTime: sTime, - Usage: usage, - RatingPlanIDs: rpIDs, - }, &rpCost); err != nil { - return nil, err - } - for k, v := range rpCost { // do not overwrite the return map - costData[k] = v + var rateRply *RateProfileCost + if len(rpS.cgrcfg.RouteSCfg().RateSConns) != 0 { + if err := rpS.connMgr.Call(rpS.cgrcfg.RouteSCfg().RateSConns, nil, utils.RateSv1CostForEvent, + &utils.ArgsCostForEvent{ + CGREventWithOpts: &utils.CGREventWithOpts{ + Opts: map[string]interface{}{ // add the setup time and usage in opts + utils.OptsRatesStartTime: sTime, + utils.OptsRatesUsage: usage, + }, + CGREvent: &utils.CGREvent{ // add the rest of the field in event + Tenant: ev.Tenant, + ID: utils.UUIDSha1Prefix(), + Event: map[string]interface{}{ + utils.Account: acnt, + utils.Subject: subj, + utils.Destination: dst, + }, + }, + }, + }, &rateRply); err != nil { + return nil, err + } + costData[utils.Cost] = rateRply.Cost + costData[utils.RateProfileMatched] = rateRply.ID + } else { + var rpCost map[string]interface{} + if err := rpS.connMgr.Call(rpS.cgrcfg.RouteSCfg().RALsConns, nil, utils.ResponderGetCostOnRatingPlans, + &utils.GetCostOnRatingPlansArgs{ + Tenant: ev.Tenant, + Account: acnt, + Subject: subj, + Destination: dst, + SetupTime: sTime, + Usage: usage, + RatingPlanIDs: rpIDs, + }, &rpCost); err != nil { + return nil, err + } + for k, v := range rpCost { // do not overwrite the return map + costData[k] = v + } } } - return } diff --git a/rates/rates.go b/rates/rates.go index 3b221a41d..6a37ffb62 100644 --- a/rates/rates.go +++ b/rates/rates.go @@ -69,7 +69,7 @@ func (rS *RateS) Call(serviceMethod string, args interface{}, reply interface{}) } // matchingRateProfileForEvent returns the matched RateProfile for the given event -func (rS *RateS) matchingRateProfileForEvent(tnt string, rPfIDs []string, args *ArgsCostForEvent) (rtPfl *engine.RateProfile, err error) { +func (rS *RateS) matchingRateProfileForEvent(tnt string, rPfIDs []string, args *utils.ArgsCostForEvent) (rtPfl *engine.RateProfile, err error) { evNm := utils.MapStorage{ utils.MetaReq: args.CGREvent.Event, utils.MetaOpts: args.Opts, @@ -123,7 +123,7 @@ func (rS *RateS) matchingRateProfileForEvent(tnt string, rPfIDs []string, args * } // costForEvent computes the cost for an event based on a preselected rating profile -func (rS *RateS) rateProfileCostForEvent(rtPfl *engine.RateProfile, args *ArgsCostForEvent) (rpCost *engine.RateProfileCost, err error) { +func (rS *RateS) rateProfileCostForEvent(rtPfl *engine.RateProfile, args *utils.ArgsCostForEvent) (rpCost *engine.RateProfileCost, err error) { var rtIDs utils.StringSet if rtIDs, err = engine.MatchingItemIDsForEvent( args.CGREventWithOpts.CGREvent.Event, @@ -170,30 +170,8 @@ func (rS *RateS) rateProfileCostForEvent(rtPfl *engine.RateProfile, args *ArgsCo return } -// ArgsCostForEvent arguments used for proccess event -type ArgsCostForEvent struct { - RateProfileIDs []string - *utils.CGREventWithOpts -} - -// StartTime returns the event time used to check active rate profiles -func (args *ArgsCostForEvent) StartTime(tmz string) (sTime time.Time, err error) { - if tIface, has := args.Opts[utils.OptsRatesStartTime]; has { - return utils.IfaceAsTime(tIface, tmz) - } - return time.Now(), nil -} - -// usage returns the event time used to check active rate profiles -func (args *ArgsCostForEvent) Usage() (usage time.Duration, err error) { - if uIface, has := args.Opts[utils.OptsRatesUsage]; has { - return utils.IfaceAsDuration(uIface) - } - return time.Duration(time.Minute), nil -} - // V1CostForEvent will be called to calculate the cost for an event -func (rS *RateS) V1CostForEvent(args *ArgsCostForEvent, rpCost *engine.RateProfileCost) (err error) { +func (rS *RateS) V1CostForEvent(args *utils.ArgsCostForEvent, rpCost *engine.RateProfileCost) (err error) { rPfIDs := make([]string, len(args.RateProfileIDs)) for i, rpID := range args.RateProfileIDs { rPfIDs[i] = rpID diff --git a/rates/rates_test.go b/rates/rates_test.go index e5dc6620c..13241b856 100644 --- a/rates/rates_test.go +++ b/rates/rates_test.go @@ -96,7 +96,7 @@ func TestMatchingRateProfileEvent(t *testing.T) { t.Error(err) } if rtPRf, err := rate.matchingRateProfileForEvent("cgrates.org", []string{}, - &ArgsCostForEvent{ + &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", @@ -115,7 +115,7 @@ func TestMatchingRateProfileEvent(t *testing.T) { } if _, err := rate.matchingRateProfileForEvent("cgrates.org", []string{}, - &ArgsCostForEvent{ + &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", @@ -131,7 +131,7 @@ func TestMatchingRateProfileEvent(t *testing.T) { t.Error(err) } if _, err := rate.matchingRateProfileForEvent("cgrates.org", []string{}, - &ArgsCostForEvent{ + &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", @@ -147,7 +147,7 @@ func TestMatchingRateProfileEvent(t *testing.T) { t.Error(err) } if _, err := rate.matchingRateProfileForEvent("cgrates.org", []string{}, - &ArgsCostForEvent{ + &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", @@ -164,7 +164,7 @@ func TestMatchingRateProfileEvent(t *testing.T) { } if _, err := rate.matchingRateProfileForEvent("cgrates.org", []string{"rp2"}, - &ArgsCostForEvent{ + &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", @@ -182,7 +182,7 @@ func TestMatchingRateProfileEvent(t *testing.T) { rpp.FilterIDs = []string{"*string:~*req.Account:1001;1002;1003", "*gt:~*req.Cost{*:10"} if _, err := rate.matchingRateProfileForEvent("cgrates.org", []string{}, - &ArgsCostForEvent{ + &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", @@ -200,7 +200,7 @@ func TestMatchingRateProfileEvent(t *testing.T) { rate.dm = nil if _, err := rate.matchingRateProfileForEvent("cgrates.org", []string{"rp3"}, - &ArgsCostForEvent{ + &utils.ArgsCostForEvent{ CGREventWithOpts: &utils.CGREventWithOpts{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", diff --git a/utils/apitpdata.go b/utils/apitpdata.go index dddeeea21..e85d8d4b2 100755 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -1485,3 +1485,25 @@ type ArgExportCDRs struct { Verbose bool // verbose is used to inform the user about the positive and negative exported cdrs RPCCDRsFilter } + +// ArgsCostForEvent arguments used for process event +type ArgsCostForEvent struct { + RateProfileIDs []string + *CGREventWithOpts +} + +// StartTime returns the event time used to check active rate profiles +func (args *ArgsCostForEvent) StartTime(tmz string) (sTime time.Time, err error) { + if tIface, has := args.Opts[OptsRatesStartTime]; has { + return IfaceAsTime(tIface, tmz) + } + return time.Now(), nil +} + +// usage returns the event time used to check active rate profiles +func (args *ArgsCostForEvent) Usage() (usage time.Duration, err error) { + if uIface, has := args.Opts[OptsRatesUsage]; has { + return IfaceAsDuration(uIface) + } + return time.Duration(time.Minute), nil +} diff --git a/utils/consts.go b/utils/consts.go index 0e94b6b7f..026c0641d 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -875,6 +875,7 @@ const ( HashtagSep = "#" MetaRounding = "*rounding" StatsNA = -1.0 + RateProfileMatched = "RateProfileMatched" ) // Migrator Action