moved rounding params from rates to destination rates

This commit is contained in:
Radu Ioan Fericean
2014-05-07 14:59:55 +03:00
parent 928adcfbf0
commit dc7330b3c9
16 changed files with 165 additions and 133 deletions

View File

@@ -161,3 +161,13 @@ func (cc *CallCost) ToDataCost() (*DataCost, error) {
}
return dc, nil
}
func (cc *CallCost) GetLongestRounding() (roundingDecimals int, roundingMethod string) {
for _, ts := range cc.Timespans {
if ts.RateInterval.Rating.RoundingDecimals > roundingDecimals {
roundingDecimals = ts.RateInterval.Rating.RoundingDecimals
roundingMethod = ts.RateInterval.Rating.RoundingMethod
}
}
return
}

View File

@@ -200,7 +200,7 @@ func TestCallCostToDataCost(t *testing.T) {
t.Error("Error convertiong to data cost: ", err)
}
js, _ := json.Marshal(dc)
expected := `{"Direction":"*out","Category":"data","Tenant":"cgrates.org","Subject":"rif","Account":"","Destination":"*any","TOR":"*data","Cost":65,"DataSpans":[{"DataStart":0,"DataEnd":60,"Cost":60,"RateInterval":{"Timing":{"Years":[],"Months":[],"MonthDays":[],"WeekDays":[],"StartTime":"00:00:00","EndTime":""},"Rating":{"ConnectFee":0,"Rates":[{"GroupIntervalStart":0,"Value":1,"RateIncrement":60000000000,"RateUnit":1000000000},{"GroupIntervalStart":60000000000,"Value":1,"RateIncrement":1000000000,"RateUnit":1000000000}],"RoundingMethod":"*up","RoundingDecimals":4},"Weight":10},"DataIndex":60,"Increments":[],"MatchedSubject":"","MatchedPrefix":"","MatchedDestId":""},{"DataStart":60,"DataEnd":65,"Cost":5,"RateInterval":{"Timing":{"Years":[],"Months":[],"MonthDays":[],"WeekDays":[],"StartTime":"00:00:00","EndTime":""},"Rating":{"ConnectFee":0,"Rates":[{"GroupIntervalStart":0,"Value":1,"RateIncrement":60000000000,"RateUnit":1000000000},{"GroupIntervalStart":60000000000,"Value":1,"RateIncrement":1000000000,"RateUnit":1000000000}],"RoundingMethod":"*up","RoundingDecimals":4},"Weight":10},"DataIndex":65,"Increments":[],"MatchedSubject":"*out:cgrates.org:data:rif","MatchedPrefix":"*any","MatchedDestId":"*any"}]}`
expected := `{"Direction":"*out","Category":"data","Tenant":"cgrates.org","Subject":"rif","Account":"","Destination":"*any","TOR":"*data","Cost":65,"DataSpans":[{"DataStart":0,"DataEnd":60,"Cost":60,"RateInterval":{"Timing":{"Years":[],"Months":[],"MonthDays":[],"WeekDays":[],"StartTime":"00:00:00","EndTime":""},"Rating":{"ConnectFee":0,"RoundingMethod":"*middle","RoundingDecimals":4,"Rates":[{"GroupIntervalStart":0,"Value":1,"RateIncrement":60000000000,"RateUnit":1000000000},{"GroupIntervalStart":60000000000,"Value":1,"RateIncrement":1000000000,"RateUnit":1000000000}]},"Weight":10},"DataIndex":60,"Increments":[],"MatchedSubject":"","MatchedPrefix":"","MatchedDestId":""},{"DataStart":60,"DataEnd":65,"Cost":5,"RateInterval":{"Timing":{"Years":[],"Months":[],"MonthDays":[],"WeekDays":[],"StartTime":"00:00:00","EndTime":""},"Rating":{"ConnectFee":0,"RoundingMethod":"*middle","RoundingDecimals":4,"Rates":[{"GroupIntervalStart":0,"Value":1,"RateIncrement":60000000000,"RateUnit":1000000000},{"GroupIntervalStart":60000000000,"Value":1,"RateIncrement":1000000000,"RateUnit":1000000000}]},"Weight":10},"DataIndex":65,"Increments":[],"MatchedSubject":"*out:cgrates.org:data:rif","MatchedPrefix":"*any","MatchedDestId":"*any"}]}`
if string(js) != expected {
t.Error("Error coverting to data cost: ", string(js))
}

View File

@@ -431,9 +431,6 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) {
}
cost += ts.getCost()
}
// global rounding
//TODO: use the longest rounding/method from ts
cost = utils.Round(cost, globalRoundingDecimals, globalRoundingMethod)
//startIndex := len(fmt.Sprintf("%s:%s:%s:", cd.Direction, cd.Tenant, cd.Category))
cc := &CallCost{
Direction: cd.Direction,
@@ -447,6 +444,9 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) {
deductConnectFee: cd.LoopIndex == 0,
TOR: cd.TOR,
}
// global rounding
roundingDecimals, roundingMethod := cc.GetLongestRounding()
cc.Cost = utils.Round(cc.Cost, roundingDecimals, roundingMethod)
//Logger.Info(fmt.Sprintf("<Rater> Get Cost: %s => %v", cd.GetKey(), cc))
cc.Timespans.Compress()
return cc, err

View File

@@ -385,7 +385,7 @@ func (csvr *CSVReader) LoadRates() (err error) {
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
tag := record[0]
var r *utils.TPRate
r, err = NewLoadRate(record[0], record[1], record[2], record[3], record[4], record[5], record[6], record[7])
r, err = NewLoadRate(record[0], record[1], record[2], record[3], record[4], record[5])
if err != nil {
return err
}
@@ -420,6 +420,11 @@ func (csvr *CSVReader) LoadDestinationRates() (err error) {
if !exists {
return fmt.Errorf("Could not get rates for tag %v", record[2])
}
roundingDecimals, err := strconv.Atoi(record[4])
if err != nil {
log.Printf("Error parsing rounding decimals: %s", record[4])
return err
}
destinationExists := false
for _, d := range csvr.destinations {
if d.Id == record[1] {
@@ -427,7 +432,7 @@ func (csvr *CSVReader) LoadDestinationRates() (err error) {
break
}
}
var err error
if !destinationExists && csvr.dataStorage != nil {
if destinationExists, err = csvr.dataStorage.HasData(DESTINATION_PREFIX, record[1]); err != nil {
return err
@@ -440,8 +445,10 @@ func (csvr *CSVReader) LoadDestinationRates() (err error) {
DestinationRateId: tag,
DestinationRates: []*utils.DestinationRate{
&utils.DestinationRate{
DestinationId: record[1],
Rate: r,
DestinationId: record[1],
Rate: r,
RoundingMethod: record[3],
RoundingDecimals: roundingDecimals,
},
},
}

View File

@@ -56,37 +56,37 @@ ALWAYS,*any,*any,*any,*any,00:00:00
ASAP,*any,*any,*any,*any,*asap
`
rates = `
R1,0,0.2,60,1,0,*middle,2
R2,0,0.1,60s,1s,0,*middle,2
R3,0,0.05,60s,1s,0,*middle,2
R4,1,1,1s,1s,0,*up,2
R5,0,0.5,1s,1s,0,*down,2
LANDLINE_OFFPEAK,0,1,1,60,0,*up,4
LANDLINE_OFFPEAK,0,1,1,1,60,*up,4
GBP_71,0.000000,5.55555,1s,1s,0s,*up,4
GBP_72,0.000000,7.77777,1s,1s,0s,*up,4
GBP_70,0.000000,1,1,1,0,*up,4
RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s,*up,8
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s,*up,8
R_URG,0,0,1,1,0,*down,2
R1,0,0.2,60,1,0
R2,0,0.1,60s,1s,0
R3,0,0.05,60s,1s,0
R4,1,1,1s,1s,0
R5,0,0.5,1s,1s,0
LANDLINE_OFFPEAK,0,1,1,60,0
LANDLINE_OFFPEAK,0,1,1,1,60
GBP_71,0.000000,5.55555,1s,1s,0s
GBP_72,0.000000,7.77777,1s,1s,0s
GBP_70,0.000000,1,1,1,0
RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s
R_URG,0,0,1,1,0
`
destinationRates = `
RT_STANDARD,GERMANY,R1
RT_STANDARD,GERMANY_O2,R2
RT_STANDARD,GERMANY_PREMIUM,R2
RT_DEFAULT,ALL,R2
RT_STD_WEEKEND,GERMANY,R2
RT_STD_WEEKEND,GERMANY_O2,R3
P1,NAT,R4
P2,NAT,R5
T1,NAT,LANDLINE_OFFPEAK
T2,GERMANY,GBP_72
T2,GERMANY_O2,GBP_70
T2,GERMANY_PREMIUM,GBP_71
DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG
DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5
DATA_RATE,*any,LANDLINE_OFFPEAK
RT_URG,URG,R_URG
RT_STANDARD,GERMANY,R1,*middle,4
RT_STANDARD,GERMANY_O2,R2,*middle,4
RT_STANDARD,GERMANY_PREMIUM,R2,*middle,4
RT_DEFAULT,ALL,R2,*middle,4
RT_STD_WEEKEND,GERMANY,R2,*middle,4
RT_STD_WEEKEND,GERMANY_O2,R3,*middle,4
P1,NAT,R4,*middle,4
P2,NAT,R5,*middle,4
T1,NAT,LANDLINE_OFFPEAK,*middle,4
T2,GERMANY,GBP_72,*middle,4
T2,GERMANY_O2,GBP_70,*middle,4
T2,GERMANY_PREMIUM,GBP_71,*middle,4
DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*middle,4
DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*middle,4
DATA_RATE,*any,LANDLINE_OFFPEAK,*middle,4
RT_URG,URG,R_URG,*middle,4
`
ratingPlans = `
STANDARD,RT_STANDARD,WORKDAYS_00,10
@@ -309,7 +309,7 @@ func TestLoadRates(t *testing.T) {
t.Error("Failed to load rates: ", csvr.rates)
}
rate := csvr.rates["R1"].RateSlots[0]
expctRs, err := utils.NewRateSlot(0, 0.2, "60", "1", "0", utils.ROUNDING_MIDDLE, 2)
expctRs, err := utils.NewRateSlot(0, 0.2, "60", "1", "0")
if err != nil {
t.Error("Error loading rate: ", rate, err.Error())
} else if !reflect.DeepEqual(rate, expctRs) ||
@@ -319,7 +319,7 @@ func TestLoadRates(t *testing.T) {
t.Error("Error loading rate: ", rate, expctRs)
}
rate = csvr.rates["R2"].RateSlots[0]
if expctRs, err = utils.NewRateSlot(0, 0.1, "60s", "1s", "0", utils.ROUNDING_MIDDLE, 2); err != nil {
if expctRs, err = utils.NewRateSlot(0, 0.1, "60s", "1s", "0"); err != nil {
t.Error("Error loading rate: ", rate, err.Error())
} else if !reflect.DeepEqual(rate, expctRs) ||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
@@ -328,7 +328,7 @@ func TestLoadRates(t *testing.T) {
t.Error("Error loading rate: ", rate)
}
rate = csvr.rates["R3"].RateSlots[0]
if expctRs, err = utils.NewRateSlot(0, 0.05, "60s", "1s", "0", utils.ROUNDING_MIDDLE, 2); err != nil {
if expctRs, err = utils.NewRateSlot(0, 0.05, "60s", "1s", "0"); err != nil {
t.Error("Error loading rate: ", rate, err.Error())
} else if !reflect.DeepEqual(rate, expctRs) ||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
@@ -337,7 +337,7 @@ func TestLoadRates(t *testing.T) {
t.Error("Error loading rate: ", rate)
}
rate = csvr.rates["R4"].RateSlots[0]
if expctRs, err = utils.NewRateSlot(1, 1.0, "1s", "1s", "0", utils.ROUNDING_UP, 2); err != nil {
if expctRs, err = utils.NewRateSlot(1, 1.0, "1s", "1s", "0"); err != nil {
t.Error("Error loading rate: ", rate, err.Error())
} else if !reflect.DeepEqual(rate, expctRs) ||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
@@ -346,7 +346,7 @@ func TestLoadRates(t *testing.T) {
t.Error("Error loading rate: ", rate)
}
rate = csvr.rates["R5"].RateSlots[0]
if expctRs, err = utils.NewRateSlot(0, 0.5, "1s", "1s", "0", utils.ROUNDING_DOWN, 2); err != nil {
if expctRs, err = utils.NewRateSlot(0, 0.5, "1s", "1s", "0"); err != nil {
t.Error("Error loading rate: ", rate, err.Error())
} else if !reflect.DeepEqual(rate, expctRs) ||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
@@ -355,7 +355,7 @@ func TestLoadRates(t *testing.T) {
t.Error("Error loading rate: ", rate)
}
rate = csvr.rates["LANDLINE_OFFPEAK"].RateSlots[0]
if expctRs, err = utils.NewRateSlot(0, 1, "1", "60", "0", utils.ROUNDING_UP, 4); err != nil {
if expctRs, err = utils.NewRateSlot(0, 1, "1", "60", "0"); err != nil {
t.Error("Error loading rate: ", rate, err.Error())
} else if !reflect.DeepEqual(rate, expctRs) ||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
@@ -364,7 +364,7 @@ func TestLoadRates(t *testing.T) {
t.Error("Error loading rate: ", rate)
}
rate = csvr.rates["LANDLINE_OFFPEAK"].RateSlots[1]
if expctRs, err = utils.NewRateSlot(0, 1, "1", "1", "60", utils.ROUNDING_UP, 4); err != nil {
if expctRs, err = utils.NewRateSlot(0, 1, "1", "1", "60"); err != nil {
t.Error("Error loading rate: ", rate, err.Error())
} else if !reflect.DeepEqual(rate, expctRs) ||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
@@ -384,16 +384,22 @@ func TestLoadDestinationRates(t *testing.T) {
DestinationRateId: "RT_STANDARD",
DestinationRates: []*utils.DestinationRate{
&utils.DestinationRate{
DestinationId: "GERMANY",
Rate: csvr.rates["R1"],
DestinationId: "GERMANY",
Rate: csvr.rates["R1"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
&utils.DestinationRate{
DestinationId: "GERMANY_O2",
Rate: csvr.rates["R2"],
DestinationId: "GERMANY_O2",
Rate: csvr.rates["R2"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
&utils.DestinationRate{
DestinationId: "GERMANY_PREMIUM",
Rate: csvr.rates["R2"],
DestinationId: "GERMANY_PREMIUM",
Rate: csvr.rates["R2"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
},
}
@@ -405,24 +411,30 @@ func TestLoadDestinationRates(t *testing.T) {
DestinationRateId: "RT_DEFAULT",
DestinationRates: []*utils.DestinationRate{
&utils.DestinationRate{
DestinationId: "ALL",
Rate: csvr.rates["R2"],
DestinationId: "ALL",
Rate: csvr.rates["R2"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
},
}) {
t.Errorf("Error loading destination rate: %+v", drs)
t.Errorf("Error loading destination rate: %+v", drs.DestinationRates[0])
}
drs = csvr.destinationRates["RT_STD_WEEKEND"]
if !reflect.DeepEqual(drs, &utils.TPDestinationRate{
DestinationRateId: "RT_STD_WEEKEND",
DestinationRates: []*utils.DestinationRate{
&utils.DestinationRate{
DestinationId: "GERMANY",
Rate: csvr.rates["R2"],
DestinationId: "GERMANY",
Rate: csvr.rates["R2"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
&utils.DestinationRate{
DestinationId: "GERMANY_O2",
Rate: csvr.rates["R3"],
DestinationId: "GERMANY_O2",
Rate: csvr.rates["R3"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
},
}) {
@@ -433,8 +445,10 @@ func TestLoadDestinationRates(t *testing.T) {
DestinationRateId: "P1",
DestinationRates: []*utils.DestinationRate{
&utils.DestinationRate{
DestinationId: "NAT",
Rate: csvr.rates["R4"],
DestinationId: "NAT",
Rate: csvr.rates["R4"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
},
}) {
@@ -445,8 +459,10 @@ func TestLoadDestinationRates(t *testing.T) {
DestinationRateId: "P2",
DestinationRates: []*utils.DestinationRate{
&utils.DestinationRate{
DestinationId: "NAT",
Rate: csvr.rates["R5"],
DestinationId: "NAT",
Rate: csvr.rates["R5"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
},
}) {
@@ -457,8 +473,10 @@ func TestLoadDestinationRates(t *testing.T) {
DestinationRateId: "T1",
DestinationRates: []*utils.DestinationRate{
&utils.DestinationRate{
DestinationId: "NAT",
Rate: csvr.rates["LANDLINE_OFFPEAK"],
DestinationId: "NAT",
Rate: csvr.rates["LANDLINE_OFFPEAK"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
},
}) {
@@ -469,16 +487,22 @@ func TestLoadDestinationRates(t *testing.T) {
DestinationRateId: "T2",
DestinationRates: []*utils.DestinationRate{
&utils.DestinationRate{
DestinationId: "GERMANY",
Rate: csvr.rates["GBP_72"],
DestinationId: "GERMANY",
Rate: csvr.rates["GBP_72"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
&utils.DestinationRate{
DestinationId: "GERMANY_O2",
Rate: csvr.rates["GBP_70"],
DestinationId: "GERMANY_O2",
Rate: csvr.rates["GBP_70"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
&utils.DestinationRate{
DestinationId: "GERMANY_PREMIUM",
Rate: csvr.rates["GBP_71"],
DestinationId: "GERMANY_PREMIUM",
Rate: csvr.rates["GBP_71"],
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
},
}) {
@@ -524,7 +548,7 @@ func TestLoadRatingPlans(t *testing.T) {
},
},
Ratings: map[string]*RIRate{
"d54545c1": &RIRate{
"822a5aef": &RIRate{
ConnectFee: 0,
Rates: []*Rate{
&Rate{
@@ -535,9 +559,9 @@ func TestLoadRatingPlans(t *testing.T) {
},
},
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 2,
RoundingDecimals: 4,
},
"4bb00b9c": &RIRate{
"4a25c533": &RIRate{
ConnectFee: 0,
Rates: []*Rate{
&Rate{
@@ -548,9 +572,9 @@ func TestLoadRatingPlans(t *testing.T) {
},
},
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 2,
RoundingDecimals: 4,
},
"e06c337f": &RIRate{
"b05c5f6b": &RIRate{
ConnectFee: 0,
Rates: []*Rate{
&Rate{
@@ -561,9 +585,9 @@ func TestLoadRatingPlans(t *testing.T) {
},
},
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 2,
RoundingDecimals: 4,
},
"2efe78aa": &RIRate{
"9f49ef8e": &RIRate{
ConnectFee: 0,
Rates: []*Rate{
&Rate{
@@ -573,56 +597,56 @@ func TestLoadRatingPlans(t *testing.T) {
RateUnit: time.Second,
},
},
RoundingMethod: utils.ROUNDING_DOWN,
RoundingDecimals: 2,
RoundingMethod: utils.ROUNDING_MIDDLE,
RoundingDecimals: 4,
},
},
DestinationRates: map[string]RPRateList{
"GERMANY": []*RPRate{
&RPRate{
Timing: "14ae6e41",
Rating: "d54545c1",
Rating: "822a5aef",
Weight: 10,
},
&RPRate{
Timing: "9a6f8e32",
Rating: "4bb00b9c",
Rating: "4a25c533",
Weight: 10,
},
&RPRate{
Timing: "7181e535",
Rating: "4bb00b9c",
Rating: "4a25c533",
Weight: 10,
},
},
"GERMANY_O2": []*RPRate{
&RPRate{
Timing: "14ae6e41",
Rating: "4bb00b9c",
Rating: "4a25c533",
Weight: 10,
},
&RPRate{
Timing: "9a6f8e32",
Rating: "e06c337f",
Rating: "b05c5f6b",
Weight: 10,
},
&RPRate{
Timing: "7181e535",
Rating: "e06c337f",
Rating: "b05c5f6b",
Weight: 10,
},
},
"GERMANY_PREMIUM": []*RPRate{
&RPRate{
Timing: "14ae6e41",
Rating: "4bb00b9c",
Rating: "4a25c533",
Weight: 10,
},
},
"URG": []*RPRate{
&RPRate{
Timing: "96c78ff5",
Rating: "2efe78aa",
Rating: "9f49ef8e",
Weight: 20,
},
},

View File

@@ -52,7 +52,7 @@ type TPLoader interface {
WriteToDatabase(bool, bool) error
}
func NewLoadRate(tag, connectFee, price, ratedUnits, rateIncrements, groupInterval, roundingMethod, roundingDecimals string) (r *utils.TPRate, err error) {
func NewLoadRate(tag, connectFee, price, ratedUnits, rateIncrements, groupInterval string) (r *utils.TPRate, err error) {
cf, err := strconv.ParseFloat(connectFee, 64)
if err != nil {
log.Printf("Error parsing connect fee from: %v", connectFee)
@@ -63,12 +63,7 @@ func NewLoadRate(tag, connectFee, price, ratedUnits, rateIncrements, groupInterv
log.Printf("Error parsing price from: %v", price)
return
}
rd, err := strconv.Atoi(roundingDecimals)
if err != nil {
log.Printf("Error parsing rounding decimals: %s", roundingDecimals)
return
}
rs, err := utils.NewRateSlot(cf, p, ratedUnits, rateIncrements, groupInterval, roundingMethod, rd)
rs, err := utils.NewRateSlot(cf, p, ratedUnits, rateIncrements, groupInterval)
if err != nil {
return nil, err
}
@@ -86,9 +81,6 @@ func ValidNextGroup(present, next *utils.RateSlot) error {
if math.Mod(next.GroupIntervalStartDuration().Seconds(), present.RateIncrementDuration().Seconds()) != 0 {
return errors.New(fmt.Sprintf("GroupIntervalStart of %#v must be a multiple of RateIncrement of %#v", next, present))
}
if present.RoundingMethod != next.RoundingMethod || present.RoundingDecimals != next.RoundingDecimals {
return errors.New(fmt.Sprintf("Rounding stuff must be equal for sam rate tag: %#v, %#v", present, next))
}
return nil
}
@@ -128,8 +120,8 @@ func GetRateInterval(rpl *utils.TPRatingPlanBinding, dr *utils.DestinationRate)
Weight: rpl.Weight,
Rating: &RIRate{
ConnectFee: dr.Rate.RateSlots[0].ConnectFee,
RoundingMethod: dr.Rate.RateSlots[0].RoundingMethod,
RoundingDecimals: dr.Rate.RateSlots[0].RoundingDecimals,
RoundingMethod: dr.RoundingMethod,
RoundingDecimals: dr.RoundingDecimals,
},
}
for _, rl := range dr.Rate.RateSlots {
@@ -189,7 +181,7 @@ var FileValidators = map[string]*FileLineRegexValidator{
regexp.MustCompile(`(?:\w+\s*,\s*){1}(?:\*any\s*,\s*|(?:\d{1,4};?)+\s*,\s*|\s*,\s*){4}(?:\d{2}:\d{2}:\d{2}|\*asap){1}$`),
"Tag([0-9A-Za-z_]),Years([0-9;]|*any|<empty>),Months([0-9;]|*any|<empty>),MonthDays([0-9;]|*any|<empty>),WeekDays([0-9;]|*any|<empty>),Time([0-9:]|*asap)"},
utils.RATES_CSV: &FileLineRegexValidator{utils.RATES_NRCOLS,
regexp.MustCompile(`(?:\w+\s*,\s*){1}(?:\d+\.?\d*,){2}(?:\d+s*,){3}(?:\*\w+,){1}(?:\d+\.?\d*,?){1}$`),
regexp.MustCompile(`(?:\w+\s*,\s*){1}(?:\d+\.?\d*,){2}(?:\d+s*,?){3}$`),
"Tag([0-9A-Za-z_]),ConnectFee([0-9.]),Rate([0-9.]),RateUnit([0-9.]),RateIncrementStart([0-9.])"},
utils.DESTINATION_RATES_CSV: &FileLineRegexValidator{utils.DESTINATION_RATES_NRCOLS,
regexp.MustCompile(`^(?:\w+\s*),(?:\w+\s*),(?:\w+\s*)$`),

View File

@@ -20,11 +20,12 @@ package engine
import (
"bufio"
"github.com/cgrates/cgrates/utils"
"io"
"reflect"
"strings"
"testing"
"github.com/cgrates/cgrates/utils"
)
var timingsSample = `#Tag,Years,Months,MonthDays,WeekDays,Time
@@ -39,7 +40,7 @@ DUMMY,INVALID;DATA
GERMANY_MOBILE,+4915
`
var ratesSample = `#Tag,DestinationRatesTag,TimingTag,Weight
RT_1CENT,0,1,1s,1s,0s,*up,2
RT_1CENT,0,1,1s,1s,0s
DUMMY,INVALID;DATA
`
@@ -410,7 +411,7 @@ func TestTPCSVFileParser(t *testing.T) {
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(record, []string{"RT_1CENT", "0", "1", "1s", "1s", "0s", "*up", "2"}) {
if !reflect.DeepEqual(record, []string{"RT_1CENT", "0", "1", "1s", "1s", "0s"}) {
t.Error("Unexpected record extracted", record)
}
case 3:

View File

@@ -54,9 +54,9 @@ func (rit *RITiming) Stringify() string {
// Separate structure used for rating plan size optimization
type RIRate struct {
ConnectFee float64
Rates RateGroups // GroupRateInterval (start time): Rate
RoundingMethod string //ROUNDING_UP, ROUNDING_DOWN, ROUNDING_MIDDLE
RoundingMethod string
RoundingDecimals int
Rates RateGroups // GroupRateInterval (start time): Rate
}
func (rir *RIRate) Stringify() string {

View File

@@ -198,8 +198,7 @@ func (self *SQLStorage) SetTPRates(tpid string, rts map[string][]*utils.RateSlot
buffer.WriteRune(',')
}
buffer.WriteString(fmt.Sprintf("('%s', '%s', %f, %f, '%s', '%s','%s','%s', %d)",
tpid, rtId, rt.ConnectFee, rt.Rate, rt.RateUnit, rt.RateIncrement, rt.GroupIntervalStart,
rt.RoundingMethod, rt.RoundingDecimals))
tpid, rtId, rt.ConnectFee, rt.Rate, rt.RateUnit, rt.RateIncrement, rt.GroupIntervalStart))
i++
}
}
@@ -900,13 +899,12 @@ func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string]*utils.TPRate,
}
defer rows.Close()
for rows.Next() {
var tag, rate_unit, rate_increment, group_interval_start, roundingMethod string
var tag, rate_unit, rate_increment, group_interval_start string
var connect_fee, rate float64
var roundingDecimals int
if err := rows.Scan(&tag, &connect_fee, &rate, &rate_unit, &rate_increment, &group_interval_start, &roundingMethod, &roundingDecimals); err != nil {
if err := rows.Scan(&tag, &connect_fee, &rate, &rate_unit, &rate_increment, &group_interval_start); err != nil {
return nil, err
}
rs, err := utils.NewRateSlot(connect_fee, rate, rate_unit, rate_increment, group_interval_start, roundingMethod, roundingDecimals)
rs, err := utils.NewRateSlot(connect_fee, rate, rate_unit, rate_increment, group_interval_start)
if err != nil {
return nil, err
}

View File

@@ -729,7 +729,7 @@ func TestTimespanCreateIncrements(t *testing.T) {
if len(ts.Increments) != 3 {
t.Error("Error creating increment slice: ", len(ts.Increments))
}
if len(ts.Increments) < 3 || ts.Increments[2].Cost != 20.0667 {
if len(ts.Increments) < 3 || ts.Increments[2].Cost != 20.0666666667 {
t.Error("Wrong second slice: ", ts.Increments[2].Cost)
}
}

View File

@@ -146,7 +146,7 @@ func (self *TPCSVImporter) importRates(fn string) error {
}
continue
}
rt, err := NewLoadRate(record[0], record[1], record[2], record[3], record[4], record[5], record[6], record[7])
rt, err := NewLoadRate(record[0], record[1], record[2], record[3], record[4], record[5])
if err != nil {
return err
}

View File

@@ -42,10 +42,10 @@ func TestLoadCsvTp(t *testing.T) {
ASAP,*any,*any,*any,*any,*asap`
destinations := `DST_UK_Mobile_BIG5,447596
DST_UK_Mobile_BIG5,447956`
rates := `RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s,*up,8
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s,*up,8`
destinationRates := `DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG
DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5`
rates := `RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s`
destinationRates := `DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*up,8
DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*up,8`
ratingPlans := `RP_UK_Mobile_BIG5_PKG,DR_UK_Mobile_BIG5_PKG,ALWAYS,10
RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10`
ratingProfiles := `*out,cgrates.org,call,*any,2013-01-06T00:00:00Z,RP_UK,

View File

@@ -42,10 +42,10 @@ func TestLoadCsvTp2(t *testing.T) {
ASAP,*any,*any,*any,*any,*asap`
destinations := `DST_UK_Mobile_BIG5,447596
DST_UK_Mobile_BIG5,447956`
rates := `RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s,*up,8
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s,*up,8`
destinationRates := `DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG
DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5`
rates := `RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s`
destinationRates := `DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*up,8
DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*up,8`
ratingPlans := `RP_UK_Mobile_BIG5_PKG,DR_UK_Mobile_BIG5_PKG,ALWAYS,10
RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10`
ratingProfiles := `*out,cgrates.org,call,*any,2013-01-06T00:00:00Z,RP_UK,

View File

@@ -42,10 +42,10 @@ func TestLoadCsvTp3(t *testing.T) {
ASAP,*any,*any,*any,*any,*asap`
destinations := `DST_UK_Mobile_BIG5,447596
DST_UK_Mobile_BIG5,447956`
rates := `RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s,*up,8
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s,*up,8`
destinationRates := `DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG
DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5`
rates := `RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s`
destinationRates := `DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*up,8
DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*up,8`
ratingPlans := `RP_UK_Mobile_BIG5_PKG,DR_UK_Mobile_BIG5_PKG,ALWAYS,10
RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10`
ratingProfiles := `*out,cgrates.org,call,*any,2013-01-06T00:00:00Z,RP_UK,

View File

@@ -40,9 +40,9 @@ type TPRate struct {
}
// Needed so we make sure we always use SetDurations() on a newly created value
func NewRateSlot(connectFee, rate float64, rateUnit, rateIncrement, grpInterval, rndMethod string, rndDecimals int) (*RateSlot, error) {
func NewRateSlot(connectFee, rate float64, rateUnit, rateIncrement, grpInterval string) (*RateSlot, error) {
rs := &RateSlot{ConnectFee: connectFee, Rate: rate, RateUnit: rateUnit, RateIncrement: rateIncrement,
GroupIntervalStart: grpInterval, RoundingMethod: rndMethod, RoundingDecimals: rndDecimals}
GroupIntervalStart: grpInterval}
if err := rs.SetDurations(); err != nil {
return nil, err
}
@@ -55,8 +55,6 @@ type RateSlot struct {
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
rateUnitDur time.Duration
rateIncrementDur time.Duration
groupIntervalStartDur time.Duration
@@ -93,9 +91,11 @@ type TPDestinationRate struct {
}
type DestinationRate struct {
DestinationId string // The destination identity
RateId string // The rate identity
Rate *TPRate
DestinationId string // The destination identity
RateId string // The rate identity
Rate *TPRate
RoundingMethod string
RoundingDecimals int
}
type ApierTPTiming struct {

View File

@@ -51,8 +51,8 @@ const (
DERIVED_CHARGERS_CSV = "DerivedChargers.csv"
TIMINGS_NRCOLS = 6
DESTINATIONS_NRCOLS = 2
RATES_NRCOLS = 8
DESTINATION_RATES_NRCOLS = 3
RATES_NRCOLS = 6
DESTINATION_RATES_NRCOLS = 5
DESTRATE_TIMINGS_NRCOLS = 4
RATE_PROFILES_NRCOLS = 7
SHARED_GROUPS_NRCOLS = 4