diff --git a/apier/v1/apier_it_test.go b/apier/v1/apier_it_test.go index 6bcb7d254..b231877ca 100644 --- a/apier/v1/apier_it_test.go +++ b/apier/v1/apier_it_test.go @@ -331,16 +331,16 @@ func testApierTPDestination(t *testing.T) { } } -// Test here TPRate APIs +// Test here TPRateRALs APIs func testApierTPRate(t *testing.T) { var reply string - rt := &utils.TPRate{TPid: utils.TEST_SQL, ID: "RT_FS_USERS", RateSlots: []*utils.RateSlot{ + rt := &utils.TPRateRALs{TPid: utils.TEST_SQL, ID: "RT_FS_USERS", RateSlots: []*utils.RateSlot{ {ConnectFee: 0, Rate: 0, RateUnit: "60s", RateIncrement: "60s", GroupIntervalStart: "0s"}, }} - rt2 := new(utils.TPRate) + rt2 := new(utils.TPRateRALs) *rt2 = *rt rt2.ID = "RT_FS_USERS2" - for _, r := range []*utils.TPRate{rt, rt2} { + for _, r := range []*utils.TPRateRALs{rt, rt2} { if err := rater.Call(utils.APIerSv1SetTPRate, r, &reply); err != nil { t.Error("Got error on APIerSv1.SetTPRate: ", err.Error()) } else if reply != utils.OK { @@ -354,13 +354,13 @@ func testApierTPRate(t *testing.T) { t.Error("Calling APIerSv1.SetTPRate got reply: ", reply) } // Check missing params - if err := rater.Call(utils.APIerSv1SetTPRate, new(utils.TPRate), &reply); err == nil { + if err := rater.Call(utils.APIerSv1SetTPRate, new(utils.TPRateRALs), &reply); err == nil { t.Error("Calling APIerSv1.SetTPDestination, expected error, received: ", reply) } else if err.Error() != "MANDATORY_IE_MISSING: [TPid ID RateSlots]" { t.Error("Calling APIerSv1.SetTPRate got unexpected error: ", err.Error()) } // Test get - var rplyRt2 *utils.TPRate + var rplyRt2 *utils.TPRateRALs if err := rater.Call(utils.APIerSv1GetTPRate, &AttrGetTPRate{rt2.TPid, rt2.ID}, &rplyRt2); err != nil { t.Error("Calling APIerSv1.GetTPRate, got error: ", err.Error()) } else if !reflect.DeepEqual(rt2, rplyRt2) { diff --git a/apier/v1/rateprofiles_it_test.go b/apier/v1/rateprofiles_it_test.go index 4ad4c5a88..40adc87ce 100644 --- a/apier/v1/rateprofiles_it_test.go +++ b/apier/v1/rateprofiles_it_test.go @@ -142,8 +142,8 @@ func testV1RatePrfVerifyRateProfile(t *testing.T) { MinCost: 0.1, MaxCost: 0.6, MaxCostStrategy: "*free", - Rates: []*engine.Rate{ - &engine.Rate{ + Rates: map[string]*engine.Rate{ + "FIRST_GI": &engine.Rate{ ID: "FIRST_GI", FilterIDs: []string{"*gi:~*req.Usage:0"}, Weight: 0, @@ -152,7 +152,7 @@ func testV1RatePrfVerifyRateProfile(t *testing.T) { Increment: time.Duration(1 * time.Minute), Blocker: false, }, - &engine.Rate{ + "SECOND_GI": &engine.Rate{ ID: "SECOND_GI", FilterIDs: []string{"*gi:~*req.Usage:1m"}, Weight: 10, diff --git a/apier/v1/tprateprofiles.go b/apier/v1/tprateprofiles.go index 10e5c29bf..8b8e307ce 100644 --- a/apier/v1/tprateprofiles.go +++ b/apier/v1/tprateprofiles.go @@ -19,16 +19,15 @@ along with this program. If not, see package v1 import ( - "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) // SetTPRateProfile creates a new TPRateProfile within a tariff plan -func (api *APIerSv1) SetTPRateProfile(attrs *engine.TPRateProfile, reply *string) error { +func (api *APIerSv1) SetTPRateProfile(attrs *utils.TPRateProfile, reply *string) error { if missing := utils.MissingStructFields(attrs, []string{"TPid", "Tenant", "ID"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } - if err := api.StorDb.SetTPRateProfiles([]*engine.TPRateProfile{attrs}); err != nil { + if err := api.StorDb.SetTPRateProfiles([]*utils.TPRateProfile{attrs}); err != nil { return utils.NewErrServerError(err) } *reply = utils.OK @@ -36,7 +35,7 @@ func (api *APIerSv1) SetTPRateProfile(attrs *engine.TPRateProfile, reply *string } // GetTPRateProfile queries specific TPRateProfile on tariff plan -func (api *APIerSv1) GetTPRateProfile(attr *utils.TPTntID, reply *engine.TPRateProfile) error { +func (api *APIerSv1) GetTPRateProfile(attr *utils.TPTntID, reply *utils.TPRateProfile) error { if missing := utils.MissingStructFields(attr, []string{"TPid", "Tenant", "ID"}); len(missing) != 0 { //Params missing return utils.NewErrMandatoryIeMissing(missing...) } diff --git a/apier/v1/tprates.go b/apier/v1/tprates.go index 50b8f137b..46c0a353d 100644 --- a/apier/v1/tprates.go +++ b/apier/v1/tprates.go @@ -25,11 +25,11 @@ import ( ) // SetTPRate creates a new rate within a tariff plan -func (api *APIerSv1) SetTPRate(attrs *utils.TPRate, reply *string) error { +func (api *APIerSv1) SetTPRate(attrs *utils.TPRateRALs, reply *string) error { if missing := utils.MissingStructFields(attrs, []string{"TPid", "ID", "RateSlots"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } - if err := api.StorDb.SetTPRates([]*utils.TPRate{attrs}); err != nil { + if err := api.StorDb.SetTPRates([]*utils.TPRateRALs{attrs}); err != nil { return utils.NewErrServerError(err) } *reply = utils.OK @@ -42,7 +42,7 @@ type AttrGetTPRate struct { } // GetTPRate queries specific Rate on tariff plan -func (api *APIerSv1) GetTPRate(attrs *AttrGetTPRate, reply *utils.TPRate) error { +func (api *APIerSv1) GetTPRate(attrs *AttrGetTPRate, reply *utils.TPRateRALs) error { if missing := utils.MissingStructFields(attrs, []string{"TPid", "ID"}); len(missing) != 0 { //Params missing return utils.NewErrMandatoryIeMissing(missing...) } diff --git a/apier/v1/tprates_it_test.go b/apier/v1/tprates_it_test.go index 06809907d..b88caf2ed 100644 --- a/apier/v1/tprates_it_test.go +++ b/apier/v1/tprates_it_test.go @@ -37,7 +37,7 @@ var ( tpRateCfg *config.CGRConfig tpRateRPC *rpc.Client tpRateDataDir = "/usr/share/cgrates" - tpRate *utils.TPRate + tpRate *utils.TPRateRALs tpRateDelay int tpRateConfigDIR string //run tests for specific configuration ) @@ -118,7 +118,7 @@ func testTPRatesRpcConn(t *testing.T) { } func testTPRatesGetTPRateforeSet(t *testing.T) { - var reply *utils.TPRate + var reply *utils.TPRateRALs if err := tpRateRPC.Call(utils.APIerSv1GetTPRate, &AttrGetTPRate{TPid: "TPidTpRate", ID: "RT_FS_USERS"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Error(err) @@ -126,7 +126,7 @@ func testTPRatesGetTPRateforeSet(t *testing.T) { } func testTPRatesSetTPRate(t *testing.T) { - tpRate = &utils.TPRate{ + tpRate = &utils.TPRateRALs{ TPid: "TPidTpRate", ID: "RT_FS_USERS", RateSlots: []*utils.RateSlot{ @@ -155,7 +155,7 @@ func testTPRatesSetTPRate(t *testing.T) { } func testTPRatesGetTPRateAfterSet(t *testing.T) { - var reply *utils.TPRate + var reply *utils.TPRateRALs if err := tpRateRPC.Call(utils.APIerSv1GetTPRate, &AttrGetTPRate{TPid: "TPidTpRate", ID: tpRate.ID}, &reply); err != nil { t.Error(err) } else if !reflect.DeepEqual(tpRate, reply) { @@ -206,7 +206,7 @@ func testTPRatesUpdateTPRate(t *testing.T) { } func testTPRatesGetTPRateAfterUpdate(t *testing.T) { - var reply *utils.TPRate + var reply *utils.TPRateRALs if err := tpRateRPC.Call(utils.APIerSv1GetTPRate, &AttrGetTPRate{TPid: "TPidTpRate", ID: tpRate.ID}, &reply); err != nil { t.Error(err) @@ -227,7 +227,7 @@ func testTPRatesRemoveTPRate(t *testing.T) { } func testTPRatesGetTPRateAfterRemove(t *testing.T) { - var reply *utils.TPRate + var reply *utils.TPRateRALs if err := tpRateRPC.Call(utils.APIerSv1GetTPRate, &AttrGetTPRate{TPid: "TPidTpRate", ID: "RT_FS_USERS"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Error(err) diff --git a/data/tariffplans/tutrates/RateProfiles.csv b/data/tariffplans/tutrates/RateProfiles.csv index d1ee780ff..6e36ccb97 100644 --- a/data/tariffplans/tutrates/RateProfiles.csv +++ b/data/tariffplans/tutrates/RateProfiles.csv @@ -1,3 +1,3 @@ -#Tenant,ID,FilterIDs,ActivationInterval,Weight,ConnectFee,RoundingMethod,RoundingDecimals,MinCost,MaxCost,MaxCostStrategy,RateID,RateFilterIDs,RateWeight,RateValue,RateUnit,RateIncrement,RateBlocker -cgrates.org,RP1,*string:~*req.Subject:1001,,0,0.1,*up,4,0.1,0.6,*free,FIRST_GI,*gi:~*req.Usage:0,0,0.12,1m,1m,FALSE -cgrates.org,RP1,*string:~*req.Subject:1002,,,,,,,,,SECOND_GI,*gi:~*req.Usage:1m,10,0.06,1m,1s,FALSE +#Tenant,ID,FilterIDs,ActivationInterval,Weight,ConnectFee,RoundingMethod,RoundingDecimals,MinCost,MaxCost,MaxCostStrategy,RateID,RateFilterIDs,RateActivationInterval,RateWeight,RateValue,RateUnit,RateIncrement,RateBlocker +cgrates.org,RP1,*string:~*req.Subject:1001,,0,0.1,*up,4,0.1,0.6,*free,FIRST_GI,*gi:~*req.Usage:0,,0,0.12,1m,1m,FALSE +cgrates.org,RP1,*string:~*req.Subject:1002,,,,,,,,,SECOND_GI,*gi:~*req.Usage:1m,,10,0.06,1m,1s,FALSE diff --git a/engine/libtest.go b/engine/libtest.go index 0e0c2e565..72745bf2e 100644 --- a/engine/libtest.go +++ b/engine/libtest.go @@ -281,9 +281,9 @@ cgrates.org,ALL1,127.0.0.1:2012,*json,true cgrates.org,ALL1,127.0.0.1:3012,*json,false ` RateProfileCSVContent = ` -#Tenant,ID,FilterIDs,ActivationInterval,Weight,ConnectFee,RoundingMethod,RoundingDecimals,MinCost,MaxCost,MaxCostStrategy,RateID,RateFilterIDs,RateWeight,RateValue,RateUnit,RateIncrement,RateBlocker -cgrates.org,RP1,*string:~*req.Subject:1001,,0,0.1,*up,4,0.1,0.6,*free,FIRST_GI,*gi:~*req.Usage:0,0,0.12,1m,1m,FALSE -cgrates.org,RP1,*string:~*req.Subject:1002,,,,,,,,,SECOND_GI,*gi:~*req.Usage:1m,10,0.06,1m,1s,FALSE +#Tenant,ID,FilterIDs,ActivationInterval,Weight,ConnectFee,RoundingMethod,RoundingDecimals,MinCost,MaxCost,MaxCostStrategy,RateID,RateFilterIDs,RateActivationInterval,RateWeight,RateValue,RateUnit,RateIncrement,RateBlocker +cgrates.org,RP1,*string:~*req.Subject:1001,,0,0.1,*up,4,0.1,0.6,*free,FIRST_GI,*gi:~*req.Usage:0,,0,0.12,1m,1m,FALSE +cgrates.org,RP1,*string:~*req.Subject:1002,,,,,,,,,SECOND_GI,*gi:~*req.Usage:1m,,10,0.06,1m,1s,FALSE ` ) diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 713be0842..21b1aed60 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -1414,7 +1414,7 @@ func TestLoadDispatcherProfiles(t *testing.T) { } func TestLoadRateProfiles(t *testing.T) { - eRatePrf := &TPRateProfile{ + eRatePrf := &utils.TPRateProfile{ TPid: testTPID, Tenant: "cgrates.org", ID: "RP1", @@ -1426,23 +1426,23 @@ func TestLoadRateProfiles(t *testing.T) { MinCost: 0.1, MaxCost: 0.6, MaxCostStrategy: "*free", - Rates: []*Rate{ - &Rate{ + Rates: map[string]*utils.TPRate{ + "FIRST_GI": &utils.TPRate{ ID: "FIRST_GI", FilterIDs: []string{"*gi:~*req.Usage:0"}, Weight: 0, Value: 0.12, - Unit: time.Duration(1 * time.Minute), - Increment: time.Duration(1 * time.Minute), + Unit: "1m", + Increment: "1m", Blocker: false, }, - &Rate{ + "SECOND_GI": &utils.TPRate{ ID: "SECOND_GI", FilterIDs: []string{"*gi:~*req.Usage:1m"}, Weight: 10, Value: 0.06, - Unit: time.Duration(1 * time.Minute), - Increment: time.Duration(1 * time.Second), + Unit: "1m", + Increment: "1s", Blocker: false, }, }, @@ -1457,12 +1457,6 @@ func TestLoadRateProfiles(t *testing.T) { sort.Slice(csvr.rateProfiles[dppKey].FilterIDs, func(i, j int) bool { return csvr.rateProfiles[dppKey].FilterIDs[i] < csvr.rateProfiles[dppKey].FilterIDs[j] }) - sort.Slice(eRatePrf.Rates, func(i, j int) bool { - return eRatePrf.Rates[i].ID < eRatePrf.Rates[j].ID - }) - sort.Slice(csvr.rateProfiles[dppKey].Rates, func(i, j int) bool { - return csvr.rateProfiles[dppKey].Rates[i].ID < csvr.rateProfiles[dppKey].Rates[j].ID - }) if !reflect.DeepEqual(eRatePrf, csvr.rateProfiles[dppKey]) { t.Errorf("Expecting: %+v, received: %+v", diff --git a/engine/model_helpers.go b/engine/model_helpers.go index c3a371fe0..6bea91e0b 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -262,10 +262,10 @@ func APItoModelTimings(ts []*utils.ApierTPTiming) (result TpTimings) { type TpRates []TpRate -func (tps TpRates) AsMapRates() (map[string]*utils.TPRate, error) { - result := make(map[string]*utils.TPRate) +func (tps TpRates) AsMapRates() (map[string]*utils.TPRateRALs, error) { + result := make(map[string]*utils.TPRateRALs) for _, tp := range tps { - r := &utils.TPRate{ + r := &utils.TPRateRALs{ TPid: tp.Tpid, ID: tp.Tag, } @@ -289,7 +289,7 @@ func (tps TpRates) AsMapRates() (map[string]*utils.TPRate, error) { return result, nil } -func (tps TpRates) AsTPRates() (result []*utils.TPRate, err error) { +func (tps TpRates) AsTPRates() (result []*utils.TPRateRALs, err error) { if atps, err := tps.AsMapRates(); err != nil { return nil, err } else { @@ -300,8 +300,8 @@ func (tps TpRates) AsTPRates() (result []*utils.TPRate, err error) { } } -func MapTPRates(s []*utils.TPRate) (map[string]*utils.TPRate, error) { - result := make(map[string]*utils.TPRate) +func MapTPRates(s []*utils.TPRateRALs) (map[string]*utils.TPRateRALs, error) { + result := make(map[string]*utils.TPRateRALs) for _, e := range s { if _, found := result[e.ID]; !found { result[e.ID] = e @@ -312,7 +312,7 @@ func MapTPRates(s []*utils.TPRate) (map[string]*utils.TPRate, error) { return result, nil } -func APItoModelRate(r *utils.TPRate) (result TpRates) { +func APItoModelRate(r *utils.TPRateRALs) (result TpRates) { if r != nil { for _, rs := range r.RateSlots { result = append(result, TpRate{ @@ -335,7 +335,7 @@ func APItoModelRate(r *utils.TPRate) (result TpRates) { return } -func APItoModelRates(rs []*utils.TPRate) (result TpRates) { +func APItoModelRates(rs []*utils.TPRateRALs) (result TpRates) { for _, r := range rs { for _, sr := range APItoModelRate(r) { result = append(result, sr) @@ -3013,15 +3013,15 @@ func (tps RateProfileMdls) CSVHeader() (result []string) { } } -func (tps RateProfileMdls) AsTPRateProfile() (result []*TPRateProfile, err error) { +func (tps RateProfileMdls) AsTPRateProfile() (result []*utils.TPRateProfile) { filtermap := make(map[string]utils.StringMap) - mst := make(map[string]*TPRateProfile) - rateMap := make(map[string]map[string]*Rate) + mst := make(map[string]*utils.TPRateProfile) + rateMap := make(map[string]map[string]*utils.TPRate) for _, tp := range tps { tenID := (&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID() rPrf, found := mst[tenID] if !found { - rPrf = &TPRateProfile{ + rPrf = &utils.TPRateProfile{ TPid: tp.Tpid, Tenant: tp.Tenant, ID: tp.ID, @@ -3029,16 +3029,11 @@ func (tps RateProfileMdls) AsTPRateProfile() (result []*TPRateProfile, err error } if tp.RateID != utils.EmptyString { if _, has := rateMap[tenID]; !has { - rateMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(map[string]*Rate) + rateMap[tenID] = make(map[string]*utils.TPRate) } - rateID := tp.RateID - if tp.RateFilterIDs != utils.EmptyString { - rateID = utils.ConcatenatedKey(rateID, - utils.NewStringSet(strings.Split(tp.RateFilterIDs, utils.INFIELD_SEP)).Sha1()) - } - rate, found := rateMap[tenID][rateID] + rate, found := rateMap[tenID][tp.RateID] if !found { - rate = &Rate{ + rate = &utils.TPRate{ ID: tp.RateID, Blocker: tp.RateBlocker, } @@ -3047,6 +3042,16 @@ func (tps RateProfileMdls) AsTPRateProfile() (result []*TPRateProfile, err error rateFilterSplit := strings.Split(tp.RateFilterIDs, utils.INFIELD_SEP) rate.FilterIDs = append(rate.FilterIDs, rateFilterSplit...) } + if tp.RateActivationInterval != utils.EmptyString { + rate.ActivationInterval = new(utils.TPActivationInterval) + aiSplt := strings.Split(tp.RateActivationInterval, utils.INFIELD_SEP) + if len(aiSplt) == 2 { + rate.ActivationInterval.ActivationTime = aiSplt[0] + rate.ActivationInterval.ExpiryTime = aiSplt[1] + } else if len(aiSplt) == 1 { + rate.ActivationInterval.ActivationTime = aiSplt[0] + } + } if tp.RateWeight != 0 { rate.Weight = tp.RateWeight } @@ -3054,17 +3059,13 @@ func (tps RateProfileMdls) AsTPRateProfile() (result []*TPRateProfile, err error rate.Value = tp.RateValue } if tp.RateIncrement != utils.EmptyString { - if rate.Increment, err = utils.ParseDurationWithNanosecs(tp.RateIncrement); err != nil { - return - } + rate.Increment = tp.RateIncrement } if tp.RateUnit != utils.EmptyString { - if rate.Unit, err = utils.ParseDurationWithNanosecs(tp.RateUnit); err != nil { - return - } + rate.Unit = tp.RateUnit } - rateMap[tenID][rateID] = rate + rateMap[tenID][tp.RateID] = rate } if tp.Weight != 0 { @@ -3109,13 +3110,11 @@ func (tps RateProfileMdls) AsTPRateProfile() (result []*TPRateProfile, err error } mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = rPrf } - result = make([]*TPRateProfile, len(mst)) + result = make([]*utils.TPRateProfile, len(mst)) i := 0 for tntID, th := range mst { result[i] = th - for _, rate := range rateMap[tntID] { - result[i].Rates = append(result[i].Rates, rate) - } + result[i].Rates = rateMap[tntID] for filterdata := range filtermap[tntID] { result[i].FilterIDs = append(result[i].FilterIDs, filterdata) } @@ -3124,11 +3123,12 @@ func (tps RateProfileMdls) AsTPRateProfile() (result []*TPRateProfile, err error return } -func APItoModelTPRateProfile(tPrf *TPRateProfile) (mdls RateProfileMdls) { +func APItoModelTPRateProfile(tPrf *utils.TPRateProfile) (mdls RateProfileMdls) { if len(tPrf.Rates) == 0 { return } - for i, rate := range tPrf.Rates { + i := 0 + for _, rate := range tPrf.Rates { mdl := &RateProfileMdl{ Tenant: tPrf.Tenant, Tpid: tPrf.TPid, @@ -3167,15 +3167,24 @@ func APItoModelTPRateProfile(tPrf *TPRateProfile) (mdls RateProfileMdls) { } mdl.RateWeight = rate.Weight mdl.RateValue = rate.Weight - mdl.RateUnit = rate.Unit.String() - mdl.RateIncrement = rate.Increment.String() + if rate.ActivationInterval != nil { + if rate.ActivationInterval.ActivationTime != utils.EmptyString { + mdl.RateActivationInterval = rate.ActivationInterval.ActivationTime + } + if rate.ActivationInterval.ExpiryTime != utils.EmptyString { + mdl.RateActivationInterval += utils.INFIELD_SEP + rate.ActivationInterval.ExpiryTime + } + } + mdl.RateUnit = rate.Unit + mdl.RateIncrement = rate.Increment mdl.RateBlocker = rate.Blocker mdls = append(mdls, mdl) + i++ } return } -func APItoRateProfile(tpRp *TPRateProfile, timezone string) (rp *RateProfile, err error) { +func APItoRateProfile(tpRp *utils.TPRateProfile, timezone string) (rp *RateProfile, err error) { rp = &RateProfile{ Tenant: tpRp.Tenant, ID: tpRp.ID, @@ -3187,7 +3196,7 @@ func APItoRateProfile(tpRp *TPRateProfile, timezone string) (rp *RateProfile, er MinCost: tpRp.MinCost, MaxCost: tpRp.MaxCost, MaxCostStrategy: tpRp.MaxCostStrategy, - Rates: make([]*Rate, len(tpRp.Rates)), + Rates: make(map[string]*Rate), } for i, stp := range tpRp.FilterIDs { rp.FilterIDs[i] = stp @@ -3197,22 +3206,31 @@ func APItoRateProfile(tpRp *TPRateProfile, timezone string) (rp *RateProfile, er return nil, err } } - for i, rate := range tpRp.Rates { - rp.Rates[i] = &Rate{ + for key, rate := range tpRp.Rates { + rp.Rates[key] = &Rate{ ID: rate.ID, Weight: rate.Weight, Blocker: rate.Blocker, FilterIDs: rate.FilterIDs, Value: rate.Value, - Unit: rate.Unit, - Increment: rate.Increment, + } + if rp.Rates[key].Unit, err = utils.ParseDurationWithNanosecs(rate.Unit); err != nil { + return nil, err + } + if rp.Rates[key].Increment, err = utils.ParseDurationWithNanosecs(rate.Increment); err != nil { + return nil, err + } + if rate.ActivationInterval != nil { + if rp.Rates[key].ActivationInterval, err = rate.ActivationInterval.AsActivationInterval(timezone); err != nil { + return nil, err + } } } return rp, nil } -func RateProfileToAPI(rp *RateProfile) (tpRp *TPRateProfile) { - tpRp = &TPRateProfile{ +func RateProfileToAPI(rp *RateProfile) (tpRp *utils.TPRateProfile) { + tpRp = &utils.TPRateProfile{ Tenant: rp.Tenant, ID: rp.ID, FilterIDs: make([]string, len(rp.FilterIDs)), @@ -3224,18 +3242,26 @@ func RateProfileToAPI(rp *RateProfile) (tpRp *TPRateProfile) { MinCost: rp.MinCost, MaxCost: rp.MaxCost, MaxCostStrategy: rp.MaxCostStrategy, - Rates: make([]*Rate, len(rp.Rates)), + Rates: make(map[string]*utils.TPRate), } - for i, rate := range rp.Rates { - tpRp.Rates[i] = &Rate{ + for key, rate := range rp.Rates { + tpRp.Rates[key] = &utils.TPRate{ ID: rate.ID, Weight: rate.Weight, Blocker: rate.Blocker, FilterIDs: rate.FilterIDs, Value: rate.Value, - Unit: rate.Unit, - Increment: rate.Increment, + Unit: rate.Unit.String(), + Increment: rate.Increment.String(), + } + if rate.ActivationInterval != nil { + if !rate.ActivationInterval.ActivationTime.IsZero() { + tpRp.Rates[key].ActivationInterval.ActivationTime = rate.ActivationInterval.ActivationTime.Format(time.RFC3339) + } + if !rate.ActivationInterval.ExpiryTime.IsZero() { + tpRp.Rates[key].ActivationInterval.ExpiryTime = rate.ActivationInterval.ExpiryTime.Format(time.RFC3339) + } } } for i, fli := range rp.FilterIDs { diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index 25ab1ee2c..942e33b64 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -85,7 +85,7 @@ func TestTpDestinationsAsTPDestinations(t *testing.T) { } func TestTPRateAsExportSlice(t *testing.T) { - tpRate := &utils.TPRate{ + tpRate := &utils.TPRateRALs{ TPid: "TEST_TPID", ID: "TEST_RATEID", RateSlots: []*utils.RateSlot{ @@ -2602,8 +2602,8 @@ func TestRateProfileToAPI(t *testing.T) { MinCost: 0.1, MaxCost: 0.6, MaxCostStrategy: "*free", - Rates: []*Rate{ - &Rate{ + Rates: map[string]*Rate{ + "FIRST_GI": &Rate{ ID: "FIRST_GI", FilterIDs: []string{"*gi:~*req.Usage:0"}, Weight: 0, @@ -2612,7 +2612,7 @@ func TestRateProfileToAPI(t *testing.T) { Increment: time.Duration(1 * time.Minute), Blocker: false, }, - &Rate{ + "SECOND_GI": &Rate{ ID: "SECOND_GI", FilterIDs: []string{"*gi:~*req.Usage:1m"}, Weight: 10, @@ -2623,7 +2623,7 @@ func TestRateProfileToAPI(t *testing.T) { }, }, } - eTPRatePrf := &TPRateProfile{ + eTPRatePrf := &utils.TPRateProfile{ Tenant: "cgrates.org", ID: "RP1", FilterIDs: []string{"*string:~*req.Subject:1001", "*string:~*req.Subject:1002"}, @@ -2635,23 +2635,23 @@ func TestRateProfileToAPI(t *testing.T) { MinCost: 0.1, MaxCost: 0.6, MaxCostStrategy: "*free", - Rates: []*Rate{ - &Rate{ + Rates: map[string]*utils.TPRate{ + "FIRST_GI": &utils.TPRate{ ID: "FIRST_GI", FilterIDs: []string{"*gi:~*req.Usage:0"}, Weight: 0, Value: 0.12, - Unit: time.Duration(1 * time.Minute), - Increment: time.Duration(1 * time.Minute), + Unit: "1m0s", + Increment: "1m0s", Blocker: false, }, - &Rate{ + "SECOND_GI": &utils.TPRate{ ID: "SECOND_GI", FilterIDs: []string{"*gi:~*req.Usage:1m"}, Weight: 10, Value: 0.06, - Unit: time.Duration(1 * time.Minute), - Increment: time.Duration(1 * time.Second), + Unit: "1m0s", + Increment: "1s", Blocker: false, }, }, diff --git a/engine/models.go b/engine/models.go index e5609b8b6..020763b46 100644 --- a/engine/models.go +++ b/engine/models.go @@ -431,27 +431,28 @@ type TPDispatcherHost struct { } type RateProfileMdl struct { - PK uint `gorm:"primary_key"` - Tpid string - Tenant string `index:"0" re:""` - ID string `index:"1" re:""` - FilterIDs string `index:"2" re:""` - ActivationInterval string `index:"3" re:""` - Weight float64 `index:"4" re:"\d+\.?\d*"` - ConnectFee float64 `index:"5" re:"\d+\.?\d*"` - RoundingMethod string `index:"6" re:""` - RoundingDecimals int `index:"7" re:""` - MinCost float64 `index:"8" re:"\d+\.?\d*""` - MaxCost float64 `index:"9" re:"\d+\.?\d*"` - MaxCostStrategy string `index:"10" re:""` - RateID string `index:"11" re:""` - RateFilterIDs string `index:"12" re:""` - RateWeight float64 `index:"13" re:"\d+\.?\d*"` - RateValue float64 `index:"14" re:"\d+\.?\d*"` - RateUnit string `index:"15" re:""` - RateIncrement string `index:"16" re:""` - RateBlocker bool `index:"17" re:""` - CreatedAt time.Time + PK uint `gorm:"primary_key"` + Tpid string + Tenant string `index:"0" re:""` + ID string `index:"1" re:""` + FilterIDs string `index:"2" re:""` + ActivationInterval string `index:"3" re:""` + Weight float64 `index:"4" re:"\d+\.?\d*"` + ConnectFee float64 `index:"5" re:"\d+\.?\d*"` + RoundingMethod string `index:"6" re:""` + RoundingDecimals int `index:"7" re:""` + MinCost float64 `index:"8" re:"\d+\.?\d*""` + MaxCost float64 `index:"9" re:"\d+\.?\d*"` + MaxCostStrategy string `index:"10" re:""` + RateID string `index:"11" re:""` + RateFilterIDs string `index:"12" re:""` + RateActivationInterval string `index:"13" re:""` + RateWeight float64 `index:"14" re:"\d+\.?\d*"` + RateValue float64 `index:"15" re:"\d+\.?\d*"` + RateUnit string `index:"16" re:""` + RateIncrement string `index:"17" re:""` + RateBlocker bool `index:"18" re:""` + CreatedAt time.Time } func (_ RateProfileMdl) TableName() string { diff --git a/engine/onstor_it_test.go b/engine/onstor_it_test.go index 61cdf7098..b0b8d2eea 100644 --- a/engine/onstor_it_test.go +++ b/engine/onstor_it_test.go @@ -2152,8 +2152,8 @@ func testOnStorITRateProfile(t *testing.T) { MinCost: 0.1, MaxCost: 0.6, MaxCostStrategy: "*free", - Rates: []*Rate{ - &Rate{ + Rates: map[string]*Rate{ + "FIRST_GI": &Rate{ ID: "FIRST_GI", FilterIDs: []string{"*gi:~*req.Usage:0"}, Weight: 0, @@ -2162,7 +2162,7 @@ func testOnStorITRateProfile(t *testing.T) { Increment: time.Duration(1 * time.Minute), Blocker: false, }, - &Rate{ + "SECOND_GI": &Rate{ ID: "SECOND_GI", FilterIDs: []string{"*gi:~*req.Usage:1m"}, Weight: 10, diff --git a/engine/rateprofile.go b/engine/rateprofile.go index a90a34e43..bc0c82985 100644 --- a/engine/rateprofile.go +++ b/engine/rateprofile.go @@ -37,7 +37,7 @@ type RateProfile struct { MinCost float64 MaxCost float64 MaxCostStrategy string - Rates []*Rate + Rates map[string]*Rate connFee *utils.Decimal // cached version of the Decimal minCost *utils.Decimal @@ -50,16 +50,18 @@ func (rpp *RateProfile) TenantID() string { // Route defines rate related information used within a RateProfile type Rate struct { - ID string // RateID - FilterIDs []string // RateFilterIDs - IntervalStart time.Duration // Starting point when the Rate kicks in - Weight float64 // RateWeight will decide the winner per interval start - Value float64 // RateValue - Unit time.Duration // RateUnit - Increment time.Duration // RateIncrement - Blocker bool // RateBlocker will make this rate recurrent, deactivating further intervals + ID string // RateID + FilterIDs []string // RateFilterIDs + ActivationInterval *utils.ActivationInterval //TPActivationInterval have ATime and ETime as strings + IntervalStart time.Duration // Starting point when the Rate kicks in + Weight float64 // RateWeight will decide the winner per interval start + Value float64 // RateValue + Unit time.Duration // RateUnit + Increment time.Duration // RateIncrement + Blocker bool // RateBlocker will make this rate recurrent, deactivating further intervals - val *utils.Decimal // cached version of the Decimal + val *utils.Decimal // cached version of the Decimal + grpItvl *time.Duration // populated from IntervalStart if duration is provided } // RateProfileWithArgDispatcher is used in replicatorV1 for dispatcher @@ -67,19 +69,3 @@ type RateProfileWithArgDispatcher struct { *RateProfile *utils.ArgDispatcher } - -type TPRateProfile struct { - TPid string - Tenant string - ID string - FilterIDs []string - ActivationInterval *utils.TPActivationInterval - Weight float64 - ConnectFee float64 - RoundingMethod string - RoundingDecimals int - MinCost float64 - MaxCost float64 - MaxCostStrategy string - Rates []*Rate -} diff --git a/engine/storage_csv.go b/engine/storage_csv.go index c3bbcaa6e..a21f40265 100644 --- a/engine/storage_csv.go +++ b/engine/storage_csv.go @@ -431,7 +431,7 @@ func (csvs *CSVStorage) GetTPDestinations(tpid, id string) ([]*utils.TPDestinati return tpDests.AsTPDestinations(), nil } -func (csvs *CSVStorage) GetTPRates(tpid, id string) ([]*utils.TPRate, error) { +func (csvs *CSVStorage) GetTPRates(tpid, id string) ([]*utils.TPRateRALs, error) { var tpRates TpRates if err := csvs.proccesData(TpRate{}, csvs.ratesFn, func(tp interface{}) { r := tp.(TpRate) @@ -653,7 +653,7 @@ func (csvs *CSVStorage) GetTPDispatcherHosts(tpid, tenant, id string) ([]*utils. return tpDDHs.AsTPDispatcherHosts(), nil } -func (csvs *CSVStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*TPRateProfile, error) { +func (csvs *CSVStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*utils.TPRateProfile, error) { var tpDPPs RateProfileMdls if err := csvs.proccesData(RateProfileMdl{}, csvs.rateProfilesFn, func(tp interface{}) { dpp := tp.(RateProfileMdl) @@ -662,7 +662,7 @@ func (csvs *CSVStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*TPRatePro }); err != nil { return nil, err } - return tpDPPs.AsTPRateProfile() + return tpDPPs.AsTPRateProfile(), nil } func (csvs *CSVStorage) GetTpIds(colName string) ([]string, error) { diff --git a/engine/storage_interface.go b/engine/storage_interface.go index a62ef155d..1522be61e 100644 --- a/engine/storage_interface.go +++ b/engine/storage_interface.go @@ -167,7 +167,7 @@ type LoadReader interface { map[string]string, *utils.PaginatorWithSearch) ([]string, error) GetTPTimings(string, string) ([]*utils.ApierTPTiming, error) GetTPDestinations(string, string) ([]*utils.TPDestination, error) - GetTPRates(string, string) ([]*utils.TPRate, error) + GetTPRates(string, string) ([]*utils.TPRateRALs, error) GetTPDestinationRates(string, string, *utils.Paginator) ([]*utils.TPDestinationRate, error) GetTPRatingPlans(string, string, *utils.Paginator) ([]*utils.TPRatingPlan, error) GetTPRatingProfiles(*utils.TPRatingProfile) ([]*utils.TPRatingProfile, error) @@ -185,14 +185,14 @@ type LoadReader interface { GetTPChargers(string, string, string) ([]*utils.TPChargerProfile, error) GetTPDispatcherProfiles(string, string, string) ([]*utils.TPDispatcherProfile, error) GetTPDispatcherHosts(string, string, string) ([]*utils.TPDispatcherHost, error) - GetTPRateProfiles(string, string, string) ([]*TPRateProfile, error) + GetTPRateProfiles(string, string, string) ([]*utils.TPRateProfile, error) } type LoadWriter interface { RemTpData(string, string, map[string]string) error SetTPTimings([]*utils.ApierTPTiming) error SetTPDestinations([]*utils.TPDestination) error - SetTPRates([]*utils.TPRate) error + SetTPRates([]*utils.TPRateRALs) error SetTPDestinationRates([]*utils.TPDestinationRate) error SetTPRatingPlans([]*utils.TPRatingPlan) error SetTPRatingProfiles([]*utils.TPRatingProfile) error @@ -210,7 +210,7 @@ type LoadWriter interface { SetTPChargers([]*utils.TPChargerProfile) error SetTPDispatcherProfiles([]*utils.TPDispatcherProfile) error SetTPDispatcherHosts([]*utils.TPDispatcherHost) error - SetTPRateProfiles([]*TPRateProfile) error + SetTPRateProfiles([]*utils.TPRateProfile) error } // NewMarshaler returns the marshaler type selected by mrshlerStr diff --git a/engine/storage_internal_stordb.go b/engine/storage_internal_stordb.go index 3197fa071..c5ced0c9e 100644 --- a/engine/storage_internal_stordb.go +++ b/engine/storage_internal_stordb.go @@ -110,7 +110,7 @@ func (iDB *InternalDB) GetTPDestinations(tpid, id string) (dsts []*utils.TPDesti return } -func (iDB *InternalDB) GetTPRates(tpid, id string) (rates []*utils.TPRate, err error) { +func (iDB *InternalDB) GetTPRates(tpid, id string) (rates []*utils.TPRateRALs, err error) { key := tpid if id != utils.EmptyString { key += utils.CONCATENATED_KEY_SEP + id @@ -121,7 +121,7 @@ func (iDB *InternalDB) GetTPRates(tpid, id string) (rates []*utils.TPRate, err e if !ok || x == nil { return nil, utils.ErrNotFound } - result := x.(*utils.TPRate) + result := x.(*utils.TPRateRALs) for _, rs := range result.RateSlots { rs.SetDurations() } @@ -566,7 +566,7 @@ func (iDB *InternalDB) GetTPDispatcherHosts(tpid, tenant, id string) (dpps []*ut return } -func (iDB *InternalDB) GetTPRateProfiles(tpid, tenant, id string) (tpPrfs []*TPRateProfile, err error) { +func (iDB *InternalDB) GetTPRateProfiles(tpid, tenant, id string) (tpPrfs []*utils.TPRateProfile, err error) { key := tpid if tenant != utils.EmptyString { key += utils.CONCATENATED_KEY_SEP + tenant @@ -580,7 +580,7 @@ func (iDB *InternalDB) GetTPRateProfiles(tpid, tenant, id string) (tpPrfs []*TPR if !ok || x == nil { return nil, utils.ErrNotFound } - tpPrfs = append(tpPrfs, x.(*TPRateProfile)) + tpPrfs = append(tpPrfs, x.(*utils.TPRateProfile)) } if len(tpPrfs) == 0 { return nil, utils.ErrNotFound @@ -628,7 +628,7 @@ func (iDB *InternalDB) SetTPDestinations(dests []*utils.TPDestination) (err erro return } -func (iDB *InternalDB) SetTPRates(rates []*utils.TPRate) (err error) { +func (iDB *InternalDB) SetTPRates(rates []*utils.TPRateRALs) (err error) { if len(rates) == 0 { return nil } @@ -827,7 +827,7 @@ func (iDB *InternalDB) SetTPDispatcherHosts(dpps []*utils.TPDispatcherHost) (err return } -func (iDB *InternalDB) SetTPRateProfiles(tpPrfs []*TPRateProfile) (err error) { +func (iDB *InternalDB) SetTPRateProfiles(tpPrfs []*utils.TPRateProfile) (err error) { if len(tpPrfs) == 0 { return nil } diff --git a/engine/storage_mongo_stordb.go b/engine/storage_mongo_stordb.go index cb7cfd33c..0c31d3a4f 100644 --- a/engine/storage_mongo_stordb.go +++ b/engine/storage_mongo_stordb.go @@ -209,19 +209,19 @@ func (ms *MongoStorage) GetTPDestinations(tpid, id string) ([]*utils.TPDestinati return results, err } -func (ms *MongoStorage) GetTPRates(tpid, id string) ([]*utils.TPRate, error) { +func (ms *MongoStorage) GetTPRates(tpid, id string) ([]*utils.TPRateRALs, error) { filter := bson.M{"tpid": tpid} if id != "" { filter["id"] = id } - var results []*utils.TPRate + var results []*utils.TPRateRALs err := ms.query(func(sctx mongo.SessionContext) (err error) { cur, err := ms.getCol(utils.TBLTPRates).Find(sctx, filter) if err != nil { return err } for cur.Next(sctx) { - var el utils.TPRate + var el utils.TPRateRALs err := cur.Decode(&el) if err != nil { return err @@ -631,7 +631,7 @@ func (ms *MongoStorage) SetTPDestinations(tpDsts []*utils.TPDestination) (err er }) } -func (ms *MongoStorage) SetTPRates(tps []*utils.TPRate) error { +func (ms *MongoStorage) SetTPRates(tps []*utils.TPRateRALs) error { if len(tps) == 0 { return nil } @@ -1531,7 +1531,7 @@ func (ms *MongoStorage) SetTPDispatcherHosts(tpDPPs []*utils.TPDispatcherHost) ( }) } -func (ms *MongoStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*TPRateProfile, error) { +func (ms *MongoStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*utils.TPRateProfile, error) { filter := bson.M{"tpid": tpid} if id != "" { filter["id"] = id @@ -1539,14 +1539,14 @@ func (ms *MongoStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*TPRatePro if tenant != "" { filter["tenant"] = tenant } - var results []*TPRateProfile + var results []*utils.TPRateProfile err := ms.query(func(sctx mongo.SessionContext) (err error) { cur, err := ms.getCol(utils.TBLTPRateProfiles).Find(sctx, filter) if err != nil { return err } for cur.Next(sctx) { - var tp TPRateProfile + var tp utils.TPRateProfile err := cur.Decode(&tp) if err != nil { return err @@ -1561,7 +1561,7 @@ func (ms *MongoStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*TPRatePro return results, err } -func (ms *MongoStorage) SetTPRateProfiles(tpDPPs []*TPRateProfile) (err error) { +func (ms *MongoStorage) SetTPRateProfiles(tpDPPs []*utils.TPRateProfile) (err error) { if len(tpDPPs) == 0 { return } diff --git a/engine/storage_sql.go b/engine/storage_sql.go index d9addb1ce..b29b56d1e 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -305,7 +305,7 @@ func (self *SQLStorage) SetTPDestinations(dests []*utils.TPDestination) error { return nil } -func (self *SQLStorage) SetTPRates(rs []*utils.TPRate) error { +func (self *SQLStorage) SetTPRates(rs []*utils.TPRateRALs) error { if len(rs) == 0 { return nil //Nothing to set } @@ -728,7 +728,7 @@ func (self *SQLStorage) SetTPDispatcherHosts(tpDPPs []*utils.TPDispatcherHost) e return nil } -func (self *SQLStorage) SetTPRateProfiles(tpDPPs []*TPRateProfile) error { +func (self *SQLStorage) SetTPRateProfiles(tpDPPs []*utils.TPRateProfile) error { if len(tpDPPs) == 0 { return nil } @@ -1206,7 +1206,7 @@ func (self *SQLStorage) GetTPDestinations(tpid, id string) (uTPDsts []*utils.TPD return tpDests.AsTPDestinations(), nil } -func (self *SQLStorage) GetTPRates(tpid, id string) ([]*utils.TPRate, error) { +func (self *SQLStorage) GetTPRates(tpid, id string) ([]*utils.TPRateRALs, error) { var tpRates TpRates q := self.db.Where("tpid = ?", tpid).Order("id") if len(id) != 0 { @@ -1595,7 +1595,7 @@ func (self *SQLStorage) GetTPDispatcherHosts(tpid, tenant, id string) ([]*utils. return arls, nil } -func (self *SQLStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*TPRateProfile, error) { +func (self *SQLStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*utils.TPRateProfile, error) { var dpps RateProfileMdls q := self.db.Where("tpid = ?", tpid) if len(id) != 0 { @@ -1607,10 +1607,8 @@ func (self *SQLStorage) GetTPRateProfiles(tpid, tenant, id string) ([]*TPRatePro if err := q.Find(&dpps).Error; err != nil { return nil, err } - arls, err := dpps.AsTPRateProfile() - if err != nil { - return nil, err - } else if len(arls) == 0 { + arls := dpps.AsTPRateProfile() + if len(arls) == 0 { return arls, utils.ErrNotFound } return arls, nil diff --git a/engine/stordb_it_test.go b/engine/stordb_it_test.go index 75ad07d6f..7a09d2583 100644 --- a/engine/stordb_it_test.go +++ b/engine/stordb_it_test.go @@ -289,7 +289,7 @@ func testStorDBitCRUDTpRates(t *testing.T) { t.Error(err) } // WRITE - var snd = []*utils.TPRate{ + var snd = []*utils.TPRateRALs{ { TPid: "testTPid", ID: "1", diff --git a/engine/tpreader.go b/engine/tpreader.go index 0de9bd8cc..4f5da86a2 100644 --- a/engine/tpreader.go +++ b/engine/tpreader.go @@ -42,7 +42,7 @@ type TpReader struct { accountActions map[string]*Account destinations map[string]*Destination timings map[string]*utils.TPTiming - rates map[string]*utils.TPRate + rates map[string]*utils.TPRateRALs destinationRates map[string]*utils.TPDestinationRate ratingPlans map[string]*RatingPlan ratingProfiles map[string]*RatingProfile @@ -56,7 +56,7 @@ type TpReader struct { chargerProfiles map[utils.TenantID]*utils.TPChargerProfile dispatcherProfiles map[utils.TenantID]*utils.TPDispatcherProfile dispatcherHosts map[utils.TenantID]*utils.TPDispatcherHost - rateProfiles map[utils.TenantID]*TPRateProfile + rateProfiles map[utils.TenantID]*utils.TPRateProfile resources []*utils.TenantID // IDs of resources which need creation based on resourceProfiles statQueues []*utils.TenantID // IDs of statQueues which need creation based on statQueueProfiles thresholds []*utils.TenantID // IDs of thresholds which need creation based on thresholdProfiles @@ -88,7 +88,7 @@ func (tpr *TpReader) Init() { tpr.actions = make(map[string][]*Action) tpr.actionPlans = make(map[string]*ActionPlan) tpr.actionsTriggers = make(map[string]ActionTriggers) - tpr.rates = make(map[string]*utils.TPRate) + tpr.rates = make(map[string]*utils.TPRateRALs) tpr.destinations = make(map[string]*Destination) tpr.destinationRates = make(map[string]*utils.TPDestinationRate) tpr.timings = make(map[string]*utils.TPTiming) @@ -104,7 +104,7 @@ func (tpr *TpReader) Init() { tpr.chargerProfiles = make(map[utils.TenantID]*utils.TPChargerProfile) tpr.dispatcherProfiles = make(map[utils.TenantID]*utils.TPDispatcherProfile) tpr.dispatcherHosts = make(map[utils.TenantID]*utils.TPDispatcherHost) - tpr.rateProfiles = make(map[utils.TenantID]*TPRateProfile) + tpr.rateProfiles = make(map[utils.TenantID]*utils.TPRateProfile) tpr.filters = make(map[utils.TenantID]*utils.TPFilterProfile) tpr.revDests = make(map[string][]string) tpr.acntActionPlans = make(map[string][]string) @@ -1251,7 +1251,7 @@ func (tpr *TpReader) LoadRateProfilesFiltered(tag string) (err error) { if err != nil { return err } - mapRateProfiles := make(map[utils.TenantID]*TPRateProfile) + mapRateProfiles := make(map[utils.TenantID]*utils.TPRateProfile) for _, rl := range rls { mapRateProfiles[utils.TenantID{Tenant: rl.Tenant, ID: rl.ID}] = rl } diff --git a/loaders/loader.go b/loaders/loader.go index 03d9a0736..9e1f73cd3 100644 --- a/loaders/loader.go +++ b/loaders/loader.go @@ -559,11 +559,7 @@ func (ldr *Loader) storeLoadedData(loaderType string, return } } - tpRpls, err := rpMdls.AsTPRateProfile() - if err != nil { - return err - } - for _, tpRpl := range tpRpls { + for _, tpRpl := range rpMdls.AsTPRateProfile() { rpl, err := engine.APItoRateProfile(tpRpl, ldr.timezone) if err != nil { return err diff --git a/migrator/tp_rates_it_test.go b/migrator/tp_rates_it_test.go index 31a305288..09bcbc0e7 100644 --- a/migrator/tp_rates_it_test.go +++ b/migrator/tp_rates_it_test.go @@ -37,7 +37,7 @@ var ( tpRatesCfgIn *config.CGRConfig tpRatesCfgOut *config.CGRConfig tpRatesMigrator *Migrator - tpRates []*utils.TPRate + tpRates []*utils.TPRateRALs ) var sTestsTpRatesIT = []func(t *testing.T){ @@ -106,7 +106,7 @@ func testTpRatesITFlush(t *testing.T) { } func testTpRatesITPopulate(t *testing.T) { - tpRates = []*utils.TPRate{ + tpRates = []*utils.TPRateRALs{ { TPid: "TPidTpRate", ID: "RT_FS_USERS", diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 486890c6b..e985b2a61 100755 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -83,8 +83,8 @@ type TPDestination struct { } // This file deals with tp_* data definition - -type TPRate struct { +// TPRateRALs -> TPRateRALs +type TPRateRALs struct { TPid string // Tariff plan id ID string // Rate id RateSlots []*RateSlot // One or more RateSlots @@ -150,7 +150,7 @@ type TPDestinationRate struct { type DestinationRate struct { DestinationId string // The destination identity RateId string // The rate identity - Rate *TPRate + Rate *TPRateRALs RoundingMethod string RoundingDecimals int MaxCost float64 @@ -1436,3 +1436,31 @@ type AttrsExecuteActionPlans struct { *ArgDispatcher TenantArg } + +type TPRateProfile struct { + TPid string + Tenant string + ID string + FilterIDs []string + ActivationInterval *TPActivationInterval + Weight float64 + ConnectFee float64 + RoundingMethod string + RoundingDecimals int + MinCost float64 + MaxCost float64 + MaxCostStrategy string + Rates map[string]*TPRate +} + +type TPRate struct { + ID string // RateID + FilterIDs []string // RateFilterIDs + ActivationInterval *TPActivationInterval //TPActivationInterval have ATime and ETime as strings + IntervalStart string + Weight float64 // RateWeight will decide the winner per interval start + Value float64 // RateValue + Unit string + Increment string + Blocker bool // RateBlocker will make this rate recurrent, deactivating further intervals +}