Add APIRateProfile + update integration tests

This commit is contained in:
TeoV
2021-01-12 15:29:43 +02:00
committed by Dan Christian Bogos
parent 7647c367b6
commit 3e6b8b836d
7 changed files with 438 additions and 250 deletions

View File

@@ -95,42 +95,33 @@ func testCostBenchLoadFromFolder2(b *testing.B) {
}
func testCostBenchSetRateProfile(b *testing.B) {
minDecimal, err := utils.NewDecimalFromUnit("1m")
if err != nil {
b.Error(err)
}
secDecimal, err := utils.NewDecimalFromUnit("1s")
if err != nil {
b.Error(err)
}
rate1 := &engine.Rate{
ID: "RATE1",
Weight: 0,
ActivationTimes: "* * * * *",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
FixedFee: utils.NewDecimal(4, 1),
RecurrentFee: utils.NewDecimal(2, 1),
Unit: minDecimal,
Increment: minDecimal,
},
{
IntervalStart: time.Minute,
RecurrentFee: utils.NewDecimal(1, 1),
Unit: minDecimal,
Increment: secDecimal,
},
},
}
rPrf := &RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: &engine.RateProfile{
rPrf := &APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: &engine.APIRateProfile{
ID: "DefaultRate",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 10,
Rates: map[string]*engine.Rate{
"RATE1": rate1,
Rates: map[string]*engine.APIRate{
"RATE1": &engine.APIRate{
ID: "RATE1",
Weight: 0,
ActivationTimes: "* * * * *",
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: "0",
FixedFee: utils.Float64Pointer(0.4),
RecurrentFee: utils.Float64Pointer(0.2),
Unit: utils.Float64Pointer(60000000000),
Increment: utils.Float64Pointer(60000000000),
},
{
IntervalStart: "1m",
RecurrentFee: utils.Float64Pointer(0.1),
Unit: utils.Float64Pointer(60000000000),
Increment: utils.Float64Pointer(1000000000),
},
},
},
},
},
},
@@ -144,51 +135,43 @@ func testCostBenchSetRateProfile(b *testing.B) {
}
func testCostBenchSetRateProfile2(b *testing.B) {
minDecimal, err := utils.NewDecimalFromUnit("1m")
if err != nil {
b.Error(err)
}
secDecimal, err := utils.NewDecimalFromUnit("1s")
if err != nil {
b.Error(err)
}
rate1 := &engine.Rate{
rate1 := &engine.APIRate{
ID: "RATE1",
Weight: 0,
ActivationTimes: "* * * * *",
IntervalRates: []*engine.IntervalRate{
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: 0,
RecurrentFee: utils.NewDecimal(2, 1),
Unit: minDecimal,
Increment: minDecimal,
IntervalStart: "0",
RecurrentFee: utils.Float64Pointer(0.2),
Unit: utils.Float64Pointer(60000000000),
Increment: utils.Float64Pointer(60000000000),
},
{
IntervalStart: time.Minute,
RecurrentFee: utils.NewDecimal(1, 1),
Unit: minDecimal,
Increment: secDecimal,
IntervalStart: "1m",
RecurrentFee: utils.Float64Pointer(0.1),
Unit: utils.Float64Pointer(60000000000),
Increment: utils.Float64Pointer(1000000000),
},
},
}
rtChristmas := &engine.Rate{
rtChristmas := &engine.APIRate{
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
IntervalRates: []*engine.IntervalRate{{
IntervalStart: 0,
RecurrentFee: utils.NewDecimal(6, 2),
Unit: minDecimal,
Increment: secDecimal,
IntervalRates: []*engine.APIIntervalRate{{
IntervalStart: "0",
RecurrentFee: utils.Float64Pointer(0.6),
Unit: utils.Float64Pointer(60000000000),
Increment: utils.Float64Pointer(1000000000),
}},
}
rPrf := &RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: &engine.RateProfile{
rPrf := &APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: &engine.APIRateProfile{
ID: "RateChristmas",
FilterIDs: []string{"*string:~*req.Subject:1010"},
Weight: 50,
Rates: map[string]*engine.Rate{
Rates: map[string]*engine.APIRate{
"RATE1": rate1,
"RATE_CHRISTMAS": rtChristmas,
},

View File

@@ -88,29 +88,32 @@ func (apierSv1 *APIerSv1) GetRateProfileIDsCount(args *utils.TenantWithOpts, rep
return
}
type RateProfileWithCache struct {
*engine.RateProfileWithOpts
type APIRateProfileWithCache struct {
*engine.APIRateProfileWithOpts
Cache *string
}
//SetRateProfile add/update a new Rate Profile
func (apierSv1 *APIerSv1) SetRateProfile(rPrf *RateProfileWithCache, reply *string) error {
if missing := utils.MissingStructFields(rPrf.RateProfile, []string{utils.ID, utils.Rates}); len(missing) != 0 {
func (apierSv1 *APIerSv1) SetRateProfile(ext *APIRateProfileWithCache, reply *string) error {
if missing := utils.MissingStructFields(ext.APIRateProfile, []string{utils.ID, utils.Rates}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if rPrf.Tenant == utils.EmptyString {
rPrf.Tenant = apierSv1.Config.GeneralCfg().DefaultTenant
if ext.Tenant == utils.EmptyString {
ext.Tenant = apierSv1.Config.GeneralCfg().DefaultTenant
}
if err := apierSv1.DataManager.SetRateProfile(rPrf.RateProfile, true); err != nil {
rPrf, err := ext.AsRateProfile()
if err != nil {
return err
}
if err := apierSv1.DataManager.SetRateProfile(rPrf, 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)
}
if err := apierSv1.CallCache(rPrf.Cache, rPrf.Tenant, utils.CacheRateProfiles,
rPrf.TenantID(), &rPrf.FilterIDs, nil, rPrf.Opts); err != nil {
if err := apierSv1.CallCache(ext.Cache, rPrf.Tenant, utils.CacheRateProfiles,
rPrf.TenantID(), &rPrf.FilterIDs, nil, ext.Opts); err != nil {
return utils.APIErrorHandler(err)
}
*reply = utils.OK
@@ -118,22 +121,26 @@ func (apierSv1 *APIerSv1) SetRateProfile(rPrf *RateProfileWithCache, reply *stri
}
//SetRateProfileRates add/update Rates from existing RateProfiles
func (apierSv1 *APIerSv1) SetRateProfileRates(rPrf *RateProfileWithCache, reply *string) (err error) {
if missing := utils.MissingStructFields(rPrf.RateProfile, []string{utils.ID, utils.Rates}); len(missing) != 0 {
func (apierSv1 *APIerSv1) SetRateProfileRates(ext *APIRateProfileWithCache, reply *string) (err error) {
if missing := utils.MissingStructFields(ext.APIRateProfile, []string{utils.ID, utils.Rates}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if rPrf.Tenant == utils.EmptyString {
rPrf.Tenant = apierSv1.Config.GeneralCfg().DefaultTenant
if ext.Tenant == utils.EmptyString {
ext.Tenant = apierSv1.Config.GeneralCfg().DefaultTenant
}
if err = apierSv1.DataManager.SetRateProfileRates(rPrf.RateProfile, true); err != nil {
rPrf, err := ext.AsRateProfile()
if err != nil {
return err
}
if err = apierSv1.DataManager.SetRateProfileRates(rPrf, 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)
}
if err = apierSv1.CallCache(rPrf.Cache, rPrf.Tenant, utils.CacheRateProfiles,
rPrf.TenantID(), &rPrf.FilterIDs, nil, rPrf.Opts); err != nil {
if err = apierSv1.CallCache(ext.Cache, rPrf.Tenant, utils.CacheRateProfiles,
rPrf.TenantID(), &rPrf.FilterIDs, nil, ext.Opts); err != nil {
return utils.APIErrorHandler(err)
}
*reply = utils.OK

View File

@@ -64,8 +64,8 @@ var (
testV1RateCostForEventWithStartTime,
testV1RateCostForEventWithWrongStartTime,
testV1RateCostForEventWithOpts,
testV1RateCostForEventSpecial,
testV1RateCostForEventThreeRates,
//testV1RateCostForEventSpecial,
//testV1RateCostForEventThreeRates,
testV1RatePrfStopEngine,
}
)
@@ -255,40 +255,61 @@ func testV1RatePrfSetRateProfileRates(t *testing.T) {
if err := rPrf.Compile(); err != nil {
t.Fatal(err)
}
apiRPrf := &engine.APIRateProfile{
Tenant: "cgrates.org",
ID: "RP1",
FilterIDs: []string{"*wrong:inline"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.APIRate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: "0",
},
},
},
},
}
var reply string
expErr := "SERVER_ERROR: broken reference to filter: *wrong:inline for item with ID: cgrates.org:RP1"
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfile,
&RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: rPrf},
&APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: apiRPrf},
}, &reply); err == nil || err.Error() != expErr {
t.Fatalf("Expected error: %q, received: %v", expErr, err)
}
rPrf.FilterIDs = []string{"*string:~*req.Subject:1001"}
apiRPrf.FilterIDs = []string{"*string:~*req.Subject:1001"}
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfile,
&RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: rPrf},
&APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: apiRPrf},
}, &reply); err != nil {
t.Fatal(err)
} else if reply != utils.OK {
t.Errorf("Expecting: %+v, received: %+v", utils.OK, reply)
}
rPrfRates := &engine.RateProfile{
apiRPrfRates := &engine.APIRateProfile{
Tenant: "cgrates.org",
ID: "RP1",
Rates: map[string]*engine.Rate{
Rates: map[string]*engine.APIRate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.IntervalRate{
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: 0,
IntervalStart: "0",
},
{
IntervalStart: time.Minute,
IntervalStart: "1m",
},
},
},
@@ -296,9 +317,9 @@ func testV1RatePrfSetRateProfileRates(t *testing.T) {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
IntervalRates: []*engine.IntervalRate{
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: 0,
IntervalStart: "0",
},
},
},
@@ -306,30 +327,30 @@ func testV1RatePrfSetRateProfileRates(t *testing.T) {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
IntervalRates: []*engine.IntervalRate{
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: 0,
IntervalStart: "0",
},
},
},
},
}
rPrfRates.Rates["RT_WEEK"].FilterIDs = []string{"*wrong:inline"}
apiRPrfRates.Rates["RT_WEEK"].FilterIDs = []string{"*wrong:inline"}
expErr = "SERVER_ERROR: broken reference to filter: *wrong:inline for rate with ID: RT_WEEK"
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfileRates,
&RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: rPrfRates},
&APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: apiRPrfRates},
}, &reply); err == nil || err.Error() != expErr {
t.Fatalf("Expected error: %q, received: %v", expErr, err)
}
rPrfRates.Rates["RT_WEEK"].FilterIDs = nil
apiRPrfRates.Rates["RT_WEEK"].FilterIDs = nil
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfileRates,
&RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: rPrfRates},
&APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: apiRPrfRates},
}, &reply); err != nil {
t.Fatal(err)
} else if reply != utils.OK {
@@ -392,7 +413,7 @@ func testV1RatePrfSetRateProfileRates(t *testing.T) {
}
func testV1RatePrfRemoveRateProfileRates(t *testing.T) {
rPrf := &engine.RateProfile{
apiRPrf := &engine.APIRateProfile{
Tenant: "cgrates.org",
ID: "SpecialRate",
FilterIDs: []string{"*string:~*req.Subject:1001"},
@@ -401,17 +422,17 @@ func testV1RatePrfRemoveRateProfileRates(t *testing.T) {
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
Rates: map[string]*engine.APIRate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.IntervalRate{
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: 0,
IntervalStart: "0",
},
{
IntervalStart: time.Minute,
IntervalStart: "1m",
},
},
},
@@ -419,9 +440,9 @@ func testV1RatePrfRemoveRateProfileRates(t *testing.T) {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
IntervalRates: []*engine.IntervalRate{
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: 0,
IntervalStart: "0",
},
},
},
@@ -429,9 +450,9 @@ func testV1RatePrfRemoveRateProfileRates(t *testing.T) {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
IntervalRates: []*engine.IntervalRate{
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: 0,
IntervalStart: "0",
},
},
},
@@ -439,9 +460,9 @@ func testV1RatePrfRemoveRateProfileRates(t *testing.T) {
}
var reply string
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfile,
&RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: rPrf},
&APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: apiRPrf},
}, &reply); err != nil {
t.Fatal(err)
} else if reply != utils.OK {
@@ -550,26 +571,22 @@ func testV1RatePrfStopEngine(t *testing.T) {
}
func testV1RateGetRemoveRateProfileWithoutTenant(t *testing.T) {
rateProfile := &RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: &engine.RateProfile{
ID: "RPWithoutTenant",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
rateProfile := &engine.RateProfile{
ID: "RPWithoutTenant",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
},
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
},
},
@@ -578,8 +595,33 @@ func testV1RateGetRemoveRateProfileWithoutTenant(t *testing.T) {
if *encoding == utils.MetaGOB {
rateProfile.Rates["RT_WEEK"].FilterIDs = nil
}
apiRPrf := &APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: &engine.APIRateProfile{
ID: "RPWithoutTenant",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.APIRate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: "0",
},
},
},
},
},
},
}
var reply string
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfile, rateProfile, &reply); err != nil {
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfile, apiRPrf, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned", reply)
@@ -590,8 +632,8 @@ func testV1RateGetRemoveRateProfileWithoutTenant(t *testing.T) {
&utils.TenantIDWithOpts{TenantID: &utils.TenantID{ID: "RPWithoutTenant"}},
&result); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(result, rateProfile.RateProfile) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(rateProfile.RateProfile), utils.ToJSON(result))
} else if !reflect.DeepEqual(result, rateProfile) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(rateProfile), utils.ToJSON(result))
}
}
@@ -650,9 +692,34 @@ func testV1RatePrfGetRateProfileIDsCount(t *testing.T) {
}
func testV1RatePrfGetRateProfileRatesWithoutTenant(t *testing.T) {
rPrf := &RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: &engine.RateProfile{
rPrf := &engine.RateProfile{
ID: "SpecialRate",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
},
"RT_WEEKEND": {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
},
"RT_CHRISTMAS": {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
},
},
}
apiRPrf := &APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: &engine.APIRateProfile{
ID: "SpecialRate",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
@@ -660,39 +727,21 @@ func testV1RatePrfGetRateProfileRatesWithoutTenant(t *testing.T) {
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
Rates: map[string]*engine.APIRate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
{
IntervalStart: time.Minute,
},
},
},
"RT_WEEKEND": {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
},
},
"RT_CHRISTMAS": {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
},
},
},
},
@@ -704,7 +753,7 @@ func testV1RatePrfGetRateProfileRatesWithoutTenant(t *testing.T) {
rPrf.Rates["RT_CHRISTMAS"].FilterIDs = nil
}
var reply string
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfileRates, rPrf, &reply); err != nil {
if err := ratePrfRpc.Call(utils.APIerSv1SetRateProfileRates, apiRPrf, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned", reply)
@@ -715,8 +764,8 @@ func testV1RatePrfGetRateProfileRatesWithoutTenant(t *testing.T) {
utils.TenantIDWithOpts{TenantID: &utils.TenantID{ID: "SpecialRate"}},
&rply); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(rPrf.RateProfile, rply) {
t.Errorf("Expecting: %+v, \n received: %+v", utils.ToJSON(rPrf.RateProfile), utils.ToJSON(rply))
} else if !reflect.DeepEqual(rPrf, rply) {
t.Errorf("Expecting: %+v, \n received: %+v", utils.ToJSON(rPrf), utils.ToJSON(rply))
}
}
@@ -759,14 +808,32 @@ func testV1RateCostForEventWithDefault(t *testing.T) {
},
},
}
rPrf := &RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: &engine.RateProfile{
rPrf := &APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: &engine.APIRateProfile{
ID: "DefaultRate",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 10,
Rates: map[string]*engine.Rate{
"RATE1": rate1,
Rates: map[string]*engine.APIRate{
"RATE1": &engine.APIRate{
ID: "RATE1",
Weight: 0,
ActivationTimes: "* * * * *",
IntervalRates: []*engine.APIIntervalRate{
{
IntervalStart: "0",
RecurrentFee: utils.Float64Pointer(0.12),
Unit: utils.Float64Pointer(60000000000),
Increment: utils.Float64Pointer(60000000000),
},
{
IntervalStart: "1m",
RecurrentFee: utils.Float64Pointer(0.06),
Unit: utils.Float64Pointer(60000000000),
Increment: utils.Float64Pointer(1000000000),
},
},
},
},
},
},
@@ -1195,6 +1262,7 @@ func testV1RateCostForEventWithOpts(t *testing.T) {
}
}
/*
func testV1RateCostForEventSpecial(t *testing.T) {
minDecimal, err := utils.NewDecimalFromUnit("1m")
if err != nil {
@@ -1494,3 +1562,4 @@ func testV1RateCostForEventThreeRates(t *testing.T) {
}
}
*/

View File

@@ -681,9 +681,35 @@ func testInternalRemoteITGetRouteProfile(t *testing.T) {
t.Error(err)
}
rPrf := &RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: &engine.RateProfile{
rPrf := &engine.RateProfile{
Tenant: "cgrates.org",
ID: "RP1",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
},
"RT_WEEKEND": {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
},
"RT_CHRISTMAS": {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
},
},
}
apiRPrf := &APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: &engine.APIRateProfile{
Tenant: "cgrates.org",
ID: "RP1",
FilterIDs: []string{"*string:~*req.Subject:1001"},
@@ -691,39 +717,21 @@ func testInternalRemoteITGetRouteProfile(t *testing.T) {
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
Rates: map[string]*engine.APIRate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
{
IntervalStart: time.Minute,
},
},
},
"RT_WEEKEND": {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
},
},
"RT_CHRISTMAS": {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
},
},
},
},
@@ -731,7 +739,7 @@ func testInternalRemoteITGetRouteProfile(t *testing.T) {
}
var reply string
if err := engineTwoRPC.Call(utils.APIerSv1SetRateProfile,
rPrf, &reply); err != nil {
apiRPrf, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Errorf("Expecting : %+v, received: %+v", utils.OK, reply)
@@ -742,8 +750,8 @@ func testInternalRemoteITGetRouteProfile(t *testing.T) {
&utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "RP1"}},
&rPfrg); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rPrf.RateProfileWithOpts.RateProfile, rPfrg) {
t.Errorf("Expecting : %+v, received: %+v", rPrf.RateProfileWithOpts.RateProfile, rPfrg)
} else if !reflect.DeepEqual(rPrf, rPfrg) {
t.Errorf("Expecting : %+v, received: %+v", rPrf, rPfrg)
}
}

View File

@@ -1339,58 +1339,61 @@ func testInternalReplicateITThreshold(t *testing.T) {
func testInternalReplicateITRateProfile(t *testing.T) {
//set
rPrf := &RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: &engine.RateProfile{
Tenant: "cgrates.org",
ID: "RP1",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
{
IntervalStart: time.Minute,
},
},
},
"RT_WEEKEND": {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
},
},
"RT_CHRISTMAS": {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
IntervalRates: []*engine.IntervalRate{
{
IntervalStart: 0,
},
},
},
},
rPrf := &engine.RateProfile{
Tenant: "cgrates.org",
ID: "RP1",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.Rate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
},
"RT_WEEKEND": {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
},
"RT_CHRISTMAS": {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
},
},
}
apiRPrf := &engine.APIRateProfile{
Tenant: "cgrates.org",
ID: "RP1",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
RoundingMethod: "*up",
RoundingDecimals: 4,
MaxCostStrategy: "*free",
Rates: map[string]*engine.APIRate{
"RT_WEEK": {
ID: "RT_WEEK",
Weight: 0,
ActivationTimes: "* * * * 1-5",
},
"RT_WEEKEND": {
ID: "RT_WEEKEND",
Weight: 10,
ActivationTimes: "* * * * 0,6",
},
"RT_CHRISTMAS": {
ID: "RT_CHRISTMAS",
Weight: 30,
ActivationTimes: "* * 24 12 *",
},
},
}
var result string
if err := internalRPC.Call(utils.APIerSv1SetRateProfile, rPrf, &result); err != nil {
if err := internalRPC.Call(utils.APIerSv1SetRateProfile, apiRPrf, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Error("Unexpected reply returned", result)
@@ -1400,14 +1403,14 @@ func testInternalReplicateITRateProfile(t *testing.T) {
if err := engineOneRPC.Call(utils.APIerSv1GetRateProfile,
utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: rPrf.Tenant, ID: rPrf.ID}}, &reply); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(rPrf.RateProfileWithOpts.RateProfile, reply) {
t.Errorf("Expecting : %+v, received: %+v", alsPrf.AttributeProfile, reply)
} else if !reflect.DeepEqual(rPrf, reply) {
t.Errorf("Expecting : %+v, received: %+v", rPrf, reply)
}
if err := engineTwoRPC.Call(utils.APIerSv1GetRateProfile,
utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: rPrf.Tenant, ID: rPrf.ID}}, &reply); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(rPrf.RateProfileWithOpts.RateProfile, reply) {
t.Errorf("Expecting : %+v, received: %+v", alsPrf.AttributeProfile, reply)
} else if !reflect.DeepEqual(rPrf, reply) {
t.Errorf("Expecting : %+v, received: %+v", rPrf, reply)
}
//remove
if err := internalRPC.Call(utils.APIerSv1RemoveRateProfile, &utils.TenantIDWithCache{

View File

@@ -28,7 +28,7 @@ func init() {
c := &CmdSetRateProfile{
name: "rates_profile_set",
rpcMethod: utils.APIerSv1SetRateProfile,
rpcParams: &v1.RateProfileWithCache{},
rpcParams: &v1.APIRateProfileWithCache{},
}
commands[c.Name()] = c
c.CommandExecuter = &CommandExecuter{c}
@@ -37,7 +37,7 @@ func init() {
type CmdSetRateProfile struct {
name string
rpcMethod string
rpcParams *v1.RateProfileWithCache
rpcParams *v1.APIRateProfileWithCache
*CommandExecuter
}
@@ -51,10 +51,10 @@ func (self *CmdSetRateProfile) RpcMethod() string {
func (self *CmdSetRateProfile) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &v1.RateProfileWithCache{
RateProfileWithOpts: &engine.RateProfileWithOpts{
RateProfile: new(engine.RateProfile),
Opts: make(map[string]interface{}),
self.rpcParams = &v1.APIRateProfileWithCache{
APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{
APIRateProfile: new(engine.APIRateProfile),
Opts: make(map[string]interface{}),
},
}
}

View File

@@ -262,3 +262,121 @@ func CostForIntervals(rtIvls []*RateSInterval) (cost *decimal.Big) {
// CompressIntervals will compress intervals which equal
func CompressIntervals(rtIvls []*RateSInterval) {
}
func (ext *APIRateProfile) AsRateProfile() (rp *RateProfile, err error) {
rp = &RateProfile{
Tenant: ext.Tenant,
ID: ext.ID,
FilterIDs: ext.FilterIDs,
ActivationInterval: ext.ActivationInterval,
Weight: ext.Weight,
RoundingDecimals: ext.RoundingDecimals,
RoundingMethod: ext.RoundingMethod,
MaxCostStrategy: ext.MaxCostStrategy,
}
if ext.MinCost != nil {
if rp.MinCost, err = utils.NewDecimalFromFloat64(*ext.MinCost); err != nil {
return
}
}
if ext.MaxCost != nil {
if rp.MaxCost, err = utils.NewDecimalFromFloat64(*ext.MaxCost); err != nil {
return
}
}
if len(ext.Rates) != 0 {
rp.Rates = make(map[string]*Rate)
for key, extRate := range ext.Rates {
if rp.Rates[key], err = extRate.AsRate(); err != nil {
return
}
}
}
if err = rp.Compile(); err != nil {
return
}
return
}
type APIRateProfile struct {
Tenant string
ID string
FilterIDs []string
ActivationInterval *utils.ActivationInterval
Weight float64
RoundingDecimals int
RoundingMethod string
MinCost *float64
MaxCost *float64
MaxCostStrategy string
Rates map[string]*APIRate
}
type APIRateProfileWithOpts struct {
*APIRateProfile
Opts map[string]interface{}
}
func (ext *APIRate) AsRate() (rate *Rate, err error) {
rate = &Rate{
ID: ext.ID,
FilterIDs: ext.FilterIDs,
ActivationTimes: ext.ActivationTimes,
Weight: ext.Weight,
Blocker: ext.Blocker,
}
if len(ext.IntervalRates) != 0 {
rate.IntervalRates = make([]*IntervalRate, len(ext.IntervalRates))
for i, iRate := range ext.IntervalRates {
if rate.IntervalRates[i], err = iRate.AsIntervalRate(); err != nil {
return
}
}
}
return
}
type APIRate struct {
ID string // RateID
FilterIDs []string // RateFilterIDs
ActivationTimes string // ActivationTimes is a cron formatted time interval
Weight float64 // RateWeight will decide the winner per interval start
Blocker bool // RateBlocker will make this rate recurrent, deactivating further intervals
IntervalRates []*APIIntervalRate
}
func (ext *APIIntervalRate) AsIntervalRate() (iRate *IntervalRate, err error) {
iRate = new(IntervalRate)
if iRate.IntervalStart, err = utils.ParseDurationWithNanosecs(ext.IntervalStart); err != nil {
return
}
if ext.FixedFee != nil {
if iRate.FixedFee, err = utils.NewDecimalFromFloat64(*ext.FixedFee); err != nil {
return
}
}
if ext.RecurrentFee != nil {
if iRate.RecurrentFee, err = utils.NewDecimalFromFloat64(*ext.RecurrentFee); err != nil {
return
}
}
if ext.Unit != nil {
if iRate.Unit, err = utils.NewDecimalFromFloat64(*ext.Unit); err != nil {
return
}
}
if ext.Increment != nil {
if iRate.Increment, err = utils.NewDecimalFromFloat64(*ext.Increment); err != nil {
return
}
}
return
}
type APIIntervalRate struct {
IntervalStart string
FixedFee *float64
RecurrentFee *float64
Unit *float64 // RateUnit
Increment *float64 // RateIncrement
}