mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-14 12:49:54 +05:00
timings and rate groups validation
This commit is contained in:
@@ -162,12 +162,8 @@ func (csvr *CSVReader) LoadRates() (err error) {
|
||||
return err
|
||||
}
|
||||
// same tag only to create rate groups
|
||||
existingRates, exists := csvr.tp.rates[tag]
|
||||
_, exists := csvr.tp.rates[tag]
|
||||
if exists {
|
||||
rss := existingRates.RateSlots
|
||||
if err := ValidNextGroup(rss[len(rss)-1], r.RateSlots[0]); err != nil {
|
||||
return fmt.Errorf("RatesTag: %s, error: <%s>", tag, err.Error())
|
||||
}
|
||||
csvr.tp.rates[tag].RateSlots = append(csvr.tp.rates[tag].RateSlots, r.RateSlots[0])
|
||||
} else {
|
||||
csvr.tp.rates[tag] = r
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
@@ -170,10 +169,18 @@ func NewTPData() *TPData {
|
||||
func (tp *TPData) IsValid() bool {
|
||||
valid := true
|
||||
for rplTag, rpl := range tp.ratingPlans {
|
||||
if !rpl.IsValid() {
|
||||
if !rpl.isContinous() {
|
||||
log.Printf("The rating plan %s is not covering all weekdays", rplTag)
|
||||
valid = false
|
||||
}
|
||||
if !rpl.areRatesSane() {
|
||||
log.Printf("The rating plan %s contains invalid rate groups", rplTag)
|
||||
valid = false
|
||||
}
|
||||
if !rpl.areTimingsSane() {
|
||||
log.Printf("The rating plan %s contains invalid timings", rplTag)
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
return valid
|
||||
}
|
||||
@@ -507,16 +514,6 @@ func NewLoadRate(tag, connectFee, price, ratedUnits, rateIncrements, groupInterv
|
||||
return
|
||||
}
|
||||
|
||||
func ValidNextGroup(present, next *utils.RateSlot) error {
|
||||
if next.GroupIntervalStartDuration() <= present.GroupIntervalStartDuration() {
|
||||
return errors.New(fmt.Sprintf("Next rate group interval start: %#v must be heigher than the previous one: %#v", next, present))
|
||||
}
|
||||
if math.Mod(next.GroupIntervalStartDuration().Seconds(), present.RateIncrementDuration().Seconds()) != 0 {
|
||||
return errors.New(fmt.Sprintf("GroupIntervalStart of %#v must be a multiple of RateIncrement of %#v", next, present))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewTiming(timingInfo ...string) (rt *utils.TPTiming) {
|
||||
rt = &utils.TPTiming{}
|
||||
rt.Id = timingInfo[0]
|
||||
|
||||
@@ -20,6 +20,7 @@ package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
|
||||
"github.com/cgrates/cgrates/history"
|
||||
)
|
||||
@@ -114,7 +115,7 @@ func (rp *RatingPlan) GetHistoryRecord() history.Record {
|
||||
}
|
||||
|
||||
// IsValid determines if the rating plan covers a continous period of time
|
||||
func (rp *RatingPlan) IsValid() bool {
|
||||
func (rp *RatingPlan) isContinous() bool {
|
||||
weekdays := make([]int, 7)
|
||||
for _, tm := range rp.Timings {
|
||||
// if it is a blank timing than it will match all
|
||||
@@ -146,3 +147,31 @@ func (rp *RatingPlan) IsValid() bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (rp *RatingPlan) areRatesSane() bool {
|
||||
for _, rating := range rp.Ratings {
|
||||
rating.Rates.Sort()
|
||||
for i, rate := range rating.Rates {
|
||||
if i < (len(rating.Rates) - 1) {
|
||||
nextRate := rating.Rates[i+1]
|
||||
if nextRate.GroupIntervalStart <= rate.GroupIntervalStart {
|
||||
return false
|
||||
}
|
||||
if math.Mod(nextRate.GroupIntervalStart.Seconds(), rate.RateIncrement.Seconds()) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (rp *RatingPlan) areTimingsSane() bool {
|
||||
for _, timing := range rp.Timings {
|
||||
if (len(timing.Years) != 0 || len(timing.Months) != 0 || len(timing.MonthDays) != 0) &&
|
||||
len(timing.WeekDays) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -218,26 +218,26 @@ func TestGetActiveForCall(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanIsValidEmpty(t *testing.T) {
|
||||
func TestRatingPlanIsContinousEmpty(t *testing.T) {
|
||||
rpl := &RatingPlan{}
|
||||
if rpl.IsValid() {
|
||||
if rpl.isContinous() {
|
||||
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanIsValidBlank(t *testing.T) {
|
||||
func TestRatingPlanIsContinousBlank(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Timings: map[string]*RITiming{
|
||||
"blank": &RITiming{StartTime: "00:00:00"},
|
||||
"other": &RITiming{WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"},
|
||||
},
|
||||
}
|
||||
if !rpl.IsValid() {
|
||||
if !rpl.isContinous() {
|
||||
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanIsValidGood(t *testing.T) {
|
||||
func TestRatingPlanIsContinousGood(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Timings: map[string]*RITiming{
|
||||
"first": &RITiming{WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"},
|
||||
@@ -245,24 +245,24 @@ func TestRatingPlanIsValidGood(t *testing.T) {
|
||||
"third": &RITiming{WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"},
|
||||
},
|
||||
}
|
||||
if !rpl.IsValid() {
|
||||
if !rpl.isContinous() {
|
||||
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanIsValidBad(t *testing.T) {
|
||||
func TestRatingPlanisContinousBad(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Timings: map[string]*RITiming{
|
||||
"first": &RITiming{WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"},
|
||||
"second": &RITiming{WeekDays: utils.WeekDays{4, 5, 0}, StartTime: "00:00:00"},
|
||||
},
|
||||
}
|
||||
if rpl.IsValid() {
|
||||
if rpl.isContinous() {
|
||||
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanIsValidSpecial(t *testing.T) {
|
||||
func TestRatingPlanIsContinousSpecial(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Timings: map[string]*RITiming{
|
||||
"special": &RITiming{Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"},
|
||||
@@ -271,12 +271,12 @@ func TestRatingPlanIsValidSpecial(t *testing.T) {
|
||||
"third": &RITiming{WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"},
|
||||
},
|
||||
}
|
||||
if !rpl.IsValid() {
|
||||
if !rpl.isContinous() {
|
||||
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanIsValidMultiple(t *testing.T) {
|
||||
func TestRatingPlanIsContinousMultiple(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Timings: map[string]*RITiming{
|
||||
"special": &RITiming{Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"},
|
||||
@@ -286,12 +286,12 @@ func TestRatingPlanIsValidMultiple(t *testing.T) {
|
||||
"third": &RITiming{WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"},
|
||||
},
|
||||
}
|
||||
if !rpl.IsValid() {
|
||||
if !rpl.isContinous() {
|
||||
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanIsValidMissing(t *testing.T) {
|
||||
func TestRatingPlanIsContinousMissing(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Timings: map[string]*RITiming{
|
||||
"special": &RITiming{Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"},
|
||||
@@ -300,11 +300,100 @@ func TestRatingPlanIsValidMissing(t *testing.T) {
|
||||
"third": &RITiming{WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"},
|
||||
},
|
||||
}
|
||||
if rpl.IsValid() {
|
||||
if rpl.isContinous() {
|
||||
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanSaneTimingsBad(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Timings: map[string]*RITiming{
|
||||
"one": &RITiming{Years: utils.Years{2015}, WeekDays: utils.WeekDays{time.Monday}},
|
||||
},
|
||||
}
|
||||
if rpl.areTimingsSane() {
|
||||
t.Errorf("Error detecting bad timings in rating profile: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanSaneTimingsGood(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Timings: map[string]*RITiming{
|
||||
"one": &RITiming{Years: utils.Years{2015}},
|
||||
"two": &RITiming{WeekDays: utils.WeekDays{0, 1, 2, 3, 4}, StartTime: "00:00:00"},
|
||||
},
|
||||
}
|
||||
if !rpl.areTimingsSane() {
|
||||
t.Errorf("Error detecting bad timings in rating profile: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanSaneRatingsEqual(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Ratings: map[string]*RIRate{
|
||||
"one": &RIRate{
|
||||
Rates: RateGroups{
|
||||
&Rate{
|
||||
GroupIntervalStart: 0 * time.Second,
|
||||
RateIncrement: 30 * time.Second,
|
||||
},
|
||||
&Rate{
|
||||
GroupIntervalStart: 0 * time.Second,
|
||||
RateIncrement: 30 * time.Second,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if rpl.areRatesSane() {
|
||||
t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanSaneRatingsNotMultiple(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Ratings: map[string]*RIRate{
|
||||
"one": &RIRate{
|
||||
Rates: RateGroups{
|
||||
&Rate{
|
||||
GroupIntervalStart: 0 * time.Second,
|
||||
RateIncrement: 30 * time.Second,
|
||||
},
|
||||
&Rate{
|
||||
GroupIntervalStart: 15 * time.Second,
|
||||
RateIncrement: 30 * time.Second,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if rpl.areRatesSane() {
|
||||
t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingPlanSaneRatingsGoot(t *testing.T) {
|
||||
rpl := &RatingPlan{
|
||||
Ratings: map[string]*RIRate{
|
||||
"one": &RIRate{
|
||||
Rates: RateGroups{
|
||||
&Rate{
|
||||
GroupIntervalStart: 60 * time.Second,
|
||||
RateIncrement: 30 * time.Second,
|
||||
},
|
||||
&Rate{
|
||||
GroupIntervalStart: 0 * time.Second,
|
||||
RateIncrement: 30 * time.Second,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if !rpl.areRatesSane() {
|
||||
t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl)
|
||||
}
|
||||
}
|
||||
|
||||
/**************************** Benchmarks *************************************/
|
||||
|
||||
func BenchmarkRatingPlanMarshalJson(b *testing.B) {
|
||||
|
||||
@@ -1234,9 +1234,6 @@ func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string]*utils.TPRate,
|
||||
// same tag only to create rate groups
|
||||
er, exists := rts[tr.Tag]
|
||||
if exists {
|
||||
if err := ValidNextGroup(er.RateSlots[len(er.RateSlots)-1], r.RateSlots[0]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
er.RateSlots = append(er.RateSlots, r.RateSlots[0])
|
||||
} else {
|
||||
rts[tr.Tag] = r
|
||||
|
||||
Reference in New Issue
Block a user