using utils types to load data

This commit is contained in:
Radu Ioan Fericean
2013-11-14 09:30:47 +02:00
parent ef9f5fe612
commit 8189bbbf36
19 changed files with 529 additions and 925 deletions

View File

@@ -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

View File

@@ -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",
},

View File

@@ -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
}
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>
*/
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
}

View File

@@ -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 <http://www.gnu.org/licenses/>
*/
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)
}
}

View File

@@ -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

View File

@@ -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,
},
},

View File

@@ -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)
}

View File

@@ -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,
})

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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"}}

View File

@@ -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})
}
}
}

View File

@@ -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)
}

View File

@@ -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, ";") {

View File

@@ -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}

View File

@@ -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())
}

View File

@@ -18,61 +18,80 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
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
}

View File

@@ -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 <http://www.gnu.org/licenses/>
*/
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
}