mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-22 15:48:44 +05:00
Add APIRateProfile + update integration tests
This commit is contained in:
committed by
Dan Christian Bogos
parent
7647c367b6
commit
3e6b8b836d
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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{}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user