new v2 SetAccount API

This commit is contained in:
Radu Ioan Fericean
2016-01-25 19:58:09 +02:00
parent a2e9e156c6
commit 8464f28d10
7 changed files with 116 additions and 75 deletions

View File

@@ -543,16 +543,16 @@ type AttrSetBalance struct {
Tenant string
Account string
BalanceType string
BalanceUuid *string
BalanceId *string
Directions *string
BalanceUUID *string
BalanceID *string
Directions *[]string
Value *float64
ExpiryTime *string
RatingSubject *string
Categories *string
DestinationIds *string
SharedGroups *string
TimingIds *string
Categories *[]string
DestinationIDs *[]string
SharedGroups *[]string
TimingIDs *[]string
Weight *float64
Blocker *bool
Disabled *bool
@@ -561,7 +561,7 @@ type AttrSetBalance struct {
func (attr *AttrSetBalance) SetBalance(b *engine.Balance) {
if attr.Directions != nil {
b.Directions = utils.ParseStringMap(*attr.Directions)
b.Directions = utils.StringMapFromSlice(*attr.Directions)
}
if attr.Value != nil {
b.Value = *attr.Value
@@ -573,16 +573,16 @@ func (attr *AttrSetBalance) SetBalance(b *engine.Balance) {
b.RatingSubject = *attr.RatingSubject
}
if attr.Categories != nil {
b.Categories = utils.ParseStringMap(*attr.Categories)
b.Categories = utils.StringMapFromSlice(*attr.Categories)
}
if attr.DestinationIds != nil {
b.DestinationIds = utils.ParseStringMap(*attr.DestinationIds)
if attr.DestinationIDs != nil {
b.DestinationIds = utils.StringMapFromSlice(*attr.DestinationIDs)
}
if attr.SharedGroups != nil {
b.SharedGroups = utils.ParseStringMap(*attr.SharedGroups)
b.SharedGroups = utils.StringMapFromSlice(*attr.SharedGroups)
}
if attr.TimingIds != nil {
b.TimingIDs = utils.ParseStringMap(*attr.TimingIds)
if attr.TimingIDs != nil {
b.TimingIDs = utils.StringMapFromSlice(*attr.TimingIDs)
}
if attr.Weight != nil {
b.Weight = *attr.Weight
@@ -602,8 +602,8 @@ func (self *ApierV1) SetBalance(attr *AttrAddBalance, reply *string) error {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if attr.BalanceId == "" && attr.BalanceUuid == "" {
return utils.NewErrMandatoryIeMissing("BalanceId", "or", "BalanceUuid")
if attr.BalanceID == "" && attr.BalanceUUID == "" {
return utils.NewErrMandatoryIeMissing("BalanceID", "or", "BalanceUUID")
}
expTime, err := utils.ParseTimeDetectLayout(attr.ExpiryTime, self.Config.DefaultTimezone)
if err != nil {
@@ -623,17 +623,17 @@ func (self *ApierV1) SetBalance(attr *AttrAddBalance, reply *string) error {
ActionType: engine.SET_BALANCE,
BalanceType: attr.BalanceType,
Balance: &engine.Balance{
Uuid: attr.BalanceUuid,
Id: attr.BalanceId,
Uuuid: attr.BalanceUUID,
ID: attr.BalanceID,
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
Directions: utils.ParseStringMap(attr.Directions),
DestinationIds: utils.ParseStringMap(attr.DestinationIds),
DestinationIDs: utils.ParseStringMap(attr.DestinationIDs),
Categories: utils.ParseStringMap(attr.Categories),
Weight: attr.Weight,
SharedGroups: utils.ParseStringMap(attr.SharedGroups),
TimingIDs: utils.ParseStringMap(attr.TimingIds),
TimingIDs: utils.ParseStringMap(attr.TimingIDs),
Blocker: true,
Disabled: attr.Disabled,
},
@@ -652,9 +652,9 @@ func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error {
if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
if (attr.BalanceId == nil || *attr.BalanceId == "") &&
(attr.BalanceUuid == nil || *attr.BalanceUuid == "") {
return utils.NewErrMandatoryIeMissing("BalanceId", "or", "BalanceUuid")
if (attr.BalanceID == nil || *attr.BalanceID == "") &&
(attr.BalanceUUID == nil || *attr.BalanceUUID == "") {
return utils.NewErrMandatoryIeMissing("BalanceID", "or", "BalanceUUID")
}
var err error
if attr.ExpiryTime != nil {
@@ -681,8 +681,8 @@ func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error {
if b.IsExpired() {
continue
}
if (attr.BalanceUuid != nil && b.Uuid == *attr.BalanceUuid) ||
(attr.BalanceId != nil && b.Id == *attr.BalanceId) {
if (attr.BalanceUUID != nil && b.Uuid == *attr.BalanceUUID) ||
(attr.BalanceID != nil && b.Id == *attr.BalanceID) {
previousSharedGroups = b.SharedGroups
balance = b
found = true
@@ -697,7 +697,7 @@ func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error {
account.BalanceMap[attr.BalanceType] = append(account.BalanceMap[attr.BalanceType], balance)
}
if attr.BalanceId != nil && *attr.BalanceId == utils.META_DEFAULT {
if attr.BalanceID != nil && *attr.BalanceID == utils.META_DEFAULT {
balance.Id = utils.META_DEFAULT
if attr.Value != nil {
balance.Value = *attr.Value
@@ -708,12 +708,12 @@ func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error {
if !found || !previousSharedGroups.Equal(balance.SharedGroups) {
_, err = engine.Guardian.Guard(func() (interface{}, error) {
for sgId := range balance.SharedGroups {
for sgID := range balance.SharedGroups {
// add shared group member
sg, err := self.RatingDb.GetSharedGroup(sgId, false)
sg, err := self.RatingDb.GetSharedGroup(sgID, false)
if err != nil || sg == nil {
//than is problem
utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgId))
utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID))
} else {
if _, found := sg.MemberIds[account.Id]; !found {
// add member and save

View File

@@ -81,9 +81,9 @@ func (self *ApierV2) GetAccount(attr *utils.AttrGetAccount, reply *engine.Accoun
type AttrSetAccount struct {
Tenant string
Account string
ActionPlanIds string
ActionPlanIds *[]string
ActionPlansOverwrite bool
ActionTriggersIds string
ActionTriggersIds *[]string
ActionTriggerOverwrite bool
AllowNegative *bool
Disabled *bool
@@ -94,7 +94,7 @@ func (self *ApierV2) SetAccount(attr AttrSetAccount, reply *string) error {
if missing := utils.MissingStructFields(&attr, []string{"Tenant", "Account"}); len(missing) != 0 {
return utils.NewErrMandatoryIeMissing(missing...)
}
var schedulerReloadNeeded = false
dirtyActionPlans := make(map[string]*engine.ActionPlan)
accID := utils.AccountKey(attr.Tenant, attr.Account)
var ub *engine.Account
_, err := engine.Guardian.Guard(func() (interface{}, error) {
@@ -105,38 +105,55 @@ func (self *ApierV2) SetAccount(attr AttrSetAccount, reply *string) error {
Id: accID,
}
}
if len(attr.ActionPlanIds) != 0 {
if attr.ActionPlanIds != nil {
_, err := engine.Guardian.Guard(func() (interface{}, error) {
var ap *engine.ActionPlan
var err error
ap, err = self.RatingDb.GetActionPlan(attr.ActionPlanIds, false)
actionPlansMap, err := self.RatingDb.GetAllActionPlans()
if err != nil {
return 0, err
}
if _, exists := ap.AccountIDs[accID]; !exists {
if ap.AccountIDs == nil {
ap.AccountIDs = make(utils.StringMap)
if attr.ActionPlansOverwrite {
// clean previous action plans
for actionPlanID, ap := range actionPlansMap {
if _, exists := ap.AccountIDs[accID]; exists {
delete(ap.AccountIDs, accID)
dirtyActionPlans[actionPlanID] = ap
}
}
ap.AccountIDs[accID] = true
schedulerReloadNeeded = true
// create tasks
for _, at := range ap.ActionTimings {
if at.IsASAP() {
t := &engine.Task{
Uuid: utils.GenUUID(),
AccountID: accID,
ActionsID: at.ActionsID,
}
if err = self.RatingDb.PushTask(t); err != nil {
return 0, err
}
for _, actionPlanID := range *attr.ActionPlanIds {
ap, ok := actionPlansMap[actionPlanID]
if !ok {
return 0, utils.ErrNotFound
}
if _, exists := ap.AccountIDs[accID]; !exists {
if ap.AccountIDs == nil {
ap.AccountIDs = make(utils.StringMap)
}
ap.AccountIDs[accID] = true
dirtyActionPlans[actionPlanID] = ap
// create tasks
for _, at := range ap.ActionTimings {
if at.IsASAP() {
t := &engine.Task{
Uuid: utils.GenUUID(),
AccountID: accID,
ActionsID: at.ActionsID,
}
if err = self.RatingDb.PushTask(t); err != nil {
return 0, err
}
}
}
}
if err := self.RatingDb.SetActionPlan(attr.ActionPlanIds, ap); err != nil {
}
for actionPlanID, ap := range dirtyActionPlans {
if err := self.RatingDb.SetActionPlan(actionPlanID, ap); err != nil {
return 0, err
}
// update cache
self.RatingDb.CacheRatingPrefixValues(map[string][]string{utils.ACTION_PLAN_PREFIX: []string{utils.ACTION_PLAN_PREFIX + attr.ActionPlanIds}})
self.RatingDb.CacheRatingPrefixValues(map[string][]string{utils.ACTION_PLAN_PREFIX: []string{utils.ACTION_PLAN_PREFIX + actionPlanID}})
}
return 0, nil
}, 0, utils.ACTION_PLAN_PREFIX)
@@ -145,14 +162,30 @@ func (self *ApierV2) SetAccount(attr AttrSetAccount, reply *string) error {
}
}
if len(attr.ActionTriggersIds) != 0 {
atrs, err := self.RatingDb.GetActionTriggers(attr.ActionTriggersIds)
if err != nil {
return 0, err
if attr.ActionTriggersIds != nil {
if attr.ActionTriggerOverwrite {
ub.ActionTriggers = make(engine.ActionTriggers, 0)
}
for _, actionTriggerID := range *attr.ActionTriggersIds {
atrs, err := self.RatingDb.GetActionTriggers(actionTriggerID)
if err != nil {
return 0, err
}
for _, at := range atrs {
var found bool
for _, existingAt := range ub.ActionTriggers {
if existingAt.Equals(at) {
found = true
break
}
}
if !found {
ub.ActionTriggers = append(ub.ActionTriggers, at)
}
}
}
ub.ActionTriggers = atrs
ub.InitCounters()
}
ub.InitCounters()
if attr.AllowNegative != nil {
ub.AllowNegative = *attr.AllowNegative
}
@@ -168,7 +201,7 @@ func (self *ApierV2) SetAccount(attr AttrSetAccount, reply *string) error {
if err != nil {
return utils.NewErrServerError(err)
}
if attr.ReloadScheduler && schedulerReloadNeeded {
if attr.ReloadScheduler && len(dirtyActionPlans) > 0 {
// reload scheduler
if self.Sched != nil {
self.Sched.Reload(true)

View File

@@ -18,12 +18,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package console
import "github.com/cgrates/cgrates/utils"
import "github.com/cgrates/cgrates/apier/v2"
func init() {
c := &CmdAddAccount{
name: "account_set",
rpcMethod: "ApierV1.SetAccount",
rpcMethod: "ApierV2.SetAccount",
}
commands[c.Name()] = c
c.CommandExecuter = &CommandExecuter{c}
@@ -33,7 +33,7 @@ func init() {
type CmdAddAccount struct {
name string
rpcMethod string
rpcParams *utils.AttrSetAccount
rpcParams *v2.AttrSetAccount
*CommandExecuter
}
@@ -47,7 +47,7 @@ func (self *CmdAddAccount) RpcMethod() string {
func (self *CmdAddAccount) RpcParams(reset bool) interface{} {
if reset || self.rpcParams == nil {
self.rpcParams = &utils.AttrSetAccount{}
self.rpcParams = &v2.AttrSetAccount{}
}
return self.rpcParams
}

View File

@@ -183,6 +183,11 @@ func (at *ActionTrigger) CreateBalance() *Balance {
}
}
func (at *ActionTrigger) Equals(oat *ActionTrigger) bool {
// ids only
return at.ID == oat.ID && at.UniqueID == oat.UniqueID
}
// Structure to store actions according to weight
type ActionTriggers []*ActionTrigger

View File

@@ -1833,7 +1833,7 @@ func TestActionCSVFilter(t *testing.T) {
if err != nil {
t.Error("error getting actions: ", err)
}
if len(act) != 1 || act[0].Filter != `{"Type":"*voice","Value":{"*gte":100}}` {
if len(act) != 1 || act[0].Filter != `{"*and":[{"Value":{"*lt":0}},{"Id":{"*eq":"*default"}}]}` {
t.Error("Error loading actions: ", act[0].Filter)
}
}

View File

@@ -174,7 +174,7 @@ DEFEE,*cdrlog,"{""Category"":""^ddi"",""MediationRunId"":""^did_run""}",,,,,,,,,
NEG,*allow_negative,,,,*monetary,*out,,,,,*unlimited,,0,10,false,false,10
BLOCK,*topup,,,bblocker,*monetary,*out,,NAT,,,*unlimited,,10,20,true,false,20
BLOCK,*topup,,,bfree,*monetary,*out,,,,,*unlimited,,20,10,false,false,10
FILTER,*topup,,"{""Type"":""*voice"",""Value"":{""*gte"":100}}",bfree,*monetary,*out,,,,,*unlimited,,20,10,false,false,10
FILTER,*topup,,"{""*and"":[{""Value"":{""*lt"":0}},{""Id"":{""*eq"":""*default""}}]}",bfree,*monetary,*out,,,,,*unlimited,,20,10,false,false,10
`
actionPlans = `
MORE_MINUTES,MINI,ONE_TIME_RUN,10

View File

@@ -74,15 +74,7 @@ func NewStringMap(s ...string) StringMap {
}
func ParseStringMap(s string) StringMap {
slice := strings.Split(s, INFIELD_SEP)
result := make(StringMap)
for _, v := range slice {
v = strings.TrimSpace(v)
if v != "" {
result[v] = true
}
}
return result
return StringMapFromSlice(strings.Split(s, INFIELD_SEP))
}
func (sm StringMap) Equal(om StringMap) bool {
@@ -130,6 +122,17 @@ func (sm StringMap) Slice() []string {
return result
}
func StringMapFromSlice(s []string) StringMap {
result := make(StringMap)
for _, v := range s {
v = strings.TrimSpace(v)
if v != "" {
result[v] = true
}
}
return result
}
func (sm StringMap) Copy(o StringMap) {
for k, v := range o {
sm[k] = v