From 643636872e02457aee48d03a84baf5fbed6f517f Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Mon, 23 Mar 2015 14:41:25 +0200 Subject: [PATCH 1/4] moved max cost and strategy at destination rate level --- .../mysql/create_tariffplan_tables.sql | 8 +- .../postgres/create_tariffplan_tables.sql | 6 +- .../tariffplans/cdrstats/DestinationRates.csv | 4 +- data/tariffplans/cdrstats/Rates.csv | 2 +- .../prepaid1centpsec/DestinationRates.csv | 10 +- data/tariffplans/prepaid1centpsec/Rates.csv | 6 +- .../tariffplans/tutorial/DestinationRates.csv | 16 +-- data/tariffplans/tutorial/Rates.csv | 14 +-- engine/loader_csv.go | 9 +- engine/loader_csv_test.go | 98 +++++++++---------- engine/loader_helpers.go | 15 ++- engine/loader_helpers_test.go | 12 +-- engine/models.go | 4 +- engine/rateinterval.go | 2 +- engine/storage_sql.go | 4 +- engine/tpimporter_csv.go | 9 +- general_tests/costs1_test.go | 14 +-- general_tests/datachrg1_test.go | 8 +- general_tests/ddazmbl1_test.go | 8 +- general_tests/ddazmbl2_test.go | 8 +- general_tests/ddazmbl3_test.go | 8 +- general_tests/smschrg1_test.go | 4 +- utils/apitpdata.go | 8 +- utils/consts.go | 4 +- 24 files changed, 147 insertions(+), 134 deletions(-) diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql index 0728fa7ea..a24329fe3 100644 --- a/data/storage/mysql/create_tariffplan_tables.sql +++ b/data/storage/mysql/create_tariffplan_tables.sql @@ -44,9 +44,7 @@ CREATE TABLE `tp_rates` ( `id` int(11) NOT NULL AUTO_INCREMENT, `tpid` varchar(64) NOT NULL, `tag` varchar(64) NOT NULL, - `connect_fee` decimal(7,4) NOT NULL, - `max_cost` decimal(7,4) NOT NULL, - `max_cost_strategy` varchar(16) NOT NULL, + `connect_fee` decimal(7,4) NOT NULL, `rate` decimal(7,4) NOT NULL, `rate_unit` varchar(16) NOT NULL, `rate_increment` varchar(16) NOT NULL, @@ -71,7 +69,9 @@ CREATE TABLE `tp_destination_rates` ( `rates_tag` varchar(64) NOT NULL, `rounding_method` varchar(255) NOT NULL, `rounding_decimals` tinyint(4) NOT NULL, - `created_at` TIMESTAMP, + `max_cost` decimal(7,4) NOT NULL, + `max_cost_strategy` varchar(16) NOT NULL, + `created_at` TIMESTAMP, PRIMARY KEY (`id`), KEY `tpid` (`tpid`), KEY `tpid_drid` (`tpid`,`tag`), diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql index 178802b85..085682dcc 100644 --- a/data/storage/postgres/create_tariffplan_tables.sql +++ b/data/storage/postgres/create_tariffplan_tables.sql @@ -40,9 +40,7 @@ CREATE TABLE tp_rates ( id SERIAL PRIMARY KEY, tpid VARCHAR(64) NOT NULL, tag VARCHAR(64) NOT NULL, - connect_fee NUMERIC(7,4) NOT NULL, - max_cost NUMERIC(7,4) NOT NULL, - max_cost_strategy VARCHAR(16) NOT NULL, + connect_fee NUMERIC(7,4) NOT NULL, rate NUMERIC(7,4) NOT NULL, rate_unit VARCHAR(16) NOT NULL, rate_increment VARCHAR(16) NOT NULL, @@ -65,6 +63,8 @@ CREATE TABLE tp_destination_rates ( rates_tag VARCHAR(64) NOT NULL, rounding_method VARCHAR(255) NOT NULL, rounding_decimals SMALLINT NOT NULL, + max_cost NUMERIC(7,4) NOT NULL, + max_cost_strategy VARCHAR(16) NOT NULL, created_at TIMESTAMP, UNIQUE (tpid, tag , destinations_tag) ); diff --git a/data/tariffplans/cdrstats/DestinationRates.csv b/data/tariffplans/cdrstats/DestinationRates.csv index 9dbe6e9a9..2749b9e4e 100644 --- a/data/tariffplans/cdrstats/DestinationRates.csv +++ b/data/tariffplans/cdrstats/DestinationRates.csv @@ -1,2 +1,2 @@ -#Tag,DestinationsTag,RatesTag,RoundingMethod,RoundingDecimals -DR_RETAIL,GERMANY,RT_1CENT,*up,4 \ No newline at end of file +#Tag,DestinationsTag,RatesTag,RoundingMethod,RoundingDecimals,MaxCost,MaxCostStrategy +DR_RETAIL,GERMANY,RT_1CENT,*up,4,0, diff --git a/data/tariffplans/cdrstats/Rates.csv b/data/tariffplans/cdrstats/Rates.csv index c4f0e9c63..2afc7701b 100644 --- a/data/tariffplans/cdrstats/Rates.csv +++ b/data/tariffplans/cdrstats/Rates.csv @@ -1,2 +1,2 @@ #Tag,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart -RT_1CENT,0,0,,1,1s,1s,0s +RT_1CENT,0,1,1s,1s,0s diff --git a/data/tariffplans/prepaid1centpsec/DestinationRates.csv b/data/tariffplans/prepaid1centpsec/DestinationRates.csv index 64164f62b..b5d2474b3 100644 --- a/data/tariffplans/prepaid1centpsec/DestinationRates.csv +++ b/data/tariffplans/prepaid1centpsec/DestinationRates.csv @@ -1,5 +1,5 @@ -#Tag,DestinationsTag,RatesTag,RoundingMethod,RoundingDecimals -DR_RETAIL,GERMANY,RT_1CENT,*up,4 -DR_RETAIL,GERMANY_MOBILE,RT_1CENT,*up,4 -DR_DATA_1,*any,RT_DATA_2c,*up,4 -DR_SMS_1,*any,RT_SMS_5c,*up,4 \ No newline at end of file +#Tag,DestinationsTag,RatesTag,RoundingMethod,RoundingDecimals,MaxCost,MaxCostStrategy +DR_RETAIL,GERMANY,RT_1CENT,*up,4,0, +DR_RETAIL,GERMANY_MOBILE,RT_1CENT,*up,4,0, +DR_DATA_1,*any,RT_DATA_2c,*up,4,0, +DR_SMS_1,*any,RT_SMS_5c,*up,4,0, diff --git a/data/tariffplans/prepaid1centpsec/Rates.csv b/data/tariffplans/prepaid1centpsec/Rates.csv index 02365a72c..991ce0720 100644 --- a/data/tariffplans/prepaid1centpsec/Rates.csv +++ b/data/tariffplans/prepaid1centpsec/Rates.csv @@ -1,4 +1,4 @@ #Tag,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart -RT_1CENT,0,0,,1,1s,1s,0s -RT_DATA_2c,0,0,,0.002,10,10,0 -RT_SMS_5c,0,0,,0.005,1,1,0 +RT_1CENT,0,1,1s,1s,0s +RT_DATA_2c,0,0.002,10,10,0 +RT_SMS_5c,0,0.005,1,1,0 diff --git a/data/tariffplans/tutorial/DestinationRates.csv b/data/tariffplans/tutorial/DestinationRates.csv index b902c0601..8a4e10c34 100644 --- a/data/tariffplans/tutorial/DestinationRates.csv +++ b/data/tariffplans/tutorial/DestinationRates.csv @@ -1,8 +1,8 @@ -#Tag,DestinationsTag,RatesTag,RoundingMethod,RoundingDecimals -DR_1002_20CNT,DST_1002,RT_20CNT,*up,4 -DR_1002_10CNT,DST_1002,RT_10CNT,*up,4 -DR_1003_20CNT,DST_1003,RT_40CNT,*up,4 -DR_1003_10CNT,DST_1003,RT_10CNT,*up,4 -DR_FS_40CNT,DST_FS,RT_40CNT,*up,4 -DR_FS_10CNT,DST_FS,RT_10CNT,*up,4 -DR_SPECIAL_1002,DST_1002,RT_1CNT,*up,4 +#Tag,DestinationsTag,RatesTag,RoundingMethod,RoundingDecimals,MaxCost,MaxCostStrategy +DR_1002_20CNT,DST_1002,RT_20CNT,*up,4,0, +DR_1002_10CNT,DST_1002,RT_10CNT,*up,4,0, +DR_1003_20CNT,DST_1003,RT_40CNT,*up,4,0, +DR_1003_10CNT,DST_1003,RT_10CNT,*up,4,0, +DR_FS_40CNT,DST_FS,RT_40CNT,*up,4,0, +DR_FS_10CNT,DST_FS,RT_10CNT,*up,4,0, +DR_SPECIAL_1002,DST_1002,RT_1CNT,*up,4,0, diff --git a/data/tariffplans/tutorial/Rates.csv b/data/tariffplans/tutorial/Rates.csv index f66af1735..a1b758e7a 100644 --- a/data/tariffplans/tutorial/Rates.csv +++ b/data/tariffplans/tutorial/Rates.csv @@ -1,8 +1,8 @@ #Tag,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart -RT_10CNT,0.2,0,,0.1,60s,60s,0s -RT_10CNT,0,0,,0.05,60s,1s,60s -RT_20CNT,0,0,.4,0.2,60s,60s,0s -RT_20CNT,0,0,,0.1,60s,1s,60s -RT_40CNT,0,0,.8,0.4,60s,30s,0s -RT_40CNT,0,0,,0.2,60s,10s,60s -RT_1CNT,0,0,,0.01,60s,60s,0s +RT_10CNT,0.2,0.1,60s,60s,0s +RT_10CNT,0,0.05,60s,1s,60s +RT_20CNT,0,.4,0.2,60s,60s,0s +RT_20CNT,0,0.1,60s,1s,60s +RT_40CNT,0,.8,0.4,60s,30s,0s +RT_40CNT,0,0.2,60s,10s,60s +RT_1CNT,0,0.01,60s,60s,0s diff --git a/engine/loader_csv.go b/engine/loader_csv.go index e787426de..d7cf74186 100644 --- a/engine/loader_csv.go +++ b/engine/loader_csv.go @@ -398,7 +398,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 } @@ -438,6 +438,11 @@ func (csvr *CSVReader) LoadDestinationRates() (err error) { log.Printf("Error parsing rounding decimals: %s", record[4]) return err } + maxCost, err := strconv.ParseFloat(record[5], 64) + if err != nil { + log.Printf("Error parsing max cost from: %v", record[5]) + return err + } destinationExists := record[1] == utils.ANY if !destinationExists { _, destinationExists = csvr.destinations[record[1]] @@ -458,6 +463,8 @@ func (csvr *CSVReader) LoadDestinationRates() (err error) { Rate: r, RoundingMethod: record[3], RoundingDecimals: roundingDecimals, + MaxCost: maxCost, + MaxCostStrategy: record[6], }, }, } diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 75daefa19..5c0901c01 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -55,37 +55,37 @@ ALWAYS,*any,*any,*any,*any,00:00:00 ASAP,*any,*any,*any,*any,*asap ` rates = ` -R1,0,0,,0.2,60,1,0 -R2,0,0,,0.1,60s,1s,0 -R3,0,0,,0.05,60s,1s,0 -R4,1,0,,1,1s,1s,0 -R5,0,0,,0.5,1s,1s,0 -LANDLINE_OFFPEAK,0,0,,1,1,60,0 -LANDLINE_OFFPEAK,0,0,,1,1,1,60 -GBP_71,0.000000,0,,5.55555,1s,1s,0s -GBP_72,0.000000,0,,7.77777,1s,1s,0s -GBP_70,0.000000,0,,1,1,1,0 -RT_UK_Mobile_BIG5_PKG,0.01,0,,0,20s,20s,0s -RT_UK_Mobile_BIG5,0.01,0,,0.10,1s,1s,0s -R_URG,0,0,,0,1,1,0 +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,*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 +RT_STANDARD,GERMANY,R1,*middle,4,0, +RT_STANDARD,GERMANY_O2,R2,*middle,4,0, +RT_STANDARD,GERMANY_PREMIUM,R2,*middle,4,0, +RT_DEFAULT,ALL,R2,*middle,4,0, +RT_STD_WEEKEND,GERMANY,R2,*middle,4,0, +RT_STD_WEEKEND,GERMANY_O2,R3,*middle,4,0, +P1,NAT,R4,*middle,4,0, +P2,NAT,R5,*middle,4,0, +T1,NAT,LANDLINE_OFFPEAK,*middle,4,0, +T2,GERMANY,GBP_72,*middle,4,0, +T2,GERMANY_O2,GBP_70,*middle,4,0, +T2,GERMANY_PREMIUM,GBP_71,*middle,4,0, +DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*middle,4,0, +DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*middle,4,0, +DATA_RATE,*any,LANDLINE_OFFPEAK,*middle,4,0, +RT_URG,URG,R_URG,*middle,4,0, ` ratingPlans = ` STANDARD,RT_STANDARD,WORKDAYS_00,10 @@ -323,7 +323,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, "", 0.2, "60", "1", "0") + 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) || @@ -333,7 +333,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, "", 0.1, "60s", "1s", "0"); 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() || @@ -342,7 +342,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, "", 0.05, "60s", "1s", "0"); 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() || @@ -351,7 +351,7 @@ func TestLoadRates(t *testing.T) { t.Error("Error loading rate: ", rate) } rate = csvr.rates["R4"].RateSlots[0] - if expctRs, err = utils.NewRateSlot(1, 0, "", 1.0, "1s", "1s", "0"); 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() || @@ -360,7 +360,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, "", 0.5, "1s", "1s", "0"); 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() || @@ -369,7 +369,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, 0, "", 1, "1", "60", "0"); 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() || @@ -378,7 +378,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, 0, "", 1, "1", "1", "60"); 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() || @@ -562,7 +562,7 @@ func TestLoadRatingPlans(t *testing.T) { }, }, Ratings: map[string]*RIRate{ - "822a5aef": &RIRate{ + "b457f86d": &RIRate{ ConnectFee: 0, Rates: []*Rate{ &Rate{ @@ -575,7 +575,7 @@ func TestLoadRatingPlans(t *testing.T) { RoundingMethod: utils.ROUNDING_MIDDLE, RoundingDecimals: 4, }, - "4a25c533": &RIRate{ + "16e9ee19": &RIRate{ ConnectFee: 0, Rates: []*Rate{ &Rate{ @@ -588,7 +588,7 @@ func TestLoadRatingPlans(t *testing.T) { RoundingMethod: utils.ROUNDING_MIDDLE, RoundingDecimals: 4, }, - "b05c5f6b": &RIRate{ + "638dc1ab": &RIRate{ ConnectFee: 0, Rates: []*Rate{ &Rate{ @@ -601,7 +601,7 @@ func TestLoadRatingPlans(t *testing.T) { RoundingMethod: utils.ROUNDING_MIDDLE, RoundingDecimals: 4, }, - "9f49ef8e": &RIRate{ + "3913037f": &RIRate{ ConnectFee: 0, Rates: []*Rate{ &Rate{ @@ -619,55 +619,55 @@ func TestLoadRatingPlans(t *testing.T) { "GERMANY": []*RPRate{ &RPRate{ Timing: "4c954a4f", - Rating: "822a5aef", + Rating: "b457f86d", Weight: 10, }, &RPRate{ Timing: "4d593287", - Rating: "4a25c533", + Rating: "16e9ee19", Weight: 10, }, &RPRate{ Timing: "a60bfb13", - Rating: "4a25c533", + Rating: "16e9ee19", Weight: 10, }, }, "GERMANY_O2": []*RPRate{ &RPRate{ Timing: "4c954a4f", - Rating: "4a25c533", + Rating: "16e9ee19", Weight: 10, }, &RPRate{ Timing: "4d593287", - Rating: "b05c5f6b", + Rating: "638dc1ab", Weight: 10, }, &RPRate{ Timing: "a60bfb13", - Rating: "b05c5f6b", + Rating: "638dc1ab", Weight: 10, }, }, "GERMANY_PREMIUM": []*RPRate{ &RPRate{ Timing: "4c954a4f", - Rating: "4a25c533", + Rating: "16e9ee19", Weight: 10, }, }, "URG": []*RPRate{ &RPRate{ Timing: "30eab300", - Rating: "9f49ef8e", + Rating: "3913037f", Weight: 20, }, }, }, } if !reflect.DeepEqual(rplan, expected) { - t.Errorf("Error loading destination rate timing: %+v", rplan.DestinationRates["GERMANY_O2"][0]) + t.Errorf("Error loading destination rate timing: %+v", rplan.Ratings) } } diff --git a/engine/loader_helpers.go b/engine/loader_helpers.go index b69d7e345..49369358e 100644 --- a/engine/loader_helpers.go +++ b/engine/loader_helpers.go @@ -95,24 +95,19 @@ type TPLoader interface { WriteToDatabase(bool, bool) error } -func NewLoadRate(tag, connectFee, maxCost, maxCostStrategy, price, ratedUnits, rateIncrements, groupInterval 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) return } - mc, err := strconv.ParseFloat(maxCost, 64) - if err != nil { - log.Printf("Error parsing max cost from: %v", maxCost) - return - } p, err := strconv.ParseFloat(price, 64) if err != nil { log.Printf("Error parsing price from: %v", price) return } - rs, err := utils.NewRateSlot(cf, mc, maxCostStrategy, p, ratedUnits, rateIncrements, groupInterval) + rs, err := utils.NewRateSlot(cf, p, ratedUnits, rateIncrements, groupInterval) if err != nil { return nil, err } @@ -312,6 +307,8 @@ func GetRateInterval(rpl *utils.TPRatingPlanBinding, dr *utils.DestinationRate) ConnectFee: dr.Rate.RateSlots[0].ConnectFee, RoundingMethod: dr.RoundingMethod, RoundingDecimals: dr.RoundingDecimals, + MaxCost: dr.MaxCost, + MaxCostStrategy: dr.MaxCostStrategy, }, } for _, rl := range dr.Rate.RateSlots { @@ -371,10 +368,10 @@ 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|),Months([0-9;]|*any|),MonthDays([0-9;]|*any|),WeekDays([0-9;]|*any|),Time([0-9:]|*asap)"}, utils.RATES_CSV: &FileLineRegexValidator{utils.RATES_NRCOLS, - regexp.MustCompile(`(?:\w+\s*),(?:\d+\.*\d*s*),(?:\d+\.*\d*s*),(?:\*free|\*diconnect)?,(?:\d+\.*\d*s*),(?:\d+\.*\d*(ns|us|µs|ms|s|m|h)*\s*),(?:\d+\.*\d*(ns|us|µs|ms|s|m|h)*\s*),(?:\d+\.*\d*(ns|us|µs|ms|s|m|h)*\s*)$`), + regexp.MustCompile(`(?:\w+\s*),(?:\d+\.*\d*s*),(?:\d+\.*\d*s*),(?:\d+\.*\d*(ns|us|µs|ms|s|m|h)*\s*),(?:\d+\.*\d*(ns|us|µs|ms|s|m|h)*\s*),(?:\d+\.*\d*(ns|us|µs|ms|s|m|h)*\s*)$`), "Tag([0-9A-Za-z_]),ConnectFee([0-9.]),Rate([0-9.]),RateUnit([0-9.]ns|us|µs|ms|s|m|h),RateIncrementStart([0-9.]ns|us|µs|ms|s|m|h),GroupIntervalStart([0-9.]ns|us|µs|ms|s|m|h)"}, utils.DESTINATION_RATES_CSV: &FileLineRegexValidator{utils.DESTINATION_RATES_NRCOLS, - regexp.MustCompile(`^(?:\w+\s*),(?:\w+\s*|\*any),(?:\w+\s*),(?:\*up|\*down|\*middle),(?:\d+)$`), + regexp.MustCompile(`^(?:\w+\s*),(?:\w+\s*|\*any),(?:\w+\s*),(?:\*up|\*down|\*middle),(?:\d+),(?:\d+\.*\d*s*),(?:\*free|\*diconnect)?$`), "Tag([0-9A-Za-z_]),DestinationsTag([0-9A-Za-z_]|*any),RatesTag([0-9A-Za-z_]),RoundingMethod(*up|*middle|*down),RoundingDecimals([0-9.])"}, utils.RATING_PLANS_CSV: &FileLineRegexValidator{utils.DESTRATE_TIMINGS_NRCOLS, regexp.MustCompile(`(?:\w+\s*,\s*){3}(?:\d+.?\d*){1}$`), diff --git a/engine/loader_helpers_test.go b/engine/loader_helpers_test.go index aef61c6b6..438e8abd3 100644 --- a/engine/loader_helpers_test.go +++ b/engine/loader_helpers_test.go @@ -40,15 +40,15 @@ DUMMY,INVALID;DATA GERMANY_MOBILE,+4915 ` var ratesSample = `#Tag,DestinationRatesTag,TimingTag,Weight -RT_1CENT,0,0,,1,1s,1s,0s +RT_1CENT,0,1,1s,1s,0s DUMMY,INVALID;DATA -RT_DATA_2c,0,0,,0.002,10,10,0 +RT_DATA_2c,0,0.002,10,10,0 ` -var destRatesSample = `#Tag,DestinationsTag,RatesTag -DR_RETAIL,GERMANY,RT_1CENT,*up,0 +var destRatesSample = `#Tag,DestinationsTag,RatesTag,MaxCost,MaxCostStrategy +DR_RETAIL,GERMANY,RT_1CENT,*up,0,0, DUMMY,INVALID;DATA -DR_DATA_1,*any,RT_DATA_2c,*up,2 +DR_DATA_1,*any,RT_DATA_2c,*up,2,0, ` var ratingPlansSample = `#Tag,DestinationRatesTag,TimingTag,Weight RP_RETAIL,DR_RETAIL,ALWAYS,10 @@ -415,7 +415,7 @@ func TestTPCSVFileParser(t *testing.T) { if err != nil { t.Error(err) } - if !reflect.DeepEqual(record, []string{"RT_1CENT", "0", "0", "", "1", "1s", "1s", "0s"}) { + if !reflect.DeepEqual(record, []string{"RT_1CENT", "0", "1", "1s", "1s", "0s"}) { t.Error("Unexpected record extracted", record) } case 3: diff --git a/engine/models.go b/engine/models.go index dae967889..4b4277b7a 100644 --- a/engine/models.go +++ b/engine/models.go @@ -54,8 +54,6 @@ type TpRate struct { Tpid string Tag string ConnectFee float64 - MaxCost float64 - MaxCostStrategy string Rate float64 RateUnit string RateIncrement string @@ -71,6 +69,8 @@ type TpDestinationRate struct { RatesTag string RoundingMethod string RoundingDecimals int + MaxCost float64 + MaxCostStrategy string CreatedAt time.Time } diff --git a/engine/rateinterval.go b/engine/rateinterval.go index b8255259a..5a2f8e273 100644 --- a/engine/rateinterval.go +++ b/engine/rateinterval.go @@ -187,7 +187,7 @@ type RIRate struct { } func (rir *RIRate) Stringify() string { - str := fmt.Sprintf("%v %v %v", rir.ConnectFee, rir.RoundingMethod, rir.RoundingDecimals) + str := fmt.Sprintf("%v %v %v %v %v", rir.ConnectFee, rir.RoundingMethod, rir.RoundingDecimals, rir.MaxCost, rir.MaxCostStrategy) for _, r := range rir.Rates { str += r.Stringify() } diff --git a/engine/storage_sql.go b/engine/storage_sql.go index af1f18925..206bc975f 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -1073,7 +1073,7 @@ func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string]*utils.TPRate, } for _, tr := range tpRates { - rs, err := utils.NewRateSlot(tr.ConnectFee, tr.MaxCost, tr.MaxCostStrategy, tr.Rate, tr.RateUnit, tr.RateIncrement, tr.GroupIntervalStart) + rs, err := utils.NewRateSlot(tr.ConnectFee, tr.Rate, tr.RateUnit, tr.RateIncrement, tr.GroupIntervalStart) if err != nil { return nil, err } @@ -1126,6 +1126,8 @@ func (self *SQLStorage) GetTpDestinationRates(tpid, tag string, pagination *util RateId: tpDr.RatesTag, RoundingMethod: tpDr.RoundingMethod, RoundingDecimals: tpDr.RoundingDecimals, + MaxCost: tpDr.MaxCost, + MaxCostStrategy: tpDr.MaxCostStrategy, }, }, } diff --git a/engine/tpimporter_csv.go b/engine/tpimporter_csv.go index e02dd60c3..a9e343081 100644 --- a/engine/tpimporter_csv.go +++ b/engine/tpimporter_csv.go @@ -157,7 +157,7 @@ func (self *TPCSVImporter) importRates(fn string) error { } continue } - newRt, err := NewLoadRate(record[0], record[1], record[2], record[3], record[4], record[5], record[6], record[7]) + newRt, err := NewLoadRate(record[0], record[1], record[2], record[3], record[4], record[5]) if err != nil { return err } @@ -200,6 +200,11 @@ func (self *TPCSVImporter) importDestinationRates(fn string) error { log.Printf("Error parsing rounding decimals: %s", record[4]) return err } + maxCost, err := strconv.ParseFloat(record[5], 64) + if err != nil { + log.Printf("Error parsing max cost from: %v", record[5]) + return err + } if _, hasIt := drs[record[0]]; !hasIt { drs[record[0]] = make([]*utils.DestinationRate, 0) } @@ -208,6 +213,8 @@ func (self *TPCSVImporter) importDestinationRates(fn string) error { RateId: record[2], RoundingMethod: record[3], RoundingDecimals: roundingDecimals, + MaxCost: maxCost, + MaxCostStrategy: record[6], }) } diff --git a/general_tests/costs1_test.go b/general_tests/costs1_test.go index 055c07d35..35cd81004 100644 --- a/general_tests/costs1_test.go +++ b/general_tests/costs1_test.go @@ -40,13 +40,13 @@ ASAP,*any,*any,*any,*any,*asap` GERMANY_MOBILE,+4915 GERMANY_MOBILE,+4916 GERMANY_MOBILE,+4917` - rates := `RT_1CENT,0,0,,1,1s,1s,0s -RT_DATA_2c,0,0,,0.002,10,10,0 -RT_SMS_5c,0,0,,0.005,1,1,0` - destinationRates := `DR_RETAIL,GERMANY,RT_1CENT,*up,4 -DR_RETAIL,GERMANY_MOBILE,RT_1CENT,*up,4 -DR_DATA_1,*any,RT_DATA_2c,*up,4 -DR_SMS_1,*any,RT_SMS_5c,*up,4` + rates := `RT_1CENT,0,1,1s,1s,0s +RT_DATA_2c,0,0.002,10,10,0 +RT_SMS_5c,0,0.005,1,1,0` + destinationRates := `DR_RETAIL,GERMANY,RT_1CENT,*up,4,0, +DR_RETAIL,GERMANY_MOBILE,RT_1CENT,*up,4,0, +DR_DATA_1,*any,RT_DATA_2c,*up,4,0, +DR_SMS_1,*any,RT_SMS_5c,*up,4,0,` ratingPlans := `RP_RETAIL,DR_RETAIL,ALWAYS,10 RP_DATA1,DR_DATA_1,ALWAYS,10 RP_SMS1,DR_SMS_1,ALWAYS,10` diff --git a/general_tests/datachrg1_test.go b/general_tests/datachrg1_test.go index ca4984a20..ce14ec326 100644 --- a/general_tests/datachrg1_test.go +++ b/general_tests/datachrg1_test.go @@ -37,10 +37,10 @@ func TestSetStorageDtChrg1(t *testing.T) { func TestLoadCsvTpDtChrg1(t *testing.T) { timings := `TM1,*any,*any,*any,*any,00:00:00 TM2,*any,*any,*any,*any,01:00:00` - rates := `RT_DATA_2c,0,0,,0.002,10,10,0 -RT_DATA_1c,0,0,,0.001,10,10,0` - destinationRates := `DR_DATA_1,*any,RT_DATA_2c,*up,4 -DR_DATA_2,*any,RT_DATA_1c,*up,4` + rates := `RT_DATA_2c,0,0.002,10,10,0 +RT_DATA_1c,0,0.001,10,10,0` + destinationRates := `DR_DATA_1,*any,RT_DATA_2c,*up,4,0, +DR_DATA_2,*any,RT_DATA_1c,*up,4,0,` ratingPlans := `RP_DATA1,DR_DATA_1,TM1,10 RP_DATA1,DR_DATA_2,TM2,10` ratingProfiles := `*out,cgrates.org,data,*any,2012-01-01T00:00:00Z,RP_DATA1,` diff --git a/general_tests/ddazmbl1_test.go b/general_tests/ddazmbl1_test.go index 7c393d9cb..1508ac91c 100644 --- a/general_tests/ddazmbl1_test.go +++ b/general_tests/ddazmbl1_test.go @@ -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,,0,20s,20s,0s -RT_UK_Mobile_BIG5,0.01,0,,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` + 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,0, +DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*up,8,0,` 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, diff --git a/general_tests/ddazmbl2_test.go b/general_tests/ddazmbl2_test.go index ea4c3e0b8..64d97f1ef 100644 --- a/general_tests/ddazmbl2_test.go +++ b/general_tests/ddazmbl2_test.go @@ -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,,0,20s,20s,0s -RT_UK_Mobile_BIG5,0.01,0,,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` + 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,0, +DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*up,8,0,` 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, diff --git a/general_tests/ddazmbl3_test.go b/general_tests/ddazmbl3_test.go index 4905f32fe..4333ec064 100644 --- a/general_tests/ddazmbl3_test.go +++ b/general_tests/ddazmbl3_test.go @@ -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,,0,20s,20s,0s -RT_UK_Mobile_BIG5,0.01,0,,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` + 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,0, +DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*up,8,0,` 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, diff --git a/general_tests/smschrg1_test.go b/general_tests/smschrg1_test.go index d9d02a8f9..2e8442092 100644 --- a/general_tests/smschrg1_test.go +++ b/general_tests/smschrg1_test.go @@ -36,8 +36,8 @@ func TestSMSSetStorageSmsChrg1(t *testing.T) { func TestSMSLoadCsvTpSmsChrg1(t *testing.T) { timings := `ALWAYS,*any,*any,*any,*any,00:00:00` - rates := `RT_SMS_5c,0,0,,0.005,1,1,0` - destinationRates := `DR_SMS_1,*any,RT_SMS_5c,*up,4` + rates := `RT_SMS_5c,0,0.005,1,1,0` + destinationRates := `DR_SMS_1,*any,RT_SMS_5c,*up,4,0,` ratingPlans := `RP_SMS1,DR_SMS_1,ALWAYS,10` ratingProfiles := `*out,cgrates.org,sms,*any,2012-01-01T00:00:00Z,RP_SMS1,` csvr := engine.NewStringCSVReader(ratingDb, acntDb, ',', "", timings, rates, destinationRates, ratingPlans, ratingProfiles, diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 31610756b..2cc0a783c 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -86,8 +86,8 @@ func (self *TPRate) AsExportSlice() [][]string { } // Needed so we make sure we always use SetDurations() on a newly created value -func NewRateSlot(connectFee, maxCost float64, maxCostStrategy string, rate float64, rateUnit, rateIncrement, grpInterval string) (*RateSlot, error) { - rs := &RateSlot{ConnectFee: connectFee, Rate: rate, RateUnit: rateUnit, RateIncrement: rateIncrement, MaxCost: maxCost, MaxCostStrategy: maxCostStrategy, +func NewRateSlot(connectFee, rate float64, rateUnit, rateIncrement, grpInterval string) (*RateSlot, error) { + rs := &RateSlot{ConnectFee: connectFee, Rate: rate, RateUnit: rateUnit, RateIncrement: rateIncrement, GroupIntervalStart: grpInterval} if err := rs.SetDurations(); err != nil { return nil, err @@ -103,8 +103,6 @@ type RateSlot struct { GroupIntervalStart string // Group position rateUnitDur time.Duration rateIncrementDur time.Duration - MaxCost float64 - MaxCostStrategy string groupIntervalStartDur time.Duration } @@ -153,6 +151,8 @@ type DestinationRate struct { Rate *TPRate RoundingMethod string RoundingDecimals int + MaxCost float64 + MaxCostStrategy string } type ApierTPTiming struct { diff --git a/utils/consts.go b/utils/consts.go index cd700a5c2..3c28c4705 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -60,8 +60,8 @@ const ( CDR_STATS_CSV = "CdrStats.csv" TIMINGS_NRCOLS = 6 DESTINATIONS_NRCOLS = 2 - RATES_NRCOLS = 8 - DESTINATION_RATES_NRCOLS = 5 + RATES_NRCOLS = 6 + DESTINATION_RATES_NRCOLS = 7 DESTRATE_TIMINGS_NRCOLS = 4 RATE_PROFILES_NRCOLS = 7 SHARED_GROUPS_NRCOLS = 4 From 67f6d1240f23ec04a147a10779e56b7919889da1 Mon Sep 17 00:00:00 2001 From: Eloy Coto Date: Mon, 23 Mar 2015 14:32:46 +0000 Subject: [PATCH 2/4] Fix changelog issues on debian jessie --- data/scripts/pkg/debian/changelog | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/scripts/pkg/debian/changelog b/data/scripts/pkg/debian/changelog index 0ea9da906..4d1301026 100644 --- a/data/scripts/pkg/debian/changelog +++ b/data/scripts/pkg/debian/changelog @@ -1,23 +1,23 @@ -cgrates (0.9.1-rc6) UNRELEASED; urgency=low +cgrates (0.9.1~rc6) UNRELEASED; urgency=low * RC6. -- DanB Wednesday, 10 September 2014 13:30:00 +0100 -cgrates (0.9.1-rc5) UNRELEASED; urgency=low +cgrates (0.9.1~rc5) UNRELEASED; urgency=low * RC5. -- DanB Monday, 18 August 2014 13:30:00 +0100 -cgrates (0.9.1-rc4) UNRELEASED; urgency=low +cgrates (0.9.1~rc4) UNRELEASED; urgency=low * RC4. -- DanB Thursday, 25 March 2014 17:30:00 +0100 -cgrates (0.9.1-rc3) UNRELEASED; urgency=low +cgrates (0.9.1~rc3) UNRELEASED; urgency=low * RC3. From 938f2fada066065c2f6eaeba9c673344b23ac8f7 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Mon, 23 Mar 2015 16:52:24 +0200 Subject: [PATCH 3/4] test for max cost strategy --- engine/account.go | 4 ++-- engine/balances.go | 46 +++++++++++++++++++++++++-------------- engine/calldesc.go | 5 +++-- engine/calldesc_test.go | 46 +++++++++++++++++++++++++++++++-------- engine/loader_csv_test.go | 18 ++++++++++----- engine/ratingplan.go | 1 - engine/timespans.go | 8 +++++-- 7 files changed, 90 insertions(+), 38 deletions(-) diff --git a/engine/account.go b/engine/account.go index 97e524d5d..3df7f04e4 100644 --- a/engine/account.go +++ b/engine/account.go @@ -256,7 +256,7 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo unitBalanceChecker = true generalBalanceChecker = true // check for max cost disconnect - if dryRun && cc.maxCostDisconect { + if dryRun && partCC.maxCostDisconect { // only return if we are in dry run (max call duration) return } @@ -294,7 +294,7 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo } moneyBalanceChecker = true generalBalanceChecker = true - if dryRun && cc.maxCostDisconect { + if dryRun && partCC.maxCostDisconect { // only return if we are in dry run (max call duration) return } diff --git a/engine/balances.go b/engine/balances.go index cec25e401..d3454d846 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -325,20 +325,26 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala } //log.Printf("TS: %+v", ts) maxCost, strategy := ts.RateInterval.GetMaxCost() - if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { - // cat the entire current timespan - cc.maxCostDisconect = true - if dryRun { - cc.Timespans = cc.Timespans[:tsIndex] - return cc, nil - } - } for incIndex, inc := range ts.Increments { // debit minutes and money seconds := inc.Duration.Seconds() cost := inc.Cost //log.Printf("INC: %+v", inc) inc.paid = false + if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { + // cat the entire current timespan + cc.maxCostDisconect = true + if dryRun { + if incIndex == 0 { + // cat the entire current timespan + cc.Timespans = cc.Timespans[:tsIndex] + } else { + ts.SplitByIncrement(incIndex) + cc.Timespans = cc.Timespans[:tsIndex+1] + } + return cc, nil + } + } if strategy == utils.MAX_COST_FREE && cd.MaxCostSoFar >= maxCost { cost, inc.Cost = 0.0, 0.0 inc.BalanceInfo.MoneyBalanceUuid = b.Uuid @@ -415,19 +421,27 @@ func (b *Balance) DebitMoney(cd *CallDescriptor, ub *Account, count bool, dryRun } //log.Printf("TS: %+v", ts) maxCost, strategy := ts.RateInterval.GetMaxCost() - if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { - // cat the entire current timespan - cc.maxCostDisconect = true - if dryRun { - cc.Timespans = cc.Timespans[:tsIndex] - return cc, nil - } - } + //log.Printf("Timing: %+v", ts.RateInterval.Timing) + //log.Printf("Rate: %+v", ts.RateInterval.Rating) for incIndex, inc := range ts.Increments { // check standard subject tags //log.Printf("INC: %+v", inc) amount := inc.Cost inc.paid = false + if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { + // cat the entire current timespan + cc.maxCostDisconect = true + if dryRun { + if incIndex == 0 { + // cat the entire current timespan + cc.Timespans = cc.Timespans[:tsIndex] + } else { + ts.SplitByIncrement(incIndex) + cc.Timespans = cc.Timespans[:tsIndex+1] + } + return cc, nil + } + } if strategy == utils.MAX_COST_FREE && cd.MaxCostSoFar >= maxCost { amount, inc.Cost = 0.0, 0.0 inc.BalanceInfo.MoneyBalanceUuid = b.Uuid diff --git a/engine/calldesc.go b/engine/calldesc.go index f2bb4960e..310742029 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -360,10 +360,10 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { } //Logger.Debug(fmt.Sprintf("After SplitByRateInterval: %+v", timespans)) - //log.Printf("After SplitByRateInterval: %+v", timespans) + //log.Printf("After SplitByRateInterval: %+v", timespans[0].RateInterval.Timing) timespans = cd.roundTimeSpansToIncrement(timespans) // Logger.Debug(fmt.Sprintf("After round: %+v", timespans)) - //log.Printf("After round: %+v", timespans) + //log.Printf("After round: %+v", timespans[0].RateInterval.Timing) return } @@ -417,6 +417,7 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) { for i, ts := range timespans { // only add connect fee if this is the first/only call cost request + //log.Printf("Interval: %+v", ts.RateInterval.Timing) if cd.LoopIndex == 0 && i == 0 && ts.RateInterval != nil { cost += ts.RateInterval.Rating.ConnectFee } diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index 0e47e5d35..e5ffef1fc 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -83,6 +83,13 @@ func populateDB() { }, }, } + max := &Account{ + Id: "*out:cgrates.org:max", + BalanceMap: map[string]BalanceChain{ + CREDIT + OUTBOUND: BalanceChain{ + &Balance{Value: 11, Weight: 20}, + }}, + } if accountingStorage != nil { accountingStorage.SetActions("TEST_ACTIONS", ats) accountingStorage.SetActions("TEST_ACTIONS_ORDER", ats1) @@ -90,6 +97,7 @@ func populateDB() { accountingStorage.SetAccount(minu) accountingStorage.SetAccount(minitsboy) accountingStorage.SetAccount(luna) + accountingStorage.SetAccount(max) } else { log.Fatal("Could not connect to db!") } @@ -355,8 +363,6 @@ func TestMaxSessionTimeWithMaxRate(t *testing.T) { } } -/* - func TestMaxSessionTimeWithMaxCost(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") for _, at := range ap { @@ -366,20 +372,42 @@ func TestMaxSessionTimeWithMaxCost(t *testing.T) { Direction: "*out", Category: "call", Tenant: "cgrates.org", - Subject: "12345", - Account: "12345", - Destination: "447956", - TimeStart: time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC), - TimeEnd: time.Date(2014, 3, 4, 6, 1, 0, 0, time.UTC), + Subject: "max", + Account: "max", + Destination: "0723123113", + TimeStart: time.Date(2015, 3, 23, 6, 0, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 3, 23, 6, 30, 0, 0, time.UTC), MaxCostSoFar: 0, } result, err := cd.GetMaxSessionDuration() - expected := 45 * time.Second + expected := 10 * time.Second + if result != expected || err != nil { + t.Errorf("Expected %v was %v", expected, result) + } +} + +func TestMaxSessionTimeWithMaxCostFree(t *testing.T) { + ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") + for _, at := range ap { + at.Execute() + } + cd := &CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "max", + Account: "max", + Destination: "0723123113", + TimeStart: time.Date(2015, 3, 23, 19, 0, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 3, 23, 19, 30, 0, 0, time.UTC), + MaxCostSoFar: 0, + } + result, err := cd.GetMaxSessionDuration() + expected := 30 * time.Minute if result != expected || err != nil { t.Errorf("Expected %v was %v", expected, result) } } -*/ func TestMaxSessionTimeWithAccountAlias(t *testing.T) { cd := &CallDescriptor{ diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 5c0901c01..4933b4a14 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -68,6 +68,7 @@ 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 +MX,0,1,1s,1s,0 ` destinationRates = ` RT_STANDARD,GERMANY,R1,*middle,4,0, @@ -86,6 +87,8 @@ DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*middle,4,0, DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*middle,4,0, DATA_RATE,*any,LANDLINE_OFFPEAK,*middle,4,0, RT_URG,URG,R_URG,*middle,4,0, +MX_FREE,RET,MX,*middle,4,10,*free +MX_DISC,RET,MX,*middle,4,10,*disconnect ` ratingPlans = ` STANDARD,RT_STANDARD,WORKDAYS_00,10 @@ -106,6 +109,8 @@ R,P1,WORKDAYS_00,10 RP_UK_Mobile_BIG5_PKG,DR_UK_Mobile_BIG5_PKG,ALWAYS,10 RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10 RP_DATA,DATA_RATE,ALWAYS,10 +RP_MX,MX_DISC,WORKDAYS_00,10 +RP_MX,MX_FREE,WORKDAYS_18,10 ` ratingProfiles = ` *out,CUSTOMER_1,0,rif:from:tm,2012-01-01T00:00:00Z,PREMIUM,danb @@ -127,6 +132,7 @@ RP_DATA,DATA_RATE,ALWAYS,10 *out,cgrates.org,call,*any,2013-01-06T00:00:00Z,RP_UK, *out,cgrates.org,call,discounted_minutes,2013-01-06T00:00:00Z,RP_UK_Mobile_BIG5_PKG, *out,cgrates.org,data,rif,2013-01-06T00:00:00Z,RP_DATA, +*out,cgrates.org,call,max,2013-03-23T00:00:00Z,RP_MX, ` sharedGroups = ` SG1,*any,*lowest, @@ -319,8 +325,8 @@ func TestLoadTimimgs(t *testing.T) { } func TestLoadRates(t *testing.T) { - if len(csvr.rates) != 12 { - t.Error("Failed to load rates: ", csvr.rates) + if len(csvr.rates) != 13 { + t.Error("Failed to load rates: ", len(csvr.rates)) } rate := csvr.rates["R1"].RateSlots[0] expctRs, err := utils.NewRateSlot(0, 0.2, "60", "1", "0") @@ -389,8 +395,8 @@ func TestLoadRates(t *testing.T) { } func TestLoadDestinationRates(t *testing.T) { - if len(csvr.destinationRates) != 11 { - t.Error("Failed to load destinationrates: ", csvr.destinationRates) + if len(csvr.destinationRates) != 13 { + t.Error("Failed to load destinationrates: ", len(csvr.destinationRates)) } drs := csvr.destinationRates["RT_STANDARD"] dr := &utils.TPDestinationRate{ @@ -525,7 +531,7 @@ func TestLoadDestinationRates(t *testing.T) { } func TestLoadRatingPlans(t *testing.T) { - if len(csvr.ratingPlans) != 10 { + if len(csvr.ratingPlans) != 11 { t.Error("Failed to load rating plans: ", len(csvr.ratingPlans)) } rplan := csvr.ratingPlans["STANDARD"] @@ -672,7 +678,7 @@ func TestLoadRatingPlans(t *testing.T) { } func TestLoadRatingProfiles(t *testing.T) { - if len(csvr.ratingProfiles) != 15 { + if len(csvr.ratingProfiles) != 16 { t.Error("Failed to load rating profiles: ", len(csvr.ratingProfiles), csvr.ratingProfiles) } rp := csvr.ratingProfiles["*out:test:0:trp"] diff --git a/engine/ratingplan.go b/engine/ratingplan.go index 8c4b3e839..c98a276f5 100644 --- a/engine/ratingplan.go +++ b/engine/ratingplan.go @@ -83,7 +83,6 @@ func (rp *RatingPlan) AddRateInterval(dId string, ris ...*RateInterval) { } if ri.Rating != nil { ratingTag := ri.Rating.Stringify() - rp.Ratings[ratingTag] = ri.Rating rpr.Rating = ratingTag } diff --git a/engine/timespans.go b/engine/timespans.go index fe9bb18c0..0ff4a0b71 100644 --- a/engine/timespans.go +++ b/engine/timespans.go @@ -247,15 +247,18 @@ Will set the interval as spans's interval if new Weight is lower then span's int or if the Weights are equal and new price is lower then spans's interval price */ func (ts *TimeSpan) SetRateInterval(i *RateInterval) { + //log.Printf("SETRATEINTERVAL: %+v", i.Timing) if ts.RateInterval == nil || ts.RateInterval.Weight < i.Weight { ts.RateInterval = i + //log.Printf("RET TS: %+v", ts.RateInterval.Timing) return } iPrice, _, _ := i.GetRateParameters(ts.GetGroupStart()) tsPrice, _, _ := ts.RateInterval.GetRateParameters(ts.GetGroupStart()) - if ts.RateInterval.Weight == i.Weight && iPrice < tsPrice { + if ts.RateInterval.Weight == i.Weight && iPrice <= tsPrice { ts.RateInterval = i } + //log.Printf("END TS: %+v", ts.RateInterval.Timing) } // Returns the cost of the timespan according to the relevant cost interval. @@ -363,8 +366,9 @@ func (ts *TimeSpan) SplitByRateInterval(i *RateInterval, data bool) (nts *TimeSp return } // if the span is enclosed in the interval try to set as new interval and return nil + //log.Printf("Timing: %+v", i.Timing) if i.Contains(ts.TimeStart, false) && i.Contains(ts.TimeEnd, true) { - //Logger.Debug("All in interval") + //log.Print("All in interval") ts.SetRateInterval(i) return } From 93b4872db98a69e259007075713abb417f089161 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Mon, 23 Mar 2015 16:58:12 +0200 Subject: [PATCH 4/4] set max cost so far in session manager --- sessionmanager/session.go | 1 + 1 file changed, 1 insertion(+) diff --git a/sessionmanager/session.go b/sessionmanager/session.go index 6eba60805..d09169cd1 100644 --- a/sessionmanager/session.go +++ b/sessionmanager/session.go @@ -101,6 +101,7 @@ func (s *Session) debitLoop(runIdx int) { // update call duration with real debited duration nextCd.DurationIndex -= debitPeriod nextCd.DurationIndex += nextCd.GetDuration() + nextCd.MaxCostSoFar += cc.Cost time.Sleep(cc.GetDuration()) index++ }