added RemoveBalances API

fixes #239
This commit is contained in:
Radu Ioan Fericean
2015-11-12 11:43:01 +02:00
parent 709d5f06ce
commit e94414e1f1
4 changed files with 144 additions and 8 deletions

View File

@@ -211,6 +211,45 @@ func (self *ApierV1) EnableDisableBalance(attr *AttrAddBalance, reply *string) e
return nil
}
func (self *ApierV1) RemoveBalances(attr *AttrAddBalance, reply *string) error {
expTime, err := utils.ParseDate(attr.ExpiryTime)
if err != nil {
*reply = err.Error()
return err
}
accId := utils.ConcatenatedKey(attr.Tenant, attr.Account)
if _, err := self.AccountDb.GetAccount(accId); err != nil {
return utils.ErrNotFound
}
at := &engine.ActionPlan{
AccountIds: []string{accId},
}
at.SetActions(engine.Actions{
&engine.Action{
ActionType: engine.REMOVE_BALANCE,
BalanceType: attr.BalanceType,
Balance: &engine.Balance{
Uuid: attr.BalanceUuid,
Id: attr.BalanceId,
Value: attr.Value,
ExpirationDate: expTime,
RatingSubject: attr.RatingSubject,
Directions: utils.ParseStringMap(attr.Directions),
DestinationIds: utils.ParseStringMap(attr.DestinationIds),
Weight: attr.Weight,
SharedGroups: utils.ParseStringMap(attr.SharedGroups),
Disabled: attr.Disabled,
},
},
})
if err := at.Execute(); err != nil {
*reply = err.Error()
return err
}
*reply = OK
return nil
}
func (self *ApierV1) ExecuteAction(attr *utils.AttrExecuteAction, reply *string) error {
accId := utils.AccountKey(attr.Tenant, attr.Account)
at := &engine.ActionPlan{

View File

@@ -97,7 +97,6 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error {
if bClone == nil {
return errors.New("nil balance")
}
if ub.BalanceMap == nil {
ub.BalanceMap = make(map[string]BalanceChain, 1)
}

View File

@@ -56,6 +56,7 @@ const (
DENY_NEGATIVE = "*deny_negative"
RESET_ACCOUNT = "*reset_account"
REMOVE_ACCOUNT = "*remove_account"
REMOVE_BALANCE = "*remove_balance"
TOPUP_RESET = "*topup_reset"
TOPUP = "*topup"
DEBIT_RESET = "*debit_reset"
@@ -128,6 +129,8 @@ func getActionFunc(typ string) (actionTypeFunc, bool) {
return mailAsync, true
case SET_DDESTINATIONS:
return setddestinations, true
case REMOVE_BALANCE:
return removeBalance, true
}
return nil, false
}
@@ -525,6 +528,29 @@ func setddestinations(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actio
return nil
}
func removeBalance(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error {
if _, exists := ub.BalanceMap[a.BalanceType]; !exists {
return utils.ErrNotFound
}
bChain := ub.BalanceMap[a.BalanceType]
found := false
for i := 0; i < len(bChain); i++ {
if bChain[i].MatchFilter(a.Balance, false) {
// delete without preserving order
bChain[i] = bChain[len(bChain)-1]
bChain = bChain[:len(bChain)-1]
i -= 1
found = true
}
}
ub.BalanceMap[a.BalanceType] = bChain
if !found {
return utils.ErrNotFound
}
// update account in storage
return accountingStorage.SetAccount(ub)
}
// Structure to store actions according to weight
type Actions []*Action

View File

@@ -21,7 +21,6 @@ package engine
import (
"encoding/json"
"fmt"
"log"
"reflect"
"testing"
"time"
@@ -1351,21 +1350,94 @@ func TestActionTransactionBalanceType(t *testing.T) {
}
}
func TestActionExecuteActionNonExistingAccount(t *testing.T) {
func TestActionWithExpireWithoutExpire(t *testing.T) {
err := accountingStorage.SetAccount(&Account{
Id: "cgrates.org:exp",
BalanceMap: map[string]BalanceChain{
utils.MONETARY: BalanceChain{&Balance{
Value: 10,
}},
},
})
if err != nil {
t.Error("Error setting account: ", err)
}
at := &ActionPlan{
AccountIds: []string{"cgrates.org:exe"},
AccountIds: []string{"cgrates.org:exp"},
Timing: &RateInterval{},
actions: []*Action{
&Action{
ActionType: TOPUP,
BalanceType: utils.MONETARY,
Balance: &Balance{Value: 1.1},
BalanceType: utils.VOICE,
Balance: &Balance{
Value: 15,
},
},
&Action{
ActionType: TOPUP,
BalanceType: utils.VOICE,
Balance: &Balance{
Value: 30,
ExpirationDate: time.Date(2025, time.November, 11, 22, 39, 0, 0, time.UTC),
},
},
},
}
err = at.Execute()
if err == nil {
log.Print("Fail to return error on action execute: ", err)
acc, err := accountingStorage.GetAccount("cgrates.org:exp")
if err != nil || acc == nil {
t.Errorf("Error getting account: %+v: %v", acc, err)
}
if len(acc.BalanceMap) != 2 ||
len(acc.BalanceMap[utils.VOICE]) != 2 {
t.Errorf("Error debiting expir and unexpire: %+v", acc.BalanceMap[utils.VOICE][0])
}
}
func TestActionRemoveBalance(t *testing.T) {
err := accountingStorage.SetAccount(&Account{
Id: "cgrates.org:rembal",
BalanceMap: map[string]BalanceChain{
utils.MONETARY: BalanceChain{
&Balance{
Value: 10,
},
&Balance{
Value: 10,
DestinationIds: utils.NewStringMap("NAT", "RET"),
ExpirationDate: time.Date(2025, time.November, 11, 22, 39, 0, 0, time.UTC),
},
&Balance{
Value: 10,
DestinationIds: utils.NewStringMap("NAT", "RET"),
},
},
},
})
if err != nil {
t.Error("Error setting account: ", err)
}
at := &ActionPlan{
AccountIds: []string{"cgrates.org:rembal"},
Timing: &RateInterval{},
actions: []*Action{
&Action{
ActionType: REMOVE_BALANCE,
BalanceType: utils.MONETARY,
Balance: &Balance{
DestinationIds: utils.NewStringMap("NAT", "RET"),
},
},
},
}
err = at.Execute()
acc, err := accountingStorage.GetAccount("cgrates.org:rembal")
if err != nil || acc == nil {
t.Errorf("Error getting account: %+v: %v", acc, err)
}
if len(acc.BalanceMap) != 1 ||
len(acc.BalanceMap[utils.MONETARY]) != 1 {
t.Errorf("Error removing balance: %+v", acc.BalanceMap[utils.MONETARY])
}
}