diff --git a/engine/action_timing.go b/engine/action_timing.go
index 9b9729a57..c29096c27 100644
--- a/engine/action_timing.go
+++ b/engine/action_timing.go
@@ -34,15 +34,14 @@ const (
)
type ActionTiming struct {
- Id string // uniquely identify the timing
- Tag string // informative purpose only
- UserBalanceIds []string
- Timing *RateInterval
- Weight float64
- ActionsId string
- actions Actions
- stCache time.Time // cached time of the next start
- ActionsTag, TimingsTag string // used only for loading
+ Id string // uniquely identify the timing
+ Tag string // informative purpose only
+ UserBalanceIds []string
+ Timing *RateInterval
+ Weight float64
+ ActionsId string
+ actions Actions
+ stCache time.Time // cached time of the next start
}
type ActionTimings []*ActionTiming
diff --git a/engine/actions_test.go b/engine/actions_test.go
index 26ea65ec9..958b7626b 100644
--- a/engine/actions_test.go
+++ b/engine/actions_test.go
@@ -86,7 +86,7 @@ func TestActionTimingOnlyMonthdays(t *testing.T) {
now := time.Now()
y, m, d := now.Date()
tomorrow := time.Date(y, m, d, 0, 0, 0, 0, time.Local).AddDate(0, 0, 1)
- at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{MonthDays: MonthDays{1, 25, 2, tomorrow.Day()}}}}
+ at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{1, 25, 2, tomorrow.Day()}}}}
st := at.GetNextStartTime()
expected := tomorrow
if !st.Equal(expected) {
@@ -103,7 +103,7 @@ func TestActionTimingHourMonthdays(t *testing.T) {
if now.After(testTime) {
day = tomorrow.Day()
}
- at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{MonthDays: MonthDays{now.Day(), tomorrow.Day()}, StartTime: "10:01:00"}}}
+ at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()}, StartTime: "10:01:00"}}}
st := at.GetNextStartTime()
expected := time.Date(y, m, day, 10, 1, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -115,7 +115,7 @@ func TestActionTimingOnlyMonths(t *testing.T) {
now := time.Now()
y, m, d := now.Date()
nextMonth := time.Date(y, m, d, 0, 0, 0, 0, time.Local).AddDate(0, 1, 0)
- at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Months: Months{time.February, time.May, nextMonth.Month()}}}}
+ at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Months: utils.Months{time.February, time.May, nextMonth.Month()}}}}
st := at.GetNextStartTime()
expected := time.Date(y, nextMonth.Month(), 1, 0, 0, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -132,7 +132,7 @@ func TestActionTimingHourMonths(t *testing.T) {
if now.After(testTime) {
month = nextMonth.Month()
}
- at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Months: Months{now.Month(), nextMonth.Month()}, StartTime: "10:01:00"}}}
+ at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Months: utils.Months{now.Month(), nextMonth.Month()}, StartTime: "10:01:00"}}}
st := at.GetNextStartTime()
expected := time.Date(y, month, d, 10, 1, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -159,8 +159,8 @@ func TestActionTimingHourMonthdaysMonths(t *testing.T) {
}
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
- Months: Months{now.Month(), nextMonth.Month()},
- MonthDays: MonthDays{now.Day(), tomorrow.Day()},
+ Months: utils.Months{now.Month(), nextMonth.Month()},
+ MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()},
StartTime: "10:01:00",
},
}}
@@ -177,8 +177,8 @@ func TestActionTimingFirstOfTheMonth(t *testing.T) {
nextMonth := time.Date(y, m, 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, 0)
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
- Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
+ MonthDays: utils.MonthDays{1},
},
}}
st := at.GetNextStartTime()
@@ -192,7 +192,7 @@ func TestActionTimingOnlyYears(t *testing.T) {
now := time.Now()
y, m, d := now.Date()
nextYear := time.Date(y, m, d, 0, 0, 0, 0, time.Local).AddDate(1, 0, 0)
- at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: Years{now.Year(), nextYear.Year()}}}}
+ at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{now.Year(), nextYear.Year()}}}}
st := at.GetNextStartTime()
expected := time.Date(nextYear.Year(), 1, 1, 0, 0, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -209,7 +209,7 @@ func TestActionTimingHourYears(t *testing.T) {
if now.After(testTime) {
year = nextYear.Year()
}
- at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: Years{now.Year(), nextYear.Year()}, StartTime: "10:01:00"}}}
+ at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{now.Year(), nextYear.Year()}, StartTime: "10:01:00"}}}
st := at.GetNextStartTime()
expected := time.Date(year, m, d, 10, 1, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -236,8 +236,8 @@ func TestActionTimingHourMonthdaysYear(t *testing.T) {
}
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
- Years: Years{now.Year(), nextYear.Year()},
- MonthDays: MonthDays{now.Day(), tomorrow.Day()},
+ Years: utils.Years{now.Year(), nextYear.Year()},
+ MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()},
StartTime: "10:01:00",
},
}}
@@ -275,9 +275,9 @@ func TestActionTimingHourMonthdaysMonthYear(t *testing.T) {
}
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
- Years: Years{now.Year(), nextYear.Year()},
- Months: Months{now.Month(), nextMonth.Month()},
- MonthDays: MonthDays{now.Day(), tomorrow.Day()},
+ Years: utils.Years{now.Year(), nextYear.Year()},
+ Months: utils.Months{now.Month(), nextMonth.Month()},
+ MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()},
StartTime: "10:01:00",
},
}}
@@ -294,9 +294,9 @@ func TestActionTimingFirstOfTheYear(t *testing.T) {
nextYear := time.Date(y, 1, 1, 0, 0, 0, 0, time.Local).AddDate(1, 0, 0)
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
- Years: Years{nextYear.Year()},
- Months: Months{time.January},
- MonthDays: MonthDays{1},
+ Years: utils.Years{nextYear.Year()},
+ Months: utils.Months{time.January},
+ MonthDays: utils.MonthDays{1},
StartTime: "00:00:00",
},
}}
@@ -313,7 +313,7 @@ func TestActionTimingFirstMonthOfTheYear(t *testing.T) {
nextYear := time.Date(y, 1, 1, 0, 0, 0, 0, time.Local).AddDate(1, 0, 0)
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
- Months: Months{time.January},
+ Months: utils.Months{time.January},
},
}}
st := at.GetNextStartTime()
@@ -367,18 +367,18 @@ func TestActionTimingLogFunction(t *testing.T) {
func TestActionTimingPriotityListSortByWeight(t *testing.T) {
at1 := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
- Years: Years{2100},
- Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
- MonthDays: MonthDays{1},
+ Years: utils.Years{2100},
+ Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
+ MonthDays: utils.MonthDays{1},
StartTime: "00:00:00",
},
Weight: 20,
}}
at2 := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
- Years: Years{2100},
- Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
- MonthDays: MonthDays{2},
+ Years: utils.Years{2100},
+ Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
+ MonthDays: utils.MonthDays{2},
StartTime: "00:00:00",
},
Weight: 10,
@@ -395,8 +395,8 @@ func TestActionTimingPriotityListWeight(t *testing.T) {
at1 := &ActionTiming{
Timing: &RateInterval{
Timing: &RITiming{
- Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
+ MonthDays: utils.MonthDays{1},
StartTime: "00:00:00",
},
},
@@ -405,8 +405,8 @@ func TestActionTimingPriotityListWeight(t *testing.T) {
at2 := &ActionTiming{
Timing: &RateInterval{
Timing: &RITiming{
- Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
+ MonthDays: utils.MonthDays{1},
StartTime: "00:00:00",
},
},
@@ -871,9 +871,9 @@ func TestActionTriggerLogging(t *testing.T) {
func TestActionTimingLogging(t *testing.T) {
i := &RateInterval{
Timing: &RITiming{
- Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
- MonthDays: MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
- WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
+ Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
+ MonthDays: utils.MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
+ WeekDays: utils.WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
StartTime: "18:00:00",
EndTime: "00:00:00",
},
diff --git a/engine/calldesc.go b/engine/calldesc.go
index 2b21e40b5..6259016e3 100644
--- a/engine/calldesc.go
+++ b/engine/calldesc.go
@@ -161,13 +161,15 @@ func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int
if err != nil || rp == nil {
return err
}
- if err = rp.GetRatingPlansForPrefix(cd); err != nil {
+ if err = rp.GetRatingPlansForPrefix(cd); err != nil || !cd.continousRatingInfos() {
// try rating profile fallback
- if len(rp.FallbackKeys) > 0 {
- recursionDepth++
- for _, fbk := range rp.FallbackKeys {
- if err := cd.getRatingPlansForPrefix(fbk, recursionDepth); err == nil {
- return err
+ for _, ri := range cd.RatingInfos {
+ if len(ri.FallbackKeys) > 0 {
+ recursionDepth++
+ for _, fbk := range ri.FallbackKeys {
+ if err := cd.getRatingPlansForPrefix(fbk, recursionDepth); err == nil {
+ return err
+ }
}
}
}
diff --git a/engine/dateseries.go b/engine/dateseries.go
deleted file mode 100644
index fca2cc4b1..000000000
--- a/engine/dateseries.go
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
-Rating system designed to be used in VoIP Carriers World
-Copyright (C) 2013 ITsysCOM
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see
-*/
-
-package engine
-
-import (
- "fmt"
- "sort"
- "strconv"
- "strings"
- "time"
-)
-
-// Defines years days series
-type Years []int
-
-func (ys Years) Sort() {
- sort.Sort(ys)
-}
-
-func (ys Years) Len() int {
- return len(ys)
-}
-
-func (ys Years) Swap(i, j int) {
- ys[i], ys[j] = ys[j], ys[i]
-}
-
-func (ys Years) Less(j, i int) bool {
- return ys[j] < ys[i]
-}
-
-// Return true if the specified date is inside the series
-func (ys Years) Contains(year int) (result bool) {
- result = false
- for _, yss := range ys {
- if yss == year {
- result = true
- break
- }
- }
- return
-}
-
-// Parse Years elements from string separated by sep.
-func (ys *Years) Parse(input, sep string) {
- switch input {
- case "*any", "":
- *ys = []int{}
- default:
- elements := strings.Split(input, sep)
- for _, yss := range elements {
- if year, err := strconv.Atoi(yss); err == nil {
- *ys = append(*ys, year)
- }
- }
- }
-}
-
-func (ys Years) Serialize(sep string) string {
- if len(ys) == 0 {
- return "*any"
- }
- var yStr string
- for idx, yr := range ys {
- if idx != 0 {
- yStr = fmt.Sprintf("%s%s%d", yStr, sep, yr)
- } else {
- yStr = strconv.Itoa(yr)
- }
- }
- return yStr
-}
-
-// Defines months series
-type Months []time.Month
-
-func (m Months) Sort() {
- sort.Sort(m)
-}
-
-func (m Months) Len() int {
- return len(m)
-}
-
-func (m Months) Swap(i, j int) {
- m[i], m[j] = m[j], m[i]
-}
-
-func (m Months) Less(j, i int) bool {
- return m[j] < m[i]
-}
-
-// Return true if the specified date is inside the series
-func (m Months) Contains(month time.Month) (result bool) {
- for _, ms := range m {
- if ms == month {
- result = true
- break
- }
- }
- return
-}
-
-// Loades Month elemnents from a string separated by sep.
-func (m *Months) Parse(input, sep string) {
- switch input {
- case "*any", "": // Apier cannot receive empty string, hence using meta-tag
- *m = []time.Month{}
- default:
- elements := strings.Split(input, sep)
- for _, ms := range elements {
- if month, err := strconv.Atoi(ms); err == nil {
- *m = append(*m, time.Month(month))
- }
- }
- }
-}
-
-// Dumps the months in a serialized string, similar to the one parsed
-func (m Months) Serialize(sep string) string {
- if len(m) == 0 {
- return "*any"
- }
- var mStr string
- for idx, mt := range m {
- if idx != 0 {
- mStr = fmt.Sprintf("%s%s%d", mStr, sep, mt)
- } else {
- mStr = strconv.Itoa(int(mt))
- }
- }
- return mStr
-}
-
-// Defines month days series
-type MonthDays []int
-
-func (md MonthDays) Sort() {
- sort.Sort(md)
-}
-
-func (md MonthDays) Len() int {
- return len(md)
-}
-
-func (md MonthDays) Swap(i, j int) {
- md[i], md[j] = md[j], md[i]
-}
-
-func (md MonthDays) Less(j, i int) bool {
- return md[j] < md[i]
-}
-
-// Return true if the specified date is inside the series
-func (md MonthDays) Contains(monthDay int) (result bool) {
- result = false
- for _, mds := range md {
- if mds == monthDay {
- result = true
- break
- }
- }
- return
-}
-
-// Parse MonthDay elements from string separated by sep.
-func (md *MonthDays) Parse(input, sep string) {
- switch input {
- case "*any", "":
- *md = []int{}
- default:
- elements := strings.Split(input, sep)
- for _, mds := range elements {
- if day, err := strconv.Atoi(mds); err == nil {
- *md = append(*md, day)
- }
- }
- }
-}
-
-// Dumps the month days in a serialized string, similar to the one parsed
-func (md MonthDays) Serialize(sep string) string {
- if len(md) == 0 {
- return "*any"
- }
- var mdsStr string
- for idx, mDay := range md {
- if idx != 0 {
- mdsStr = fmt.Sprintf("%s%s%d", mdsStr, sep, mDay)
- } else {
- mdsStr = strconv.Itoa(mDay)
- }
- }
- return mdsStr
-}
-
-// Defines week days series
-type WeekDays []time.Weekday
-
-func (wd WeekDays) Sort() {
- sort.Sort(wd)
-}
-
-func (wd WeekDays) Len() int {
- return len(wd)
-}
-
-func (wd WeekDays) Swap(i, j int) {
- wd[i], wd[j] = wd[j], wd[i]
-}
-
-func (wd WeekDays) Less(j, i int) bool {
- return wd[j] < wd[i]
-}
-
-// Return true if the specified date is inside the series
-func (wd WeekDays) Contains(weekDay time.Weekday) (result bool) {
- result = false
- for _, wds := range wd {
- if wds == weekDay {
- result = true
- break
- }
- }
- return
-}
-
-func (wd *WeekDays) Parse(input, sep string) {
- switch input {
- case "*any", "":
- *wd = []time.Weekday{}
- default:
- elements := strings.Split(input, sep)
- for _, wds := range elements {
- if day, err := strconv.Atoi(wds); err == nil {
- *wd = append(*wd, time.Weekday(day%7)) // %7 for sunday = 7 normalization
- }
- }
- }
-}
-
-// Dumps the week days in a serialized string, similar to the one parsed
-func (wd WeekDays) Serialize(sep string) string {
- if len(wd) == 0 {
- return "*any"
- }
- var wdStr string
- for idx, d := range wd {
- if idx != 0 {
- wdStr = fmt.Sprintf("%s%s%d", wdStr, sep, d)
- } else {
- wdStr = strconv.Itoa(int(d))
- }
- }
- return wdStr
-}
diff --git a/engine/dateseries_test.go b/engine/dateseries_test.go
deleted file mode 100644
index 11c6110ad..000000000
--- a/engine/dateseries_test.go
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
-Rating system designed to be used in VoIP Carriers World
-Copyright (C) 2013 ITsysCOM
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see
-*/
-
-package engine
-
-import (
- "encoding/json"
- "reflect"
- "testing"
- "time"
-)
-
-func TestMonthStoreRestoreJson(t *testing.T) {
- m := Months{5, 6, 7, 8}
- r, _ := json.Marshal(m)
- if string(r) != "[5,6,7,8]" {
- t.Errorf("Error serializing months: %v", string(r))
- }
- o := Months{}
- json.Unmarshal(r, &o)
- if !reflect.DeepEqual(o, m) {
- t.Errorf("Expected %v was %v", m, o)
- }
-}
-
-func TestMonthDayStoreRestoreJson(t *testing.T) {
- md := MonthDays{24, 25, 26}
- r, _ := json.Marshal(md)
- if string(r) != "[24,25,26]" {
- t.Errorf("Error serializing month days: %v", string(r))
- }
- o := MonthDays{}
- json.Unmarshal(r, &o)
- if !reflect.DeepEqual(o, md) {
- t.Errorf("Expected %v was %v", md, o)
- }
-}
-
-func TestWeekDayStoreRestoreJson(t *testing.T) {
- wd := WeekDays{time.Saturday, time.Sunday}
- r, _ := json.Marshal(wd)
- if string(r) != "[6,0]" {
- t.Errorf("Error serializing week days: %v", string(r))
- }
- o := WeekDays{}
- json.Unmarshal(r, &o)
- if !reflect.DeepEqual(o, wd) {
- t.Errorf("Expected %v was %v", wd, o)
- }
-}
-
-func TestYearsSerialize(t *testing.T) {
- ys := &Years{}
- yString := ys.Serialize(";")
- expectString := "*any"
- if expectString != yString {
- t.Errorf("Expected: %s, got: %s", expectString, yString)
- }
- ys2 := &Years{2012}
- yString2 := ys2.Serialize(";")
- expectString2 := "2012"
- if expectString2 != yString2 {
- t.Errorf("Expected: %s, got: %s", expectString2, yString2)
- }
- ys3 := &Years{2013, 2014, 2015}
- yString3 := ys3.Serialize(";")
- expectString3 := "2013;2014;2015"
- if expectString3 != yString3 {
- t.Errorf("Expected: %s, got: %s", expectString3, yString3)
- }
-}
-
-func TestMonthsSerialize(t *testing.T) {
- mths := &Months{}
- mString := mths.Serialize(";")
- expectString := "*any"
- if expectString != mString {
- t.Errorf("Expected: %s, got: %s", expectString, mString)
- }
- mths2 := &Months{time.January}
- mString2 := mths2.Serialize(";")
- expectString2 := "1"
- if expectString2 != mString2 {
- t.Errorf("Expected: %s, got: %s", expectString2, mString2)
- }
- mths3 := &Months{time.January, time.December}
- mString3 := mths3.Serialize(";")
- expectString3 := "1;12"
- if expectString3 != mString3 {
- t.Errorf("Expected: %s, got: %s", expectString3, mString3)
- }
-}
-
-func TestMonthDaysSerialize(t *testing.T) {
- mds := &MonthDays{}
- mdsString := mds.Serialize(";")
- expectString := "*any"
- if expectString != mdsString {
- t.Errorf("Expected: %s, got: %s", expectString, mdsString)
- }
- mds2 := &MonthDays{1}
- mdsString2 := mds2.Serialize(";")
- expectString2 := "1"
- if expectString2 != mdsString2 {
- t.Errorf("Expected: %s, got: %s", expectString2, mdsString2)
- }
- mds3 := &MonthDays{1, 2, 3, 4, 5}
- mdsString3 := mds3.Serialize(";")
- expectString3 := "1;2;3;4;5"
- if expectString3 != mdsString3 {
- t.Errorf("Expected: %s, got: %s", expectString3, mdsString3)
- }
-}
-
-func TestWeekDaysSerialize(t *testing.T) {
- wds := &WeekDays{}
- wdsString := wds.Serialize(";")
- expectString := "*any"
- if expectString != wdsString {
- t.Errorf("Expected: %s, got: %s", expectString, wdsString)
- }
- wds2 := &WeekDays{time.Monday}
- wdsString2 := wds2.Serialize(";")
- expectString2 := "1"
- if expectString2 != wdsString2 {
- t.Errorf("Expected: %s, got: %s", expectString2, wdsString2)
- }
- wds3 := &WeekDays{time.Monday, time.Saturday, time.Sunday}
- wdsString3 := wds3.Serialize(";")
- expectString3 := "1;6;0"
- if expectString3 != wdsString3 {
- t.Errorf("Expected: %s, got: %s", expectString3, wdsString3)
- }
-}
diff --git a/engine/loader_csv.go b/engine/loader_csv.go
index e3447ed66..2759eca48 100644
--- a/engine/loader_csv.go
+++ b/engine/loader_csv.go
@@ -38,9 +38,9 @@ type CSVReader struct {
actionsTriggers map[string][]*ActionTrigger
accountActions []*UserBalance
destinations []*Destination
- timings map[string]*Timing
- rates map[string][]*LoadRate
- destinationRates map[string][]*DestinationRate
+ timings map[string]*utils.TPTiming
+ rates map[string]*utils.TPRate
+ destinationRates map[string]*utils.TPDestinationRate
ratingPlans map[string]*RatingPlan
ratingProfiles map[string]*RatingProfile
// file names
@@ -55,9 +55,9 @@ func NewFileCSVReader(storage DataStorage, sep rune, destinationsFn, timingsFn,
c.actions = make(map[string][]*Action)
c.actionsTimings = make(map[string][]*ActionTiming)
c.actionsTriggers = make(map[string][]*ActionTrigger)
- c.rates = make(map[string][]*LoadRate)
- c.destinationRates = make(map[string][]*DestinationRate)
- c.timings = make(map[string]*Timing)
+ c.rates = make(map[string]*utils.TPRate)
+ c.destinationRates = make(map[string]*utils.TPDestinationRate)
+ c.timings = make(map[string]*utils.TPTiming)
c.ratingPlans = make(map[string]*RatingPlan)
c.ratingProfiles = make(map[string]*RatingProfile)
c.readerFunc = openFileCSVReader
@@ -236,7 +236,7 @@ func (csvr *CSVReader) LoadRates() (err error) {
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
tag := record[0]
- var r *LoadRate
+ var r *utils.TPRate
r, err = NewLoadRate(record[0], record[1], record[2], record[3], record[4], record[5], record[6], record[7])
if err != nil {
return err
@@ -244,11 +244,14 @@ func (csvr *CSVReader) LoadRates() (err error) {
// same tag only to create rate groups
existingRates, exists := csvr.rates[tag]
if exists {
- if err := existingRates[len(existingRates)-1].ValidNextGroup(r); err != nil {
+ rss := existingRates.RateSlots
+ if err := ValidNextGroup(rss[len(rss)-1], r.RateSlots[0]); err != nil {
return err
}
+ csvr.rates[tag].RateSlots = append(csvr.rates[tag].RateSlots, r.RateSlots[0])
+ } else {
+ csvr.rates[tag] = r
}
- csvr.rates[tag] = append(csvr.rates[tag], r)
}
return
}
@@ -283,13 +286,22 @@ func (csvr *CSVReader) LoadDestinationRates() (err error) {
return fmt.Errorf("Could not get destination for tag %v", record[1])
}
}
- dr := &DestinationRate{
- Tag: tag,
- DestinationsTag: record[1],
- rates: r,
+ dr := &utils.TPDestinationRate{
+ DestinationRateId: tag,
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: record[1],
+ Rate: r,
+ },
+ },
}
-
- csvr.destinationRates[tag] = append(csvr.destinationRates[tag], dr)
+ existingDR, exists := csvr.destinationRates[tag]
+ if exists {
+ existingDR.DestinationRates = append(existingDR.DestinationRates, dr.DestinationRates[0])
+ } else {
+ existingDR = dr
+ }
+ csvr.destinationRates[tag] = existingDR
}
return
}
@@ -314,14 +326,14 @@ func (csvr *CSVReader) LoadRatingPlans() (err error) {
if !exists {
return errors.New(fmt.Sprintf("Could not find destination rate for tag %v", record[1]))
}
- drt := NewDestinationRateTiming(t, record[3])
+ rpl := NewRatingPlan(t, record[3])
plan, exists := csvr.ratingPlans[tag]
if !exists {
plan = &RatingPlan{Id: tag}
csvr.ratingPlans[tag] = plan
}
- for _, dr := range drs {
- plan.AddRateInterval(dr.DestinationsTag, drt.GetRateInterval(dr))
+ for _, dr := range drs.DestinationRates {
+ plan.AddRateInterval(dr.DestinationId, GetRateInterval(rpl, dr))
}
}
return
diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go
index 1e1ed0124..3e41256ce 100644
--- a/engine/loader_csv_test.go
+++ b/engine/loader_csv_test.go
@@ -190,45 +190,45 @@ func TestLoadTimimgs(t *testing.T) {
t.Error("Failed to load timings: ", csvr.timings)
}
timing := csvr.timings["WORKDAYS_00"]
- if !reflect.DeepEqual(timing, &Timing{
+ if !reflect.DeepEqual(timing, &utils.TPTiming{
Id: "WORKDAYS_00",
- Years: Years{},
- Months: Months{},
- MonthDays: MonthDays{},
- WeekDays: WeekDays{1, 2, 3, 4, 5},
+ Years: utils.Years{},
+ Months: utils.Months{},
+ MonthDays: utils.MonthDays{},
+ WeekDays: utils.WeekDays{1, 2, 3, 4, 5},
StartTime: "00:00:00",
}) {
t.Error("Error loading timing: ", timing)
}
timing = csvr.timings["WORKDAYS_18"]
- if !reflect.DeepEqual(timing, &Timing{
+ if !reflect.DeepEqual(timing, &utils.TPTiming{
Id: "WORKDAYS_18",
- Years: Years{},
- Months: Months{},
- MonthDays: MonthDays{},
- WeekDays: WeekDays{1, 2, 3, 4, 5},
+ Years: utils.Years{},
+ Months: utils.Months{},
+ MonthDays: utils.MonthDays{},
+ WeekDays: utils.WeekDays{1, 2, 3, 4, 5},
StartTime: "18:00:00",
}) {
t.Error("Error loading timing: ", timing)
}
timing = csvr.timings["WEEKENDS"]
- if !reflect.DeepEqual(timing, &Timing{
+ if !reflect.DeepEqual(timing, &utils.TPTiming{
Id: "WEEKENDS",
- Years: Years{},
- Months: Months{},
- MonthDays: MonthDays{},
- WeekDays: WeekDays{time.Saturday, time.Sunday},
+ Years: utils.Years{},
+ Months: utils.Months{},
+ MonthDays: utils.MonthDays{},
+ WeekDays: utils.WeekDays{time.Saturday, time.Sunday},
StartTime: "00:00:00",
}) {
t.Error("Error loading timing: ", timing)
}
timing = csvr.timings["ONE_TIME_RUN"]
- if !reflect.DeepEqual(timing, &Timing{
+ if !reflect.DeepEqual(timing, &utils.TPTiming{
Id: "ONE_TIME_RUN",
- Years: Years{2012},
- Months: Months{},
- MonthDays: MonthDays{},
- WeekDays: WeekDays{},
+ Years: utils.Years{2012},
+ Months: utils.Months{},
+ MonthDays: utils.MonthDays{},
+ WeekDays: utils.WeekDays{},
StartTime: "*asap",
}) {
t.Error("Error loading timing: ", timing)
@@ -239,24 +239,22 @@ func TestLoadRates(t *testing.T) {
if len(csvr.rates) != 9 {
t.Error("Failed to load rates: ", csvr.rates)
}
- rate := csvr.rates["R1"][0]
- if !reflect.DeepEqual(rate, &LoadRate{
- Tag: "R1",
+ rate := csvr.rates["R1"].RateSlots[0]
+ if !reflect.DeepEqual(rate, &utils.RateSlot{
ConnectFee: 0,
- Price: 0.2,
+ Rate: 0.2,
RateUnit: time.Minute,
RateIncrement: time.Second,
GroupIntervalStart: 0,
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 2,
}) {
- t.Error("Error loading rate: ", csvr.rates["R1"][0])
+ t.Error("Error loading rate: ", csvr.rates["R1"].RateSlots[0])
}
- rate = csvr.rates["R2"][0]
- if !reflect.DeepEqual(rate, &LoadRate{
- Tag: "R2",
+ rate = csvr.rates["R2"].RateSlots[0]
+ if !reflect.DeepEqual(rate, &utils.RateSlot{
ConnectFee: 0,
- Price: 0.1,
+ Rate: 0.1,
RateUnit: time.Minute,
RateIncrement: time.Second,
GroupIntervalStart: 0,
@@ -265,11 +263,10 @@ func TestLoadRates(t *testing.T) {
}) {
t.Error("Error loading rate: ", csvr.rates)
}
- rate = csvr.rates["R3"][0]
- if !reflect.DeepEqual(rate, &LoadRate{
- Tag: "R3",
+ rate = csvr.rates["R3"].RateSlots[0]
+ if !reflect.DeepEqual(rate, &utils.RateSlot{
ConnectFee: 0,
- Price: 0.05,
+ Rate: 0.05,
RateUnit: time.Minute,
RateIncrement: time.Second,
GroupIntervalStart: 0,
@@ -278,11 +275,10 @@ func TestLoadRates(t *testing.T) {
}) {
t.Error("Error loading rate: ", csvr.rates)
}
- rate = csvr.rates["R4"][0]
- if !reflect.DeepEqual(rate, &LoadRate{
- Tag: "R4",
+ rate = csvr.rates["R4"].RateSlots[0]
+ if !reflect.DeepEqual(rate, &utils.RateSlot{
ConnectFee: 1,
- Price: 1.0,
+ Rate: 1.0,
RateUnit: time.Second,
RateIncrement: time.Second,
GroupIntervalStart: 0,
@@ -291,11 +287,10 @@ func TestLoadRates(t *testing.T) {
}) {
t.Error("Error loading rate: ", csvr.rates)
}
- rate = csvr.rates["R5"][0]
- if !reflect.DeepEqual(rate, &LoadRate{
- Tag: "R5",
+ rate = csvr.rates["R5"].RateSlots[0]
+ if !reflect.DeepEqual(rate, &utils.RateSlot{
ConnectFee: 0,
- Price: 0.5,
+ Rate: 0.5,
RateUnit: time.Second,
RateIncrement: time.Second,
GroupIntervalStart: 0,
@@ -305,11 +300,10 @@ func TestLoadRates(t *testing.T) {
t.Error("Error loading rate: ", csvr.rates)
}
- rate = csvr.rates["LANDLINE_OFFPEAK"][0]
- if !reflect.DeepEqual(rate, &LoadRate{
- Tag: "LANDLINE_OFFPEAK",
+ rate = csvr.rates["LANDLINE_OFFPEAK"].RateSlots[0]
+ if !reflect.DeepEqual(rate, &utils.RateSlot{
ConnectFee: 0,
- Price: 1,
+ Rate: 1,
RateUnit: time.Second,
RateIncrement: time.Minute,
GroupIntervalStart: 0,
@@ -318,11 +312,10 @@ func TestLoadRates(t *testing.T) {
}) {
t.Errorf("Error loading rate: %+v", rate)
}
- rate = csvr.rates["LANDLINE_OFFPEAK"][1]
- if !reflect.DeepEqual(rate, &LoadRate{
- Tag: "LANDLINE_OFFPEAK",
+ rate = csvr.rates["LANDLINE_OFFPEAK"].RateSlots[1]
+ if !reflect.DeepEqual(rate, &utils.RateSlot{
ConnectFee: 0,
- Price: 1,
+ Rate: 1,
RateUnit: time.Second,
RateIncrement: time.Second,
GroupIntervalStart: 60 * time.Second,
@@ -338,96 +331,107 @@ func TestLoadDestinationRates(t *testing.T) {
t.Error("Failed to load destinationrates: ", csvr.destinationRates)
}
drs := csvr.destinationRates["RT_STANDARD"]
- if !reflect.DeepEqual(drs, []*DestinationRate{
- &DestinationRate{
- Tag: "RT_STANDARD",
- DestinationsTag: "GERMANY",
- rates: csvr.rates["R1"],
+ dr := &utils.TPDestinationRate{
+ TPid: "",
+ DestinationRateId: "RT_STANDARD",
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: "GERMANY",
+ Rate: csvr.rates["R1"],
+ },
+ &utils.DestinationRate{
+ DestinationId: "GERMANY_O2",
+ Rate: csvr.rates["R2"],
+ },
+ &utils.DestinationRate{
+ DestinationId: "GERMANY_PREMIUM",
+ Rate: csvr.rates["R2"],
+ },
},
- &DestinationRate{
- Tag: "RT_STANDARD",
- DestinationsTag: "GERMANY_O2",
- rates: csvr.rates["R2"],
- },
- &DestinationRate{
- Tag: "RT_STANDARD",
- DestinationsTag: "GERMANY_PREMIUM",
- rates: csvr.rates["R2"],
- },
- }) {
- t.Error("Error loading destination rate: ", drs)
+ }
+ if !reflect.DeepEqual(drs, dr) {
+ t.Errorf("Error loading destination rate: \n%+v \n%+v", drs, dr)
}
drs = csvr.destinationRates["RT_DEFAULT"]
- if !reflect.DeepEqual(drs, []*DestinationRate{
- &DestinationRate{
- Tag: "RT_DEFAULT",
- DestinationsTag: "ALL",
- rates: csvr.rates["R2"],
+ if !reflect.DeepEqual(drs, &utils.TPDestinationRate{
+ DestinationRateId: "RT_DEFAULT",
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: "ALL",
+ Rate: csvr.rates["R2"],
+ },
},
}) {
- t.Error("Error loading destination rate: ", drs)
+ t.Errorf("Error loading destination rate: %+v", drs)
}
drs = csvr.destinationRates["RT_STD_WEEKEND"]
- if !reflect.DeepEqual(drs, []*DestinationRate{
- &DestinationRate{
- Tag: "RT_STD_WEEKEND",
- DestinationsTag: "GERMANY",
- rates: csvr.rates["R2"],
- },
- &DestinationRate{
- Tag: "RT_STD_WEEKEND",
- DestinationsTag: "GERMANY_O2",
- rates: csvr.rates["R3"],
+ if !reflect.DeepEqual(drs, &utils.TPDestinationRate{
+ DestinationRateId: "RT_STD_WEEKEND",
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: "GERMANY",
+ Rate: csvr.rates["R2"],
+ },
+ &utils.DestinationRate{
+ DestinationId: "GERMANY_O2",
+ Rate: csvr.rates["R3"],
+ },
},
}) {
t.Error("Error loading destination rate: ", drs)
}
drs = csvr.destinationRates["P1"]
- if !reflect.DeepEqual(drs, []*DestinationRate{
- &DestinationRate{
- Tag: "P1",
- DestinationsTag: "NAT",
- rates: csvr.rates["R4"],
+ if !reflect.DeepEqual(drs, &utils.TPDestinationRate{
+ DestinationRateId: "P1",
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: "NAT",
+ Rate: csvr.rates["R4"],
+ },
},
}) {
t.Error("Error loading destination rate: ", drs)
}
drs = csvr.destinationRates["P2"]
- if !reflect.DeepEqual(drs, []*DestinationRate{
- &DestinationRate{
- Tag: "P2",
- DestinationsTag: "NAT",
- rates: csvr.rates["R5"],
+ if !reflect.DeepEqual(drs, &utils.TPDestinationRate{
+ DestinationRateId: "P2",
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: "NAT",
+ Rate: csvr.rates["R5"],
+ },
},
}) {
t.Error("Error loading destination rate: ", drs)
}
drs = csvr.destinationRates["T1"]
- if !reflect.DeepEqual(drs, []*DestinationRate{
- &DestinationRate{
- Tag: "T1",
- DestinationsTag: "NAT",
- rates: csvr.rates["LANDLINE_OFFPEAK"],
+ if !reflect.DeepEqual(drs, &utils.TPDestinationRate{
+ DestinationRateId: "T1",
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: "NAT",
+ Rate: csvr.rates["LANDLINE_OFFPEAK"],
+ },
},
}) {
t.Error("Error loading destination rate: ", drs)
}
drs = csvr.destinationRates["T2"]
- if !reflect.DeepEqual(drs, []*DestinationRate{
- &DestinationRate{
- Tag: "T2",
- DestinationsTag: "GERMANY",
- rates: csvr.rates["GBP_72"],
- },
- &DestinationRate{
- Tag: "T2",
- DestinationsTag: "GERMANY_O2",
- rates: csvr.rates["GBP_70"],
- },
- &DestinationRate{
- Tag: "T2",
- DestinationsTag: "GERMANY_PREMIUM",
- rates: csvr.rates["GBP_71"],
+ if !reflect.DeepEqual(drs, &utils.TPDestinationRate{
+ DestinationRateId: "T2",
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: "GERMANY",
+ Rate: csvr.rates["GBP_72"],
+ },
+ &utils.DestinationRate{
+ DestinationId: "GERMANY_O2",
+ Rate: csvr.rates["GBP_70"],
+ },
+ &utils.DestinationRate{
+ DestinationId: "GERMANY_PREMIUM",
+ Rate: csvr.rates["GBP_71"],
+ },
},
}) {
t.Error("Error loading destination rate: ", drs)
@@ -443,24 +447,24 @@ func TestLoadDestinationRateTimings(t *testing.T) {
Id: "STANDARD",
Timings: map[string]*RITiming{
"14ae6e41": &RITiming{
- Years: Years{},
- Months: Months{},
- MonthDays: MonthDays{},
- WeekDays: WeekDays{1, 2, 3, 4, 5},
+ Years: utils.Years{},
+ Months: utils.Months{},
+ MonthDays: utils.MonthDays{},
+ WeekDays: utils.WeekDays{1, 2, 3, 4, 5},
StartTime: "00:00:00",
},
"9a6f8e32": &RITiming{
- Years: Years{},
- Months: Months{},
- MonthDays: MonthDays{},
- WeekDays: WeekDays{1, 2, 3, 4, 5},
+ Years: utils.Years{},
+ Months: utils.Months{},
+ MonthDays: utils.MonthDays{},
+ WeekDays: utils.WeekDays{1, 2, 3, 4, 5},
StartTime: "18:00:00",
},
"7181e535": &RITiming{
- Years: Years{},
- Months: Months{},
- MonthDays: MonthDays{},
- WeekDays: WeekDays{time.Saturday, time.Sunday},
+ Years: utils.Years{},
+ Months: utils.Months{},
+ MonthDays: utils.MonthDays{},
+ WeekDays: utils.WeekDays{time.Saturday, time.Sunday},
StartTime: "00:00:00",
},
},
@@ -625,10 +629,10 @@ func TestLoadActionTimings(t *testing.T) {
UserBalanceIds: []string{"*out:vdf:minitsboy"},
Timing: &RateInterval{
Timing: &RITiming{
- Years: Years{2012},
- Months: Months{},
- MonthDays: MonthDays{},
- WeekDays: WeekDays{},
+ Years: utils.Years{2012},
+ Months: utils.Months{},
+ MonthDays: utils.MonthDays{},
+ WeekDays: utils.WeekDays{},
StartTime: ASAP,
},
},
diff --git a/engine/loader_db.go b/engine/loader_db.go
index 00c054646..36a246839 100644
--- a/engine/loader_db.go
+++ b/engine/loader_db.go
@@ -34,9 +34,9 @@ type DbReader struct {
actionsTriggers map[string][]*ActionTrigger
accountActions []*UserBalance
destinations []*Destination
- timings map[string]*Timing
- rates map[string][]*LoadRate
- destinationRates map[string][]*DestinationRate
+ timings map[string]*utils.TPTiming
+ rates map[string]*utils.TPRate
+ destinationRates map[string]*utils.TPDestinationRate
ratingPlans map[string]*RatingPlan
ratingProfiles map[string]*RatingProfile
}
@@ -153,15 +153,15 @@ func (dbr *DbReader) LoadDestinationRates() (err error) {
return err
}
for _, drs := range dbr.destinationRates {
- for _, dr := range drs {
- rates, exists := dbr.rates[dr.RateTag]
+ for _, dr := range drs.DestinationRates {
+ rate, exists := dbr.rates[dr.RateId]
if !exists {
- return errors.New(fmt.Sprintf("Could not find rate for tag %v", dr.RateTag))
+ return errors.New(fmt.Sprintf("Could not find rate for tag %v", dr.RateId))
}
- dr.rates = rates
+ dr.Rate = rate
destinationExists := false
for _, d := range dbr.destinations {
- if d.Id == dr.DestinationsTag {
+ if d.Id == dr.DestinationId {
destinationExists = true
break
}
@@ -183,24 +183,24 @@ func (dbr *DbReader) LoadRatingPlans() error {
if err != nil {
return err
}
- for _, drt := range drts {
- t, exists := dbr.timings[drt.TimingTag]
+ for _, drt := range drts.RatingPlans {
+ t, exists := dbr.timings[drt.TimingId]
if !exists {
- return errors.New(fmt.Sprintf("Could not get timing for tag %v", drt.TimingTag))
+ return errors.New(fmt.Sprintf("Could not get timing for tag %v", drt.TimingId))
}
- drt.timing = t
- drs, exists := dbr.destinationRates[drt.DestinationRatesTag]
+ drt.Timing = t
+ drs, exists := dbr.destinationRates[drt.DestRatesId]
if !exists {
- return errors.New(fmt.Sprintf("Could not find destination rate for tag %v", drt.DestinationRatesTag))
+ return errors.New(fmt.Sprintf("Could not find destination rate for tag %v", drt.DestRatesId))
}
- plan, exists := dbr.ratingPlans[drt.Tag]
+ plan, exists := dbr.ratingPlans[drts.RatingPlanId]
if !exists {
- plan = &RatingPlan{Id: drt.Tag}
- dbr.ratingPlans[drt.Tag] = plan
+ plan = &RatingPlan{Id: drts.RatingPlanId}
+ dbr.ratingPlans[drts.RatingPlanId] = plan
}
- for _, dr := range drs {
- plan.AddRateInterval(dr.DestinationsTag, drt.GetRateInterval(dr))
+ for _, dr := range drs.DestinationRates {
+ plan.AddRateInterval(dr.DestinationId, GetRateInterval(drt, dr))
}
}
return nil
@@ -212,11 +212,12 @@ func (dbr *DbReader) LoadRatingProfiles() error {
return err
}
for _, rp := range rpfs {
+ rpf := &RatingProfile{Id: rp.RatingProfileId}
at, err := utils.ParseDate(rp.ActivationTime)
if err != nil {
return errors.New(fmt.Sprintf("Cannot parse activation time from %v", rp.ActivationTime))
}
- _, exists := dbr.ratingPlans[rp.DestRatesTimingTag]
+ _, exists := dbr.ratingPlans[rp.RatingPlanId]
if !exists {
if dbExists, err := dbr.dataDb.ExistsData(RATING_PLAN, rp.DestRatesTimingTag); err != nil {
return err
@@ -224,13 +225,13 @@ func (dbr *DbReader) LoadRatingProfiles() error {
return errors.New(fmt.Sprintf("Could not load rating plans for tag: %v", rp.DestRatesTimingTag))
}
}
- rp.RatingPlanActivations = append(rp.RatingPlanActivations,
+ rpf.RatingPlanActivations = append(rpf.RatingPlanActivations,
&RatingPlanActivation{
ActivationTime: at,
- RatingPlanId: rp.DestRatesTimingTag,
+ RatingPlanId: rp.RatingPlanId,
FallbackKeys: rp.FallbackKeys,
})
- dbr.ratingProfiles[rp.Id] = rp
+ dbr.ratingProfiles[rpf.Id] = rpf
}
return nil
}
@@ -238,31 +239,30 @@ func (dbr *DbReader) LoadRatingProfiles() error {
func (dbr *DbReader) LoadRatingPlanByTag(tag string) error {
ratingPlan := &RatingPlan{}
rps, err := dbr.storDb.GetTpRatingPlans(dbr.tpid, tag)
- if err != nil || len(rps) == 0 {
+ if err != nil || len(rps.RatingPlans) == 0 {
return fmt.Errorf("No DestRateTimings profile with id %s: %v", tag, err)
}
- for _, rp := range rps {
-
+ for _, rp := range rps.RatingPlans {
Logger.Debug(fmt.Sprintf("Rating Plan: %v", rp))
- tm, err := dbr.storDb.GetTpTimings(dbr.tpid, rp.TimingTag)
+ tm, err := dbr.storDb.GetTpTimings(dbr.tpid, rp.TimingId)
Logger.Debug(fmt.Sprintf("Timing: %v", tm))
if err != nil || len(tm) == 0 {
- return fmt.Errorf("No Timings profile with id %s: %v", rp.TimingTag, err)
+ return fmt.Errorf("No Timings profile with id %s: %v", rp.TimingId, err)
}
- rp.timing = tm[rp.TimingTag]
- drm, err := dbr.storDb.GetTpDestinationRates(dbr.tpid, rp.DestinationRatesTag)
+ rp.Timing = tm[rp.TimingId]
+ drm, err := dbr.storDb.GetTpDestinationRates(dbr.tpid, rp.DestRatesId)
if err != nil || len(drm) == 0 {
- return fmt.Errorf("No DestinationRates profile with id %s: %v", rp.DestinationRatesTag, err)
+ return fmt.Errorf("No DestinationRates profile with id %s: %v", rp.DestRatesId, err)
}
- for _, drate := range drm[rp.DestinationRatesTag] {
+ for _, drate := range drm[rp.DestRatesId].DestinationRates {
Logger.Debug(fmt.Sprintf("Destination rate: %v", drate))
- rt, err := dbr.storDb.GetTpRates(dbr.tpid, drate.RateTag)
+ rt, err := dbr.storDb.GetTpRates(dbr.tpid, drate.RateId)
if err != nil || len(rt) == 0 {
- return fmt.Errorf("No Rates profile with id %s: %v", drate.RateTag, err)
+ return fmt.Errorf("No Rates profile with id %s: %v", drate.RateId, err)
}
Logger.Debug(fmt.Sprintf("Rate: %v", rt))
- drate.rates = rt[drate.RateTag]
- ratingPlan.AddRateInterval(drate.DestinationsTag, rp.GetRateInterval(drate))
+ drate.Rate = rt[drate.RateId]
+ ratingPlan.AddRateInterval(drate.DestinationId, GetRateInterval(rp, drate))
dms, err := dbr.storDb.GetTpDestinations(dbr.tpid, drate.DestinationsTag)
if err != nil {
@@ -275,7 +275,7 @@ func (dbr *DbReader) LoadRatingPlanByTag(tag string) error {
}
continue
}
- Logger.Debug(fmt.Sprintf("Tag: %s Destinations: %v", drate.DestinationsTag, dms))
+ Logger.Debug(fmt.Sprintf("Tag: %s Destinations: %v", drate.DestinationId, dms))
for _, destination := range dms {
Logger.Debug(fmt.Sprintf("Destination: %v", destination))
dbr.dataDb.SetDestination(destination)
@@ -287,16 +287,16 @@ func (dbr *DbReader) LoadRatingPlanByTag(tag string) error {
func (dbr *DbReader) LoadRatingProfileByTag(tag string) error {
resultRatingProfile := &RatingProfile{}
- rpm, err := dbr.storDb.GetTpRatingProfiles(dbr.tpid, tag)
- if err != nil || len(rpm) == 0 {
+ rpfs, err := dbr.storDb.GetTpRatingProfiles(dbr.tpid, tag)
+ if err != nil || len(rpfs) == 0 {
return fmt.Errorf("No RateProfile with id %s: %v", tag, err)
}
- for _, ratingProfile := range rpm {
- Logger.Debug(fmt.Sprintf("Rating profile: %v", rpm))
- resultRatingProfile.Id = ratingProfile.Id // idem
- at, err := utils.ParseDate(ratingProfile.ActivationTime)
+ for _, rp := range rpfs {
+ Logger.Debug(fmt.Sprintf("Rating profile: %v", rpfs))
+ resultRatingProfile.Id = rp.RatingProfileId
+ at, err := utils.ParseDate(rp.ActivationTime)
if err != nil {
- return fmt.Errorf("Cannot parse activation time from %v", ratingProfile.ActivationTime)
+ return fmt.Errorf("Cannot parse activation time from %v", rp.ActivationTime)
}
// Check if referenced RatingPlan exists
_, exists := dbr.ratingPlans[ratingProfile.DestRatesTimingTag]
@@ -307,7 +307,7 @@ func (dbr *DbReader) LoadRatingProfileByTag(tag string) error {
return errors.New(fmt.Sprintf("Could not load rating plans for tag: %v", ratingProfile.DestRatesTimingTag))
}
}
- resultRatingProfile.RatingPlanActivations = append(resultRatingProfile.RatingPlanActivations, &RatingPlanActivation{at, ratingProfile.DestRatesTimingTag, ratingProfile.FallbackKeys})
+ resultRatingProfile.RatingPlanActivations = append(resultRatingProfile.RatingPlanActivations, &RatingPlanActivation{at, rp.RatingPlanId, rp.FallbackKeys})
}
return dbr.dataDb.SetRatingProfile(resultRatingProfile)
}
@@ -323,18 +323,18 @@ func (dbr *DbReader) LoadActionTimings() (err error) {
return err
}
for tag, ats := range atsMap {
- for _, at := range ats {
+ for _, at := range ats.ActionTimings {
_, exists := dbr.actions[at.ActionsId]
if !exists {
return errors.New(fmt.Sprintf("ActionTiming: Could not load the action for tag: %v", at.ActionsId))
}
- t, exists := dbr.timings[at.Tag]
+ t, exists := dbr.timings[ats.ActionTimingsId]
if !exists {
- return errors.New(fmt.Sprintf("ActionTiming: Could not load the timing for tag: %v", at.Tag))
+ return errors.New(fmt.Sprintf("ActionTiming: Could not load the timing for tag: %v", ats.ActionTimingsId))
}
actTmg := &ActionTiming{
Id: utils.GenUUID(),
- Tag: at.Tag,
+ Tag: ats.ActionTimingsId,
Weight: at.Weight,
Timing: &RateInterval{
Timing: &RITiming{
@@ -419,23 +419,24 @@ func (dbr *DbReader) LoadAccountActionsByTag(tag string) error {
return fmt.Errorf("No ActionTimings with id <%s>", accountAction.ActionTimingsTag)
}
var actionTimings []*ActionTiming
- for _, at := range actionTimingsMap[accountAction.ActionTimingsTag] {
+ ats := actionTimingsMap[accountAction.ActionTimingsTag]
+ for _, at := range ats.ActionTimings {
existsAction, err := dbr.storDb.ExistsTPActions(dbr.tpid, at.ActionsId)
if err != nil {
return err
} else if !existsAction {
return fmt.Errorf("No Action with id <%s>", at.ActionsId)
}
- timingsMap, err := dbr.storDb.GetTpTimings(dbr.tpid, at.Tag)
+ timingsMap, err := dbr.storDb.GetTpTimings(dbr.tpid, ats.ActionTimingsId)
if err != nil {
return err
} else if len(timingsMap) == 0 {
- return fmt.Errorf("No Timing with id <%s>", at.Tag)
+ return fmt.Errorf("No Timing with id <%s>", ats.ActionTimingsId)
}
- t := timingsMap[at.Tag]
+ t := timingsMap[ats.ActionTimingsId]
actTmg := &ActionTiming{
Id: utils.GenUUID(),
- Tag: at.Tag,
+ Tag: ats.ActionTimingsId,
Weight: at.Weight,
Timing: &RateInterval{
Timing: &RITiming{
@@ -458,7 +459,7 @@ func (dbr *DbReader) LoadAccountActionsByTag(tag string) error {
}
}
if !found {
- at.UserBalanceIds = append(exitingUserBalanceIds, id)
+ actTmg.UserBalanceIds = append(exitingUserBalanceIds, id)
}
actionTimings = append(actionTimings, actTmg)
}
diff --git a/engine/loader_helpers.go b/engine/loader_helpers.go
index 98c7b4e4b..b5b2a8038 100644
--- a/engine/loader_helpers.go
+++ b/engine/loader_helpers.go
@@ -47,15 +47,15 @@ type TPLoader interface {
WriteToDatabase(bool, bool) error
}
-type LoadRate struct {
+/*type LoadRate struct {
Tag string
ConnectFee, Price float64
RateUnit, RateIncrement, GroupIntervalStart time.Duration
RoundingMethod string
RoundingDecimals int
-}
+}*/
-func NewLoadRate(tag, connectFee, price, ratedUnits, rateIncrements, groupInterval, roundingMethod, roundingDecimals string) (r *LoadRate, err error) {
+func NewLoadRate(tag, connectFee, price, ratedUnits, rateIncrements, groupInterval, roundingMethod, roundingDecimals string) (r *utils.TPRate, err error) {
cf, err := strconv.ParseFloat(connectFee, 64)
if err != nil {
log.Printf("Error parsing connect fee from: %v", connectFee)
@@ -87,20 +87,24 @@ func NewLoadRate(tag, connectFee, price, ratedUnits, rateIncrements, groupInterv
return
}
- r = &LoadRate{
- Tag: tag,
- ConnectFee: cf,
- Price: p,
- GroupIntervalStart: gi,
- RateUnit: ru,
- RateIncrement: ri,
- RoundingMethod: roundingMethod,
- RoundingDecimals: rd,
+ r = &utils.TPRate{
+ RateId: tag,
+ RateSlots: []*utils.RateSlot{
+ &utils.RateSlot{
+ ConnectFee: cf,
+ Rate: p,
+ GroupIntervalStart: gi,
+ RateUnit: ru,
+ RateIncrement: ri,
+ RoundingMethod: roundingMethod,
+ RoundingDecimals: rd,
+ },
+ },
}
return
}
-func (present *LoadRate) ValidNextGroup(next *LoadRate) error {
+func ValidNextGroup(present, next *utils.RateSlot) error {
if next.GroupIntervalStart <= present.GroupIntervalStart {
return errors.New(fmt.Sprintf("Next rate group interval start must be heigher than the last one: %#v", next))
}
@@ -113,24 +117,8 @@ func (present *LoadRate) ValidNextGroup(next *LoadRate) error {
return nil
}
-type DestinationRate struct {
- Tag string
- DestinationsTag string
- RateTag string // intermediary used when loading from db
- rates []*LoadRate
-}
-
-type Timing struct {
- Id string
- Years Years
- Months Months
- MonthDays MonthDays
- WeekDays WeekDays
- StartTime string
-}
-
-func NewTiming(timingInfo ...string) (rt *Timing) {
- rt = &Timing{}
+func NewTiming(timingInfo ...string) (rt *utils.TPTiming) {
+ rt = &utils.TPTiming{}
rt.Id = timingInfo[0]
rt.Years.Parse(timingInfo[1], ";")
rt.Months.Parse(timingInfo[2], ";")
@@ -140,47 +128,39 @@ func NewTiming(timingInfo ...string) (rt *Timing) {
return
}
-type DestinationRateTiming struct {
- Tag string
- DestinationRatesTag string // intermediary used when loading from db
- Weight float64
- TimingTag string // intermediary used when loading from db
- timing *Timing
-}
-
-func NewDestinationRateTiming(timing *Timing, weight string) (drt *DestinationRateTiming) {
+func NewRatingPlan(timing *utils.TPTiming, weight string) (drt *utils.RatingPlan) {
w, err := strconv.ParseFloat(weight, 64)
if err != nil {
log.Printf("Error parsing weight unit from: %v", weight)
return
}
- drt = &DestinationRateTiming{
- timing: timing,
+ drt = &utils.RatingPlan{
+ Timing: timing,
Weight: w,
}
return
}
-func (drt *DestinationRateTiming) GetRateInterval(dr *DestinationRate) (i *RateInterval) {
+func GetRateInterval(rpl *utils.RatingPlan, dr *utils.DestinationRate) (i *RateInterval) {
i = &RateInterval{
Timing: &RITiming{
- Years: drt.timing.Years,
- Months: drt.timing.Months,
- MonthDays: drt.timing.MonthDays,
- WeekDays: drt.timing.WeekDays,
- StartTime: drt.timing.StartTime,
+ Years: rpl.Timing.Years,
+ Months: rpl.Timing.Months,
+ MonthDays: rpl.Timing.MonthDays,
+ WeekDays: rpl.Timing.WeekDays,
+ StartTime: rpl.Timing.StartTime,
},
- Weight: drt.Weight,
+ Weight: rpl.Weight,
Rating: &RIRate{
- ConnectFee: dr.rates[0].ConnectFee,
- RoundingMethod: dr.rates[0].RoundingMethod,
- RoundingDecimals: dr.rates[0].RoundingDecimals,
+ ConnectFee: dr.Rate.RateSlots[0].ConnectFee,
+ RoundingMethod: dr.Rate.RateSlots[0].RoundingMethod,
+ RoundingDecimals: dr.Rate.RateSlots[0].RoundingDecimals,
},
}
- for _, rl := range dr.rates {
+ for _, rl := range dr.Rate.RateSlots {
i.Rating.Rates = append(i.Rating.Rates, &Rate{
GroupIntervalStart: rl.GroupIntervalStart,
- Value: rl.Price,
+ Value: rl.Rate,
RateIncrement: rl.RateIncrement,
RateUnit: rl.RateUnit,
})
diff --git a/engine/rateinterval.go b/engine/rateinterval.go
index 50b0cf771..1f4beda43 100644
--- a/engine/rateinterval.go
+++ b/engine/rateinterval.go
@@ -39,10 +39,10 @@ type RateInterval struct {
// Separate structure used for rating plan size optimization
type RITiming struct {
- Years Years
- Months Months
- MonthDays MonthDays
- WeekDays WeekDays
+ Years utils.Years
+ Months utils.Months
+ MonthDays utils.MonthDays
+ WeekDays utils.WeekDays
StartTime, EndTime string // ##:##:## format
}
diff --git a/engine/rateinterval_test.go b/engine/rateinterval_test.go
index 4f195c0d8..de24999a3 100644
--- a/engine/rateinterval_test.go
+++ b/engine/rateinterval_test.go
@@ -27,7 +27,7 @@ import (
func TestRateIntervalSimpleContains(t *testing.T) {
i := &RateInterval{
Timing: &RITiming{
- WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
+ WeekDays: utils.WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
StartTime: "18:00:00",
EndTime: "",
},
@@ -39,7 +39,7 @@ func TestRateIntervalSimpleContains(t *testing.T) {
}
func TestRateIntervalMonth(t *testing.T) {
- i := &RateInterval{Timing: &RITiming{Months: Months{time.February}}}
+ i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}}}
d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC)
d1 := time.Date(2012, time.January, 10, 23, 0, 0, 0, time.UTC)
if !i.Contains(d, false) {
@@ -51,7 +51,7 @@ func TestRateIntervalMonth(t *testing.T) {
}
func TestRateIntervalMonthDay(t *testing.T) {
- i := &RateInterval{Timing: &RITiming{MonthDays: MonthDays{10}}}
+ i := &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{10}}}
d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC)
d1 := time.Date(2012, time.February, 11, 23, 0, 0, 0, time.UTC)
if !i.Contains(d, false) {
@@ -63,7 +63,7 @@ func TestRateIntervalMonthDay(t *testing.T) {
}
func TestRateIntervalMonthAndMonthDay(t *testing.T) {
- i := &RateInterval{Timing: &RITiming{Months: Months{time.February}, MonthDays: MonthDays{10}}}
+ i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}, MonthDays: utils.MonthDays{10}}}
d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC)
d1 := time.Date(2012, time.February, 11, 23, 0, 0, 0, time.UTC)
d2 := time.Date(2012, time.January, 10, 23, 0, 0, 0, time.UTC)
@@ -98,8 +98,8 @@ func TestRateIntervalWeekDays(t *testing.T) {
}
func TestRateIntervalMonthAndMonthDayAndWeekDays(t *testing.T) {
- i := &RateInterval{Timing: &RITiming{Months: Months{time.February}, MonthDays: MonthDays{1}, WeekDays: []time.Weekday{time.Wednesday}}}
- i2 := &RateInterval{Timing: &RITiming{Months: Months{time.February}, MonthDays: MonthDays{2}, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}}}
+ i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}, MonthDays: utils.MonthDays{1}, WeekDays: []time.Weekday{time.Wednesday}}}
+ i2 := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}, MonthDays: utils.MonthDays{2}, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}}}
d := time.Date(2012, time.February, 1, 23, 0, 0, 0, time.UTC)
d1 := time.Date(2012, time.February, 2, 23, 0, 0, 0, time.UTC)
if !i.Contains(d, false) {
@@ -139,9 +139,9 @@ func TestRateIntervalHours(t *testing.T) {
func TestRateIntervalEverything(t *testing.T) {
i := &RateInterval{
Timing: &RITiming{
- Months: Months{time.February},
- Years: Years{2012},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.February},
+ Years: utils.Years{2012},
+ MonthDays: utils.MonthDays{1},
WeekDays: []time.Weekday{time.Wednesday, time.Thursday},
StartTime: "14:30:00",
EndTime: "15:00:00"}}
@@ -170,14 +170,14 @@ func TestRateIntervalEverything(t *testing.T) {
func TestRateIntervalEqual(t *testing.T) {
i1 := &RateInterval{
Timing: &RITiming{
- Months: Months{time.February},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.February},
+ MonthDays: utils.MonthDays{1},
WeekDays: []time.Weekday{time.Wednesday, time.Thursday},
StartTime: "14:30:00",
EndTime: "15:00:00"}}
i2 := &RateInterval{Timing: &RITiming{
- Months: Months{time.February},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.February},
+ MonthDays: utils.MonthDays{1},
WeekDays: []time.Weekday{time.Wednesday, time.Thursday},
StartTime: "14:30:00",
EndTime: "15:00:00"}}
@@ -189,14 +189,14 @@ func TestRateIntervalEqual(t *testing.T) {
func TestRateIntervalNotEqual(t *testing.T) {
i1 := &RateInterval{
Timing: &RITiming{
- Months: Months{time.February},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.February},
+ MonthDays: utils.MonthDays{1},
WeekDays: []time.Weekday{time.Wednesday},
StartTime: "14:30:00",
EndTime: "15:00:00"}}
i2 := &RateInterval{Timing: &RITiming{
- Months: Months{time.February},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.February},
+ MonthDays: utils.MonthDays{1},
WeekDays: []time.Weekday{time.Wednesday, time.Thursday},
StartTime: "14:30:00",
EndTime: "15:00:00"}}
@@ -207,15 +207,15 @@ func TestRateIntervalNotEqual(t *testing.T) {
func TestRitStrigyfy(t *testing.T) {
rit1 := &RITiming{
- Years: Years{},
- Months: Months{time.January, time.February},
- MonthDays: MonthDays{},
+ Years: utils.Years{},
+ Months: utils.Months{time.January, time.February},
+ MonthDays: utils.MonthDays{},
StartTime: "00:00:00",
}
rit2 := &RITiming{
- Years: Years{},
- Months: Months{time.January, time.February},
- MonthDays: MonthDays{},
+ Years: utils.Years{},
+ Months: utils.Months{time.January, time.February},
+ MonthDays: utils.MonthDays{},
StartTime: "00:00:00",
}
if rit1.Stringify() != rit2.Stringify() {
@@ -286,7 +286,7 @@ func TestRateStrigyfy(t *testing.T) {
/*********************************Benchmarks**************************************/
func BenchmarkRateIntervalContainsDate(b *testing.B) {
- i := &RateInterval{Timing: &RITiming{Months: Months{time.February}, MonthDays: MonthDays{1}, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, StartTime: "14:30:00", EndTime: "15:00:00"}}
+ i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.February}, MonthDays: utils.MonthDays{1}, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, StartTime: "14:30:00", EndTime: "15:00:00"}}
d := time.Date(2012, time.February, 1, 14, 30, 0, 0, time.UTC)
for x := 0; x < b.N; x++ {
i.Contains(d, false)
diff --git a/engine/ratingplan_test.go b/engine/ratingplan_test.go
index 9e492d717..5be37e5b1 100644
--- a/engine/ratingplan_test.go
+++ b/engine/ratingplan_test.go
@@ -20,6 +20,7 @@ package engine
import (
"encoding/json"
+ "github.com/cgrates/cgrates/utils"
"reflect"
"testing"
"time"
@@ -148,20 +149,20 @@ func TestFallbackNoInfiniteLoopSelf(t *testing.T) {
func TestApAddIntervalIfNotPresent(t *testing.T) {
i1 := &RateInterval{
Timing: &RITiming{
- Months: Months{time.February},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.February},
+ MonthDays: utils.MonthDays{1},
WeekDays: []time.Weekday{time.Wednesday, time.Thursday},
StartTime: "14:30:00",
EndTime: "15:00:00"}}
i2 := &RateInterval{Timing: &RITiming{
- Months: Months{time.February},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.February},
+ MonthDays: utils.MonthDays{1},
WeekDays: []time.Weekday{time.Wednesday, time.Thursday},
StartTime: "14:30:00",
EndTime: "15:00:00"}}
i3 := &RateInterval{Timing: &RITiming{
- Months: Months{time.February},
- MonthDays: MonthDays{1},
+ Months: utils.Months{time.February},
+ MonthDays: utils.MonthDays{1},
WeekDays: []time.Weekday{time.Wednesday},
StartTime: "14:30:00",
EndTime: "15:00:00"}}
diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go
index ab7813932..594082f71 100644
--- a/engine/ratingprofile.go
+++ b/engine/ratingprofile.go
@@ -26,11 +26,8 @@ import (
)
type RatingProfile struct {
- Id string
- RatingPlanActivations RatingPlanActivations
- Tag, Tenant, TOR, Direction, Subject string // used only for loading
- DestRatesTimingTag, RatesFallbackSubject, ActivationTime string // used only for loading
- FallbackKeys []string // used only for loading
+ Id string
+ RatingPlanActivations RatingPlanActivations
}
type RatingPlanActivation struct {
@@ -82,6 +79,7 @@ type RatingInfo struct {
MatchedPrefix string
ActivationTime time.Time
RateIntervals RateIntervalList
+ FallbackKeys []string
}
type RatingInfos []*RatingInfo
@@ -127,11 +125,11 @@ func (rp *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error)
}
}
if bestPrecision > 0 {
- ris = append(ris, &RatingInfo{rp.Id, cd.Destination[:bestPrecision], rpa.ActivationTime, rps})
+ ris = append(ris, &RatingInfo{rp.Id, cd.Destination[:bestPrecision], rpa.ActivationTime, rps, rpa.FallbackKeys})
} else {
// mark the end of previous!
if len(cd.RatingInfos) > 0 {
- ris = append(ris, &RatingInfo{"", "", rpa.ActivationTime, nil})
+ ris = append(ris, &RatingInfo{"", "", rpa.ActivationTime, nil, rpa.FallbackKeys})
}
}
}
diff --git a/engine/storage_interface.go b/engine/storage_interface.go
index 25470c52c..5c7615153 100644
--- a/engine/storage_interface.go
+++ b/engine/storage_interface.go
@@ -104,28 +104,28 @@ type LoadStorage interface {
Storage
// Apier functions
GetTPIds() ([]string, error)
- SetTPTiming(string, *Timing) error
+ SetTPTiming(string, *utils.TPTiming) error
ExistsTPTiming(string, string) (bool, error)
- GetTPTiming(string, string) (*Timing, error)
+ GetTPTiming(string, string) (*utils.TPTiming, error)
GetTPTimingIds(string) ([]string, error)
SetTPDestination(string, *Destination) error
ExistsTPDestination(string, string) (bool, error)
GetTPDestination(string, string) (*Destination, error)
GetTPDestinationIds(string) ([]string, error)
ExistsTPRate(string, string) (bool, error)
- SetTPRates(string, map[string][]*LoadRate) error
+ SetTPRates(string, map[string]*utils.TPRate) error
GetTPRate(string, string) (*utils.TPRate, error)
GetTPRateIds(string) ([]string, error)
ExistsTPDestinationRate(string, string) (bool, error)
- SetTPDestinationRates(string, map[string][]*DestinationRate) error
+ SetTPDestinationRates(string, map[string]*utils.TPDestinationRate) error
GetTPDestinationRate(string, string) (*utils.TPDestinationRate, error)
GetTPDestinationRateIds(string) ([]string, error)
ExistsTPRatingPlan(string, string) (bool, error)
- SetTPRatingPlans(string, map[string][]*DestinationRateTiming) error
+ SetTPRatingPlans(string, map[string]*utils.TPRatingPlan) error
GetTPRatingPlan(string, string) (*utils.TPRatingPlan, error)
GetTPRatingPlanIds(string) ([]string, error)
ExistsTPRatingProfile(string, string) (bool, error)
- SetTPRatingProfiles(string, map[string][]*RatingProfile) error
+ SetTPRatingProfiles(string, map[string][]*utils.TPRatingProfile) error
GetTPRatingProfile(string, string) (*utils.TPRatingProfile, error)
GetTPRatingProfileIds(*utils.AttrTPRatingProfileIds) ([]string, error)
ExistsTPActions(string, string) (bool, error)
@@ -133,8 +133,8 @@ type LoadStorage interface {
GetTPActions(string, string) (*utils.TPActions, error)
GetTPActionIds(string) ([]string, error)
ExistsTPActionTimings(string, string) (bool, error)
- SetTPActionTimings(string, map[string][]*ActionTiming) error
- GetTPActionTimings(string, string) (map[string][]*utils.TPActionTimingsRow, error)
+ SetTPActionTimings(string, map[string]*utils.ApiTPActionTimings) error
+ GetTPActionTimings(string, string) (map[string]*utils.ApiTPActionTimings, error)
GetTPActionTimingIds(string) ([]string, error)
ExistsTPActionTriggers(string, string) (bool, error)
SetTPActionTriggers(string, map[string][]*ActionTrigger) error
@@ -144,13 +144,13 @@ type LoadStorage interface {
GetTPAccountActionIds(string) ([]string, error)
// loader functions
GetTpDestinations(string, string) ([]*Destination, error)
- GetTpTimings(string, string) (map[string]*Timing, error)
- GetTpRates(string, string) (map[string][]*LoadRate, error)
- GetTpDestinationRates(string, string) (map[string][]*DestinationRate, error)
- GetTpRatingPlans(string, string) ([]*DestinationRateTiming, error)
- GetTpRatingProfiles(string, string) (map[string]*RatingProfile, error)
+ GetTpTimings(string, string) (map[string]*utils.TPTiming, error)
+ GetTpRates(string, string) (map[string]*utils.TPRate, error)
+ GetTpDestinationRates(string, string) (map[string]*utils.TPDestinationRate, error)
+ GetTpRatingPlans(string, string) (*utils.TPRatingPlan, error)
+ GetTpRatingProfiles(string, string) (map[string]*utils.TPRatingProfile, error)
GetTpActions(string, string) (map[string][]*Action, error)
- GetTpActionTimings(string, string) (map[string][]*ActionTiming, error)
+ GetTpActionTimings(string, string) (map[string]utils.ApiTPActionTimings, error)
GetTpActionTriggers(string, string) (map[string][]*ActionTrigger, error)
GetTpAccountActions(string, string) (map[string]*AccountAction, error)
}
diff --git a/engine/storage_sql.go b/engine/storage_sql.go
index 4fe086aae..24f2da06f 100644
--- a/engine/storage_sql.go
+++ b/engine/storage_sql.go
@@ -64,7 +64,7 @@ func (self *SQLStorage) GetTPIds() ([]string, error) {
return ids, nil
}
-func (self *SQLStorage) SetTPTiming(tpid string, tm *Timing) error {
+func (self *SQLStorage) SetTPTiming(tpid string, tm *utils.TPTiming) error {
if _, err := self.Db.Exec(fmt.Sprintf("INSERT INTO %s (tpid, tag, years, months, month_days, week_days, time) VALUES('%s','%s','%s','%s','%s','%s','%s')",
utils.TBL_TP_TIMINGS, tpid, tm.Id, tm.Years.Serialize(";"), tm.Months.Serialize(";"), tm.MonthDays.Serialize(";"),
tm.WeekDays.Serialize(";"), tm.StartTime)); err != nil {
@@ -82,7 +82,7 @@ func (self *SQLStorage) ExistsTPTiming(tpid, tmId string) (bool, error) {
return exists, nil
}
-func (self *SQLStorage) GetTPTiming(tpid, tmId string) (*Timing, error) {
+func (self *SQLStorage) GetTPTiming(tpid, tmId string) (*utils.TPTiming, error) {
var years, months, monthDays, weekDays, time string
err := self.Db.QueryRow(fmt.Sprintf("SELECT years, months, month_days, week_days, time FROM %s WHERE tpid='%s' AND tag='%s' LIMIT 1",
utils.TBL_TP_TIMINGS, tpid, tmId)).Scan(&years, &months, &monthDays, &weekDays, &time)
@@ -193,19 +193,19 @@ func (self *SQLStorage) ExistsTPRate(tpid, rtId string) (bool, error) {
return exists, nil
}
-func (self *SQLStorage) SetTPRates(tpid string, rts map[string][]*LoadRate) error {
+func (self *SQLStorage) SetTPRates(tpid string, rts map[string]*utils.TPRate) error {
if len(rts) == 0 {
return nil //Nothing to set
}
qry := fmt.Sprintf("INSERT INTO %s (tpid, tag, connect_fee, rate, rate_unit, rate_increment, group_interval_start, rounding_method, rounding_decimals) VALUES ", utils.TBL_TP_RATES)
i := 0
for rtId, rtRows := range rts {
- for _, rt := range rtRows {
+ for _, rt := range rtRows.RateSlots {
if i != 0 { //Consecutive values after the first will be prefixed with "," as separator
qry += ","
}
qry += fmt.Sprintf("('%s', '%s', %f, %f, %d, %d,%d,'%s', %d)",
- tpid, rtId, rt.ConnectFee, rt.Price, rt.RateUnit, rt.RateIncrement, rt.GroupIntervalStart,
+ tpid, rtId, rt.ConnectFee, rt.Rate, rt.RateUnit, rt.RateIncrement, rt.GroupIntervalStart,
rt.RoundingMethod, rt.RoundingDecimals)
i++
}
@@ -234,8 +234,7 @@ func (self *SQLStorage) GetTPRate(tpid, rtId string) (*utils.TPRate, error) {
if err != nil {
return nil, err
}
- rt.RateSlots = append(rt.RateSlots, utils.RateSlot{connectFee, rate, rateUnit.String(), rateIncrement.String(),
- groupIntervalStart.String(), roundingMethod, roundingDecimals})
+ rt.RateSlots = append(rt.RateSlots, &utils.RateSlot{connectFee, rate, rateUnit, rateIncrement, groupIntervalStart, roundingMethod, roundingDecimals})
}
if i == 0 {
return nil, nil
@@ -275,19 +274,19 @@ func (self *SQLStorage) ExistsTPDestinationRate(tpid, drId string) (bool, error)
return exists, nil
}
-func (self *SQLStorage) SetTPDestinationRates(tpid string, drs map[string][]*DestinationRate) error {
+func (self *SQLStorage) SetTPDestinationRates(tpid string, drs map[string]*utils.TPDestinationRate) error {
if len(drs) == 0 {
return nil //Nothing to set
}
qry := fmt.Sprintf("INSERT INTO %s (tpid, tag, destinations_tag, rates_tag) VALUES ", utils.TBL_TP_DESTINATION_RATES)
i := 0
for drId, drRows := range drs {
- for _, dr := range drRows {
+ for _, dr := range drRows.DestinationRates {
if i != 0 { //Consecutive values after the first will be prefixed with "," as separator
qry += ","
}
qry += fmt.Sprintf("('%s','%s','%s','%s')",
- tpid, drId, dr.DestinationsTag, dr.RateTag)
+ tpid, drId, dr.DestinationId, dr.RateId)
i++
}
}
@@ -312,7 +311,7 @@ func (self *SQLStorage) GetTPDestinationRate(tpid, drId string) (*utils.TPDestin
if err != nil {
return nil, err
}
- dr.DestinationRates = append(dr.DestinationRates, utils.DestinationRate{dstTag, ratesTag})
+ dr.DestinationRates = append(dr.DestinationRates, &utils.DestinationRate{dstTag, ratesTag, nil})
}
if i == 0 {
return nil, nil
@@ -352,19 +351,19 @@ func (self *SQLStorage) ExistsTPRatingPlan(tpid, drtId string) (bool, error) {
return exists, nil
}
-func (self *SQLStorage) SetTPRatingPlans(tpid string, drts map[string][]*DestinationRateTiming) error {
+func (self *SQLStorage) SetTPRatingPlans(tpid string, drts map[string]*utils.TPRatingPlan) error {
if len(drts) == 0 {
return nil //Nothing to set
}
qry := fmt.Sprintf("INSERT INTO %s (tpid, tag, destrates_tag, timing_tag, weight) VALUES ", utils.TBL_TP_RATING_PLANS)
i := 0
for drtId, drtRows := range drts {
- for _, drt := range drtRows {
+ for _, drt := range drtRows.RatingPlans {
if i != 0 { //Consecutive values after the first will be prefixed with "," as separator
qry += ","
}
qry += fmt.Sprintf("('%s','%s','%s','%s',%f)",
- tpid, drtId, drt.DestinationRatesTag, drt.TimingTag, drt.Weight)
+ tpid, drtId, drt.DestRatesId, drt.TimingId, drt.Weight)
i++
}
}
@@ -390,7 +389,7 @@ func (self *SQLStorage) GetTPRatingPlan(tpid, drtId string) (*utils.TPRatingPlan
if err != nil {
return nil, err
}
- drt.RatingPlans = append(drt.RatingPlans, utils.RatingPlan{drTag, timingTag, weight})
+ drt.RatingPlans = append(drt.RatingPlans, &utils.RatingPlan{drTag, timingTag, weight, nil})
}
if i == 0 {
return nil, nil
@@ -430,7 +429,7 @@ func (self *SQLStorage) ExistsTPRatingProfile(tpid, rpId string) (bool, error) {
return exists, nil
}
-func (self *SQLStorage) SetTPRatingProfiles(tpid string, rps map[string][]*RatingProfile) error {
+func (self *SQLStorage) SetTPRatingProfiles(tpid string, rps map[string][]*utils.TPRatingProfile) error {
if len(rps) == 0 {
return nil //Nothing to set
}
@@ -443,7 +442,7 @@ func (self *SQLStorage) SetTPRatingProfiles(tpid string, rps map[string][]*Ratin
qry += ","
}
qry += fmt.Sprintf("('%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s')", tpid, rpId, rpa.Tenant, rpa.TOR, rpa.Direction,
- rpa.Subject, rpa.ActivationTime, rpa.DestRatesTimingTag, rpa.RatesFallbackSubject)
+ rpa.Subject, rpa.ActivationTime, rpa.RatingPlanId, rpa.FallbackKeys)
i++
}
@@ -474,9 +473,9 @@ func (self *SQLStorage) GetTPRatingProfile(tpid, rpId string) (*utils.TPRatingPr
rp.TOR = tor
rp.Direction = direction
rp.Subject = subject
- rp.RatesFallbackSubject = fallbackSubj
+ rp.FallbackKeys = strings.Split(fallbackSubj, FALLBACK_SEP)
}
- rp.RatingActivations = append(rp.RatingActivations, utils.RatingActivation{aTime, drtId})
+ rp.RatingPlanActivations = append(rp.RatingPlanActivations, &utils.RatingActivation{aTime, drtId})
}
if i == 0 {
return nil, nil
@@ -567,7 +566,7 @@ func (self *SQLStorage) GetTPActions(tpid, actsId string) (*utils.TPActions, err
if err = rows.Scan(&action, &balanceId, &dir, &units, &expTime, &destId, &rateSubject, &balanceWeight, &extraParameters, &weight); err != nil {
return nil, err
}
- acts.Actions = append(acts.Actions, utils.Action{action, balanceId, dir, units, expTime, destId, rateSubject, balanceWeight, extraParameters, weight})
+ acts.Actions = append(acts.Actions, &utils.Action{action, balanceId, dir, units, expTime, destId, rateSubject, balanceWeight, extraParameters, weight})
}
if i == 0 {
return nil, nil
@@ -607,19 +606,19 @@ func (self *SQLStorage) ExistsTPActionTimings(tpid, atId string) (bool, error) {
}
// Sets actionTimings in sqlDB. Imput is expected in form map[actionTimingId][]rows, eg a full .csv file content
-func (self *SQLStorage) SetTPActionTimings(tpid string, ats map[string][]*ActionTiming) error {
+func (self *SQLStorage) SetTPActionTimings(tpid string, ats map[string]utils.ApiTPActionTimings) error {
if len(ats) == 0 {
return nil //Nothing to set
}
qry := fmt.Sprintf("INSERT INTO %s (tpid,tag,actions_tag,timing_tag,weight) VALUES ", utils.TBL_TP_ACTION_TIMINGS)
i := 0
for atId, atRows := range ats {
- for _, at := range atRows {
+ for _, at := range atRows.ActionTimings {
if i != 0 { //Consecutive values after the first will be prefixed with "," as separator
qry += ","
}
qry += fmt.Sprintf("('%s','%s','%s','%s',%f)",
- tpid, atId, at.ActionsTag, at.TimingsTag, at.Weight)
+ tpid, atId, at.ActionsId, at.TimingId, at.Weight)
i++
}
}
@@ -629,8 +628,8 @@ func (self *SQLStorage) SetTPActionTimings(tpid string, ats map[string][]*Action
return nil
}
-func (self *SQLStorage) GetTPActionTimings(tpid, atId string) (map[string][]*utils.TPActionTimingsRow, error) {
- ats := make(map[string][]*utils.TPActionTimingsRow)
+func (self *SQLStorage) GetTPActionTimings(tpid, atId string) (map[string][]*utils.ApiActionTiming, error) {
+ ats := make(map[string][]*utils.ApiActionTiming)
q := fmt.Sprintf("SELECT tag,actions_tag,timing_tag,weight FROM %s WHERE tpid='%s'", utils.TBL_TP_ACTION_TIMINGS, tpid)
if atId != "" {
q += fmt.Sprintf(" AND tag='%s'", atId)
@@ -648,7 +647,7 @@ func (self *SQLStorage) GetTPActionTimings(tpid, atId string) (map[string][]*uti
if err = rows.Scan(&tag, &actionsId, &timingId, &weight); err != nil {
return nil, err
}
- ats[tag] = append(ats[tag], &utils.TPActionTimingsRow{actionsId, timingId, weight})
+ ats[tag] = append(ats[tag], &utils.ApiActionTiming{actionsId, timingId, weight})
}
return ats, nil
}
@@ -957,8 +956,8 @@ func (self *SQLStorage) GetTpDestinations(tpid, tag string) ([]*Destination, err
return dests, nil
}
-func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string][]*LoadRate, error) {
- rts := make(map[string][]*LoadRate)
+func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string]*utils.TPRate, error) {
+ rts := make(map[string]*utils.TPRate)
q := fmt.Sprintf("SELECT tag, connect_fee, rate, rate_unit, rate_increment, group_interval_start, rounding_method, rounding_decimals FROM %s WHERE tpid='%s' ", utils.TBL_TP_RATES, tpid)
if tag != "" {
q += fmt.Sprintf(" AND tag='%s'", tag)
@@ -976,30 +975,38 @@ func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string][]*LoadRate, er
if err := rows.Scan(&tag, &connect_fee, &rate, &rate_unit, &rate_increment, &group_interval_start, &roundingMethod, &roundingDecimals); err != nil {
return nil, err
}
- r := &LoadRate{
- Tag: tag,
- ConnectFee: connect_fee,
- Price: rate,
- RateUnit: rate_unit,
- RateIncrement: rate_increment,
- GroupIntervalStart: group_interval_start,
- RoundingMethod: roundingMethod,
- RoundingDecimals: roundingDecimals,
+ r := &utils.TPRate{
+ RateId: tag,
+ RateSlots: []*utils.RateSlot{
+ &utils.RateSlot{
+ ConnectFee: connect_fee,
+ Rate: rate,
+ RateUnit: rate_unit,
+ RateIncrement: rate_increment,
+ GroupIntervalStart: group_interval_start,
+ RoundingMethod: roundingMethod,
+ RoundingDecimals: roundingDecimals,
+ },
+ },
}
// same tag only to create rate groups
existingRates, exists := rts[tag]
if exists {
- if err := existingRates[len(existingRates)-1].ValidNextGroup(r); err != nil {
+ rss := existingRates.RateSlots
+ if err := ValidNextGroup(rss[len(rss)-1], r.RateSlots[0]); err != nil {
return nil, err
}
+ rts[tag].RateSlots = append(rts[tag].RateSlots, r.RateSlots[0])
+ } else {
+ rts[tag] = r
+
}
- rts[tag] = append(rts[tag], r)
}
return rts, nil
}
-func (self *SQLStorage) GetTpDestinationRates(tpid, tag string) (map[string][]*DestinationRate, error) {
- rts := make(map[string][]*DestinationRate)
+func (self *SQLStorage) GetTpDestinationRates(tpid, tag string) (map[string]*utils.TPDestinationRate, error) {
+ rts := make(map[string]*utils.TPDestinationRate)
q := fmt.Sprintf("SELECT * FROM %s WHERE tpid='%s'", utils.TBL_TP_DESTINATION_RATES, tpid)
if tag != "" {
q += fmt.Sprintf(" AND tag='%s'", tag)
@@ -1015,18 +1022,29 @@ func (self *SQLStorage) GetTpDestinationRates(tpid, tag string) (map[string][]*D
if err := rows.Scan(&id, &tpid, &tag, &destinations_tag, &rate_tag); err != nil {
return nil, err
}
- dr := &DestinationRate{
- Tag: tag,
- DestinationsTag: destinations_tag,
- RateTag: rate_tag,
+
+ dr := &utils.TPDestinationRate{
+ DestinationRateId: tag,
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: destinations_tag,
+ RateId: rate_tag,
+ },
+ },
}
- rts[tag] = append(rts[tag], dr)
+ existingDR, exists := rts[tag]
+ if exists {
+ existingDR.DestinationRates = append(existingDR.DestinationRates, dr.DestinationRates[0])
+ } else {
+ existingDR = dr
+ }
+ rts[tag] = existingDR
}
return rts, nil
}
-func (self *SQLStorage) GetTpTimings(tpid, tag string) (map[string]*Timing, error) {
- tms := make(map[string]*Timing)
+func (self *SQLStorage) GetTpTimings(tpid, tag string) (map[string]*utils.TPTiming, error) {
+ tms := make(map[string]*utils.TPTiming)
q := fmt.Sprintf("SELECT * FROM %s WHERE tpid='%s'", utils.TBL_TP_TIMINGS, tpid)
if tag != "" {
q += fmt.Sprintf(" AND tag='%s'", tag)
@@ -1047,8 +1065,8 @@ func (self *SQLStorage) GetTpTimings(tpid, tag string) (map[string]*Timing, erro
return tms, nil
}
-func (self *SQLStorage) GetTpRatingPlans(tpid, tag string) ([]*DestinationRateTiming, error) {
- var rts []*DestinationRateTiming
+func (self *SQLStorage) GetTpRatingPlans(tpid, tag string) (*utils.TPRatingPlan, error) {
+ rts := &utils.TPRatingPlan{RatingPlanId: tag}
q := fmt.Sprintf("SELECT * FROM %s WHERE tpid='%s'", utils.TBL_TP_RATING_PLANS, tpid)
if tag != "" {
q += fmt.Sprintf(" AND tag='%s'", tag)
@@ -1065,19 +1083,18 @@ func (self *SQLStorage) GetTpRatingPlans(tpid, tag string) ([]*DestinationRateTi
if err := rows.Scan(&id, &tpid, &tag, &destination_rates_tag, &timings_tag, &weight); err != nil {
return nil, err
}
- rt := &DestinationRateTiming{
- Tag: tag,
- DestinationRatesTag: destination_rates_tag,
- Weight: weight,
- TimingTag: timings_tag,
+ rt := &utils.RatingPlan{
+ DestRatesId: destination_rates_tag,
+ Weight: weight,
+ TimingId: timings_tag,
}
- rts = append(rts, rt)
+ rts.RatingPlans = append(rts.RatingPlans, rt)
}
return rts, nil
}
-func (self *SQLStorage) GetTpRatingProfiles(tpid, tag string) (map[string]*RatingProfile, error) {
- rpfs := make(map[string]*RatingProfile)
+func (self *SQLStorage) GetTpRatingProfiles(tpid, tag string) (map[string]*utils.TPRatingProfile, error) {
+ rpfs := make(map[string]*utils.TPRatingProfile)
q := fmt.Sprintf("SELECT tag,tenant,tor,direction,subject,activation_time,rating_plan_tag,fallback_subject FROM %s WHERE tpid='%s'",
utils.TBL_TP_RATE_PROFILES, tpid)
if tag != "" {
@@ -1095,11 +1112,11 @@ func (self *SQLStorage) GetTpRatingProfiles(tpid, tag string) (map[string]*Ratin
}
key := fmt.Sprintf("%s:%s:%s:%s", direction, tenant, tor, subject)
rp, ok := rpfs[key]
- if !ok || rp.Tag != tag {
- rp = &RatingProfile{Id: key, Tag: tag}
+ if !ok || rp.RatingProfileId != tag {
+ rp = &utils.TPRatingProfile{RatingProfileId: key, Tag: tag}
rpfs[key] = rp
}
- rp.DestRatesTimingTag = rating_plan_tag
+ rp.RatingPlanId = rating_plan_tag
rp.ActivationTime = activation_time
if fallback_subject != "" {
for _, fbs := range strings.Split(fallback_subject, ";") {
diff --git a/engine/timespans_test.go b/engine/timespans_test.go
index e4381fb51..8d1b4b074 100644
--- a/engine/timespans_test.go
+++ b/engine/timespans_test.go
@@ -54,7 +54,7 @@ func TestRightMargin(t *testing.T) {
func TestSplitMiddle(t *testing.T) {
i := &RateInterval{
Timing: &RITiming{
- WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
+ WeekDays: utils.WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
StartTime: "18:00:00",
EndTime: "",
}}
@@ -123,7 +123,7 @@ func TestLeftMargin(t *testing.T) {
}
func TestLeftHourMargin(t *testing.T) {
- i := &RateInterval{Timing: &RITiming{Months: Months{time.December}, MonthDays: MonthDays{1}, StartTime: "09:00:00"}}
+ i := &RateInterval{Timing: &RITiming{Months: utils.Months{time.December}, MonthDays: utils.MonthDays{1}, StartTime: "09:00:00"}}
t1 := time.Date(2012, time.December, 1, 8, 45, 0, 0, time.UTC)
t2 := time.Date(2012, time.December, 1, 9, 20, 0, 0, time.UTC)
ts := &TimeSpan{TimeStart: t1, TimeEnd: t2}
diff --git a/engine/tpimporter_csv.go b/engine/tpimporter_csv.go
index e1688e0ad..562e6bb61 100644
--- a/engine/tpimporter_csv.go
+++ b/engine/tpimporter_csv.go
@@ -24,6 +24,7 @@ import (
"io/ioutil"
"log"
"strconv"
+ "strings"
)
// Import tariff plan from csv into storDb
@@ -142,7 +143,7 @@ func (self *TPCSVImporter) importRates(fn string) error {
if err != nil {
return err
}
- if err := self.StorDb.SetTPRates(self.TPid, map[string][]*LoadRate{record[0]: []*LoadRate{rt}}); err != nil {
+ if err := self.StorDb.SetTPRates(self.TPid, map[string]*utils.TPRate{record[0]: rt}); err != nil {
if self.Verbose {
log.Printf("Ignoring line %d, storDb operational error: <%s> ", lineNr, err.Error())
}
@@ -169,9 +170,17 @@ func (self *TPCSVImporter) importDestinationRates(fn string) error {
}
continue
}
- dr := &DestinationRate{record[0], record[1], record[2], nil}
+ dr := &utils.TPDestinationRate{
+ DestinationRateId: record[0],
+ DestinationRates: []*utils.DestinationRate{
+ &utils.DestinationRate{
+ DestinationId: record[1],
+ RateId: record[2],
+ },
+ },
+ }
if err := self.StorDb.SetTPDestinationRates(self.TPid,
- map[string][]*DestinationRate{dr.Tag: []*DestinationRate{dr}}); err != nil {
+ map[string]*utils.TPDestinationRate{dr.DestinationRateId: dr}); err != nil {
if self.Verbose {
log.Printf("Ignoring line %d, storDb operational error: <%s> ", lineNr, err.Error())
}
@@ -205,12 +214,17 @@ func (self *TPCSVImporter) importRatingPlans(fn string) error {
}
continue
}
- drt := &DestinationRateTiming{Tag: record[0],
- DestinationRatesTag: record[1],
- Weight: weight,
- TimingTag: record[2],
+ drt := &utils.TPRatingPlan{
+ RatingPlanId: record[0],
+ RatingPlans: []*utils.RatingPlan{
+ &utils.RatingPlan{
+ DestRatesId: record[1],
+ Weight: weight,
+ TimingId: record[2],
+ },
+ },
}
- if err := self.StorDb.SetTPRatingPlans(self.TPid, map[string][]*DestinationRateTiming{drt.Tag: []*DestinationRateTiming{drt}}); err != nil {
+ if err := self.StorDb.SetTPRatingPlans(self.TPid, map[string]*utils.TPRatingPlan{drt.RatingPlanId: drt}); err != nil {
if self.Verbose {
log.Printf("Ignoring line %d, storDb operational error: <%s> ", lineNr, err.Error())
}
@@ -249,17 +263,17 @@ func (self *TPCSVImporter) importRatingProfiles(fn string) error {
if self.ImportId != "" {
rpTag += "_" + self.ImportId
}
- rp := &RatingProfile{
- Tag: rpTag,
- Tenant: tenant,
- TOR: tor,
- Direction: direction,
- Subject: subject,
- ActivationTime: record[4],
- DestRatesTimingTag: destRatesTimingTag,
- RatesFallbackSubject: fallbacksubject,
+ rp := &utils.TPRatingProfile{
+ Tag: rpTag,
+ Tenant: tenant,
+ TOR: tor,
+ Direction: direction,
+ Subject: subject,
+ ActivationTime: record[4],
+ RatingPlanId: destRatesTimingTag,
+ FallbackKeys: strings.Split(fallbacksubject, FALLBACK_SEP),
}
- if err := self.StorDb.SetTPRatingProfiles(self.TPid, map[string][]*RatingProfile{rpTag: []*RatingProfile{rp}}); err != nil {
+ if err := self.StorDb.SetTPRatingProfiles(self.TPid, map[string][]*utils.TPRatingProfile{rpTag: []*utils.TPRatingProfile{rp}}); err != nil {
if self.Verbose {
log.Printf("Ignoring line %d, storDb operational error: <%s> ", lineNr, err.Error())
}
@@ -351,13 +365,17 @@ func (self *TPCSVImporter) importActionTimings(fn string) error {
}
continue
}
- at := &ActionTiming{
- Tag: tag,
- ActionsTag: actionsTag,
- TimingsTag: timingTag,
- Weight: weight,
+ ats := &utils.ApiTPActionTimings{
+ ActionTimingsId: tag,
+ ActionTimings: []*utils.ApiActionTiming{
+ &utils.ApiActionTiming{
+ ActionsId: actionsTag,
+ TimingId: timingTag,
+ Weight: weight,
+ },
+ },
}
- if err := self.StorDb.SetTPActionTimings(self.TPid, map[string][]*ActionTiming{tag: []*ActionTiming{at}}); err != nil {
+ if err := self.StorDb.SetTPActionTimings(self.TPid, map[string]*utils.ApiTPActionTimings{tag: ats}); err != nil {
if self.Verbose {
log.Printf("Ignoring line %d, storDb operational error: <%s> ", lineNr, err.Error())
}
diff --git a/utils/apitpdata.go b/utils/apitpdata.go
index c39fd103f..dd622c886 100644
--- a/utils/apitpdata.go
+++ b/utils/apitpdata.go
@@ -18,61 +18,80 @@ along with this program. If not, see
package utils
+import (
+ "time"
+)
+
// This file deals with tp_* data definition
type TPRate struct {
- TPid string // Tariff plan id
- RateId string // Rate id
- RateSlots []RateSlot // One or more RateSlots
+ TPid string // Tariff plan id
+ RateId string // Rate id
+ RateSlots []*RateSlot // One or more RateSlots
}
type RateSlot struct {
- ConnectFee float64 // ConnectFee applied once the call is answered
- Rate float64 // Rate applied
- RateUnit string // Number of billing units this rate applies to
- RateIncrement string // This rate will apply in increments of duration
- GroupIntervalStart string // Group position
- RoundingMethod string // Use this method to round the cost
- RoundingDecimals int // Round the cost number of decimals
+ ConnectFee float64 // ConnectFee applied once the call is answered
+ Rate float64 // Rate applied
+ RateUnit time.Duration // Number of billing units this rate applies to
+ RateIncrement time.Duration // This rate will apply in increments of duration
+ GroupIntervalStart time.Duration // Group position
+ RoundingMethod string // Use this method to round the cost
+ RoundingDecimals int // Round the cost number of decimals
}
type TPDestinationRate struct {
- TPid string // Tariff plan id
- DestinationRateId string // DestinationRate profile id
- DestinationRates []DestinationRate // Set of destinationid-rateid bindings
+ TPid string // Tariff plan id
+ DestinationRateId string // DestinationRate profile id
+ DestinationRates []*DestinationRate // Set of destinationid-rateid bindings
}
type DestinationRate struct {
DestinationId string // The destination identity
RateId string // The rate identity
+ Rate *TPRate
+}
+
+type TPTiming struct {
+ Id string
+ Years Years
+ Months Months
+ MonthDays MonthDays
+ WeekDays WeekDays
+ StartTime string
}
type TPRatingPlan struct {
- TPid string // Tariff plan id
- RatingPlanId string // RatingPlan profile id
- RatingPlans []RatingPlan // Set of destinationid-rateid bindings
+ TPid string // Tariff plan id
+ RatingPlanId string // RatingPlan profile id
+ RatingPlans []*RatingPlan // Set of destinationid-rateid bindings
}
type RatingPlan struct {
DestRatesId string // The DestinationRate identity
TimingId string // The timing identity
Weight float64 // Binding priority taken into consideration when more DestinationRates are active on a time slot
+ Timing *TPTiming
}
type TPRatingProfile struct {
- TPid string // Tariff plan id
- RatingProfileId string // RatingProfile id
- Tenant string // Tenant's Id
- TOR string // TypeOfRecord
- Direction string // Traffic direction, OUT is the only one supported for now
- Subject string // Rating subject, usually the same as account
- RatesFallbackSubject string // Fallback on this subject if rates not found for destination
- RatingActivations []RatingActivation // Activate rate profiles at specific time
+ TPid string // Tariff plan id
+ Tag string
+ RatingProfileId string // RatingProfile id
+ RatingPlanId string
+ Tenant string // Tenant's Id
+ TOR string // TypeOfRecord
+ Direction string // Traffic direction, OUT is the only one supported for now
+ Subject string // Rating subject, usually the same as account
+ FallbackKeys []string // Fallback on this subject if rates not found for destination
+ ActivationTime string
+ RatingPlanActivations []*RatingActivation // Activate rate profiles at specific time
}
type RatingActivation struct {
ActivationTime string // Time when this profile will become active, defined as unix epoch time
DestRateTimingId string // Id of DestRateTiming profile
+ // FallbackKeys []string
}
type AttrTPRatingProfileIds struct {
@@ -84,9 +103,9 @@ type AttrTPRatingProfileIds struct {
}
type TPActions struct {
- TPid string // Tariff plan id
- ActionsId string // Actions id
- Actions []Action // Set of actions this Actions profile will perform
+ TPid string // Tariff plan id
+ ActionsId string // Actions id
+ Actions []*Action // Set of actions this Actions profile will perform
}
type Action struct {
@@ -94,7 +113,7 @@ type Action struct {
BalanceType string // Type of balance the action will operate on
Direction string // Balance direction
Units float64 // Number of units to add/deduct
- ExpiryTime string // Time when the units will expire
+ ExpiryTime string // Time when the units will expire\
DestinationId string // Destination profile id
RatingSubject string // Reference a rate subject defined in RatingProfiles
BalanceWeight float64 // Balance weight
@@ -103,9 +122,9 @@ type Action struct {
}
type ApiTPActionTimings struct {
- TPid string // Tariff plan id
- ActionTimingsId string // ActionTimings id
- ActionTimings []ApiActionTiming // Set of ActionTiming bindings this profile will group
+ TPid string // Tariff plan id
+ ActionTimingsId string // ActionTimings id
+ ActionTimings []*ApiActionTiming // Set of ActionTiming bindings this profile will group
}
type ApiActionTiming struct {
@@ -115,9 +134,9 @@ type ApiActionTiming struct {
}
type ApiTPActionTriggers struct {
- TPid string // Tariff plan id
- ActionTriggersId string // Profile id
- ActionTriggers []ApiActionTrigger // Set of triggers grouped in this profile
+ TPid string // Tariff plan id
+ ActionTriggersId string // Profile id
+ ActionTriggers []*ApiActionTrigger // Set of triggers grouped in this profile
}
diff --git a/utils/tpdata.go b/utils/tpdata.go
deleted file mode 100644
index a3c5001c3..000000000
--- a/utils/tpdata.go
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-Rating system designed to be used in VoIP Carriers World
-Copyright (C) 2013 ITsysCOM
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see
-*/
-
-package utils
-
-// Represents a single row in .csv or storDb, id will be used as key in the map holding all rows
-type TPActionTimingsRow struct {
- ActionsId string // Actions id
- TimingId string // Timing profile id
- Weight float64 // Binding's weight
-}