diff --git a/apier/tpactiontimings.go b/apier/tpactiontimings.go
new file mode 100644
index 000000000..802e53b9f
--- /dev/null
+++ b/apier/tpactiontimings.go
@@ -0,0 +1,97 @@
+/*
+Rating system designed to be used in VoIP Carriers World
+Copyright (C) 2013 ITsysCOM
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package apier
+
+import (
+ "errors"
+ "fmt"
+ "github.com/cgrates/cgrates/utils"
+)
+
+// Creates a new ActionTimings profile within a tariff plan
+func (self *Apier) SetTPActionTimings(attrs utils.ApiTPActionTimings, reply *string) error {
+ if missing := utils.MissingStructFields(&attrs, []string{"TPid", "ActionsId", "ActionTimings"}); len(missing) != 0 {
+ return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing)
+ }
+ for _, at := range attrs.ActionTimings {
+ requiredFields := []string{"ActionsId", "TimingId", "Weight"}
+ if missing := utils.MissingStructFields(&at, requiredFields); len(missing) != 0 {
+ return fmt.Errorf("%s:Action:%s:%v", utils.ERR_MANDATORY_IE_MISSING, at.ActionsId, missing)
+ }
+ }
+ if exists, err := self.StorDb.ExistsTPActionTimings(attrs.TPid, attrs.ActionTimingsId); err != nil {
+ return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
+ } else if exists {
+ return errors.New(utils.ERR_DUPLICATE)
+ }
+ ats := make(map[string][]*utils.TPActionTimingsRow, 1) // Only one id will be stored in the map
+ for _,at := range attrs.ActionTimings {
+ ats[attrs.ActionTimingsId] = append( ats[attrs.ActionTimingsId], &utils.TPActionTimingsRow{at.ActionsId, at.TimingId, at.Weight} )
+ }
+ if err := self.StorDb.SetTPActionTimings(attrs.TPid, ats); err != nil {
+ return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
+ }
+ *reply = "OK"
+ return nil
+}
+
+type AttrGetTPActionTimings struct {
+ TPid string // Tariff plan id
+ ActionTimingsId string // ActionTimings id
+}
+
+// Queries specific ActionTimings profile on tariff plan
+func (self *Apier) GetTPActionTimings(attrs AttrGetTPActionTimings, reply *utils.ApiTPActionTimings) error {
+ if missing := utils.MissingStructFields(&attrs, []string{"TPid", "ActionTimingsId"}); len(missing) != 0 { //Params missing
+ return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing)
+ }
+ if ats, err := self.StorDb.GetTPActionTimings(attrs.TPid, attrs.ActionTimingsId); err != nil {
+ return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
+ } else if len(ats) == 0 {
+ return errors.New(utils.ERR_NOT_FOUND)
+ } else { // Got the data we need, convert it from []TPActionTimingsRow into ApiTPActionTimings
+ atRply := &utils.ApiTPActionTimings{ attrs.TPid, attrs.ActionTimingsId, make([]utils.ApiActionTiming, len(ats[attrs.ActionTimingsId])) }
+ for idx,row := range ats[attrs.ActionTimingsId] {
+ atRply.ActionTimings[idx] = utils.ApiActionTiming{ row.ActionsId, row.TimingId, row.Weight }
+ }
+ *reply = *atRply
+ }
+ return nil
+}
+
+type AttrGetTPActionTimingIds struct {
+ TPid string // Tariff plan id
+}
+
+// Queries ActionTimings identities on specific tariff plan.
+func (self *Apier) GetTPActionTimingIds(attrs AttrGetTPActionTimingIds, reply *[]string) error {
+ if missing := utils.MissingStructFields(&attrs, []string{"TPid"}); len(missing) != 0 { //Params missing
+ return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing)
+ }
+ if ids, err := self.StorDb.GetTPActionTimingIds(attrs.TPid); err != nil {
+ return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
+ } else if ids == nil {
+ return errors.New(utils.ERR_NOT_FOUND)
+ } else {
+ *reply = ids
+ }
+ return nil
+}
+
+
diff --git a/docs/apicalls.rst b/docs/apicalls.rst
index 401a337ea..4e3781e6b 100644
--- a/docs/apicalls.rst
+++ b/docs/apicalls.rst
@@ -189,7 +189,7 @@ Actions
.. toctree::
:maxdepth: 2
- api_actions
+ api_tpactions
6.1.5. Management API
diff --git a/rater/storage_interface.go b/rater/storage_interface.go
index a28054afa..17e5bbd1a 100644
--- a/rater/storage_interface.go
+++ b/rater/storage_interface.go
@@ -87,6 +87,10 @@ type DataStorage interface {
SetTPActions(*utils.TPActions) error
GetTPActions(string, string) (*utils.TPActions, error)
GetTPActionIds(string) ([]string, error)
+ ExistsTPActionTimings(string, string) (bool, error)
+ SetTPActionTimings(string, map[string][]*utils.TPActionTimingsRow) error
+ GetTPActionTimings(string, string) (map[string][]*utils.TPActionTimingsRow, error)
+ GetTPActionTimingIds(string) ([]string, error)
// End Apier functions
GetActions(string) (Actions, error)
SetActions(string, Actions) error
diff --git a/rater/storage_map.go b/rater/storage_map.go
index c3672ba90..ad26d0887 100644
--- a/rater/storage_map.go
+++ b/rater/storage_map.go
@@ -189,6 +189,22 @@ func (ms *MapStorage) GetTPActionIds(tpid string) ([]string, error) {
return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
+func (ms *MapStorage) ExistsTPActionTimings(tpid, atId string) (bool, error) {
+ return false, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (ms *MapStorage) SetTPActionTimings(tpid string, ats map[string][]*utils.TPActionTimingsRow) error {
+ return errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (ms *MapStorage) GetTPActionTimings(tpid, atId string) (map[string][]*utils.TPActionTimingsRow, error) {
+ return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (ms *MapStorage) GetTPActionTimingIds(tpid string) ([]string, error) {
+ return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
func (ms *MapStorage) GetActions(key string) (as Actions, err error) {
if values, ok := ms.dict[ACTION_PREFIX+key]; ok {
err = ms.ms.Unmarshal(values, &as)
diff --git a/rater/storage_mongo.go b/rater/storage_mongo.go
index 1fbcab6a3..53870a070 100644
--- a/rater/storage_mongo.go
+++ b/rater/storage_mongo.go
@@ -264,6 +264,22 @@ func (ms *MongoStorage) GetTPActionIds(tpid string) ([]string, error) {
return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
+func (ms *MongoStorage) ExistsTPActionTimings(tpid, atId string) (bool, error) {
+ return false, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (ms *MongoStorage) SetTPActionTimings(tpid string, ats map[string][]*utils.TPActionTimingsRow) error {
+ return errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (ms *MongoStorage) GetTPActionTimings(tpid, atId string) (map[string][]*utils.TPActionTimingsRow, error) {
+ return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (ms *MongoStorage) GetTPActionTimingIds(tpid string) ([]string, error) {
+ return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
func (ms *MongoStorage) GetActions(key string) (as Actions, err error) {
result := AcKeyValue{}
err = ms.db.C("actions").Find(bson.M{"key": key}).One(&result)
diff --git a/rater/storage_redis.go b/rater/storage_redis.go
index b97de290d..3009ad410 100644
--- a/rater/storage_redis.go
+++ b/rater/storage_redis.go
@@ -219,6 +219,22 @@ func (rs *RedisStorage) GetTPActionIds(tpid string) ([]string, error) {
return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
}
+func (rs *RedisStorage) ExistsTPActionTimings(tpid, atId string) (bool, error) {
+ return false, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (rs *RedisStorage) SetTPActionTimings(tpid string, ats map[string][]*utils.TPActionTimingsRow) error {
+ return errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (rs *RedisStorage) GetTPActionTimings(tpid, atId string) (map[string][]*utils.TPActionTimingsRow, error) {
+ return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
+func (rs *RedisStorage) GetTPActionTimingIds(tpid string) ([]string, error) {
+ return nil, errors.New(utils.ERR_NOT_IMPLEMENTED)
+}
+
func (rs *RedisStorage) GetActions(key string) (as Actions, err error) {
var values string
if values, err = rs.db.Get(ACTION_PREFIX + key); err == nil {
diff --git a/rater/storage_sql.go b/rater/storage_sql.go
index c76dca64e..dafefc9e0 100644
--- a/rater/storage_sql.go
+++ b/rater/storage_sql.go
@@ -586,16 +586,92 @@ func (self *SQLStorage) GetTPActionIds(tpid string) ([]string, error) {
return ids, nil
}
+func (self *SQLStorage) ExistsTPActionTimings(tpid, atId string) (bool, error) {
+ var exists bool
+ err := self.Db.QueryRow(fmt.Sprintf("SELECT EXISTS (SELECT 1 FROM %s WHERE tpid='%s' AND tag='%s')", utils.TBL_TP_ACTION_TIMINGS, tpid, atId)).Scan(&exists)
+ if err != nil {
+ return false, err
+ }
+ return exists, nil
+}
+
+// Sets actionTimings in sqlDB. Imput is expected in form map[actionTimingId][]rows, eg a full .csv file content
+func (self *SQLStorage) SetTPActionTimings(tpid string, ats map[string][]*utils.TPActionTimingsRow) error {
+ if len(ats) == 0 {
+ return nil //Nothing to set
+ }
+ qry := fmt.Sprintf("INSERT INTO %s (tpid,tag,actions_tag,timing_tag,weight) VALUES ", utils.TBL_TP_ACTION_TIMINGS)
+ for atId, atRows := range ats {
+ for idx, atsRow := range atRows {
+ if idx != 0 { //Consecutive values after the first will be prefixed with "," as separator
+ qry += ","
+ }
+ qry += fmt.Sprintf("('%s','%s','%s','%s',%f)",
+ tpid, atId, atsRow.ActionsId, atsRow.TimingId, atsRow.Weight)
+ }
+ }
+ if _, err := self.Db.Exec(qry); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (self *SQLStorage) GetTPActionTimings(tpid, atId string) (map[string][]*utils.TPActionTimingsRow, error) {
+ ats := make(map[string][]*utils.TPActionTimingsRow)
+ q := fmt.Sprintf("SELECT tag,actions_tag,timing_tag,weight FROM %s WHERE tpid='%s'", utils.TBL_TP_ACTION_TIMINGS, tpid)
+ if atId != "" {
+ q += fmt.Sprintf(" AND tag='%s'", atId)
+ }
+ rows, err := self.Db.Query(q)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ i := 0
+ for rows.Next() {
+ i++ //Keep here a reference so we know we got at least one result
+ var tag, actionsId, timingId string
+ var weight float64
+ if err = rows.Scan(&tag, &actionsId, &timingId, &weight); err!= nil {
+ return nil, err
+ }
+ ats[tag] = append(ats[tag], &utils.TPActionTimingsRow{actionsId, timingId, weight})
+ }
+ return ats, nil
+}
+
+func (self *SQLStorage) GetTPActionTimingIds(tpid string) ([]string, error) {
+ rows, err := self.Db.Query(fmt.Sprintf("SELECT DISTINCT tag FROM %s where tpid='%s'", utils.TBL_TP_ACTION_TIMINGS, tpid))
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ ids := []string{}
+ i := 0
+ for rows.Next() {
+ i++ //Keep here a reference so we know we got at least one
+ var id string
+ if err = rows.Scan(&id); err != nil {
+ return nil, err
+ }
+ ids = append(ids, id)
+ }
+ if i == 0 {
+ return nil, nil
+ }
+ return ids, nil
+}
+
+func (self *SQLStorage) GetUserBalance(string) (ub *UserBalance, err error) { return }
+
+func (self *SQLStorage) SetUserBalance(ub *UserBalance) (err error) { return }
+
func (self *SQLStorage) GetActions(string) (as Actions, err error) {
return
}
func (self *SQLStorage) SetActions(key string, as Actions) (err error) { return }
-func (self *SQLStorage) GetUserBalance(string) (ub *UserBalance, err error) { return }
-
-func (self *SQLStorage) SetUserBalance(ub *UserBalance) (err error) { return }
-
func (self *SQLStorage) GetActionTimings(key string) (ats ActionTimings, err error) { return }
func (self *SQLStorage) SetActionTimings(key string, ats ActionTimings) (err error) { return }
@@ -978,7 +1054,7 @@ func (self *SQLStorage) GetTpActionTriggers(tpid, tag string) (map[string][]*Act
var id int
var threshold, weight float64
var tpid, tag, balances_tag, direction, destinations_tag, actions_tag, thresholdType string
- if err := rows.Scan(&id, &tpid, &tag, &balances_tag, &direction, &threshold, &thresholdType, &destinations_tag, &actions_tag, &weight); err != nil {
+ if err := rows.Scan(&id, &tpid, &tag, &balances_tag, &direction, &thresholdType, &threshold, &destinations_tag, &actions_tag, &weight); err != nil {
return nil, err
}
@@ -986,8 +1062,8 @@ func (self *SQLStorage) GetTpActionTriggers(tpid, tag string) (map[string][]*Act
Id: utils.GenUUID(),
BalanceId: balances_tag,
Direction: direction,
- ThresholdValue: threshold,
ThresholdType: thresholdType,
+ ThresholdValue: threshold,
DestinationId: destinations_tag,
ActionsId: actions_tag,
Weight: weight,
diff --git a/utils/apitpdata.go b/utils/apitpdata.go
new file mode 100644
index 000000000..c946aafe2
--- /dev/null
+++ b/utils/apitpdata.go
@@ -0,0 +1,137 @@
+/*
+Rating system designed to be used in VoIP Carriers World
+Copyright (C) 2013 ITsysCOM
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package utils
+
+// This file deals with tp_* data definition
+
+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
+ 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
+}
+
+type TPDestinationRate struct {
+ TPid string // Tariff plan id
+ DestinationRateId string // DestinationRate profile id
+ DestinationRates []DestinationRate // Set of destinationid-rateid bindings
+}
+
+type DestinationRate struct {
+ DestinationId string // The destination identity
+ RateId string // The rate identity
+}
+
+type TPDestRateTiming struct {
+ TPid string // Tariff plan id
+ DestRateTimingId string // DestinationRate profile id
+ DestRateTimings []DestRateTiming // Set of destinationid-rateid bindings
+}
+
+type DestRateTiming struct {
+ DestRatesId string // The DestinationRate identity
+ TimingId string // The timing identity
+ Weight float64 // Binding priority taken into consideration when more DestinationRates are active on a time slot
+}
+
+type TPRateProfile struct {
+ TPid string // Tariff plan id
+ RateProfileId string // RateProfile id
+ Tenant string // Tenant's Id
+ TOR string // TypeOfRecord
+ Direction string // Traffic direction, OUT is the only one supported for now
+ Subject string // Rating subject, usually the same as account
+ RatesFallbackSubject string // Fallback on this subject if rates not found for destination
+ RatingActivations []RatingActivation // Activate rate profiles at specific time
+}
+
+type RatingActivation struct {
+ ActivationTime int64 // Time when this profile will become active, defined as unix epoch time
+ DestRateTimingId string // Id of DestRateTiming profile
+}
+
+type AttrTPRateProfileIds struct {
+ TPid string // Tariff plan id
+ Tenant string // Tenant's Id
+ TOR string // TypeOfRecord
+ Direction string // Traffic direction
+ Subject string // Rating subject, usually the same as account
+}
+
+type TPActions struct {
+ TPid string // Tariff plan id
+ ActionsId string // Actions id
+ Actions []Action // Set of actions this Actions profile will perform
+}
+
+type Action struct {
+ Identifier string // Identifier mapped in the code
+ BalanceId string // Type of balance the action will operate on
+ Direction string // Balance direction
+ Units float64 // Number of units to add/deduct
+ ExpirationTime int64 // Time when the units will expire
+ DestinationId string // Destination profile id
+ RateType string // Type of price
+ Rate float64 // Price value
+ MinutesWeight float64 // Minutes weight
+ Weight float64 // Action's weight
+}
+
+type ApiTPActionTimings struct {
+ TPid string // Tariff plan id
+ ActionTimingsId string // ActionTimings id
+ ActionTimings []ApiActionTiming // Set of ActionTiming bindings this profile will group
+}
+
+type ApiActionTiming struct {
+ ActionsId string // Actions id
+ TimingId string // Timing profile id
+ Weight float64 // Binding's weight
+}
+
+type TPActionTriggers struct {
+ TPid string // Tariff plan id
+ ActionTriggerId string // ActionTrigger id
+ BalanceId string // Id of the balance this trigger monitors
+ Direction string // Traffic direction
+ ThresholdType string // This threshold type
+ ThresholdValue float64 // Threshold
+ DestinationId string // Id of the destination profile
+ ActionsId string // Actions which will execute on threshold reached
+ Weight float64 // weight
+}
+
+type TPAccountActions struct {
+ TPid string // Tariff plan id
+ AccountActionsId string // AccountActions id
+ Tenant string // Tenant's Id
+ Account string // Account name
+ Direction string // Traffic direction
+ ActionTimingsId string // Id of ActionTimings profile to use
+ ActionTriggersId string // Id of ActionTriggers profile to use
+}
diff --git a/utils/tpdata.go b/utils/tpdata.go
index d622886cf..3b1fe33e8 100644
--- a/utils/tpdata.go
+++ b/utils/tpdata.go
@@ -18,120 +18,11 @@ along with this program. If not, see
package utils
-// This file deals with tp_* data definition
-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
- 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
-}
-
-type TPDestinationRate struct {
- TPid string // Tariff plan id
- DestinationRateId string // DestinationRate profile id
- DestinationRates []DestinationRate // Set of destinationid-rateid bindings
-}
-
-type DestinationRate struct {
- DestinationId string // The destination identity
- RateId string // The rate identity
-}
-
-type TPDestRateTiming struct {
- TPid string // Tariff plan id
- DestRateTimingId string // DestinationRate profile id
- DestRateTimings []DestRateTiming // Set of destinationid-rateid bindings
-}
-
-type DestRateTiming struct {
- DestRatesId string // The DestinationRate identity
- TimingId string // The timing identity
- Weight float64 // Binding priority taken into consideration when more DestinationRates are active on a time slot
-}
-
-type TPRateProfile struct {
- TPid string // Tariff plan id
- RateProfileId string // RateProfile id
- Tenant string // Tenant's Id
- TOR string // TypeOfRecord
- Direction string // Traffic direction, OUT is the only one supported for now
- Subject string // Rating subject, usually the same as account
- RatesFallbackSubject string // Fallback on this subject if rates not found for destination
- RatingActivations []RatingActivation // Activate rate profiles at specific time
-}
-
-type RatingActivation struct {
- ActivationTime int64 // Time when this profile will become active, defined as unix epoch time
- DestRateTimingId string // Id of DestRateTiming profile
-}
-
-type AttrTPRateProfileIds struct {
- TPid string // Tariff plan id
- Tenant string // Tenant's Id
- TOR string // TypeOfRecord
- Direction string // Traffic direction
- Subject string // Rating subject, usually the same as account
-}
-
-type TPActions struct {
- TPid string // Tariff plan id
- ActionsId string // Actions id
- Actions []Action // Set of actions this Actions profile will perform
-}
-
-type Action struct {
- Identifier string // Identifier mapped in the code
- BalanceId string // Type of balance the action will operate on
- Direction string // Balance direction
- Units float64 // Number of units to add/deduct
- ExpirationTime int64 // Time when the units will expire
- DestinationId string // Destination profile id
- RateType string // Type of price
- Rate float64 // Price value
- MinutesWeight float64 // Minutes weight
- Weight float64 // Action's weight
-}
-
-type TPActionTimings struct {
- TPid string // Tariff plan id
- ActionTimingsId string // ActionTimings id
- ActionTimings []ActionTiming // Set of ActionTiming bindings this profile will group
-}
-
-type ActionTiming struct {
+// Represents a single row in .csv or storDb, id will be used as key in the map holding all rows
+type TPActionTimingsRow struct {
ActionsId string // Actions id
TimingId string // Timing profile id
Weight float64 // Binding's weight
}
-type TPActionTriggers struct {
- TPid string // Tariff plan id
- ActionTriggerId string // ActionTrigger id
- BalanceId string // Id of the balance this trigger monitors
- Direction string // Traffic direction
- ThresholdType string // This threshold type
- ThresholdValue float64 // Threshold
- DestinationId string // Id of the destination profile
- ActionsId string // Actions which will execute on threshold reached
- Weight float64 // weight
-}
-
-type TPAccountActions struct {
- TPid string // Tariff plan id
- AccountActionsId string // AccountActions id
- Tenant string // Tenant's Id
- Account string // Account name
- Direction string // Traffic direction
- ActionTimingsId string // Id of ActionTimings profile to use
- ActionTriggersId string // Id of ActionTriggers profile to use
-}