From 42718617b93d9dc1a74919cfb177450360e601e7 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 24 Apr 2014 20:01:20 +0300 Subject: [PATCH] data get cost --- engine/calldesc.go | 17 ++++++++---- engine/calldesc_test.go | 54 ++++++++++++++++++++++++++++++++++----- engine/loader_csv_test.go | 17 ++++++------ engine/timespans.go | 3 +-- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/engine/calldesc.go b/engine/calldesc.go index 356417ee7..0966c9adc 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -116,6 +116,7 @@ type CallDescriptor struct { FallbackSubject string // the subject to check for destination if not found on primary subject RatingInfos RatingInfos Increments Increments + Amount float64 account *Account } @@ -296,10 +297,9 @@ func (cd *CallDescriptor) GetKey(subject string) string { } // Splits the received timespan into sub time spans according to the activation periods intervals. -func (cd *CallDescriptor) splitInTimeSpans(firstSpan *TimeSpan) (timespans []*TimeSpan) { - if firstSpan == nil { - firstSpan = &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cd.TimeEnd, CallDuration: cd.CallDuration} - } +func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { + firstSpan := &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cd.TimeEnd, CallDuration: cd.CallDuration} + timespans = append(timespans, firstSpan) if len(cd.RatingInfos) == 0 { return @@ -327,6 +327,12 @@ func (cd *CallDescriptor) splitInTimeSpans(firstSpan *TimeSpan) (timespans []*Ti } } } + if cd.Amount > 0 { + cd.TimeEnd = cd.TimeStart.Add(time.Duration(utils.Round(cd.Amount, 0, utils.ROUNDING_UP)) * time.Second) + cd.CallDuration = cd.TimeEnd.Sub(cd.TimeStart) + //first span should be still the only one + firstSpan.TimeStart, firstSpan.TimeEnd, firstSpan.CallDuration = cd.TimeStart, cd.TimeEnd, cd.CallDuration + } // Logger.Debug(fmt.Sprintf("After SplitByRatingPlan: %+v", timespans)) // split on price intervals for i := 0; i < len(timespans); i++ { @@ -402,7 +408,8 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) { Logger.Err(fmt.Sprintf("error getting cost for key %s: %v", cd.GetKey(cd.Subject), err)) return &CallCost{Cost: -1}, err } - timespans := cd.splitInTimeSpans(nil) + + timespans := cd.splitInTimeSpans() cost := 0.0 for i, ts := range timespans { diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index d19611387..c43019d4b 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -93,7 +93,7 @@ func TestSplitSpans(t *testing.T) { cd := &CallDescriptor{Direction: "*out", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} cd.LoadRatingPlans() - timespans := cd.splitInTimeSpans(nil) + timespans := cd.splitInTimeSpans() if len(timespans) != 2 { t.Log(cd.RatingInfos) t.Error("Wrong number of timespans: ", len(timespans)) @@ -106,7 +106,7 @@ func TestSplitSpansRoundToIncrements(t *testing.T) { cd := &CallDescriptor{Direction: "*out", TOR: "0", Tenant: "test", Subject: "trp", Destination: "0256", TimeStart: t1, TimeEnd: t2, CallDuration: 132 * time.Second} cd.LoadRatingPlans() - timespans := cd.splitInTimeSpans(nil) + timespans := cd.splitInTimeSpans() if len(timespans) != 2 { t.Logf("%+v", cd) t.Log(cd.RatingInfos) @@ -649,16 +649,56 @@ func TestMaxDebitConsumesMinutes(t *testing.T) { func TestCDGetCostANY(t *testing.T) { cd1 := &CallDescriptor{ Direction: "*out", - TOR: "0", - Tenant: "vdf", + TOR: "data", + Tenant: "cgrates.org", Subject: "rif", Destination: utils.ANY, TimeStart: time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC), - TimeEnd: time.Date(2014, 3, 4, 6, 0, 5, 0, time.UTC), + TimeEnd: time.Date(2014, 3, 4, 6, 0, 1, 0, time.UTC), LoopIndex: 0, CallDuration: 0} cc, err := cd1.GetCost() - if err != nil || cc.Cost != 6 { + if err != nil || cc.Cost != 60 { + t.Errorf("Error getting *any dest: %+v %v", cc, err) + } +} + +func TestCDSplitInDataSlots(t *testing.T) { + cd := &CallDescriptor{ + Direction: "*out", + TOR: "data", + Tenant: "cgrates.org", + Subject: "rif", + Destination: utils.ANY, + TimeStart: time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC), + TimeEnd: time.Date(2014, 3, 4, 6, 0, 1, 0, time.UTC), + LoopIndex: 0, + CallDuration: 0, + Amount: 65, + } + cd.LoadRatingPlans() + timespans := cd.splitInTimeSpans() + if len(timespans) != 2 { + t.Log(cd.RatingInfos[0]) + t.Error("Wrong number of timespans: ", len(timespans)) + } +} + +func TestCDDataGetCost(t *testing.T) { + cd := &CallDescriptor{ + Direction: "*out", + TOR: "data", + Tenant: "cgrates.org", + Subject: "rif", + Destination: utils.ANY, + TimeStart: time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC), + TimeEnd: time.Date(2014, 3, 4, 6, 0, 1, 0, time.UTC), + LoopIndex: 0, + CallDuration: 0, + Amount: 65, + } + cc, err := cd.GetCost() + if err != nil || cc.Cost != 65 { t.Errorf("Error getting *any dest: %+v %v", cc, err) } } @@ -705,7 +745,7 @@ func BenchmarkSplitting(b *testing.B) { cd.LoadRatingPlans() b.StartTimer() for i := 0; i < b.N; i++ { - cd.splitInTimeSpans(nil) + cd.splitInTimeSpans() } } diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 2cfa863cc..0ffbd09a9 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -61,8 +61,8 @@ R2,0,0.1,60s,1s,0,*middle,2 R3,0,0.05,60s,1s,0,*middle,2 R4,1,1,1s,1s,0,*up,2 R5,0,0.5,1s,1s,0,*down,2 -LANDLINE_OFFPEAK,0,1,1s,60s,0s,*up,4 -LANDLINE_OFFPEAK,0,1,1s,1s,60s,*up,4 +LANDLINE_OFFPEAK,0,1,1,60,0,*up,4 +LANDLINE_OFFPEAK,0,1,1,1,60,*up,4 GBP_71,0.000000,5.55555,1s,1s,0s,*up,4 GBP_72,0.000000,7.77777,1s,1s,0s,*up,4 GBP_70,0.000000,1,1,1,0,*up,4 @@ -84,7 +84,7 @@ T2,GERMANY_O2,GBP_70 T2,GERMANY_PREMIUM,GBP_71 DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5 -DATA_RATE,*any,R4 +DATA_RATE,*any,LANDLINE_OFFPEAK ` ratingPlans = ` STANDARD,RT_STANDARD,WORKDAYS_00,10 @@ -97,13 +97,13 @@ DEFAULT,RT_DEFAULT,WORKDAYS_00,10 EVENING,P1,WORKDAYS_00,10 EVENING,P2,WORKDAYS_18,10 EVENING,P2,WEEKENDS,10 -EVENING,DATA_RATE,ALWAYS,10 TDRT,T1,WORKDAYS_00,10 TDRT,T2,WORKDAYS_00,10 G,RT_STANDARD,WORKDAYS_00,10 R,P1,WORKDAYS_00,10 RP_UK_Mobile_BIG5_PKG,DR_UK_Mobile_BIG5_PKG,ALWAYS,10 RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10 +RP_DATA,DATA_RATE,ALWAYS,10 ` ratingProfiles = ` CUSTOMER_1,0,*out,rif:from:tm,2012-01-01T00:00:00Z,PREMIUM,danb @@ -124,6 +124,7 @@ vdf,0,*out,fallback1,2013-11-18T13:47:00Z,G,fallback2 vdf,0,*out,fallback2,2013-11-18T13:45:00Z,R,rif cgrates.org,call,*out,*any,2013-01-06T00:00:00Z,RP_UK, cgrates.org,call,*out,discounted_minutes,2013-01-06T00:00:00Z,RP_UK_Mobile_BIG5_PKG, +cgrates.org,data,*out,rif,2013-01-06T00:00:00Z,RP_DATA, ` sharedGroups = ` SG1,*any,*lowest, @@ -345,7 +346,7 @@ func TestLoadRates(t *testing.T) { t.Error("Error loading rate: ", rate) } rate = csvr.rates["LANDLINE_OFFPEAK"].RateSlots[0] - if expctRs, err = utils.NewRateSlot(0, 1, "1s", "60s", "0s", utils.ROUNDING_UP, 4); err != nil { + if expctRs, err = utils.NewRateSlot(0, 1, "1", "60", "0", utils.ROUNDING_UP, 4); err != nil { t.Error("Error loading rate: ", rate, err.Error()) } else if !reflect.DeepEqual(rate, expctRs) || rate.RateUnitDuration() != expctRs.RateUnitDuration() || @@ -354,7 +355,7 @@ func TestLoadRates(t *testing.T) { t.Error("Error loading rate: ", rate) } rate = csvr.rates["LANDLINE_OFFPEAK"].RateSlots[1] - if expctRs, err = utils.NewRateSlot(0, 1, "1s", "1s", "60s", utils.ROUNDING_UP, 4); err != nil { + if expctRs, err = utils.NewRateSlot(0, 1, "1", "1", "60", utils.ROUNDING_UP, 4); err != nil { t.Error("Error loading rate: ", rate, err.Error()) } else if !reflect.DeepEqual(rate, expctRs) || rate.RateUnitDuration() != expctRs.RateUnitDuration() || @@ -477,7 +478,7 @@ func TestLoadDestinationRates(t *testing.T) { } func TestLoadRatingPlans(t *testing.T) { - if len(csvr.ratingPlans) != 9 { + if len(csvr.ratingPlans) != 10 { t.Error("Failed to load rating plans: ", len(csvr.ratingPlans)) } rplan := csvr.ratingPlans["STANDARD"] @@ -597,7 +598,7 @@ func TestLoadRatingPlans(t *testing.T) { } func TestLoadRatingProfiles(t *testing.T) { - if len(csvr.ratingProfiles) != 14 { + if len(csvr.ratingProfiles) != 15 { t.Error("Failed to load rating profiles: ", len(csvr.ratingProfiles), csvr.ratingProfiles) } rp := csvr.ratingProfiles["*out:test:0:trp"] diff --git a/engine/timespans.go b/engine/timespans.go index f54026028..6328a4a43 100644 --- a/engine/timespans.go +++ b/engine/timespans.go @@ -317,7 +317,6 @@ a new timespan starting from the end of the received one. The interval will attach itself to the timespan that overlaps the interval. */ func (ts *TimeSpan) SplitByRateInterval(i *RateInterval) (nts *TimeSpan) { - //Logger.Debug("here: ", ts, " +++ ", i) // if the span is not in interval return nil if !(i.Contains(ts.TimeStart, false) || i.Contains(ts.TimeEnd, true)) { //Logger.Debug("Not in interval") @@ -328,7 +327,7 @@ func (ts *TimeSpan) SplitByRateInterval(i *RateInterval) (nts *TimeSpan) { if i.Rating != nil { i.Rating.Rates.Sort() for _, rate := range i.Rating.Rates { - // Logger.Debug(fmt.Sprintf("Rate: %+v", rate)) + //Logger.Debug(fmt.Sprintf("Rate: %+v", rate)) if ts.GetGroupStart() < rate.GroupIntervalStart && ts.GetGroupEnd() > rate.GroupIntervalStart { // Logger.Debug(fmt.Sprintf("Splitting")) ts.SetRateInterval(i)