From e66ff36383e6db565ada369d6bcf186f2181e2bc Mon Sep 17 00:00:00 2001 From: TeoV Date: Mon, 29 Jun 2020 18:07:53 +0300 Subject: [PATCH] Update structure for Rates from RateProfile --- apier/v1/rateprofiles.go | 65 +++++-- .../mysql/create_tariffplan_tables.sql | 4 +- .../postgres/create_tariffplan_tables.sql | 4 +- data/tariffplans/tutrates/RateProfiles.csv | 4 +- engine/model_helpers.go | 182 +++++++++--------- engine/models.go | 46 ++--- engine/rateprofile.go | 24 ++- rates/librates.go | 9 +- utils/apitpdata.go | 22 ++- utils/consts.go | 2 + 10 files changed, 206 insertions(+), 156 deletions(-) diff --git a/apier/v1/rateprofiles.go b/apier/v1/rateprofiles.go index 8e0efaf75..c22f33902 100644 --- a/apier/v1/rateprofiles.go +++ b/apier/v1/rateprofiles.go @@ -28,11 +28,11 @@ import ( ) // GetRateProfile returns an Rate Profile -func (APIerSv1 *APIerSv1) GetRateProfile(arg *utils.TenantIDWithArgDispatcher, reply *engine.RateProfile) error { +func (apierSv1 *APIerSv1) GetRateProfile(arg *utils.TenantIDWithArgDispatcher, reply *engine.RateProfile) error { if missing := utils.MissingStructFields(arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing return utils.NewErrMandatoryIeMissing(missing...) } - if rPrf, err := APIerSv1.DataManager.GetRateProfile(arg.Tenant, arg.ID, true, true, utils.NonTransactional); err != nil { + if rPrf, err := apierSv1.DataManager.GetRateProfile(arg.Tenant, arg.ID, true, true, utils.NonTransactional); err != nil { if err.Error() != utils.ErrNotFound.Error() { err = utils.NewErrServerError(err) } @@ -44,12 +44,12 @@ func (APIerSv1 *APIerSv1) GetRateProfile(arg *utils.TenantIDWithArgDispatcher, r } // GetRateProfileIDs returns list of rate profile IDs registered for a tenant -func (APIerSv1 *APIerSv1) GetRateProfileIDs(args *utils.TenantArgWithPaginator, attrPrfIDs *[]string) error { +func (apierSv1 *APIerSv1) GetRateProfileIDs(args *utils.TenantArgWithPaginator, attrPrfIDs *[]string) error { if missing := utils.MissingStructFields(args, []string{utils.Tenant}); len(missing) != 0 { //Params missing return utils.NewErrMandatoryIeMissing(missing...) } prfx := utils.RateProfilePrefix + args.Tenant + ":" - keys, err := APIerSv1.DataManager.DataDB().GetKeysForPrefix(prfx) + keys, err := apierSv1.DataManager.DataDB().GetKeysForPrefix(prfx) if err != nil { return err } @@ -66,13 +66,13 @@ func (APIerSv1 *APIerSv1) GetRateProfileIDs(args *utils.TenantArgWithPaginator, // GetRateProfileIDsCount sets in reply var the total number of RateProfileIDs registered for a tenant // returns ErrNotFound in case of 0 RateProfileIDs -func (APIerSv1 *APIerSv1) GetRateProfileIDsCount(args *utils.TenantArg, reply *int) (err error) { +func (apierSv1 *APIerSv1) GetRateProfileIDsCount(args *utils.TenantArg, reply *int) (err error) { if missing := utils.MissingStructFields(args, []string{utils.Tenant}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } var keys []string prfx := utils.RateProfilePrefix + args.Tenant + ":" - if keys, err = APIerSv1.DataManager.DataDB().GetKeysForPrefix(prfx); err != nil { + if keys, err = apierSv1.DataManager.DataDB().GetKeysForPrefix(prfx); err != nil { return err } if len(keys) == 0 { @@ -88,23 +88,58 @@ type RateProfileWithCache struct { } //SetRateProfile add/update a new Rate Profile -func (APIerSv1 *APIerSv1) SetRateProfile(rPrf *RateProfileWithCache, reply *string) error { +func (apierSv1 *APIerSv1) SetRateProfile(rPrf *RateProfileWithCache, reply *string) error { if missing := utils.MissingStructFields(rPrf.RateProfile, []string{"Tenant", "ID", "Rates"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } - if err := APIerSv1.DataManager.SetRateProfile(rPrf.RateProfile, true); err != nil { + if err := apierSv1.DataManager.SetRateProfile(rPrf.RateProfile, true); err != nil { return utils.APIErrorHandler(err) } - //generate a loadID for CacheAttributeProfiles and store it in database - if err := APIerSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil { + //generate a loadID for CacheRateProfiles and store it in database + if err := apierSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil { return utils.APIErrorHandler(err) } args := utils.ArgsGetCacheItem{ CacheID: utils.CacheRateProfiles, ItemID: rPrf.TenantID(), } - if err := APIerSv1.CallCache(GetCacheOpt(rPrf.Cache), args); err != nil { + if err := apierSv1.CallCache(GetCacheOpt(rPrf.Cache), args); err != nil { + return utils.APIErrorHandler(err) + } + *reply = utils.OK + return nil +} + +//SetRateProfileRates add/update Rates from existing RateProfiles +func (apierSv1 *APIerSv1) SetRateProfileRates(rPrf *RateProfileWithCache, reply *string) (err error) { + if missing := utils.MissingStructFields(rPrf.RateProfile, []string{"Tenant", "ID", "Rates"}); len(missing) != 0 { + return utils.NewErrMandatoryIeMissing(missing...) + } + var rateProfile *engine.RateProfile + // make sure the RateProfile exists + if rateProfile, err = apierSv1.DataManager.GetRateProfile(rPrf.Tenant, rPrf.ID, true, true, utils.NonTransactional); err != nil { + if err.Error() != utils.ErrNotFound.Error() { + err = utils.NewErrServerError(err) + } + return err + } + // add the new rates and overwrite the existing ones + for key, rate := range rPrf.Rates { + rateProfile.Rates[key] = rate + } + if err = apierSv1.DataManager.SetRateProfile(rateProfile, true); err != nil { + return utils.APIErrorHandler(err) + } + //generate a loadID for CacheRateProfiles and store it in database + if err = apierSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil { + return utils.APIErrorHandler(err) + } + args := utils.ArgsGetCacheItem{ + CacheID: utils.CacheRateProfiles, + ItemID: rPrf.TenantID(), + } + if err = apierSv1.CallCache(GetCacheOpt(rPrf.Cache), args); err != nil { return utils.APIErrorHandler(err) } *reply = utils.OK @@ -112,23 +147,23 @@ func (APIerSv1 *APIerSv1) SetRateProfile(rPrf *RateProfileWithCache, reply *stri } // RemoveRateProfile remove a specific Rate Profile -func (APIerSv1 *APIerSv1) RemoveRateProfile(arg *utils.TenantIDWithCache, reply *string) error { +func (apierSv1 *APIerSv1) RemoveRateProfile(arg *utils.TenantIDWithCache, reply *string) error { if missing := utils.MissingStructFields(arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing return utils.NewErrMandatoryIeMissing(missing...) } - if err := APIerSv1.DataManager.RemoveRateProfile(arg.Tenant, arg.ID, + if err := apierSv1.DataManager.RemoveRateProfile(arg.Tenant, arg.ID, utils.NonTransactional, true); err != nil { return utils.APIErrorHandler(err) } //generate a loadID for CacheAttributeProfiles and store it in database - if err := APIerSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil { + if err := apierSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheRateProfiles: time.Now().UnixNano()}); err != nil { return utils.APIErrorHandler(err) } args := utils.ArgsGetCacheItem{ CacheID: utils.CacheRateProfiles, ItemID: utils.ConcatenatedKey(arg.Tenant, arg.ID), } - if err := APIerSv1.CallCache(GetCacheOpt(arg.Cache), args); err != nil { + if err := apierSv1.CallCache(GetCacheOpt(arg.Cache), args); err != nil { return utils.APIErrorHandler(err) } *reply = utils.OK diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql index 147b84e9b..a4f97890a 100644 --- a/data/storage/mysql/create_tariffplan_tables.sql +++ b/data/storage/mysql/create_tariffplan_tables.sql @@ -490,11 +490,13 @@ CREATE TABLE tp_rate_profiles ( `max_cost_strategy` varchar(64) NOT NULL, `rate_id` varchar(32) NOT NULL, `rate_filter_ids` varchar(64) NOT NULL, + `rate_activation_start` varchar(64) NOT NULL, `route_weight` decimal(8,2) NOT NULL, + `rate_blocker` BOOLEAN NOT NULL, + `rate_interval_start` varchar(64) NOT NULL, `rate_value` decimal(8,4) NOT NULL, `rate_unit` varchar(64) NOT NULL, `rate_increment` varchar(64) NOT NULL, - `rate_blocker` BOOLEAN NOT NULL, `created_at` TIMESTAMP, PRIMARY KEY (`pk`), KEY `tpid` (`tpid`), diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql index ca7b04576..26c08d518 100644 --- a/data/storage/postgres/create_tariffplan_tables.sql +++ b/data/storage/postgres/create_tariffplan_tables.sql @@ -476,11 +476,13 @@ CREATE INDEX tp_routes_unique ON tp_routes ("tpid", "tenant", "id", "max_cost_strategy" VARCHAR(64) NOT NULL, "rate_id" VARCHAR(64) NOT NULL, "rate_filter_ids" VARCHAR(64) NOT NULL, + "rate_activation_start" VARCHAR(64) NOT NULL, "rate_weight" decimal(8,2) NOT NULL, + "rate_blocker" BOOLEAN NOT NULL, + "rate_interval_start" VARCHAR(64) NOT NULL, "rate_value" decimal(8,4) NOT NULL, "rate_unit" VARCHAR(64) NOT NULL, "rate_increment" VARCHAR(64) NOT NULL, - "rate_blocker" BOOLEAN NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE ); CREATE INDEX tp_rate_profiles_ids ON tp_rate_profiles (tpid); diff --git a/data/tariffplans/tutrates/RateProfiles.csv b/data/tariffplans/tutrates/RateProfiles.csv index 6e36ccb97..49a229fcc 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,RateActivationInterval,RateWeight,RateValue,RateUnit,RateIncrement,RateBlocker +#Tenant,ID,FilterIDs,ActivationInterval,Weight,ConnectFee,RoundingMethod,RoundingDecimals,MinCost,MaxCost,MaxCostStrategy,RateID,RateFilterIDs,RateActivationStart,RateWeight,RateBlocker,RateIntervalStart,RateValue,RateUnit,RateIncrement 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 +cgrates.org,RP1,,,,,,,,,,SECOND_GI,*gi:~*req.Usage:1m,,10,0.06,1m,1s,FALSE diff --git a/engine/model_helpers.go b/engine/model_helpers.go index 7fc660f71..3d8ce3057 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -1,4 +1,5 @@ /* +/* Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments Copyright (C) ITsysCOM GmbH @@ -3006,10 +3007,11 @@ type RateProfileMdls []*RateProfileMdl // CSVHeader return the header for csv fields as a slice of string func (tps RateProfileMdls) CSVHeader() (result []string) { - return []string{"#" + utils.Tenant, utils.ID, utils.FilterIDs, utils.ActivationIntervalString, - utils.Weight, utils.ConnectFee, utils.RoundingMethod, utils.RoundingDecimals, utils.MinCost, - utils.MaxCost, utils.MaxCostStrategy, utils.RateID, utils.RateFilterIDs, utils.RateWeight, - utils.RateValue, utils.RateUnit, utils.RateIncrement, utils.RateBlocker, + return []string{"#" + utils.Tenant, utils.ID, utils.FilterIDs, + utils.ActivationIntervalString, utils.Weight, utils.ConnectFee, utils.RoundingMethod, + utils.RoundingDecimals, utils.MinCost, utils.MaxCost, utils.MaxCostStrategy, utils.RateID, + utils.RateFilterIDs, utils.RateActivationStart, utils.RateWeight, utils.RateBlocker, + utils.RateIntervalStart, utils.RateValue, utils.RateUnit, utils.RateIncrement, } } @@ -3034,37 +3036,36 @@ func (tps RateProfileMdls) AsTPRateProfile() (result []*utils.TPRateProfile) { rate, found := rateMap[tenID][tp.RateID] if !found { rate = &utils.TPRate{ - ID: tp.RateID, - Blocker: tp.RateBlocker, + ID: tp.RateID, + IntervalRates: make([]*utils.TPIntervalRate, 0), + Blocker: tp.RateBlocker, } } if tp.RateFilterIDs != utils.EmptyString { 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.RateActivationStart != utils.EmptyString { + rate.ActivationStart = tp.RateActivationStart } if tp.RateWeight != 0 { rate.Weight = tp.RateWeight } + // create new interval rate and append to the slice + intervalRate := new(utils.TPIntervalRate) + if tp.RateIntervalStart != utils.EmptyString { + intervalRate.IntervalStart = tp.RateIntervalStart + } if tp.RateValue != 0 { - rate.Value = tp.RateValue + intervalRate.Value = tp.RateValue } if tp.RateIncrement != utils.EmptyString { - rate.Increment = tp.RateIncrement + intervalRate.Increment = tp.RateIncrement } if tp.RateUnit != utils.EmptyString { - rate.Unit = tp.RateUnit + intervalRate.Unit = tp.RateUnit } - + rate.IntervalRates = append(rate.IntervalRates, intervalRate) rateMap[tenID][tp.RateID] = rate } @@ -3129,57 +3130,57 @@ func APItoModelTPRateProfile(tPrf *utils.TPRateProfile) (mdls RateProfileMdls) { } i := 0 for _, rate := range tPrf.Rates { - mdl := &RateProfileMdl{ - Tenant: tPrf.Tenant, - Tpid: tPrf.TPid, - ID: tPrf.ID, - } - if i == 0 { - for i, val := range tPrf.FilterIDs { - if i != 0 { - mdl.FilterIDs += utils.INFIELD_SEP - } - mdl.FilterIDs += val + for j, intervalRate := range rate.IntervalRates { + mdl := &RateProfileMdl{ + Tenant: tPrf.Tenant, + Tpid: tPrf.TPid, + ID: tPrf.ID, } + if i == 0 { + for i, val := range tPrf.FilterIDs { + if i != 0 { + mdl.FilterIDs += utils.INFIELD_SEP + } + mdl.FilterIDs += val + } - if tPrf.ActivationInterval != nil { - if tPrf.ActivationInterval.ActivationTime != utils.EmptyString { - mdl.ActivationInterval = tPrf.ActivationInterval.ActivationTime + if tPrf.ActivationInterval != nil { + if tPrf.ActivationInterval.ActivationTime != utils.EmptyString { + mdl.ActivationInterval = tPrf.ActivationInterval.ActivationTime + } + if tPrf.ActivationInterval.ExpiryTime != utils.EmptyString { + mdl.ActivationInterval += utils.INFIELD_SEP + tPrf.ActivationInterval.ExpiryTime + } } - if tPrf.ActivationInterval.ExpiryTime != utils.EmptyString { - mdl.ActivationInterval += utils.INFIELD_SEP + tPrf.ActivationInterval.ExpiryTime + mdl.Weight = tPrf.Weight + mdl.ConnectFee = tPrf.ConnectFee + mdl.RoundingMethod = tPrf.RoundingMethod + mdl.RoundingDecimals = tPrf.RoundingDecimals + mdl.MinCost = tPrf.MinCost + mdl.MaxCost = tPrf.MaxCost + mdl.MaxCostStrategy = tPrf.MaxCostStrategy + } + mdl.RateID = rate.ID + if j == 0 { + for i, val := range rate.FilterIDs { + if i != 0 { + mdl.RateFilterIDs += utils.INFIELD_SEP + } + mdl.RateFilterIDs += val } + mdl.RateWeight = rate.Weight + mdl.RateActivationStart = rate.ActivationStart + mdl.RateBlocker = rate.Blocker + } - mdl.Weight = tPrf.Weight - mdl.ConnectFee = tPrf.ConnectFee - mdl.RoundingMethod = tPrf.RoundingMethod - mdl.RoundingDecimals = tPrf.RoundingDecimals - mdl.MinCost = tPrf.MinCost - mdl.MaxCost = tPrf.MaxCost - mdl.MaxCostStrategy = tPrf.MaxCostStrategy + mdl.RateValue = intervalRate.Value + mdl.RateUnit = intervalRate.Unit + mdl.RateIncrement = intervalRate.Increment + mdl.RateIntervalStart = intervalRate.IntervalStart + mdls = append(mdls, mdl) + i++ } - mdl.RateID = rate.ID - for i, val := range rate.FilterIDs { - if i != 0 { - mdl.RateFilterIDs += utils.INFIELD_SEP - } - mdl.RateFilterIDs += val - } - mdl.RateWeight = rate.Weight - mdl.RateValue = rate.Value - 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 } @@ -3208,20 +3209,22 @@ func APItoRateProfile(tpRp *utils.TPRateProfile, timezone string) (rp *RateProfi } 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, + ID: rate.ID, + Weight: rate.Weight, + Blocker: rate.Blocker, + FilterIDs: rate.FilterIDs, + ActivationStart: rate.ActivationStart, + IntervalRates: make([]*IntervalRate, len(rate.IntervalRates)), } - 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 { + for i, iRate := range rate.IntervalRates { + if rp.Rates[key].IntervalRates[i].IntervalStart, err = utils.ParseDurationWithNanosecs(iRate.IntervalStart); err != nil { + return nil, err + } + rp.Rates[key].IntervalRates[i].Value = iRate.Value + if rp.Rates[key].IntervalRates[i].Unit, err = utils.ParseDurationWithNanosecs(iRate.Unit); err != nil { + return nil, err + } + if rp.Rates[key].IntervalRates[i].Increment, err = utils.ParseDurationWithNanosecs(iRate.Increment); err != nil { return nil, err } } @@ -3247,20 +3250,19 @@ func RateProfileToAPI(rp *RateProfile) (tpRp *utils.TPRateProfile) { 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.String(), - Increment: rate.Increment.String(), + ID: rate.ID, + Weight: rate.Weight, + Blocker: rate.Blocker, + FilterIDs: rate.FilterIDs, + ActivationStart: rate.ActivationStart, + IntervalRates: make([]*utils.TPIntervalRate, len(rate.IntervalRates)), } - 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, iRate := range rate.IntervalRates { + tpRp.Rates[key].IntervalRates[i] = &utils.TPIntervalRate{ + IntervalStart: iRate.IntervalStart.String(), + Value: iRate.Value, + Unit: iRate.Unit.String(), + Increment: iRate.Increment.String(), } } } diff --git a/engine/models.go b/engine/models.go index 020763b46..b38a26166 100644 --- a/engine/models.go +++ b/engine/models.go @@ -431,28 +431,30 @@ 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:""` - 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 + 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:""` + RateActivationStart string `index:"13" re:""` + RateWeight float64 `index:"14" re:"\d+\.?\d*"` + RateBlocker bool `index:"15" re:""` + RateIntervalStart string `index:"16" re:""` + RateValue float64 `index:"17" re:"\d+\.?\d*"` + RateUnit string `index:"18" re:""` + RateIncrement string `index:"19" re:""` + + CreatedAt time.Time } func (_ RateProfileMdl) TableName() string { diff --git a/engine/rateprofile.go b/engine/rateprofile.go index b1fd539a4..0c7a10968 100644 --- a/engine/rateprofile.go +++ b/engine/rateprofile.go @@ -50,15 +50,21 @@ func (rpp *RateProfile) TenantID() string { // Route defines rate related information used within a RateProfile type Rate struct { - 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 + ID string // RateID + FilterIDs []string // RateFilterIDs + ActivationStart string //TPActivationInterval have ATime and ETime as strings + Weight float64 // RateWeight will decide the winner per interval start + Blocker bool // RateBlocker will make this rate recurrent, deactivating further intervals + IntervalRates []*IntervalRate + + //aTime cron.Schedule // compiled version of activation time as cron.Schedule interface +} + +type IntervalRate struct { + IntervalStart time.Duration // Starting point when the Rate kicks in + Unit time.Duration // RateUnit + Increment time.Duration // RateIncrement + Value float64 // RateValue val *utils.Decimal // cached version of the Decimal } diff --git a/rates/librates.go b/rates/librates.go index ce58d45e3..4e6e81a70 100644 --- a/rates/librates.go +++ b/rates/librates.go @@ -18,13 +18,7 @@ along with this program. If not, see package rates -import ( - "sort" - "time" - - "github.com/cgrates/cgrates/engine" -) - +/* // orderRatesOnIntervals will order the rates based on ActivationInterval and intervalStart of each Rate // there can be only one winning Rate for each interval, prioritized by the Weight func orderRatesOnIntervals(aRts []*engine.Rate, sTime time.Time, isDuration bool) (ordRts []*engine.RateSInterval) { @@ -77,3 +71,4 @@ func orderRatesOnIntervals(aRts []*engine.Rate, sTime time.Time, isDuration bool return } +*/ diff --git a/utils/apitpdata.go b/utils/apitpdata.go index e985b2a61..e009c861f 100755 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -1454,13 +1454,17 @@ type TPRateProfile struct { } 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 + ID string // RateID + FilterIDs []string // RateFilterIDs + ActivationStart string + Weight float64 // RateWeight will decide the winner per interval start + Blocker bool // RateBlocker will make this rate recurrent, deactivating further intervals + IntervalRates []*TPIntervalRate +} + +type TPIntervalRate struct { + IntervalStart string + Value float64 // RateValue + Unit string + Increment string } diff --git a/utils/consts.go b/utils/consts.go index 92dd3ee4c..62030eb61 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -558,7 +558,9 @@ const ( MaxCostStrategy = "MaxCostStrategy" RateID = "RateID" RateFilterIDs = "RateFilterIDs" + RateActivationStart = "RateActivationStart" RateWeight = "RateWeight" + RateIntervalStart = "RateIntervalStart" RateValue = "RateValue" RateBlocker = "RateBlocker" TimingID = "TimingID"