mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
improve rating selection with splitting on days
This commit is contained in:
@@ -362,6 +362,7 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) {
|
||||
// split on rating plans
|
||||
afterStart, afterEnd := false, false //optimization for multiple activation periods
|
||||
for _, rp := range cd.RatingInfos {
|
||||
//log.Print("RP: ", utils.ToJSON(rp))
|
||||
if !afterStart && !afterEnd && rp.ActivationTime.Before(cd.TimeStart) {
|
||||
firstSpan.setRatingInfo(rp)
|
||||
} else {
|
||||
@@ -369,7 +370,6 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) {
|
||||
for i := 0; i < len(timespans); i++ {
|
||||
newTs := timespans[i].SplitByRatingPlan(rp)
|
||||
if newTs != nil {
|
||||
//log.Print("NEW TS", newTs.TimeStart)
|
||||
timespans = append(timespans, newTs)
|
||||
} else {
|
||||
afterEnd = true
|
||||
@@ -379,7 +379,22 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// utils.Logger.Debug(fmt.Sprintf("After SplitByRatingPlan: %+v", timespans))
|
||||
//log.Printf("After SplitByRatingPlan: %+v", utils.ToJSON(timespans))
|
||||
// split on days
|
||||
for i := 0; i < len(timespans); i++ {
|
||||
rp := timespans[i].ratingInfo
|
||||
newTs := timespans[i].SplitByDay()
|
||||
if newTs != nil {
|
||||
//log.Print("NEW TS: ", newTs.TimeStart, newTs.TimeEnd)
|
||||
newTs.setRatingInfo(rp)
|
||||
// insert the new timespan
|
||||
index := i + 1
|
||||
timespans = append(timespans, nil)
|
||||
copy(timespans[index+1:], timespans[index:])
|
||||
timespans[index] = newTs
|
||||
}
|
||||
}
|
||||
//log.Printf("After SplitByDay: %+v", utils.ToJSON(timespans))
|
||||
// split on rate intervals
|
||||
for i := 0; i < len(timespans); i++ {
|
||||
//log.Printf("==============%v==================", i)
|
||||
@@ -388,6 +403,7 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) {
|
||||
// utils.Logger.Debug(fmt.Sprintf("rp: %+v", rp))
|
||||
//timespans[i].RatingPlan = nil
|
||||
rateIntervals := rp.SelectRatingIntevalsForTimespan(timespans[i])
|
||||
//log.Print("RIs: ", utils.ToJSON(rateIntervals))
|
||||
/*for _, interval := range rp.RateIntervals {
|
||||
if !timespans[i].hasBetterRateIntervalThan(interval) {
|
||||
timespans[i].SetRateInterval(interval)
|
||||
@@ -520,6 +536,7 @@ func (cd *CallDescriptor) getCost() (*CallCost, error) {
|
||||
cd.TOR = utils.VOICE
|
||||
}
|
||||
err := cd.LoadRatingPlans()
|
||||
//log.Print("RI: ", utils.ToJSON(cd.RatingInfos))
|
||||
if err != nil {
|
||||
//utils.Logger.Err(fmt.Sprintf("error getting cost for key <%s>: %s", cd.GetKey(cd.Subject), err.Error()))
|
||||
return &CallCost{Cost: -1}, err
|
||||
|
||||
@@ -326,6 +326,43 @@ func TestGetCostRatingPlansAndRatingIntervalsMore(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCostRatingPlansAndRatingIntervalsMoreDays(t *testing.T) {
|
||||
t1 := time.Date(2012, time.February, 20, 9, 50, 0, 0, time.UTC)
|
||||
t2 := time.Date(2012, time.February, 23, 18, 10, 0, 0, time.UTC)
|
||||
cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "CUSTOMER_1", Subject: "rif:from:tm", Destination: "49178", TimeStart: t1, TimeEnd: t2, LoopIndex: 0, DurationIndex: t2.Sub(t1)}
|
||||
result, _ := cd.GetCost()
|
||||
if len(result.Timespans) != 8 ||
|
||||
!result.Timespans[0].TimeEnd.Equal(result.Timespans[1].TimeStart) ||
|
||||
!result.Timespans[1].TimeEnd.Equal(result.Timespans[2].TimeStart) ||
|
||||
!result.Timespans[2].TimeEnd.Equal(result.Timespans[3].TimeStart) ||
|
||||
!result.Timespans[3].TimeEnd.Equal(result.Timespans[4].TimeStart) ||
|
||||
!result.Timespans[4].TimeEnd.Equal(result.Timespans[5].TimeStart) ||
|
||||
!result.Timespans[5].TimeEnd.Equal(result.Timespans[6].TimeStart) ||
|
||||
!result.Timespans[6].TimeEnd.Equal(result.Timespans[7].TimeStart) {
|
||||
for _, ts := range result.Timespans {
|
||||
t.Logf("TS %+v", ts)
|
||||
}
|
||||
t.Errorf("Expected %+v was %+v", 4, len(result.Timespans))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCostRatingPlansAndRatingIntervalsMoreDaysWeekend(t *testing.T) {
|
||||
t1 := time.Date(2012, time.February, 24, 9, 50, 0, 0, time.UTC)
|
||||
t2 := time.Date(2012, time.February, 27, 18, 10, 0, 0, time.UTC)
|
||||
cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "CUSTOMER_1", Subject: "rif:from:tm", Destination: "49178", TimeStart: t1, TimeEnd: t2, LoopIndex: 0, DurationIndex: t2.Sub(t1)}
|
||||
result, _ := cd.GetCost()
|
||||
if len(result.Timespans) != 5 ||
|
||||
!result.Timespans[0].TimeEnd.Equal(result.Timespans[1].TimeStart) ||
|
||||
!result.Timespans[1].TimeEnd.Equal(result.Timespans[2].TimeStart) ||
|
||||
!result.Timespans[2].TimeEnd.Equal(result.Timespans[3].TimeStart) ||
|
||||
!result.Timespans[3].TimeEnd.Equal(result.Timespans[4].TimeStart) {
|
||||
for _, ts := range result.Timespans {
|
||||
t.Logf("TS %+v", ts)
|
||||
}
|
||||
t.Errorf("Expected %+v was %+v", 4, len(result.Timespans))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCostRateGroups(t *testing.T) {
|
||||
t1 := time.Date(2013, time.October, 7, 14, 50, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.October, 7, 14, 52, 12, 0, time.UTC)
|
||||
|
||||
@@ -59,12 +59,7 @@ func (rp *RatingPlan) RateIntervalList(dId string) RateIntervalList {
|
||||
return ril
|
||||
}
|
||||
|
||||
/*
|
||||
type xCachedRatingPlan struct {
|
||||
rp *RatingPlan
|
||||
*cache2go.XEntry
|
||||
}
|
||||
*/
|
||||
// no sorter because it's sorted with RateIntervalTimeSorter
|
||||
|
||||
/*
|
||||
Adds one ore more intervals to the internal interval list only if it is not allready in the list.
|
||||
|
||||
@@ -250,6 +250,41 @@ func TestRatingProfileRIforTSMidnight(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingProfileYearMonthDay(t *testing.T) {
|
||||
ri := &RatingInfo{
|
||||
RateIntervals: RateIntervalList{
|
||||
&RateInterval{
|
||||
Timing: &RITiming{
|
||||
StartTime: "09:00:00",
|
||||
},
|
||||
},
|
||||
&RateInterval{
|
||||
Timing: &RITiming{
|
||||
StartTime: "00:00:00",
|
||||
},
|
||||
},
|
||||
&RateInterval{
|
||||
Timing: &RITiming{
|
||||
Years: utils.Years{2016},
|
||||
Months: utils.Months{1},
|
||||
MonthDays: utils.MonthDays{6, 7},
|
||||
WeekDays: utils.WeekDays{},
|
||||
StartTime: "19:00:00",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ts := &TimeSpan{
|
||||
TimeStart: time.Date(2016, 1, 6, 23, 40, 0, 0, time.UTC),
|
||||
TimeEnd: time.Date(2016, 1, 7, 1, 1, 30, 0, time.UTC),
|
||||
}
|
||||
rIntervals := ri.SelectRatingIntevalsForTimespan(ts)
|
||||
if len(rIntervals) != 1 ||
|
||||
rIntervals[0].Timing.StartTime != "19:00:00" {
|
||||
t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRatingProfileSubjectPrefixMatching(t *testing.T) {
|
||||
rpSubjectPrefixMatching = true
|
||||
rp, err := RatingProfileSubjectPrefixMatching("*out:cgrates.org:data:rif")
|
||||
|
||||
@@ -612,6 +612,28 @@ func (ts *TimeSpan) SplitByRatingPlan(rp *RatingInfo) (newTs *TimeSpan) {
|
||||
return
|
||||
}
|
||||
|
||||
// Splits the given timespan on activation period's activation time.
|
||||
func (ts *TimeSpan) SplitByDay() (newTs *TimeSpan) {
|
||||
if ts.TimeStart.Day() == ts.TimeEnd.Day() {
|
||||
return
|
||||
}
|
||||
splitDate := ts.TimeStart.AddDate(0, 0, 1)
|
||||
splitDate = time.Date(splitDate.Year(), splitDate.Month(), splitDate.Day(), 0, 0, 0, 0, splitDate.Location())
|
||||
if splitDate == ts.TimeEnd { // the end date time was actually 00:00:00
|
||||
return
|
||||
}
|
||||
newTs = &TimeSpan{
|
||||
TimeStart: splitDate,
|
||||
TimeEnd: ts.TimeEnd,
|
||||
}
|
||||
newTs.copyRatingInfo(ts)
|
||||
newTs.DurationIndex = ts.DurationIndex
|
||||
ts.TimeEnd = splitDate
|
||||
ts.SetNewDurationIndex(newTs)
|
||||
// Logger.Debug(fmt.Sprintf("RP SPLITTING: %+v %+v", ts, newTs))
|
||||
return
|
||||
}
|
||||
|
||||
// Returns the starting time of this timespan
|
||||
func (ts *TimeSpan) GetGroupStart() time.Duration {
|
||||
s := ts.DurationIndex - ts.GetDuration()
|
||||
|
||||
Reference in New Issue
Block a user