Few more methods on TPCSVImporter, API TPRates modifications to include GroupInterval

This commit is contained in:
DanB
2013-07-29 12:40:23 +02:00
parent 63d9612932
commit 1a1403ace1
11 changed files with 120 additions and 43 deletions

View File

@@ -24,6 +24,7 @@ import (
"errors"
"fmt"
"github.com/cgrates/cgrates/utils"
"github.com/cgrates/cgrates/engine"
)
// Creates a new rate within a tariff plan
@@ -36,7 +37,12 @@ func (self *Apier) SetTPRate(attrs utils.TPRate, reply *string) error {
} else if exists {
return errors.New(utils.ERR_DUPLICATE)
}
if err := self.StorDb.SetTPRate(&attrs); err != nil {
rts := make([]*engine.Rate, len(attrs.RateSlots))
for idx,rtSlot := range attrs.RateSlots {
rts[idx] = &engine.Rate{attrs.RateId, rtSlot.ConnectFee, rtSlot.Rate, float64(rtSlot.RatedUnits),
float64(rtSlot.RateIncrements), float64(rtSlot.GroupInterval), rtSlot.RoundingMethod, rtSlot.RoundingDecimals, rtSlot.Weight}
}
if err := self.StorDb.SetTPRates( attrs.TPid, map[string][]*engine.Rate{ attrs.RateId: rts } ); err != nil {
return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
}
*reply = "OK"

View File

@@ -43,11 +43,12 @@ CREATE TABLE `tp_rates` (
`rate` decimal(5,4) NOT NULL,
`rated_units` int(11) NOT NULL,
`rate_increments` int(11) NOT NULL,
`group_interval` int(11) NOT NULL,
`rounding_method` varchar(255) NOT NULL,
`rounding_decimals` tinyint(4) NOT NULL,
`weight` decimal(5,2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `tpid_tag_rate_weight` (`tpid`,`tag`,`weight`),
UNIQUE KEY `unique_tprate` (`tpid`,`tag`,`group_interval`),
KEY `tpid` (`tpid`),
KEY `tpid_tag` (`tpid`,`tag`)
);

View File

@@ -15,13 +15,14 @@ Creates a new rate within a tariff plan.
}
type RateSlot struct {
ConnectFee float64 // ConnectFee applied once the call is answered
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
RoundingMethod string // Use this method to round the cost
RoundingDecimals int // Round the cost number of decimals
Weight float64 // Rate's priority when dealing with grouped rates
ConnectFee float64 // ConnectFee applied once the call is answered
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
GroupInterval int // Group position
RoundingMethod string // Use this method to round the cost
RoundingDecimals int // Round the cost number of decimals
Weight float64 // Rate's priority when dealing with grouped rates
}
Mandatory parameters: ``[]string{"TPid", "RateId", "ConnectFee", "RateSlots"}``
@@ -39,9 +40,10 @@ Creates a new rate within a tariff plan.
{
"ConnectFee": 0.2,
"Rate": 2,
"RateIncrements": 1,
"RateIncrements": 60,
"RatedUnits": 1,
"RoundingDecimals": 2,
"RoundingDecimals": 2,
"GroupInterval": 0,
"RoundingMethod": "*up",
"Weight": 10.0
},
@@ -50,7 +52,8 @@ Creates a new rate within a tariff plan.
"Rate": 2.1,
"RateIncrements": 1,
"RatedUnits": 1,
"RoundingDecimals": 2,
"RoundingDecimals": 2,
"GroupInterval": 60,
"RoundingMethod": "*up",
"Weight": 20.0
}
@@ -131,13 +134,14 @@ Queries specific rate on tariff plan.
}
type RateSlot struct {
ConnectFee float64 // ConnectFee applied once the call is answered
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
RoundingMethod string // Use this method to round the cost
RoundingDecimals int // Round the cost number of decimals
Weight float64 // Rate's priority when dealing with grouped rates
ConnectFee float64 // ConnectFee applied once the call is answered
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
GroupInterval int // Group position
RoundingMethod string // Use this method to round the cost
RoundingDecimals int // Round the cost number of decimals
Weight float64 // Rate's priority when dealing with grouped rates
}
*JSON sample*:
@@ -152,9 +156,10 @@ Queries specific rate on tariff plan.
{
"ConnectFee": 0.2,
"Rate": 2,
"RateIncrements": 1,
"RateIncrements": 60,
"RatedUnits": 1,
"RoundingDecimals": 2,
"RoundingDecimals": 2,
"GroupInterval": 0,
"RoundingMethod": "*up",
"Weight": 10
},
@@ -163,7 +168,8 @@ Queries specific rate on tariff plan.
"Rate": 2.1,
"RateIncrements": 1,
"RatedUnits": 1,
"RoundingDecimals": 2,
"RoundingDecimals": 2,
"GroupInterval": 60,
"RoundingMethod": "*up",
"Weight": 20
}

View File

@@ -116,7 +116,7 @@ func topupResetAction(ub *UserBalance, a *Action) (err error) {
if a.BalanceId == MINUTES {
ub.MinuteBuckets = make([]*MinuteBucket, 0)
} else {
ub.BalanceMap[a.BalanceId+a.Direction] = BalanceChain{&Balance{Value: 0}}
ub.BalanceMap[a.BalanceId+a.Direction] = BalanceChain{&Balance{Value: 0}} // ToDo: can ub be empty here?
}
genericMakeNegative(a)
genericDebit(ub, a)

View File

@@ -68,7 +68,7 @@ type DataStorage interface {
GetTPDestination(string, string) (*Destination, error)
GetTPDestinationIds(string) ([]string, error)
ExistsTPRate(string, string) (bool, error)
SetTPRate(*utils.TPRate) error
SetTPRates(string, map[string][]*Rate) error
GetTPRate(string, string) (*utils.TPRate, error)
GetTPRateIds(string) ([]string, error)
ExistsTPDestinationRate(string, string) (bool, error)

View File

@@ -113,7 +113,7 @@ func (ms *MapStorage) ExistsTPRate(tpid, rtId string) (bool, error) {
return false, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
func (ms *MapStorage) SetTPRate(rt *utils.TPRate) error {
func (ms *MapStorage) SetTPRates(tpid string, rts map[string][]*Rate) error {
return errors.New(utils.ERR_NOT_IMPLEMENTED)
}

View File

@@ -188,7 +188,7 @@ func (ms *MongoStorage) ExistsTPRate(tpid, rtId string) (bool, error) {
return false, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
func (ms *MongoStorage) SetTPRate(rt *utils.TPRate) error {
func (ms *MongoStorage) SetTPRates(tpid string, rts map[string][]*Rate) error {
return errors.New(utils.ERR_NOT_IMPLEMENTED)
}

View File

@@ -143,7 +143,7 @@ func (rs *RedisStorage) ExistsTPRate(tpid, rtId string) (bool, error) {
return false, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
func (rs *RedisStorage) SetTPRate(rt *utils.TPRate) error {
func (rs *RedisStorage) SetTPRates(tpid string, rts map[string][]*Rate) error {
return errors.New(utils.ERR_NOT_IMPLEMENTED)
}

View File

@@ -210,19 +210,29 @@ func (self *SQLStorage) ExistsTPRate(tpid, rtId string) (bool, error) {
return exists, nil
}
func (self *SQLStorage) SetTPRate(rt *utils.TPRate) error {
for _, rtSlot := range rt.RateSlots {
if _, err := self.Db.Exec(fmt.Sprintf("INSERT INTO %s (tpid, tag, connect_fee, rate, rated_units, rate_increments, rounding_method, rounding_decimals, weight) VALUES ('%s', '%s', %f, %f, %d, %d,'%s', %d, %f)",
utils.TBL_TP_RATES, rt.TPid, rt.RateId, rtSlot.ConnectFee, rtSlot.Rate, rtSlot.RatedUnits, rtSlot.RateIncrements,
rtSlot.RoundingMethod, rtSlot.RoundingDecimals, rtSlot.Weight)); err != nil {
return err
func (self *SQLStorage) SetTPRates(tpid string, rts map[string][]*Rate) error {
if len(rts) == 0 {
return nil //Nothing to set
}
qry := fmt.Sprintf("INSERT INTO %s (tpid, tag, connect_fee, rate, rated_units, rate_increments, group_interval, rounding_method, rounding_decimals, weight) VALUES ", utils.TBL_TP_RATES)
for rtId, rtRows := range rts {
for idx, rt := range rtRows {
if idx != 0 { //Consecutive values after the first will be prefixed with "," as separator
qry += ","
}
qry += fmt.Sprintf("('%s', '%s', %f, %f, %d, %d,%d,'%s', %d, %f)",
tpid, rtId, rt.ConnectFee, rt.Price, int(rt.PricedUnits), int(rt.RateIncrements), int(rt.GroupInterval),
rt.RoundingMethod, rt.RoundingDecimals, rt.Weight)
}
}
if _, err := self.Db.Exec(qry); err != nil {
return err
}
return nil
}
func (self *SQLStorage) GetTPRate(tpid, rtId string) (*utils.TPRate, error) {
rows, err := self.Db.Query(fmt.Sprintf("SELECT connect_fee, rate, rated_units, rate_increments, rounding_method, rounding_decimals, weight FROM %s WHERE tpid='%s' AND tag='%s'", utils.TBL_TP_RATES, tpid, rtId))
rows, err := self.Db.Query(fmt.Sprintf("SELECT connect_fee, rate, rated_units, rate_increments, group_interval, rounding_method, rounding_decimals, weight FROM %s WHERE tpid='%s' AND tag='%s'", utils.TBL_TP_RATES, tpid, rtId))
if err != nil {
return nil, err
}
@@ -232,13 +242,14 @@ func (self *SQLStorage) GetTPRate(tpid, rtId string) (*utils.TPRate, error) {
for rows.Next() {
i++ //Keep here a reference so we know we got at least one prefix
var connectFee, rate, weight float64
var ratedUnits, rateIncrements, roundingDecimals int
var ratedUnits, rateIncrements, roundingDecimals, groupInterval int
var roundingMethod string
err = rows.Scan(&connectFee, &rate, &ratedUnits, &rateIncrements, &roundingMethod, &roundingDecimals, &weight)
err = rows.Scan(&connectFee, &rate, &ratedUnits, &rateIncrements, &groupInterval, &roundingMethod, &roundingDecimals, &weight)
if err != nil {
return nil, err
}
rt.RateSlots = append(rt.RateSlots, utils.RateSlot{connectFee, rate, ratedUnits, rateIncrements, roundingMethod, roundingDecimals, weight})
rt.RateSlots = append(rt.RateSlots, utils.RateSlot{connectFee, rate, ratedUnits, rateIncrements, groupInterval,
roundingMethod, roundingDecimals, weight})
}
if i == 0 {
return nil, nil

View File

@@ -35,6 +35,8 @@ type TPCSVImporter struct {
Verbose bool // If true will print a detailed information instead of silently discarding it
}
// Maps csv file to handler which should process it. Defined like this since tests on 1.0.3 were failing on Travis.
// Change it to func(string) error as soon as Travis updates.
var fileHandlers = map[string]func(*TPCSVImporter,string) error{
utils.TIMINGS_CSV: (*TPCSVImporter).importTimings,
utils.DESTINATIONS_CSV: (*TPCSVImporter).importDestinations,
@@ -49,10 +51,6 @@ var fileHandlers = map[string]func(*TPCSVImporter,string) error{
}
func (self *TPCSVImporter) Run() error {
// Maps csv file to handler which should process it
files, _ := ioutil.ReadDir(self.DirPath)
for _, f := range files {
fHandler,hasName := fileHandlers[f.Name()]
@@ -66,6 +64,9 @@ func (self *TPCSVImporter) Run() error {
// Handler importing timings from file, saved row by row to storDb
func (self *TPCSVImporter) importTimings(fn string) error {
if self.Verbose {
log.Printf("Processing file: <%s> ", fn)
}
fParser, err := NewTPCSVFileParser( self.DirPath, fn )
if err!=nil {
return err
@@ -90,11 +91,62 @@ func (self *TPCSVImporter) importTimings(fn string) error {
return nil
}
func (self *TPCSVImporter) importDestinations(fPath string) error {
func (self *TPCSVImporter) importDestinations(fn string) error {
if self.Verbose {
log.Printf("Processing file: <%s> ", fn)
}
fParser, err := NewTPCSVFileParser( self.DirPath, fn )
if err!=nil {
return err
}
lineNr := 0
for {
lineNr++
record, err := fParser.ParseNextLine()
if err == io.EOF { // Reached end of file
break
} else if err != nil {
if self.Verbose {
log.Printf("Ignoring line %d, warning: <%s> ", lineNr, err.Error())
}
continue
}
dst := &Destination{record[0], []string{record[1]}}
if err := self.StorDb.SetTPDestination(self.TPid, dst); err != nil {
log.Printf("Ignoring line %d, storDb operational error: <%s> ", lineNr, err.Error())
}
}
return nil
}
func (self *TPCSVImporter) importRates(fPath string) error {
func (self *TPCSVImporter) importRates(fn string) error {
if self.Verbose {
log.Printf("Processing file: <%s> ", fn)
}
fParser, err := NewTPCSVFileParser( self.DirPath, fn )
if err!=nil {
return err
}
lineNr := 0
for {
lineNr++
record, err := fParser.ParseNextLine()
if err == io.EOF { // Reached end of file
break
} else if err != nil {
if self.Verbose {
log.Printf("Ignoring line %d, warning: <%s> ", lineNr, err.Error())
}
continue
}
rt, err := NewRate(record[0], record[1], record[2], record[3], record[4], record[5], record[6], record[7], record[8])
if err != nil {
return err
}
if err := self.StorDb.SetTPRates( self.TPid, map[string][]*Rate{ record[0]: []*Rate{rt} } ); err != nil {
log.Printf("Ignoring line %d, storDb operational error: <%s> ", lineNr, err.Error())
}
}
return nil
}

View File

@@ -31,6 +31,7 @@ type RateSlot struct {
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
GroupInterval int // Group position
RoundingMethod string // Use this method to round the cost
RoundingDecimals int // Round the cost number of decimals
Weight float64 // Rate's priority when dealing with grouped rates