From e893862f268a5ae1f892905e4d7e253f97e65c09 Mon Sep 17 00:00:00 2001 From: DanB Date: Thu, 8 May 2014 10:20:46 +0200 Subject: [PATCH] MySQL data structures refactoring, fixups rounding methods migration --- apier/apier_local_test.go | 22 ++-- apier/tutfscsv_local_test.go | 2 +- apier/tutfsjson_local_test.go | 8 +- cdrc/cdrc_local_test.go | 2 +- data/storage/mysql/create_cdrs_tables.sql | 60 ++++++++++- .../mysql/create_costdetails_tables.sql | 23 ---- data/storage/mysql/create_mediator_tables.sql | 16 --- data/storage/mysql/setup_cgr_db.sh | 7 +- .../cgrates/tariffplans/DestinationRates.csv | 8 +- .../fs_csv/cgrates/tariffplans/Rates.csv | 14 +-- .../cgrates/tariffplans/DestinationRates.csv | 14 +-- .../fs_json/cgrates/tariffplans/Rates.csv | 14 +-- engine/callcost.go | 14 --- engine/storage_sql.go | 102 ++++++++++++------ engine/storage_sql_local_test.go | 2 +- engine/tpimporter_csv.go | 11 +- mediator/mediator_local_test.go | 8 +- 17 files changed, 175 insertions(+), 152 deletions(-) delete mode 100644 data/storage/mysql/create_mediator_tables.sql diff --git a/apier/apier_local_test.go b/apier/apier_local_test.go index 291eb9ec8..6f60b5f91 100644 --- a/apier/apier_local_test.go +++ b/apier/apier_local_test.go @@ -94,8 +94,7 @@ func TestCreateTables(t *testing.T) { } else { mysql = d.(*engine.MySQLStorage) } - for _, scriptName := range []string{engine.CREATE_CDRS_TABLES_SQL, engine.CREATE_COSTDETAILS_TABLES_SQL, engine.CREATE_MEDIATOR_TABLES_SQL, - engine.CREATE_TARIFFPLAN_TABLES_SQL} { + for _, scriptName := range []string{engine.CREATE_CDRS_TABLES_SQL, engine.CREATE_TARIFFPLAN_TABLES_SQL} { if err := mysql.CreateTablesFromScript(path.Join(*dataDir, "storage", *storDbType, scriptName)); err != nil { t.Fatal("Error on mysql creation: ", err.Error()) return // No point in going further @@ -340,10 +339,10 @@ func TestApierTPDestinationRate(t *testing.T) { } reply := "" dr := &utils.TPDestinationRate{TPid: engine.TEST_SQL, DestinationRateId: "DR_FREESWITCH_USERS", DestinationRates: []*utils.DestinationRate{ - &utils.DestinationRate{DestinationId: "FS_USERS", RateId: "RT_FS_USERS"}, + &utils.DestinationRate{DestinationId: "FS_USERS", RateId: "RT_FS_USERS", RoundingMethod: "*up", RoundingDecimals: 2}, }} drDe := &utils.TPDestinationRate{TPid: engine.TEST_SQL, DestinationRateId: "DR_FREESWITCH_USERS", DestinationRates: []*utils.DestinationRate{ - &utils.DestinationRate{DestinationId: "GERMANY_MOBILE", RateId: "RT_FS_USERS"}, + &utils.DestinationRate{DestinationId: "GERMANY_MOBILE", RateId: "RT_FS_USERS", RoundingMethod: "*up", RoundingDecimals: 2}, }} dr2 := new(utils.TPDestinationRate) *dr2 = *dr @@ -891,7 +890,6 @@ func TestApierGetRatingPlan(t *testing.T) { } reply := new(engine.RatingPlan) rplnId := "RETAIL1" - //{"Id":"RETAIL1","Timings":{"96c78ff5":{"Years":[],"Months":[],"MonthDays":[],"WeekDays":[],"StartTime":"00:00:00","EndTime":""}},"Ratings":{"e41ffcf2":{"ConnectFee":0,"Rates":[{"GroupIntervalStart":0,"Value":0,"RateIncrement":60000000000,"RateUnit":60000000000}],"RoundingMethod":"*up","RoundingDecimals":0}},"DestinationRates":{"FS_USERS":[{"Timing":"96c78ff5","Rating":"e41ffcf2","Weight":10}],"GERMANY_MOBILE":[{"Timing":"96c78ff5","Rating":"e41ffcf2","Weight":10}]} if err := rater.Call("ApierV1.GetRatingPlan", rplnId, reply); err != nil { t.Error("Got error on ApierV1.GetRatingPlan: ", err.Error()) } @@ -902,21 +900,13 @@ func TestApierGetRatingPlan(t *testing.T) { if len(reply.Timings) != 1 || len(reply.Ratings) != 1 { t.Error("Unexpected number of items received") } - /* - riTiming := &engine.RITiming{StartTime: "00:00:00"} - for _, tm := range reply.Timings { // We only get one loop - if !reflect.DeepEqual(tm, riTiming) { - t.Errorf("Unexpected timings value: %v, expecting: %v", tm, riTiming) - } - } - */ - riRate := &engine.RIRate{ConnectFee: 0, RoundingMethod: "*up", RoundingDecimals: 0, Rates: []*engine.Rate{ + riRate := &engine.RIRate{ConnectFee: 0, RoundingMethod: "*up", RoundingDecimals: 2, Rates: []*engine.Rate{ &engine.Rate{GroupIntervalStart: 0, Value: 0, RateIncrement: time.Duration(60) * time.Second, RateUnit: time.Duration(60) * time.Second}, }} for _, rating := range reply.Ratings { - riRateJsson, _ := json.Marshal(rating) + riRateJson, _ := json.Marshal(rating) if !reflect.DeepEqual(rating, riRate) { - t.Errorf("Unexpected riRate received: %s", riRateJsson) + t.Errorf("Unexpected riRate received: %s", riRateJson) // {"Id":"RT_FS_USERS","ConnectFee":0,"Rates":[{"GroupIntervalStart":0,"Value":0,"RateIncrement":60000000000,"RateUnit":60000000000}],"RoundingMethod":"*up","RoundingDecimals":0} } } diff --git a/apier/tutfscsv_local_test.go b/apier/tutfscsv_local_test.go index a2721457d..d862401b8 100644 --- a/apier/tutfscsv_local_test.go +++ b/apier/tutfscsv_local_test.go @@ -67,7 +67,7 @@ func TestFsCsvCreateTables(t *testing.T) { } else { mysql = d.(*engine.MySQLStorage) } - for _, scriptName := range []string{engine.CREATE_CDRS_TABLES_SQL, engine.CREATE_COSTDETAILS_TABLES_SQL, engine.CREATE_MEDIATOR_TABLES_SQL, engine.CREATE_TARIFFPLAN_TABLES_SQL} { + for _, scriptName := range []string{engine.CREATE_CDRS_TABLES_SQL, engine.CREATE_TARIFFPLAN_TABLES_SQL} { if err := mysql.CreateTablesFromScript(path.Join(*dataDir, "storage", *storDbType, scriptName)); err != nil { t.Fatal("Error on mysql creation: ", err.Error()) return // No point in going further diff --git a/apier/tutfsjson_local_test.go b/apier/tutfsjson_local_test.go index 13c0a6b90..70ea86210 100644 --- a/apier/tutfsjson_local_test.go +++ b/apier/tutfsjson_local_test.go @@ -70,11 +70,9 @@ func TestFsJsonCreateTables(t *testing.T) { } else { mysql = d.(*engine.MySQLStorage) } - for _, scriptName := range []string{engine.CREATE_CDRS_TABLES_SQL, engine.CREATE_COSTDETAILS_TABLES_SQL, engine.CREATE_MEDIATOR_TABLES_SQL} { - if err := mysql.CreateTablesFromScript(path.Join(*dataDir, "storage", *storDbType, scriptName)); err != nil { - t.Fatal("Error on mysql creation: ", err.Error()) - return // No point in going further - } + if err := mysql.CreateTablesFromScript(path.Join(*dataDir, "storage", *storDbType, engine.CREATE_CDRS_TABLES_SQL)); err != nil { + t.Fatal("Error on mysql creation: ", err.Error()) + return // No point in going further } for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} { if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil { diff --git a/cdrc/cdrc_local_test.go b/cdrc/cdrc_local_test.go index c3051e642..cebca12d6 100644 --- a/cdrc/cdrc_local_test.go +++ b/cdrc/cdrc_local_test.go @@ -102,7 +102,7 @@ func TestEmptyTables(t *testing.T) { } else { mysql = d.(*engine.MySQLStorage) } - for _, scriptName := range []string{engine.CREATE_CDRS_TABLES_SQL, engine.CREATE_COSTDETAILS_TABLES_SQL, engine.CREATE_MEDIATOR_TABLES_SQL, engine.CREATE_TARIFFPLAN_TABLES_SQL} { + for _, scriptName := range []string{engine.CREATE_CDRS_TABLES_SQL, engine.CREATE_TARIFFPLAN_TABLES_SQL} { if err := mysql.CreateTablesFromScript(path.Join(*dataDir, "storage", *storDbType, scriptName)); err != nil { t.Fatal("Error on mysql creation: ", err.Error()) return // No point in going further diff --git a/data/storage/mysql/create_cdrs_tables.sql b/data/storage/mysql/create_cdrs_tables.sql index 0c7c48275..ec83f0200 100644 --- a/data/storage/mysql/create_cdrs_tables.sql +++ b/data/storage/mysql/create_cdrs_tables.sql @@ -1,5 +1,9 @@ -DROP TABLE IF EXISTS cdrs_primary; +-- +-- Table structure for table `cdrs_primary` +-- + +DROP TABLE IF EXISTS cdrs_primary; CREATE TABLE cdrs_primary ( tbid int(11) NOT NULL AUTO_INCREMENT, cgrid char(40) NOT NULL, @@ -20,8 +24,11 @@ CREATE TABLE cdrs_primary ( UNIQUE KEY cgrid (cgrid) ); -DROP TABLE IF EXISTS cdrs_extra; +-- +-- Table structure for table `cdrs_extra` +-- +DROP TABLE IF EXISTS cdrs_extra; CREATE TABLE cdrs_extra ( tbid int(11) NOT NULL AUTO_INCREMENT, cgrid char(40) NOT NULL, @@ -29,3 +36,52 @@ CREATE TABLE cdrs_extra ( PRIMARY KEY (tbid), UNIQUE KEY cgrid (cgrid) ); + +-- +-- Table structure for table `cost_details` +-- + +DROP TABLE IF EXISTS cost_details; +CREATE TABLE cost_details ( + tbid int(11) NOT NULL AUTO_INCREMENT, + cost_time datetime NOT NULL, + cost_source varchar(64) NOT NULL, + cgrid char(40) NOT NULL, + runid varchar(64) NOT NULL, + tor varchar(16) NOT NULL, + direction varchar(8) NOT NULL, + tenant varchar(128) NOT NULL, + category varchar(32) NOT NULL, + account varchar(128) NOT NULL, + subject varchar(128) NOT NULL, + destination varchar(128) NOT NULL, + cost DECIMAL(20,4) NOT NULL, + timespans text, + PRIMARY KEY (`tbid`), + UNIQUE KEY `costid` (`cgrid`,`runid`) +); + +-- +-- Table structure for table `rated_cdrs` +-- +DROP TABLE IF EXISTS rated_cdrs; +CREATE TABLE `rated_cdrs` ( + tbid int(11) NOT NULL AUTO_INCREMENT, + mediation_time datetime NOT NULL, + cgrid char(40) NOT NULL, + runid varchar(64) NOT NULL, + reqtype varchar(24) NOT NULL, + direction varchar(8) NOT NULL, + tenant varchar(64) NOT NULL, + category varchar(16) NOT NULL, + account varchar(128) NOT NULL, + subject varchar(128) NOT NULL, + destination varchar(128) NOT NULL, + setup_time datetime NOT NULL, + answer_time datetime NOT NULL, + duration bigint NOT NULL, + cost DECIMAL(20,4) DEFAULT NULL, + extra_info text, + PRIMARY KEY (`tbid`), + UNIQUE KEY `costid` (`cgrid`,`runid`) +); \ No newline at end of file diff --git a/data/storage/mysql/create_costdetails_tables.sql b/data/storage/mysql/create_costdetails_tables.sql index 986949627..139597f9c 100644 --- a/data/storage/mysql/create_costdetails_tables.sql +++ b/data/storage/mysql/create_costdetails_tables.sql @@ -1,25 +1,2 @@ --- --- Table structure for table `cost_details` --- - -DROP TABLE IF EXISTS `cost_details`; -CREATE TABLE `cost_details` ( - `tbid` int(11) NOT NULL AUTO_INCREMENT, - `cgrid` char(40) NOT NULL, - `accid` varchar(64) NOT NULL, - `direction` varchar(8) NOT NULL, - `tenant` varchar(128) NOT NULL, - `category` varchar(32) NOT NULL, - `account` varchar(128) NOT NULL, - `subject` varchar(128) NOT NULL, - `destination` varchar(128) NOT NULL, - `cost` DECIMAL(20,4) NOT NULL, - `timespans` text, - `source` varchar(64) NOT NULL, - `runid` varchar(64) NOT NULL, - `cost_time` datetime NOT NULL, - PRIMARY KEY (`tbid`), - UNIQUE KEY `costid` (`cgrid`,`runid`) -); diff --git a/data/storage/mysql/create_mediator_tables.sql b/data/storage/mysql/create_mediator_tables.sql deleted file mode 100644 index da820dcda..000000000 --- a/data/storage/mysql/create_mediator_tables.sql +++ /dev/null @@ -1,16 +0,0 @@ - --- --- Table structure for table `rated_cdrs` --- -DROP TABLE IF EXISTS `rated_cdrs`; -CREATE TABLE `rated_cdrs` ( - `tbid` int(11) NOT NULL AUTO_INCREMENT, - `cgrid` char(40) NOT NULL, - `runid` varchar(64) NOT NULL, - `subject` varchar(64) NOT NULL, - `cost` DECIMAL(20,4) DEFAULT NULL, - `mediation_time` datetime NOT NULL, - `extra_info` text, - PRIMARY KEY (`tbid`), - UNIQUE KEY `costid` (`cgrid`,`runid`) -); diff --git a/data/storage/mysql/setup_cgr_db.sh b/data/storage/mysql/setup_cgr_db.sh index 40b5e803c..e15d6696b 100755 --- a/data/storage/mysql/setup_cgr_db.sh +++ b/data/storage/mysql/setup_cgr_db.sh @@ -15,17 +15,12 @@ fi mysql -u $1 -p$2 -h $host < create_db_with_users.sql cu=$? - mysql -u $1 -p$2 -h $host -D cgrates < create_cdrs_tables.sql cdrt=$? -mysql -u $1 -p$2 -h $host -D cgrates < create_costdetails_tables.sql -cdt=$? -mysql -u $1 -p$2 -h $host -D cgrates < create_mediator_tables.sql -mdt=$? mysql -u $1 -p$2 -h $host -D cgrates < create_tariffplan_tables.sql tpt=$? -if [ $cu = 0 ] && [ $cdrt = 0 ] && [ $cdt = 0 ] && [ $mdt = 0 ] && [ $tpt = 0 ]; then +if [ $cu = 0 ] && [ $cdrt = 0 ] && [ $tpt = 0 ]; then echo "" echo "\t+++ CGR-DB successfully set-up! +++" echo "" diff --git a/data/tutorials/fs_csv/cgrates/tariffplans/DestinationRates.csv b/data/tutorials/fs_csv/cgrates/tariffplans/DestinationRates.csv index 4513ad04e..c8d302fc5 100644 --- a/data/tutorials/fs_csv/cgrates/tariffplans/DestinationRates.csv +++ b/data/tutorials/fs_csv/cgrates/tariffplans/DestinationRates.csv @@ -1,4 +1,4 @@ -#Tag,DestinationsTag,RatesTag -DR_RETAIL,DST_1002,RT_20CNT -DR_RETAIL,DST_1003,RT_40CNT -DR_RETAIL,DST_FS,RT_10CNT +#Tag,DestinationsTag,RatesTag,RoundingMethod,RoundingDecimals +DR_RETAIL,DST_1002,RT_20CNT,*up,4 +DR_RETAIL,DST_1003,RT_40CNT,*up,4 +DR_RETAIL,DST_FS,RT_10CNT,*up,4 diff --git a/data/tutorials/fs_csv/cgrates/tariffplans/Rates.csv b/data/tutorials/fs_csv/cgrates/tariffplans/Rates.csv index 4cfb2dd9e..ded15468d 100644 --- a/data/tutorials/fs_csv/cgrates/tariffplans/Rates.csv +++ b/data/tutorials/fs_csv/cgrates/tariffplans/Rates.csv @@ -1,7 +1,7 @@ -#Tag,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart,RoundingMethod,RoundingDecimals -RT_10CNT,0.2,0.1,60s,60s,0s,*up,4 -RT_10CNT,0,0.05,60s,1s,60s,*up,4 -RT_20CNT,0.4,0.2,60s,60s,0s,*up,4 -RT_20CNT,0,0.1,60s,1s,60s,*up,4 -RT_40CNT,0.8,0.4,60s,30s,0s,*up,4 -RT_40CNT,0,0.2,60s,10s,60s,*up,4 +#Tag,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart +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 diff --git a/data/tutorials/fs_json/cgrates/tariffplans/DestinationRates.csv b/data/tutorials/fs_json/cgrates/tariffplans/DestinationRates.csv index 7c94d0974..03d4c30a8 100644 --- a/data/tutorials/fs_json/cgrates/tariffplans/DestinationRates.csv +++ b/data/tutorials/fs_json/cgrates/tariffplans/DestinationRates.csv @@ -1,7 +1,7 @@ -#Tag,DestinationsTag,RatesTag -DR_1002_20CNT,DST_1002,RT_20CNT -DR_1002_10CNT,DST_1002,RT_10CNT -DR_1003_20CNT,DST_1003,RT_40CNT -DR_1003_10CNT,DST_1003,RT_10CNT -DR_FS_40CNT,DST_FS,RT_40CNT -DR_FS_10CNT,DST_FS,RT_10CNT +#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 diff --git a/data/tutorials/fs_json/cgrates/tariffplans/Rates.csv b/data/tutorials/fs_json/cgrates/tariffplans/Rates.csv index 4cfb2dd9e..ded15468d 100644 --- a/data/tutorials/fs_json/cgrates/tariffplans/Rates.csv +++ b/data/tutorials/fs_json/cgrates/tariffplans/Rates.csv @@ -1,7 +1,7 @@ -#Tag,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart,RoundingMethod,RoundingDecimals -RT_10CNT,0.2,0.1,60s,60s,0s,*up,4 -RT_10CNT,0,0.05,60s,1s,60s,*up,4 -RT_20CNT,0.4,0.2,60s,60s,0s,*up,4 -RT_20CNT,0,0.1,60s,1s,60s,*up,4 -RT_40CNT,0.8,0.4,60s,30s,0s,*up,4 -RT_40CNT,0,0.2,60s,10s,60s,*up,4 +#Tag,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart +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 diff --git a/engine/callcost.go b/engine/callcost.go index 0cb79c919..0b8b21bee 100644 --- a/engine/callcost.go +++ b/engine/callcost.go @@ -31,20 +31,6 @@ type CallCost struct { deductConnectFee bool } -// Pretty printing for call cost -/*func (cc *CallCost) String() (r string) { - connectFee := 0.0 - if cc.deductConnectFee { - connectFee = cc.GetConnectFee() - } - r = fmt.Sprintf("%v[%v] : %s(%s) - > %s (", cc.Cost, connectFee, cc.Subject, cc.Account, cc.Destination) - for _, ts := range cc.Timespans { - r += fmt.Sprintf(" %v,", ts.GetDuration()) - } - r += " )" - return -}*/ - // Merges the received timespan if they are similar (same activation period, same interval, same minute info. func (cc *CallCost) Merge(other *CallCost) { if len(cc.Timespans)-1 < 0 || len(other.Timespans) == 0 { diff --git a/engine/storage_sql.go b/engine/storage_sql.go index f1948085a..3fcc94b81 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -189,7 +189,7 @@ func (self *SQLStorage) SetTPRates(tpid string, rts map[string][]*utils.RateSlot return nil //Nothing to set } var buffer bytes.Buffer - buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid, id, connect_fee, rate, rate_unit, rate_increment, group_interval_start, rounding_method, rounding_decimals) VALUES ", + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid, id, connect_fee, rate, rate_unit, rate_increment, group_interval_start) VALUES ", utils.TBL_TP_RATES)) i := 0 for rtId, rtRows := range rts { @@ -197,12 +197,12 @@ func (self *SQLStorage) SetTPRates(tpid string, rts map[string][]*utils.RateSlot if i != 0 { //Consecutive values after the first will be prefixed with "," as separator buffer.WriteRune(',') } - buffer.WriteString(fmt.Sprintf("('%s', '%s', %f, %f, '%s', '%s','%s','%s', %d)", + buffer.WriteString(fmt.Sprintf("('%s', '%s', %f, %f, '%s', '%s','%s')", tpid, rtId, rt.ConnectFee, rt.Rate, rt.RateUnit, rt.RateIncrement, rt.GroupIntervalStart)) i++ } } - buffer.WriteString(" ON DUPLICATE KEY UPDATE connect_fee=values(connect_fee), rate=values(rate), rate_increment=values(rate_increment), group_interval_start=values(group_interval_start), rounding_method=values(rounding_method), rounding_decimals=values(rounding_decimals)") + buffer.WriteString(" ON DUPLICATE KEY UPDATE connect_fee=values(connect_fee),rate=values(rate),rate_increment=values(rate_increment),group_interval_start=values(group_interval_start)") if _, err := self.Db.Exec(buffer.String()); err != nil { return err } @@ -214,18 +214,18 @@ func (self *SQLStorage) SetTPDestinationRates(tpid string, drs map[string][]*uti return nil //Nothing to set } var buffer bytes.Buffer - buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid,id,destinations_id,rates_id) VALUES ", utils.TBL_TP_DESTINATION_RATES)) + buffer.WriteString(fmt.Sprintf("INSERT INTO %s (tpid,id,destinations_id,rates_id,rounding_method,rounding_decimals) VALUES ", utils.TBL_TP_DESTINATION_RATES)) i := 0 for drId, drRows := range drs { for _, dr := range drRows { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator buffer.WriteRune(',') } - buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s')", tpid, drId, dr.DestinationId, dr.RateId)) + buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s','%s', %d)", tpid, drId, dr.DestinationId, dr.RateId, dr.RoundingMethod, dr.RoundingDecimals)) i++ } } - buffer.WriteString(" ON DUPLICATE KEY UPDATE destinations_id=values(destinations_id),rates_id=values(rates_id)") + buffer.WriteString(" ON DUPLICATE KEY UPDATE destinations_id=values(destinations_id),rates_id=values(rates_id),rounding_method=values(rounding_method),rounding_decimals=values(rounding_decimals)") if _, err := self.Db.Exec(buffer.String()); err != nil { return err } @@ -495,9 +495,12 @@ func (self *SQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) ( if err != nil { Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err)) } - _, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (cgrid, direction, tenant, category, account, subject, destination, cost, timespans, source, runid, cost_time) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', %f, '%s','%s','%s',now()) ON DUPLICATE KEY UPDATE direction=values(direction), tenant=values(tenant), category=values(category), account=values(account), subject=values(subject), destination=values(destination), cost=values(cost), timespans=values(timespans), source=values(source), cost_time=now()", + _, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (cost_time,cost_source,cgrid,runid,tor,direction,tenant,category,account,subject,destination,cost,timespans) VALUES (now(),'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',%f,'%s') ON DUPLICATE KEY UPDATE cost_time=now(),cost_source=values(cost_source),tor=values(tor),direction=values(direction),tenant=values(tenant),category=values(category),account=values(account),subject=values(subject),destination=values(destination),cost=values(cost),timespans=values(timespans)", utils.TBL_COST_DETAILS, + source, cgrid, + runid, + cc.TOR, cc.Direction, cc.Tenant, cc.Category, @@ -505,9 +508,7 @@ func (self *SQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) ( cc.Subject, cc.Destination, cc.Cost, - tss, - source, - runid)) + tss)) if err != nil { Logger.Err(fmt.Sprintf("failed to execute insert statement: %v", err)) } @@ -515,17 +516,15 @@ func (self *SQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) ( } func (self *SQLStorage) GetCallCostLog(cgrid, source, runid string) (cc *CallCost, err error) { - qry := fmt.Sprintf("SELECT cgrid, direction, tenant, category, account, subject, destination, cost, timespans, source FROM %s WHERE cgrid='%s' AND runid='%s'", + qry := fmt.Sprintf("SELECT tor,direction,tenant,category,account,subject,destination,cost,timespans FROM %s WHERE cgrid='%s' AND runid='%s'", utils.TBL_COST_DETAILS, cgrid, runid) if len(source) != 0 { - qry += fmt.Sprintf(" AND source='%s'", source) + qry += fmt.Sprintf(" AND cost_source='%s'", source) } row := self.Db.QueryRow(qry) - var src string var timespansJson string cc = &CallCost{Cost: -1} - err = row.Scan(&cgrid, &cc.Direction, &cc.Tenant, &cc.Category, &cc.Account, &cc.Subject, - &cc.Destination, &cc.Cost, ×pansJson, &src) + err = row.Scan(&cc.TOR, &cc.Direction, &cc.Tenant, &cc.Category, &cc.Account, &cc.Subject, &cc.Destination, &cc.Cost, ×pansJson) if len(timespansJson) == 0 { // No costs returned return nil, nil } @@ -581,11 +580,20 @@ func (self *SQLStorage) SetCdr(cdr *utils.StoredCdr) (err error) { } func (self *SQLStorage) SetRatedCdr(storedCdr *utils.StoredCdr, extraInfo string) (err error) { - _, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (cgrid,runid,subject,cost,mediation_time,extra_info) VALUES ('%s','%s','%s',%f,now(),'%s') ON DUPLICATE KEY UPDATE subject=values(subject),cost=values(cost),mediation_time=now(),extra_info=values(extra_info)", + _, err = self.Db.Exec(fmt.Sprintf("INSERT INTO %s (mediation_time,cgrid,runid,reqtype,direction,tenant,category,account,subject,destination,setup_time,answer_time,duration,cost,extra_info) VALUES (now(),'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',%f,'%s') ON DUPLICATE KEY UPDATE mediation_time=now(),reqtype=values(reqtype),direction=values(direction),tenant=values(tenant),category=values(category),account=values(account),subject=values(subject),destination=values(destination),setup_time=values(setup_time),answer_time=values(answer_time),duration=values(duration),cost=values(cost),extra_info=values(extra_info)", utils.TBL_RATED_CDRS, storedCdr.CgrId, storedCdr.MediationRunId, + storedCdr.ReqType, + storedCdr.Direction, + storedCdr.Tenant, + storedCdr.Category, + storedCdr.Account, storedCdr.Subject, + storedCdr.Destination, + storedCdr.SetupTime, + storedCdr.AnswerTime, + storedCdr.Duration, storedCdr.Cost, extraInfo)) if err != nil { @@ -600,7 +608,32 @@ func (self *SQLStorage) SetRatedCdr(storedCdr *utils.StoredCdr, extraInfo string func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqTypes, directions, tenants, categories, accounts, subjects, destPrefixes []string, orderIdStart, orderIdEnd int64, timeStart, timeEnd time.Time, ignoreErr, ignoreRated bool) ([]*utils.StoredCdr, error) { var cdrs []*utils.StoredCdr - q := bytes.NewBufferString(fmt.Sprintf("SELECT %s.cgrid,%s.tbid,accid,cdrhost,cdrsource,reqtype,direction,tenant,category,account,%s.subject,destination,setup_time,answer_time,duration,extra_fields,runid,cost FROM %s LEFT JOIN %s ON %s.cgrid=%s.cgrid LEFT JOIN %s ON %s.cgrid=%s.cgrid", utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA, utils.TBL_RATED_CDRS, utils.TBL_CDRS_PRIMARY, utils.TBL_RATED_CDRS)) + q := bytes.NewBufferString(fmt.Sprintf("SELECT %s.cgrid,%s.tbid,%s.accid,%s.cdrhost,%s.cdrsource,%s.reqtype,%s.direction,%s.tenant,%s.category,%s.account,%s.subject,%s.destination,%s.setup_time,%s.answer_time,%s.duration,%s.extra_fields,%s.runid,%s.cost FROM %s LEFT JOIN %s ON %s.cgrid=%s.cgrid LEFT JOIN %s ON %s.cgrid=%s.cgrid", + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_EXTRA, + utils.TBL_RATED_CDRS, + utils.TBL_RATED_CDRS, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_EXTRA, + utils.TBL_CDRS_PRIMARY, + utils.TBL_CDRS_EXTRA, + utils.TBL_RATED_CDRS, + utils.TBL_CDRS_PRIMARY, + utils.TBL_RATED_CDRS)) fltr := new(bytes.Buffer) if len(cgrIds) != 0 { qIds := bytes.NewBufferString(" (") @@ -622,7 +655,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" runid='%s'", runId)) + qIds.WriteString(fmt.Sprintf(" %s.runid='%s'", utils.TBL_RATED_CDRS, runId)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -636,7 +669,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" cdrhost='%s'", host)) + qIds.WriteString(fmt.Sprintf(" %s.cdrhost='%s'", utils.TBL_CDRS_PRIMARY, host)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -650,7 +683,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" cdrsource='%s'", src)) + qIds.WriteString(fmt.Sprintf(" %s.cdrsource='%s'", utils.TBL_CDRS_PRIMARY, src)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -664,7 +697,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" reqtype='%s'", reqType)) + qIds.WriteString(fmt.Sprintf(" %s.reqtype='%s'", utils.TBL_CDRS_PRIMARY, reqType)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -678,7 +711,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" direction='%s'", direction)) + qIds.WriteString(fmt.Sprintf(" %s.direction='%s'", utils.TBL_CDRS_PRIMARY, direction)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -692,7 +725,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" tenant='%s'", tenant)) + qIds.WriteString(fmt.Sprintf(" %s.tenant='%s'", utils.TBL_CDRS_PRIMARY, tenant)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -706,7 +739,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" category='%s'", category)) + qIds.WriteString(fmt.Sprintf(" %s.category='%s'", utils.TBL_CDRS_PRIMARY, category)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -720,7 +753,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" account='%s'", account)) + qIds.WriteString(fmt.Sprintf(" %s.account='%s'", utils.TBL_CDRS_PRIMARY, account)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -748,7 +781,7 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if idx != 0 { qIds.WriteString(" OR") } - qIds.WriteString(fmt.Sprintf(" destination LIKE '%s%%'", destPrefix)) + qIds.WriteString(fmt.Sprintf(" %s.destination LIKE '%s%%'", utils.TBL_CDRS_PRIMARY, destPrefix)) } qIds.WriteString(" )") if fltr.Len() != 0 { @@ -772,28 +805,28 @@ func (self *SQLStorage) GetStoredCdrs(cgrIds, runIds, cdrHosts, cdrSources, reqT if fltr.Len() != 0 { fltr.WriteString(" AND") } - fltr.WriteString(fmt.Sprintf(" answer_time>='%s'", timeStart)) + fltr.WriteString(fmt.Sprintf(" %s.answer_time>='%s'", utils.TBL_CDRS_PRIMARY, timeStart)) } if !timeEnd.IsZero() { if fltr.Len() != 0 { fltr.WriteString(" AND") } - fltr.WriteString(fmt.Sprintf(" answer_time<'%s'", timeEnd)) + fltr.WriteString(fmt.Sprintf(" %s.answer_time<'%s'", utils.TBL_CDRS_PRIMARY, timeEnd)) } if ignoreRated { if fltr.Len() != 0 { fltr.WriteString(" AND") } if ignoreErr { - fltr.WriteString(" cost IS NULL") + fltr.WriteString(fmt.Sprintf(" %s.cost IS NULL", utils.TBL_RATED_CDRS)) } else { - fltr.WriteString(" (cost=-1 OR cost IS NULL)") + fltr.WriteString(fmt.Sprintf(" (%s.cost=-1 OR %s.cost IS NULL)", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS)) } } else if ignoreErr { if fltr.Len() != 0 { fltr.WriteString(" AND") } - fltr.WriteString(" (cost!=-1 OR cost IS NULL)") + fltr.WriteString(fmt.Sprintf(" (%s.cost!=-1 OR %s.cost IS NULL)", utils.TBL_RATED_CDRS, utils.TBL_RATED_CDRS)) } if fltr.Len() != 0 { q.WriteString(fmt.Sprintf(" WHERE %s", fltr.String())) @@ -889,7 +922,7 @@ func (self *SQLStorage) GetTpDestinations(tpid, tag string) ([]*Destination, err func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string]*utils.TPRate, error) { rts := make(map[string]*utils.TPRate) - q := fmt.Sprintf("SELECT id, connect_fee, rate, rate_unit, rate_increment, group_interval_start, rounding_method, rounding_decimals FROM %s WHERE tpid='%s' ", utils.TBL_TP_RATES, tpid) + q := fmt.Sprintf("SELECT id, connect_fee, rate, rate_unit, rate_increment, group_interval_start FROM %s WHERE tpid='%s' ", utils.TBL_TP_RATES, tpid) if tag != "" { q += fmt.Sprintf(" AND id='%s'", tag) } @@ -932,7 +965,7 @@ func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string]*utils.TPRate, 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) + q := fmt.Sprintf("SELECT tpid,id,destinations_id,rates_id,rounding_method,rounding_decimals FROM %s WHERE tpid='%s'", utils.TBL_TP_DESTINATION_RATES, tpid) if tag != "" { q += fmt.Sprintf(" AND id='%s'", tag) } @@ -942,10 +975,9 @@ func (self *SQLStorage) GetTpDestinationRates(tpid, tag string) (map[string]*uti } defer rows.Close() for rows.Next() { - var id int var tpid, tag, destinations_tag, rate_tag, rounding_method string var rounding_decimals int - if err := rows.Scan(&id, &tpid, &tag, &destinations_tag, &rate_tag, &rounding_method, &rounding_decimals); err != nil { + if err := rows.Scan(&tpid, &tag, &destinations_tag, &rate_tag, &rounding_method, &rounding_decimals); err != nil { return nil, err } diff --git a/engine/storage_sql_local_test.go b/engine/storage_sql_local_test.go index 25ba19540..f1088120a 100644 --- a/engine/storage_sql_local_test.go +++ b/engine/storage_sql_local_test.go @@ -54,7 +54,7 @@ func TestCreateTables(t *testing.T) { } else { mysql = d.(*MySQLStorage) } - for _, scriptName := range []string{CREATE_CDRS_TABLES_SQL, CREATE_COSTDETAILS_TABLES_SQL, CREATE_MEDIATOR_TABLES_SQL, CREATE_TARIFFPLAN_TABLES_SQL} { + for _, scriptName := range []string{CREATE_CDRS_TABLES_SQL, CREATE_TARIFFPLAN_TABLES_SQL} { if err := mysql.CreateTablesFromScript(path.Join(*dataDir, "storage", "mysql", scriptName)); err != nil { t.Error("Error on mysql creation: ", err.Error()) return // No point in going further diff --git a/engine/tpimporter_csv.go b/engine/tpimporter_csv.go index 7adacbb11..f0ddf2be4 100644 --- a/engine/tpimporter_csv.go +++ b/engine/tpimporter_csv.go @@ -179,10 +179,17 @@ func (self *TPCSVImporter) importDestinationRates(fn string) error { } continue } + roundingDecimals, err := strconv.Atoi(record[4]) + if err != nil { + log.Printf("Error parsing rounding decimals: %s", record[4]) + return err + } drs := []*utils.DestinationRate{ &utils.DestinationRate{ - DestinationId: record[1], - RateId: record[2], + DestinationId: record[1], + RateId: record[2], + RoundingMethod: record[3], + RoundingDecimals: roundingDecimals, }, } if err := self.StorDb.SetTPDestinationRates(self.TPid, diff --git a/mediator/mediator_local_test.go b/mediator/mediator_local_test.go index b1e0287ec..1725639b5 100644 --- a/mediator/mediator_local_test.go +++ b/mediator/mediator_local_test.go @@ -91,11 +91,9 @@ func TestInitStorDb(t *testing.T) { } else { mysql = cdrStor.(*engine.MySQLStorage) } - for _, scriptName := range []string{engine.CREATE_CDRS_TABLES_SQL, engine.CREATE_COSTDETAILS_TABLES_SQL, engine.CREATE_MEDIATOR_TABLES_SQL} { - if err := mysql.CreateTablesFromScript(path.Join(*dataDir, "storage", *storDbType, scriptName)); err != nil { - t.Fatal("Error on mysql creation: ", err.Error()) - return // No point in going further - } + if err := mysql.CreateTablesFromScript(path.Join(*dataDir, "storage", *storDbType, engine.CREATE_CDRS_TABLES_SQL)); err != nil { + t.Fatal("Error on mysql creation: ", err.Error()) + return // No point in going further } for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} { if _, err := mysql.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil {