From e4530fdd0e4ececc835b29b84d0b78adc2abe738 Mon Sep 17 00:00:00 2001 From: DanB Date: Sat, 20 Jul 2013 13:59:13 +0200 Subject: [PATCH] Adding TPAccountActions api methods --- apier/tpaccountactions.go | 95 ++++++++++++++++++++++++++++++++++++++ rater/loader_db.go | 2 +- rater/storage_interface.go | 5 +- rater/storage_map.go | 14 +++++- rater/storage_mongo.go | 14 +++++- rater/storage_redis.go | 14 +++++- rater/storage_sql.go | 69 +++++++++++++++++++++++---- utils/apitpdata.go | 2 +- 8 files changed, 199 insertions(+), 16 deletions(-) create mode 100644 apier/tpaccountactions.go diff --git a/apier/tpaccountactions.go b/apier/tpaccountactions.go new file mode 100644 index 000000000..52f409b3a --- /dev/null +++ b/apier/tpaccountactions.go @@ -0,0 +1,95 @@ +/* +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/rater" + "github.com/cgrates/cgrates/utils" +) + + +// Creates a new AccountActions profile within a tariff plan +func (self *Apier) SetTPAccountActions(attrs utils.ApiTPAccountActions, reply *string) error { + if missing := utils.MissingStructFields(&attrs, + []string{"TPid", "AccountActionsId","Tenant","Account","Direction","ActionTimingsId","ActionTriggersId"}); len(missing) != 0 { + return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) + } + if exists, err := self.StorDb.ExistsTPAccountActions(attrs.TPid, attrs.AccountActionsId); err != nil { + return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) + } else if exists { + return errors.New(utils.ERR_DUPLICATE) + } + aa := map[string]*rater.AccountAction{ + attrs.AccountActionsId: &rater.AccountAction{Tenant: attrs.Tenant, Account: attrs.Account, Direction: attrs.Direction, + ActionTimingsTag: attrs.ActionTimingsId, ActionTriggersTag: attrs.ActionTriggersId}, + } + + if err := self.StorDb.SetTPAccountActions(attrs.TPid, aa); err != nil { + return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) + } + *reply = "OK" + return nil +} + +type AttrGetTPAccountActions struct { + TPid string // Tariff plan id + AccountActionsId string // AccountActions id +} + +// Queries specific AccountActions profile on tariff plan +func (self *Apier) GetTPAccountActions(attrs AttrGetTPAccountActions, reply *utils.ApiTPAccountActions) error { + if missing := utils.MissingStructFields(&attrs, []string{"TPid", "AccountActionsId"}); len(missing) != 0 { //Params missing + return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) + } + if aa, err := self.StorDb.GetTpAccountActions(attrs.TPid, attrs.AccountActionsId); err != nil { + return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) + } else if len(aa) == 0 { + return errors.New(utils.ERR_NOT_FOUND) + } else { + *reply = utils.ApiTPAccountActions{TPid: attrs.TPid, + AccountActionsId: attrs.AccountActionsId, + Tenant: aa[attrs.AccountActionsId].Tenant, + Account:aa[attrs.AccountActionsId].Account, + Direction: aa[attrs.AccountActionsId].Direction, + ActionTimingsId: aa[attrs.AccountActionsId].ActionTimingsTag, + ActionTriggersId: aa[attrs.AccountActionsId].ActionTriggersTag } + } + return nil +} + +type AttrGetTPAccountActionIds struct { + TPid string // Tariff plan id +} + +// Queries AccountActions identities on specific tariff plan. +func (self *Apier) GetTPAccountActionIds(attrs AttrGetTPAccountActionIds, 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.GetTPAccountActionIds(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/rater/loader_db.go b/rater/loader_db.go index add07a8b1..0624edfa7 100644 --- a/rater/loader_db.go +++ b/rater/loader_db.go @@ -340,7 +340,7 @@ func (dbr *DbReader) LoadAccountActionsByTag(tag string) error { if err != nil || len(accountActions) != 1 { return err } - accountAction := accountActions[0] + accountAction := accountActions[tag] id := fmt.Sprintf("%s:%s:%s", accountAction.Direction, accountAction.Tenant, accountAction.Account) var actionsIds []string // collects action ids diff --git a/rater/storage_interface.go b/rater/storage_interface.go index bdbe71e74..263e4a9e8 100644 --- a/rater/storage_interface.go +++ b/rater/storage_interface.go @@ -94,6 +94,9 @@ type DataStorage interface { ExistsTPActionTriggers(string, string) (bool, error) SetTPActionTriggers(string, map[string][]*ActionTrigger) error GetTPActionTriggerIds(string) ([]string, error) + ExistsTPAccountActions(string, string) (bool, error) + SetTPAccountActions(string, map[string]*AccountAction) error + GetTPAccountActionIds(string) ([]string, error) // End Apier functions GetActions(string) (Actions, error) SetActions(string, Actions) error @@ -121,7 +124,7 @@ type DataStorage interface { GetTpActions(string, string) (map[string][]*Action, error) GetTpActionTimings(string, string) (map[string][]*ActionTiming, error) GetTpActionTriggers(string, string) (map[string][]*ActionTrigger, error) - GetTpAccountActions(string, string) ([]*AccountAction, error) + GetTpAccountActions(string, string) (map[string]*AccountAction, error) } type Marshaler interface { diff --git a/rater/storage_map.go b/rater/storage_map.go index f0ac3a841..0e1d57363 100644 --- a/rater/storage_map.go +++ b/rater/storage_map.go @@ -217,6 +217,18 @@ func (ms *MapStorage) GetTPActionTriggerIds(tpid string) ([]string, error) { return nil, errors.New(utils.ERR_NOT_IMPLEMENTED) } +func (ms *MapStorage) ExistsTPAccountActions(tpid, aaId string) (bool, error) { + return false, errors.New(utils.ERR_NOT_IMPLEMENTED) +} + +func (ms *MapStorage) SetTPAccountActions(tpid string, aa map[string]*AccountAction) error { + return errors.New(utils.ERR_NOT_IMPLEMENTED) +} + +func (ms *MapStorage) GetTPAccountActionIds(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) @@ -369,6 +381,6 @@ func (ms *MapStorage) GetTpActionTimings(tpid, tag string) (map[string][]*Action func (ms *MapStorage) GetTpActionTriggers(tpid, tag string) (map[string][]*ActionTrigger, error) { return nil, nil } -func (ms *MapStorage) GetTpAccountActions(tpid, tag string) ([]*AccountAction, error) { +func (ms *MapStorage) GetTpAccountActions(tpid, tag string) (map[string]*AccountAction, error) { return nil, nil } diff --git a/rater/storage_mongo.go b/rater/storage_mongo.go index d70947521..4ad2e752e 100644 --- a/rater/storage_mongo.go +++ b/rater/storage_mongo.go @@ -292,6 +292,18 @@ func (ms *MongoStorage) GetTPActionTriggerIds(tpid string) ([]string, error) { return nil, errors.New(utils.ERR_NOT_IMPLEMENTED) } +func (ms *MongoStorage) ExistsTPAccountActions(tpid, aaId string) (bool, error) { + return false, errors.New(utils.ERR_NOT_IMPLEMENTED) +} + +func (ms *MongoStorage) SetTPAccountActions(tpid string, aa map[string]*AccountAction) error { + return errors.New(utils.ERR_NOT_IMPLEMENTED) +} + +func (ms *MongoStorage) GetTPAccountActionIds(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) @@ -399,6 +411,6 @@ func (ms *MongoStorage) GetTpActionTimings(tpid, tag string) (map[string][]*Acti func (ms *MongoStorage) GetTpActionTriggers(tpid, tag string) (map[string][]*ActionTrigger, error) { return nil, nil } -func (ms *MongoStorage) GetTpAccountActions(tpid, tag string) ([]*AccountAction, error) { +func (ms *MongoStorage) GetTpAccountActions(tpid, tag string) (map[string]*AccountAction, error) { return nil, nil } diff --git a/rater/storage_redis.go b/rater/storage_redis.go index f3f8a555a..ec1b22e4d 100644 --- a/rater/storage_redis.go +++ b/rater/storage_redis.go @@ -247,6 +247,18 @@ func (rs *RedisStorage) GetTPActionTriggerIds(tpid string) ([]string, error) { return nil, errors.New(utils.ERR_NOT_IMPLEMENTED) } +func (rs *RedisStorage) ExistsTPAccountActions(tpid, aaId string) (bool, error) { + return false, errors.New(utils.ERR_NOT_IMPLEMENTED) +} + +func (rs *RedisStorage) SetTPAccountActions(tpid string, aa map[string]*AccountAction) error { + return errors.New(utils.ERR_NOT_IMPLEMENTED) +} + +func (rs *RedisStorage) GetTPAccountActionIds(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 { @@ -405,6 +417,6 @@ func (rs *RedisStorage) GetTpActionTimings(tpid, tag string) (map[string][]*Acti func (rs *RedisStorage) GetTpActionTriggers(tpid, tag string) (map[string][]*ActionTrigger, error) { return nil, nil } -func (rs *RedisStorage) GetTpAccountActions(tpid, tag string) ([]*AccountAction, error) { +func (rs *RedisStorage) GetTpAccountActions(tpid, tag string) (map[string]*AccountAction, error) { return nil, nil } diff --git a/rater/storage_sql.go b/rater/storage_sql.go index f83a5df4e..85aaab251 100644 --- a/rater/storage_sql.go +++ b/rater/storage_sql.go @@ -717,6 +717,58 @@ func (self *SQLStorage) GetTPActionTriggerIds(tpid string) ([]string, error) { return ids, nil } +func (self *SQLStorage) ExistsTPAccountActions(tpid, aaId 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_ACCOUNT_ACTIONS, tpid, aaId)).Scan(&exists) + if err != nil { + return false, err + } + return exists, nil +} + +func (self *SQLStorage) SetTPAccountActions(tpid string, aa map[string]*AccountAction) error { + if len(aa) == 0 { + return nil //Nothing to set + } + qry := fmt.Sprintf("INSERT INTO %s (tpid, tag, tenant, account, direction, action_timings_tag, action_triggers_tag) VALUES ", + utils.TBL_TP_ACCOUNT_ACTIONS) + i := 0 + for aaId, aActs := range aa { + i++ + if i != 1 { //Consecutive values after the first will be prefixed with "," as separator + qry += "," + } + qry += fmt.Sprintf("('%s','%s','%s','%s','%s','%s','%s')", + tpid, aaId, aActs.Tenant, aActs.Account, aActs.Direction, aActs.ActionTimingsTag, aActs.ActionTriggersTag) + } + if _, err := self.Db.Exec(qry); err != nil { + return err + } + return nil +} + +func (self *SQLStorage) GetTPAccountActionIds(tpid string) ([]string, error) { + rows, err := self.Db.Query(fmt.Sprintf("SELECT DISTINCT tag FROM %s where tpid='%s'", utils.TBL_TP_ACCOUNT_ACTIONS, 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 } @@ -1130,9 +1182,8 @@ func (self *SQLStorage) GetTpActionTriggers(tpid, tag string) (map[string][]*Act return ats, nil } -func (self *SQLStorage) GetTpAccountActions(tpid, tag string) ([]*AccountAction, error) { - var acs []*AccountAction - q := fmt.Sprintf("SELECT * FROM %s WHERE tpid='%s'", utils.TBL_TP_ACCOUNT_ACTIONS, tpid) +func (self *SQLStorage) GetTpAccountActions(tpid, tag string) (map[string]*AccountAction, error) { + q := fmt.Sprintf("SELECT tag, tenant, account, direction, action_timings_tag, action_triggers_tag FROM %s WHERE tpid='%s'", utils.TBL_TP_ACCOUNT_ACTIONS, tpid) if tag != "" { q += fmt.Sprintf(" AND tag='%s'", tag) } @@ -1141,21 +1192,19 @@ func (self *SQLStorage) GetTpAccountActions(tpid, tag string) ([]*AccountAction, return nil, err } defer rows.Close() + aa := make(map[string]*AccountAction) for rows.Next() { - var id int - var tpid, tenant, account, direction, action_timings_tag, action_triggers_tag string - if err := rows.Scan(&id, &tpid, &tenant, &account, &direction, &action_timings_tag, &action_triggers_tag); err != nil { + var aaId, tenant, account, direction, action_timings_tag, action_triggers_tag string + if err := rows.Scan(&aaId, &tenant, &account, &direction, &action_timings_tag, &action_triggers_tag); err != nil { return nil, err } - - aa := &AccountAction{ + aa[aaId] = &AccountAction{ Tenant: tenant, Account: account, Direction: direction, ActionTimingsTag: action_timings_tag, ActionTriggersTag: action_triggers_tag, } - acs = append(acs, aa) } - return acs, nil + return aa, nil } diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 20d56003c..c389db1cf 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -131,7 +131,7 @@ type ApiActionTrigger struct { Weight float64 // weight } -type TPAccountActions struct { +type ApiTPAccountActions struct { TPid string // Tariff plan id AccountActionsId string // AccountActions id Tenant string // Tenant's Id