Adding Apier TPRates documentation

This commit is contained in:
DanB
2013-07-10 12:23:51 +02:00
parent f443d384d0
commit 57c47987e2
21 changed files with 347 additions and 138 deletions

View File

@@ -26,8 +26,6 @@ import (
"github.com/cgrates/cgrates/utils"
)
// Creates a new rate within a tariff plan
func (self *Apier) SetTPRate(attrs utils.TPRate, reply *string) error {
if missing := utils.MissingStructFields(&attrs, []string{"TPid", "RateId", "ConnectFee", "RateSlots"}); len(missing) != 0 {
@@ -38,7 +36,7 @@ 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 {
if err := self.StorDb.SetTPRate(&attrs); err != nil {
return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
}
*reply = "OK"
@@ -46,7 +44,7 @@ func (self *Apier) SetTPRate(attrs utils.TPRate, reply *string) error {
}
type AttrGetTPRate struct {
TPid string // Tariff plan id
TPid string // Tariff plan id
RateId string // Rate id
}

230
docs/api_rates.rst Normal file
View File

@@ -0,0 +1,230 @@
Apier.SetTPRate
+++++++++++++++++
Creates a new rate within a tariff plan.
**Request**:
Data:
::
type TPRate struct {
TPid string // Tariff plan id
RateId string // Rate id
RateSlots []RateSlot // One or more RateSlots
}
type RateSlot struct {
ConnectFee float64 // ConnectFee applied once the call is answered
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
Weight float64 // Rate's priority when dealing with grouped rates
}
Mandatory parameters: ``[]string{"TPid", "RateId", "ConnectFee", "RateSlots"}``
*JSON sample*:
::
{
"id": 0,
"method": "Apier.SetTPRate",
"params": [
{
"RateId": "SAMPLE_RATE_4",
"RateSlots": [
{
"ConnectFee": 0,
"Rate": 1.2,
"RateIncrements": 1,
"RatedUnits": 60,
"Weight": 10
},
{
"ConnectFee": 0,
"Rate": 2.2,
"RateIncrements": 1,
"RatedUnits": 60,
"Weight": 20
}
],
"TPid": "SAMPLE_TP"
}
]
}
**Reply**:
Data:
::
string
Possible answers:
``OK`` - Success.
*JSON sample*:
::
{
"error": null,
"id": 0,
"result": "OK"
}
**Errors**:
``MANDATORY_IE_MISSING`` - Mandatory parameter missing from request.
``SERVER_ERROR`` - Server error occurred.
``DUPLICATE`` - The specified combination of TPid/RateId already exists in StorDb.
Apier.GetTPRate
+++++++++++++++
Queries specific rate on tariff plan.
**Request**:
Data:
::
type AttrGetTPRate struct {
TPid string // Tariff plan id
RateId string // Rate id
}
Mandatory parameters: ``[]string{"TPid", "RateId"}``
*JSON sample*:
::
{
"id": 1,
"method": "Apier.GetTPRate",
"params": [
{
"RateId": "SAMPLE_RATE_4",
"TPid": "SAMPLE_TP"
}
]
}
**Reply**:
Data:
::
type TPRate struct {
TPid string // Tariff plan id
RateId string // Rate id
RateSlots []RateSlot // One or more RateSlots
}
type RateSlot struct {
ConnectFee float64 // ConnectFee applied once the call is answered
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
Weight float64 // Rate's priority when dealing with grouped rates
}
*JSON sample*:
::
{
"error": null,
"id": 1,
"result": {
"RateId": "SAMPLE_RATE_4",
"RateSlots": [
{
"ConnectFee": 0,
"Rate": 1.2,
"RateIncrements": 1,
"RatedUnits": 60,
"Weight": 10
},
{
"ConnectFee": 0,
"Rate": 2.2,
"RateIncrements": 1,
"RatedUnits": 60,
"Weight": 20
}
],
"TPid": "SAMPLE_TP"
}
}
**Errors**:
``MANDATORY_IE_MISSING`` - Mandatory parameter missing from request.
``SERVER_ERROR`` - Server error occurred.
``NOT_FOUND`` - Requested rate id not found.
Apier.GetTPRateIds
+++++++++++++++++++++++++
Queries rate identities on tariff plan.
**Request**:
Data:
::
type AttrGetTPRateIds struct {
TPid string // Tariff plan id
}
Mandatory parameters: ``[]string{"TPid"}``
*JSON sample*:
::
{
"id": 1,
"method": "Apier.GetTPRateIds",
"params": [
{
"TPid": "SAMPLE_TP"
}
]
}
**Reply**:
Data:
::
[]string
*JSON sample*:
::
{
"error": null,
"id": 1,
"result": [
"SAMPLE_RATE_1",
"SAMPLE_RATE_2",
"SAMPLE_RATE_3",
"SAMPLE_RATE_4"
]
}
**Errors**:
``MANDATORY_IE_MISSING`` - Mandatory parameter missing from request.
``SERVER_ERROR`` - Server error occurred.
``NOT_FOUND`` - Requested tariff plan not found.

View File

@@ -64,7 +64,7 @@ Creates a new timing within a tariff plan.
``SERVER_ERROR`` - Server error occurred.
``DUPLICATE`` - The specified combination of TPid/DestinationId already exists in StorDb.
``DUPLICATE`` - The specified combination of TPid/TimingId already exists in StorDb.
Apier.GetTPTiming
@@ -136,10 +136,10 @@ Queries specific Timing on tariff plan.
``SERVER_ERROR`` - Server error occurred.
``NOT_FOUND`` - Requested destination id not found.
``NOT_FOUND`` - Requested timing id not found.
Apier.GetTPDestinationIds
Apier.GetTPTimingIds
+++++++++++++++++++++++++
Queries timing identities on tariff plan.
@@ -149,11 +149,11 @@ Queries timing identities on tariff plan.
Data:
::
type AttrGetTPDestinationIds struct {
type AttrGetTPTimingIds struct {
TPid string // Tariff plan id
}
Required parameters: ``[]string{"TPid"}``
Mandatory parameters: ``[]string{"TPid"}``
*JSON sample*:
::

View File

@@ -149,13 +149,13 @@ Timings
api_tptimings
SetTPRate
Rates
~~~~~~~
GetTPRate
.. toctree::
:maxdepth: 2
DeleteTPRate
GetAllTPRates
api_tprates
GetTPRateTiming

View File

@@ -19,32 +19,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package mediator
import (
"time"
"strconv"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
"strconv"
"time"
)
type FScsvCDR struct {
rowData []string // The original row extracted form csv file
rowData []string // The original row extracted form csv file
accIdIdx,
subjectIdx,
reqtypeIdx,
directionIdx,
tenantIdx,
torIdx,
accountIdx,
destinationIdx,
answerTimeIdx,
durationIdx int // Field indexes
cgrCfg *config.CGRConfig // CGR Config instance
subjectIdx,
reqtypeIdx,
directionIdx,
tenantIdx,
torIdx,
accountIdx,
destinationIdx,
answerTimeIdx,
durationIdx int // Field indexes
cgrCfg *config.CGRConfig // CGR Config instance
}
func NewFScsvCDR(cdrRow []string, accIdIdx, subjectIdx, reqtypeIdx, directionIdx, tenantIdx, torIdx,
accountIdx, destinationIdx, answerTimeIdx, durationIdx int, cfg *config.CGRConfig ) (*FScsvCDR, error) {
fscdr := FScsvCDR{ cdrRow, accIdIdx, subjectIdx, reqtypeIdx, directionIdx, tenantIdx,
torIdx, accountIdx, destinationIdx, answerTimeIdx, durationIdx, cfg }
func NewFScsvCDR(cdrRow []string, accIdIdx, subjectIdx, reqtypeIdx, directionIdx, tenantIdx, torIdx,
accountIdx, destinationIdx, answerTimeIdx, durationIdx int, cfg *config.CGRConfig) (*FScsvCDR, error) {
fscdr := FScsvCDR{cdrRow, accIdIdx, subjectIdx, reqtypeIdx, directionIdx, tenantIdx,
torIdx, accountIdx, destinationIdx, answerTimeIdx, durationIdx, cfg}
return &fscdr, nil
}
@@ -111,11 +110,3 @@ func (self *FScsvCDR) GetFallbackSubj() string {
func (self *FScsvCDR) GetExtraFields() map[string]string {
return nil
}

View File

@@ -19,13 +19,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package mediator
import (
"errors"
"bufio"
"encoding/csv"
"errors"
"flag"
"fmt"
"github.com/cgrates/cgrates/rater"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/rater"
"github.com/cgrates/cgrates/utils"
"github.com/howeyc/fsnotify"
"os"
@@ -35,14 +35,14 @@ import (
"time"
)
func NewMediator( connector rater.Connector, storDb rater.DataStorage, cfg *config.CGRConfig) (m *Mediator, err error) {
func NewMediator(connector rater.Connector, storDb rater.DataStorage, cfg *config.CGRConfig) (m *Mediator, err error) {
m = &Mediator{
connector: connector,
storDb: storDb,
cgrCfg: cfg,
storDb: storDb,
cgrCfg: cfg,
}
m.fieldNames = make( map[string][]string )
m.fieldIdxs = make( map[string][]int )
m.fieldNames = make(map[string][]string)
m.fieldIdxs = make(map[string][]int)
// Load config fields
if errLoad := m.loadConfig(); errLoad != nil {
return nil, errLoad
@@ -51,14 +51,14 @@ func NewMediator( connector rater.Connector, storDb rater.DataStorage, cfg *conf
}
type Mediator struct {
connector rater.Connector
storDb rater.DataStorage
cgrCfg *config.CGRConfig
cdrInDir, cdrOutDir string
accIdField string
accIdIdx int // Populated only for csv files where we have no names but indexes for the fields
fieldNames map[string][]string
fieldIdxs map[string][]int // Populated only for csv files where we have no names but indexes for the fields
connector rater.Connector
storDb rater.DataStorage
cgrCfg *config.CGRConfig
cdrInDir, cdrOutDir string
accIdField string
accIdIdx int // Populated only for csv files where we have no names but indexes for the fields
fieldNames map[string][]string
fieldIdxs map[string][]int // Populated only for csv files where we have no names but indexes for the fields
}
/*
@@ -77,8 +77,8 @@ Method logic:
*/
func (self *Mediator) loadConfig() error {
fieldKeys := []string{"subject", "reqtype", "direction", "tenant", "tor", "account", "destination", "time_start", "duration"}
cfgVals := [][]string{self.cgrCfg.MediatorSubjectFields, self.cgrCfg.MediatorReqTypeFields, self.cgrCfg.MediatorDirectionFields,
self.cgrCfg.MediatorTenantFields, self.cgrCfg.MediatorTORFields, self.cgrCfg.MediatorAccountFields, self.cgrCfg.MediatorDestFields,
cfgVals := [][]string{self.cgrCfg.MediatorSubjectFields, self.cgrCfg.MediatorReqTypeFields, self.cgrCfg.MediatorDirectionFields,
self.cgrCfg.MediatorTenantFields, self.cgrCfg.MediatorTORFields, self.cgrCfg.MediatorAccountFields, self.cgrCfg.MediatorDestFields,
self.cgrCfg.MediatorTimeAnswerFields, self.cgrCfg.MediatorDurationFields}
refIdx := 0 // Subject becomes reference for our checks
@@ -87,7 +87,7 @@ func (self *Mediator) loadConfig() error {
}
// All other configured fields must match the length of reference fields
for iCfgVal := range cfgVals {
if ( len(cfgVals[refIdx])!=len(cfgVals[iCfgVal]) ) {
if len(cfgVals[refIdx]) != len(cfgVals[iCfgVal]) {
// Make sure we have everywhere the length of reference key (subject)
return errors.New("Inconsistent lenght of mediator fields.")
}
@@ -122,7 +122,7 @@ func (self *Mediator) loadConfig() error {
for idx, key := range fieldKeys {
self.fieldNames[key] = cfgVals[idx]
if self.cgrCfg.MediatorCDRType == utils.FSCDR_FILE_CSV { // Special case when field names represent indexes of their location in file
self.fieldIdxs[key] = make( []int, len(cfgVals[idx]) )
self.fieldIdxs[key] = make([]int, len(cfgVals[idx]))
for iStr, cfgStr := range cfgVals[idx] {
if self.fieldIdxs[key][iStr], errConv = strconv.Atoi(cfgStr); errConv != nil {
return fmt.Errorf("All mediator index members (%s) must be ints", key)
@@ -134,8 +134,6 @@ func (self *Mediator) loadConfig() error {
return nil
}
// Watch the specified folder for file moves and parse the files on events
func (self *Mediator) TrackCDRFiles() (err error) {
watcher, err := fsnotify.NewWatcher()
@@ -173,7 +171,7 @@ func (self *Mediator) getCostsFromDB(cdr utils.CDR) (cc *rater.CallCost, err err
// Retrive the cost from rater
func (self *Mediator) getCostsFromRater(cdr utils.CDR) (*rater.CallCost, error) {
cc := &rater.CallCost{}
d, err := time.ParseDuration(strconv.FormatInt(cdr.GetDuration(),10) + "s")
d, err := time.ParseDuration(strconv.FormatInt(cdr.GetDuration(), 10) + "s")
if err != nil {
return nil, err
}
@@ -193,7 +191,7 @@ func (self *Mediator) getCostsFromRater(cdr utils.CDR) (*rater.CallCost, error)
Destination: cdr.GetDestination(),
TimeStart: t1,
TimeEnd: t1.Add(d)}
if cdr.GetReqType()== utils.PSEUDOPREPAID {
if cdr.GetReqType() == utils.PSEUDOPREPAID {
err = self.connector.Debit(cd, cc)
} else {
err = self.connector.GetCost(cd, cc)
@@ -207,7 +205,6 @@ func (self *Mediator) getCostsFromRater(cdr utils.CDR) (*rater.CallCost, error)
return cc, nil
}
// Parse the files and get cost for every record
func (self *Mediator) MediateCSVCDR(cdrfn string) (err error) {
flag.Parse()
@@ -230,29 +227,29 @@ func (self *Mediator) MediateCSVCDR(cdrfn string) (err error) {
for record, ok := csvReader.Read(); ok == nil; record, ok = csvReader.Read() {
//t, _ := time.Parse("2006-01-02 15:04:05", record[5])
var cc *rater.CallCost
for runIdx := range self.fieldIdxs["subject"] { // Query costs for every run index given by subject
csvCDR, errCDR := NewFScsvCDR( record, self.accIdIdx,
self.fieldIdxs["subject"][runIdx],
self.fieldIdxs["reqtype"][runIdx],
self.fieldIdxs["direction"][runIdx],
self.fieldIdxs["tenant"][runIdx],
self.fieldIdxs["tor"][runIdx],
self.fieldIdxs["account"][runIdx],
self.fieldIdxs["destination"][runIdx],
self.fieldIdxs["answer_time"][runIdx],
self.fieldIdxs["duration"][runIdx],
self.cgrCfg)
csvCDR, errCDR := NewFScsvCDR(record, self.accIdIdx,
self.fieldIdxs["subject"][runIdx],
self.fieldIdxs["reqtype"][runIdx],
self.fieldIdxs["direction"][runIdx],
self.fieldIdxs["tenant"][runIdx],
self.fieldIdxs["tor"][runIdx],
self.fieldIdxs["account"][runIdx],
self.fieldIdxs["destination"][runIdx],
self.fieldIdxs["answer_time"][runIdx],
self.fieldIdxs["duration"][runIdx],
self.cgrCfg)
if errCDR != nil {
rater.Logger.Err(fmt.Sprintf("<Mediator> Could not calculate price for accid: <%s>, err: <%s>",
rater.Logger.Err(fmt.Sprintf("<Mediator> Could not calculate price for accid: <%s>, err: <%s>",
record[self.accIdIdx], errCDR.Error()))
}
var errCost error
if (csvCDR.GetReqType()==utils.PREPAID || csvCDR.GetReqType()==utils.POSTPAID){
var errCost error
if csvCDR.GetReqType() == utils.PREPAID || csvCDR.GetReqType() == utils.POSTPAID {
// Should be previously calculated and stored in DB
cc, errCost = self.getCostsFromDB( csvCDR )
cc, errCost = self.getCostsFromDB(csvCDR)
} else {
cc, errCost = self.getCostsFromRater( csvCDR )
cc, errCost = self.getCostsFromRater(csvCDR)
}
cost := "-1"
if errCost != nil || cc == nil {
@@ -271,12 +268,12 @@ func (self *Mediator) MediateCSVCDR(cdrfn string) (err error) {
func (self *Mediator) MediateDBCDR(cdr utils.CDR, db rater.DataStorage) error {
var cc *rater.CallCost
var errCost error
if (cdr.GetReqType()==utils.PREPAID || cdr.GetReqType()==utils.POSTPAID){
var errCost error
if cdr.GetReqType() == utils.PREPAID || cdr.GetReqType() == utils.POSTPAID {
// Should be previously calculated and stored in DB
cc, errCost = self.getCostsFromDB( cdr )
cc, errCost = self.getCostsFromDB(cdr)
} else {
cc, errCost = self.getCostsFromRater( cdr )
cc, errCost = self.getCostsFromRater(cdr)
}
cost := "-1"
if errCost != nil || cc == nil {
@@ -287,4 +284,3 @@ func (self *Mediator) MediateDBCDR(cdr utils.CDR, db rater.DataStorage) error {
}
return self.storDb.SetRatedCdr(cdr, cc)
}

View File

@@ -1,7 +1,7 @@
package mediator
import (
//"testing"
//"testing"
)
/*

View File

@@ -690,7 +690,6 @@ func TestActionResetCounterCREDIT(t *testing.T) {
}
}
func TestActionTriggerLogging(t *testing.T) {
at := &ActionTrigger{
Id: "some_uuid",

View File

@@ -19,12 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package rater
import (
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"time"
"fmt"
"reflect"
)
// Defines years days series
@@ -73,7 +73,7 @@ func (ys *Years) Parse(input, sep string) {
}
}
func (ys Years) Serialize( sep string ) string {
func (ys Years) Serialize(sep string) string {
if len(ys) == 0 {
return "*all"
}
@@ -89,7 +89,7 @@ func (ys Years) Serialize( sep string ) string {
}
var allMonths []time.Month = []time.Month{time.January, time.February, time.March, time.April, time.May, time.June,
time.July, time.August, time.September, time.October, time.November, time.December}
time.July, time.August, time.September, time.October, time.November, time.December}
// Defines months series
type Months []time.Month
@@ -141,11 +141,11 @@ func (m *Months) Parse(input, sep string) {
}
// Dumps the months in a serialized string, similar to the one parsed
func (m Months) Serialize( sep string ) string {
func (m Months) Serialize(sep string) string {
if len(m) == 0 {
return "*none"
}
if reflect.DeepEqual( m, Months(allMonths) ) {
if reflect.DeepEqual(m, Months(allMonths)) {
return "*all"
}
var mStr string
@@ -159,7 +159,6 @@ func (m Months) Serialize( sep string ) string {
return mStr
}
var allMonthDays []int = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
// Defines month days series
@@ -211,7 +210,7 @@ func (md *MonthDays) Parse(input, sep string) {
}
// Dumps the month days in a serialized string, similar to the one parsed
func (md MonthDays) Serialize( sep string ) string {
func (md MonthDays) Serialize(sep string) string {
if len(md) == 0 {
return "*none"
}
@@ -230,6 +229,7 @@ func (md MonthDays) Serialize( sep string ) string {
}
var allWeekDays []time.Weekday = []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday, time.Saturday, time.Sunday}
// Defines week days series
type WeekDays []time.Weekday
@@ -278,11 +278,11 @@ func (wd *WeekDays) Parse(input, sep string) {
}
// Dumps the week days in a serialized string, similar to the one parsed
func (wd WeekDays) Serialize( sep string ) string {
func (wd WeekDays) Serialize(sep string) string {
if len(wd) == 0 {
return "*none"
}
if reflect.DeepEqual( wd, WeekDays(allWeekDays) ) {
if reflect.DeepEqual(wd, WeekDays(allWeekDays)) {
return "*all"
}
var wdStr string

View File

@@ -77,7 +77,7 @@ func TestYearsSerialize(t *testing.T) {
if expectString2 != yString2 {
t.Errorf("Expected: %s, got: %s", expectString2, yString2)
}
ys3 := &Years{2013,2014,2015}
ys3 := &Years{2013, 2014, 2015}
yString3 := ys3.Serialize(";")
expectString3 := "2013;2014;2015"
if expectString3 != yString3 {
@@ -104,7 +104,7 @@ func TestMonthsSerialize(t *testing.T) {
if expectString2 != mString2 {
t.Errorf("Expected: %s, got: %s", expectString2, mString2)
}
mths3 := &Months{time.January,time.December}
mths3 := &Months{time.January, time.December}
mString3 := mths3.Serialize(";")
expectString3 := "1;12"
if expectString3 != mString3 {
@@ -131,7 +131,7 @@ func TestMonthDaysSerialize(t *testing.T) {
if expectString2 != mdsString2 {
t.Errorf("Expected: %s, got: %s", expectString2, mdsString2)
}
mds3 := &MonthDays{1,2,3,4,5}
mds3 := &MonthDays{1, 2, 3, 4, 5}
mdsString3 := mds3.Serialize(";")
expectString3 := "1;2;3;4;5"
if expectString3 != mdsString3 {
@@ -158,11 +158,10 @@ func TestWeekDaysSerialize(t *testing.T) {
if expectString2 != wdsString2 {
t.Errorf("Expected: %s, got: %s", expectString2, wdsString2)
}
wds3 := &WeekDays{time.Monday, time.Saturday,time.Sunday}
wds3 := &WeekDays{time.Monday, time.Saturday, time.Sunday}
wdsString3 := wds3.Serialize(";")
expectString3 := "1;6;0"
if expectString3 != wdsString3 {
t.Errorf("Expected: %s, got: %s", expectString3, wdsString3)
}
}

View File

@@ -43,7 +43,7 @@ type TPLoader interface {
}
type Rate struct {
Tag string
Tag string
ConnectFee, Price, PricedUnits, RateIncrements, Weight float64
}
@@ -79,7 +79,7 @@ func NewRate(tag, connectFee, price, pricedUnits, rateIncrements, weight string)
Price: p,
PricedUnits: pu,
RateIncrements: ri,
Weight: wght,
Weight: wght,
}
return
}
@@ -92,7 +92,7 @@ type DestinationRate struct {
}
type Timing struct {
Id string
Id string
Years Years
Months Months
MonthDays MonthDays

View File

@@ -148,8 +148,8 @@ func (ms *MongoStorage) SetDestination(dest *Destination) error {
}
func (ms *MongoStorage) GetTPIds() ([]string, error) {
return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
func (ms *MongoStorage) SetTPTiming(tpid string, tm *Timing) error {
return errors.New(utils.ERR_NOT_IMPLEMENTED)

View File

@@ -103,7 +103,7 @@ func (rs *RedisStorage) SetDestination(dest *Destination) (err error) {
}
func (rs *RedisStorage) GetTPIds() ([]string, error) {
return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
func (rs *RedisStorage) SetTPTiming(tpid string, tm *Timing) error {

View File

@@ -83,8 +83,8 @@ func (self *SQLStorage) GetTPIds() ([]string, error) {
func (self *SQLStorage) SetTPTiming(tpid string, tm *Timing) error {
if _, err := self.Db.Exec(fmt.Sprintf("INSERT INTO %s (tpid, tag, years, months, month_days, week_days, time) VALUES('%s','%s','%s','%s','%s','%s','%s')",
utils.TBL_TP_TIMINGS, tpid, tm.Id, tm.Years.Serialize(";"), tm.Months.Serialize(";"), tm.MonthDays.Serialize(";"),
tm.WeekDays.Serialize(";"), tm.StartTime )); err != nil {
return err
tm.WeekDays.Serialize(";"), tm.StartTime)); err != nil {
return err
}
return nil
}
@@ -100,15 +100,15 @@ func (self *SQLStorage) ExistsTPTiming(tpid, tmId string) (bool, error) {
func (self *SQLStorage) GetTPTiming(tpid, tmId string) (*Timing, error) {
var years, months, monthDays, weekDays, time string
err := self.Db.QueryRow(fmt.Sprintf("SELECT years, months, month_days, week_days, time FROM %s WHERE tpid='%s' AND tag='%s' LIMIT 1",
utils.TBL_TP_TIMINGS, tpid, tmId)).Scan(&years,&months,&monthDays,&weekDays,&time)
err := self.Db.QueryRow(fmt.Sprintf("SELECT years, months, month_days, week_days, time FROM %s WHERE tpid='%s' AND tag='%s' LIMIT 1",
utils.TBL_TP_TIMINGS, tpid, tmId)).Scan(&years, &months, &monthDays, &weekDays, &time)
switch {
case err == sql.ErrNoRows:
return nil,nil
case err!=nil:
return nil, nil
case err != nil:
return nil, err
}
return NewTiming( tmId, years, months, monthDays, weekDays, time ), nil
return NewTiming(tmId, years, months, monthDays, weekDays, time), nil
}
func (self *SQLStorage) GetTPTimingIds(tpid string) ([]string, error) {
@@ -211,8 +211,8 @@ func (self *SQLStorage) ExistsTPRate(tpid, rtId string) (bool, error) {
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, weight) VALUES ('%s', '%s', %f, %f, %d, %d, %f)",
utils.TBL_TP_RATES, rt.TPid, rt.RateId, rtSlot.ConnectFee, rtSlot.Rate, rtSlot.RatedUnits, rtSlot.RateIncrements,
if _, err := self.Db.Exec(fmt.Sprintf("INSERT INTO %s (tpid, tag, connect_fee, rate, rated_units, rate_increments, weight) VALUES ('%s', '%s', %f, %f, %d, %d, %f)",
utils.TBL_TP_RATES, rt.TPid, rt.RateId, rtSlot.ConnectFee, rtSlot.Rate, rtSlot.RatedUnits, rtSlot.RateIncrements,
rtSlot.Weight)); err != nil {
return err
}
@@ -226,7 +226,7 @@ func (self *SQLStorage) GetTPRate(tpid, rtId string) (*utils.TPRate, error) {
return nil, err
}
defer rows.Close()
rt := &utils.TPRate{TPid: tpid, RateId:rtId}
rt := &utils.TPRate{TPid: tpid, RateId: rtId}
i := 0
for rows.Next() {
i++ //Keep here a reference so we know we got at least one prefix

View File

@@ -108,7 +108,7 @@ The interval will attach itself to the timespan that overlaps the interval.
*/
func (ts *TimeSpan) SplitByInterval(i *Interval) (nts *TimeSpan) {
//Logger.Debug("here: ", ts, " +++ ", i)
// if the span is not in interval return nil
// if the span is not in interval return nil
if !(i.Contains(ts.TimeStart) || i.Contains(ts.TimeEnd)) {
//Logger.Debug("Not in interval")
return

View File

@@ -19,10 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package utils
import (
"crypto/sha1"
"fmt"
"encoding/hex"
"crypto/rand"
"crypto/sha1"
"encoding/hex"
"fmt"
"strconv"
"time"
)

View File

@@ -20,17 +20,16 @@ package utils
// This file deals with tp_rates data definition
type TPRate struct {
TPid string // Tariff plan id
RateId string // Rate id
RateSlots []RateSlot // One or more RateSlots
TPid string // Tariff plan id
RateId string // Rate id
RateSlots []RateSlot // One or more RateSlots
}
type RateSlot struct {
ConnectFee float64 // ConnectFee applied once the call is answered
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
Weight float64 // Rate's priority when dealing with grouped rates
Rate float64 // Rate applied
RatedUnits int // Number of billing units this rate applies to
RateIncrements int // This rate will apply in increments of duration
Weight float64 // Rate's priority when dealing with grouped rates
}

View File

@@ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package utils
// Converts map[string]string into map[string]interface{}

View File

@@ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package utils
import (

View File

@@ -105,4 +105,3 @@ func UpdateStructWithStrMap(s interface{}, m map[string]string) []string {
}
return notMatched
}

View File

@@ -34,8 +34,8 @@ func TestFirstNonEmpty(t *testing.T) {
}
func TestUUID(t *testing.T) {
uuid := GenUUID()
if len(uuid) == 0 {
t.Fatalf("GenUUID error %s", uuid)
}
uuid := GenUUID()
if len(uuid) == 0 {
t.Fatalf("GenUUID error %s", uuid)
}
}