From 05c4974275945ec981d3ccebd5ea9e860b57a909 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Mon, 27 Apr 2015 19:53:51 +0300 Subject: [PATCH] fix for #61 thank you eloycoto --- engine/callcost_test.go | 2 + engine/calldesc.go | 12 ++++-- engine/calldesc_test.go | 81 ++++++++++++++++++++++++++++++++++++++ engine/ratingprofile.go | 13 +------ engine/timespans.go | 33 ++++++++++++++-- engine/timespans_test.go | 84 ++++++++++++++++++++++++++++++++++++++++ utils/coreutils.go | 5 +++ 7 files changed, 212 insertions(+), 18 deletions(-) diff --git a/engine/callcost_test.go b/engine/callcost_test.go index aabbb3b69..5d862b228 100644 --- a/engine/callcost_test.go +++ b/engine/callcost_test.go @@ -84,6 +84,8 @@ func TestMultipleInputLeftMerge(t *testing.T) { t2 := time.Date(2012, time.February, 2, 18, 01, 0, 0, time.UTC) cd := &CallDescriptor{Direction: OUTBOUND, Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} cc1, _ := cd.GetCost() + //log.Printf("Timing: %+v", cc1.Timespans[1].RateInterval.Timing) + //log.Printf("Rating: %+v", cc1.Timespans[1].RateInterval.Rating) if cc1.Cost != 91 { t.Errorf("expected 91 was %v", cc1.Cost) } diff --git a/engine/calldesc.go b/engine/calldesc.go index 6a6511181..092e797da 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -302,7 +302,6 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { if len(cd.RatingInfos) == 0 { return } - firstSpan.setRatingInfo(cd.RatingInfos[0]) if cd.TOR == utils.VOICE { // split on rating plans @@ -335,11 +334,14 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { //timespans[i].RatingPlan = nil rp.RateIntervals.Sort() for _, interval := range rp.RateIntervals { - //log.Printf("\tINTERVAL: %+v %v", interval, len(rp.RateIntervals)) - if timespans[i].RateInterval != nil && timespans[i].RateInterval.Weight < interval.Weight { + //log.Printf("\tINTERVAL: %+v", interval.Timing) + if timespans[i].hasBetterRateIntervalThan(interval) { + //log.Print("continue") continue // if the timespan has an interval than it already has a heigher weight } newTs := timespans[i].SplitByRateInterval(interval, cd.TOR != utils.VOICE) + //utils.PrintFull(timespans[i]) + //utils.PrintFull(newTs) if newTs != nil { newTs.setRatingInfo(rp) // insert the new timespan @@ -347,7 +349,9 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { timespans = append(timespans, nil) copy(timespans[index+1:], timespans[index:]) timespans[index] = newTs - break + if timespans[i].RateInterval != nil { + break + } } } } diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index 1b2fc80d8..c778d16ad 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -116,6 +116,87 @@ func TestSplitSpans(t *testing.T) { } } +func TestSplitSpansWeekend(t *testing.T) { + cd := &CallDescriptor{Direction: OUTBOUND, + Category: "postpaid", + TOR: utils.VOICE, + Tenant: "foehn", + Subject: "foehn", + Account: "foehn", + Destination: "0034678096720", + TimeStart: time.Date(2015, 4, 24, 7, 59, 4, 0, time.UTC), + TimeEnd: time.Date(2015, 4, 24, 8, 2, 0, 0, time.UTC), + LoopIndex: 0, + DurationIndex: 176 * time.Second, + FallbackSubject: "", + RatingInfos: RatingInfos{ + &RatingInfo{ + MatchedSubject: "*out:foehn:postpaid:foehn", + MatchedPrefix: "0034678", + MatchedDestId: "SPN_MOB", + ActivationTime: time.Date(2015, 4, 23, 0, 0, 0, 0, time.UTC), + RateIntervals: []*RateInterval{ + &RateInterval{ + Timing: &RITiming{ + WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, + StartTime: "08:00:00", + }, + Rating: &RIRate{ + ConnectFee: 0, + RoundingMethod: "*up", + RoundingDecimals: 6, + Rates: RateGroups{ + &Rate{Value: 1, RateIncrement: 1 * time.Second, RateUnit: 1 * time.Second}, + }, + }, + }, + &RateInterval{ + Timing: &RITiming{ + WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, + StartTime: "00:00:00", + }, + Rating: &RIRate{ + ConnectFee: 0, + RoundingMethod: "*up", + RoundingDecimals: 6, + Rates: RateGroups{ + &Rate{Value: 1, RateIncrement: 1 * time.Second, RateUnit: 1 * time.Second}, + }, + }, + }, + &RateInterval{ + Timing: &RITiming{ + WeekDays: []time.Weekday{time.Saturday, time.Sunday}, + StartTime: "00:00:00", + }, + Rating: &RIRate{ + ConnectFee: 0, + RoundingMethod: "*up", + RoundingDecimals: 6, + Rates: RateGroups{ + &Rate{Value: 1, RateIncrement: 1 * time.Second, RateUnit: 1 * time.Second}, + }, + }, + }, + }, + }, + }, + } + + //log.Print("=============================") + timespans := cd.splitInTimeSpans() + if len(timespans) != 2 { + t.Log(cd.RatingInfos) + t.Error("Wrong number of timespans: ", len(timespans)) + } + if timespans[0].RateInterval == nil || + timespans[0].RateInterval.Timing.StartTime != "00:00:00" || + timespans[1].RateInterval == nil || + timespans[1].RateInterval.Timing.StartTime != "08:00:00" { + t.Errorf("Error setting rateinterval: %+v %+v", timespans[0].RateInterval.Timing.StartTime, timespans[1].RateInterval.Timing.StartTime) + } +} + func TestSplitSpansRoundToIncrements(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) diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go index 6193cdebd..c8be32613 100644 --- a/engine/ratingprofile.go +++ b/engine/ratingprofile.go @@ -108,17 +108,8 @@ func (ris RatingInfos) Sort() { } func (ris RatingInfos) String() string { - result := "Rating Infos:\n" - for _, ri := range ris { - result += fmt.Sprintf("%+v\n", ri) - result += "Rate Intervals:\n" - for _, interval := range ri.RateIntervals { - result += fmt.Sprintf("%+v\n", interval.Timing) - result += fmt.Sprintf("%+v\n", interval.Rating) - result += fmt.Sprintf("%+v\n", interval.Weight) - } - } - return result + b, _ := json.MarshalIndent(ris, "", " ") + return string(b) } func (rp *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error) { diff --git a/engine/timespans.go b/engine/timespans.go index 0ff4a0b71..beb311042 100644 --- a/engine/timespans.go +++ b/engine/timespans.go @@ -331,8 +331,9 @@ The interval will attach itself to the timespan that overlaps the interval. */ func (ts *TimeSpan) SplitByRateInterval(i *RateInterval, data bool) (nts *TimeSpan) { // if the span is not in interval return nil + //log.Printf("Checking: %+v (%v,%v)", i.Timing, ts.TimeStart, ts.TimeEnd) if !(i.Contains(ts.TimeStart, false) || i.Contains(ts.TimeEnd, true)) { - //Logger.Debug("Not in interval") + //log.Print("Not in interval") return } //Logger.Debug(fmt.Sprintf("TS: %+v", ts)) @@ -374,7 +375,7 @@ func (ts *TimeSpan) SplitByRateInterval(i *RateInterval, data bool) (nts *TimeSp } // if only the start time is in the interval split the interval to the right if i.Contains(ts.TimeStart, false) { - //Logger.Debug("Start in interval") + //log.Print("Start in interval") splitTime := i.getRightMargin(ts.TimeStart) ts.SetRateInterval(i) @@ -394,7 +395,7 @@ func (ts *TimeSpan) SplitByRateInterval(i *RateInterval, data bool) (nts *TimeSp } // if only the end time is in the interval split the interval to the left if i.Contains(ts.TimeEnd, true) { - //Logger.Debug("End in interval") + //log.Print("End in interval") //tmpTime := time.Date(ts.TimeStart.) splitTime := i.getLeftMargin(ts.TimeEnd) splitTime = utils.CopyHour(splitTime, ts.TimeStart) @@ -538,3 +539,29 @@ func (ts *TimeSpan) AddIncrement(inc *Increment) { ts.Increments = append(ts.Increments, inc) ts.TimeEnd.Add(inc.Duration) } + +func (ts *TimeSpan) hasBetterRateIntervalThan(interval *RateInterval) bool { + if ts.RateInterval == nil { + return false + } + //log.Print("StartTime: ", ts.TimeStart) + //log.Printf("OWN: %+v", ts.RateInterval.Timing) + //log.Printf("OTHER: %+v", interval.Timing) + if ts.RateInterval != nil && + ts.RateInterval.Weight < interval.Weight { + return true + } + // check interval is closer + ownLeftMargin := ts.RateInterval.getLeftMargin(ts.TimeStart) + otherLeftMargin := interval.getLeftMargin(ts.TimeStart) + ownDistance := ts.TimeStart.Sub(ownLeftMargin) + otherDistance := ts.TimeStart.Sub(otherLeftMargin) + endOtherDistance := ts.TimeEnd.Sub(otherLeftMargin) + if otherDistance < 0 && endOtherDistance < 0 { + return true + } + if ownDistance <= otherDistance { + return true + } + return false +} diff --git a/engine/timespans_test.go b/engine/timespans_test.go index 35baf8be5..57539eb7d 100644 --- a/engine/timespans_test.go +++ b/engine/timespans_test.go @@ -1597,3 +1597,87 @@ func TestTSMultipleCompressDecompress(t *testing.T) { t.Error("Error decompressing timespans: ", tss[0].Increments) } } + +func TestTSBetterIntervalZero(t *testing.T) { + ts := &TimeSpan{ + TimeStart: time.Date(2015, 4, 27, 8, 0, 0, 0, time.UTC), + RateInterval: &RateInterval{Timing: &RITiming{StartTime: "08:00:00"}}, + } + + interval := &RateInterval{Timing: &RITiming{StartTime: "00:00:00"}} + if !ts.hasBetterRateIntervalThan(interval) { + t.Error("Wrong better rate interval!") + } +} + +func TestTSBetterIntervalBefore(t *testing.T) { + ts := &TimeSpan{ + TimeStart: time.Date(2015, 4, 27, 8, 0, 0, 0, time.UTC), + RateInterval: &RateInterval{Timing: &RITiming{StartTime: "08:00:00"}}, + } + + interval := &RateInterval{Timing: &RITiming{StartTime: "07:00:00"}} + if !ts.hasBetterRateIntervalThan(interval) { + t.Error("Wrong better rate interval!") + } +} + +func TestTSBetterIntervalEqual(t *testing.T) { + ts := &TimeSpan{ + TimeStart: time.Date(2015, 4, 27, 8, 0, 0, 0, time.UTC), + RateInterval: &RateInterval{Timing: &RITiming{StartTime: "08:00:00"}}, + } + + interval := &RateInterval{Timing: &RITiming{StartTime: "08:00:00"}} + if !ts.hasBetterRateIntervalThan(interval) { + t.Error("Wrong better rate interval!") + } +} + +func TestTSBetterIntervalAfter(t *testing.T) { + ts := &TimeSpan{ + TimeStart: time.Date(2015, 4, 27, 8, 0, 0, 0, time.UTC), + RateInterval: &RateInterval{Timing: &RITiming{StartTime: "08:00:00"}}, + } + + interval := &RateInterval{Timing: &RITiming{StartTime: "13:00:00"}} + if !ts.hasBetterRateIntervalThan(interval) { + t.Error("Wrong better rate interval!") + } +} + +func TestTSBetterIntervalBetter(t *testing.T) { + ts := &TimeSpan{ + TimeStart: time.Date(2015, 4, 27, 8, 0, 0, 0, time.UTC), + RateInterval: &RateInterval{Timing: &RITiming{StartTime: "00:00:00"}}, + } + + interval := &RateInterval{Timing: &RITiming{StartTime: "08:00:00"}} + if ts.hasBetterRateIntervalThan(interval) { + t.Error("Wrong better rate interval!") + } +} + +func TestTSBetterIntervalBetterHour(t *testing.T) { + ts := &TimeSpan{ + TimeStart: time.Date(2015, 4, 27, 8, 0, 0, 0, time.UTC), + RateInterval: &RateInterval{Timing: &RITiming{StartTime: "00:00:00"}}, + } + + interval := &RateInterval{Timing: &RITiming{StartTime: "06:00:00"}} + if ts.hasBetterRateIntervalThan(interval) { + t.Error("Wrong better rate interval!") + } +} + +func TestTSBetterIntervalAgainAfter(t *testing.T) { + ts := &TimeSpan{ + TimeStart: time.Date(2015, 4, 27, 8, 0, 0, 0, time.UTC), + RateInterval: &RateInterval{Timing: &RITiming{StartTime: "00:00:00"}}, + } + + interval := &RateInterval{Timing: &RITiming{StartTime: "13:00:00"}} + if !ts.hasBetterRateIntervalThan(interval) { + t.Error("Wrong better rate interval!") + } +} diff --git a/utils/coreutils.go b/utils/coreutils.go index e9078c574..10e329701 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -373,3 +373,8 @@ func ReflectFuncLocation(handler interface{}) (file string, line int) { entry := f.Entry() return f.FileLine(entry) } + +func PrintFull(v interface{}) { + b, _ := json.MarshalIndent(v, "", " ") + log.Print(string(b)) +}