mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 02:26:26 +05:00
@@ -699,7 +699,9 @@ func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balance
|
||||
|
||||
func (acc *Account) matchConditions(condition string) (bool, error) {
|
||||
cl := &utils.CondLoader{}
|
||||
cl.Parse(condition)
|
||||
if err := cl.Parse(condition); err != nil {
|
||||
return false, err
|
||||
}
|
||||
for balanceType, balanceChain := range acc.BalanceMap {
|
||||
for _, b := range balanceChain {
|
||||
check, err := cl.Check(&struct {
|
||||
|
||||
@@ -1568,6 +1568,197 @@ func TestActionTransferMonetaryDefaultFilter(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionConditionalTopup(t *testing.T) {
|
||||
err := accountingStorage.SetAccount(
|
||||
&Account{
|
||||
Id: "cgrates.org:cond",
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
utils.MONETARY: BalanceChain{
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Id: utils.META_DEFAULT,
|
||||
Value: 10,
|
||||
Weight: 20,
|
||||
},
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 3,
|
||||
Weight: 20,
|
||||
},
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 1,
|
||||
Weight: 10,
|
||||
},
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 6,
|
||||
Weight: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("error setting account: %v", err)
|
||||
}
|
||||
|
||||
a := &Action{
|
||||
ActionType: CONDITIONAL_TOPUP,
|
||||
BalanceType: utils.MONETARY,
|
||||
ExtraParameters: `{"Type":"*monetary","Value":1,"Weight":10}`,
|
||||
Balance: &Balance{
|
||||
Value: 11,
|
||||
Weight: 30,
|
||||
},
|
||||
}
|
||||
|
||||
at := &ActionTiming{
|
||||
accountIDs: map[string]struct{}{"cgrates.org:cond": struct{}{}},
|
||||
actions: Actions{a},
|
||||
}
|
||||
at.Execute()
|
||||
|
||||
afterUb, err := accountingStorage.GetAccount("cgrates.org:cond")
|
||||
if err != nil {
|
||||
t.Error("account not found: ", err, afterUb)
|
||||
}
|
||||
if len(afterUb.BalanceMap[utils.MONETARY]) != 5 ||
|
||||
afterUb.BalanceMap[utils.MONETARY].GetTotalValue() != 31 ||
|
||||
afterUb.BalanceMap[utils.MONETARY][4].Value != 11 {
|
||||
for _, b := range afterUb.BalanceMap[utils.MONETARY] {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
t.Error("ransfer balance value: ", afterUb.BalanceMap[utils.MONETARY].GetTotalValue())
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionConditionalTopupNoMatch(t *testing.T) {
|
||||
err := accountingStorage.SetAccount(
|
||||
&Account{
|
||||
Id: "cgrates.org:cond",
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
utils.MONETARY: BalanceChain{
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Id: utils.META_DEFAULT,
|
||||
Value: 10,
|
||||
Weight: 20,
|
||||
},
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 3,
|
||||
Weight: 20,
|
||||
},
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 1,
|
||||
Weight: 10,
|
||||
},
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 6,
|
||||
Weight: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("error setting account: %v", err)
|
||||
}
|
||||
|
||||
a := &Action{
|
||||
ActionType: CONDITIONAL_TOPUP,
|
||||
BalanceType: utils.MONETARY,
|
||||
ExtraParameters: `{"Type":"*monetary","Value":2,"Weight":10}`,
|
||||
Balance: &Balance{
|
||||
Value: 11,
|
||||
Weight: 30,
|
||||
},
|
||||
}
|
||||
|
||||
at := &ActionTiming{
|
||||
accountIDs: map[string]struct{}{"cgrates.org:cond": struct{}{}},
|
||||
actions: Actions{a},
|
||||
}
|
||||
at.Execute()
|
||||
|
||||
afterUb, err := accountingStorage.GetAccount("cgrates.org:cond")
|
||||
if err != nil {
|
||||
t.Error("account not found: ", err, afterUb)
|
||||
}
|
||||
if len(afterUb.BalanceMap[utils.MONETARY]) != 4 ||
|
||||
afterUb.BalanceMap[utils.MONETARY].GetTotalValue() != 20 {
|
||||
for _, b := range afterUb.BalanceMap[utils.MONETARY] {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
t.Error("ransfer balance value: ", afterUb.BalanceMap[utils.MONETARY].GetTotalValue())
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionConditionalTopupExistingBalance(t *testing.T) {
|
||||
err := accountingStorage.SetAccount(
|
||||
&Account{
|
||||
Id: "cgrates.org:cond",
|
||||
BalanceMap: map[string]BalanceChain{
|
||||
utils.MONETARY: BalanceChain{
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 1,
|
||||
Weight: 10,
|
||||
},
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 6,
|
||||
Weight: 20,
|
||||
},
|
||||
},
|
||||
utils.VOICE: BalanceChain{
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 10,
|
||||
Weight: 10,
|
||||
},
|
||||
&Balance{
|
||||
Uuid: utils.GenUUID(),
|
||||
Value: 100,
|
||||
Weight: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("error setting account: %v", err)
|
||||
}
|
||||
|
||||
a := &Action{
|
||||
ActionType: CONDITIONAL_TOPUP,
|
||||
BalanceType: utils.MONETARY,
|
||||
ExtraParameters: `{"Type":"*voice","Value":{"*gte":100}}`,
|
||||
Balance: &Balance{
|
||||
Value: 11,
|
||||
Weight: 10,
|
||||
},
|
||||
}
|
||||
|
||||
at := &ActionTiming{
|
||||
accountIDs: map[string]struct{}{"cgrates.org:cond": struct{}{}},
|
||||
actions: Actions{a},
|
||||
}
|
||||
at.Execute()
|
||||
|
||||
afterUb, err := accountingStorage.GetAccount("cgrates.org:cond")
|
||||
if err != nil {
|
||||
t.Error("account not found: ", err, afterUb)
|
||||
}
|
||||
if len(afterUb.BalanceMap[utils.MONETARY]) != 2 ||
|
||||
afterUb.BalanceMap[utils.MONETARY].GetTotalValue() != 18 {
|
||||
for _, b := range afterUb.BalanceMap[utils.MONETARY] {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
t.Error("ransfer balance value: ", afterUb.BalanceMap[utils.MONETARY].GetTotalValue())
|
||||
}
|
||||
}
|
||||
|
||||
/**************** Benchmarks ********************************/
|
||||
|
||||
func BenchmarkUUID(b *testing.B) {
|
||||
|
||||
@@ -148,6 +148,13 @@ func (kv *keyValue) checkStruct(o interface{}) (bool, error) {
|
||||
return value.Interface() == kv.value, nil
|
||||
}
|
||||
|
||||
type trueElement struct{}
|
||||
|
||||
func (te *trueElement) addChild(condElement) error { return ErrNotImplemented }
|
||||
func (te *trueElement) checkStruct(o interface{}) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func isOperator(s string) bool {
|
||||
return strings.HasPrefix(s, "*")
|
||||
}
|
||||
@@ -186,18 +193,27 @@ func (cp *CondLoader) load(a map[string]interface{}, parentElement condElement)
|
||||
if parentElement != nil {
|
||||
parentElement.addChild(currentElement)
|
||||
} else {
|
||||
return currentElement, nil
|
||||
if len(a) > 1 {
|
||||
parentElement = &operatorSlice{operator: CondAND}
|
||||
parentElement.addChild(currentElement)
|
||||
} else {
|
||||
return currentElement, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
return parentElement, nil
|
||||
}
|
||||
|
||||
func (cp *CondLoader) Parse(s string) (err error) {
|
||||
a := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte([]byte(s)), &a); err != nil {
|
||||
return err
|
||||
if len(s) != 0 {
|
||||
if err := json.Unmarshal([]byte([]byte(s)), &a); err != nil {
|
||||
return err
|
||||
}
|
||||
cp.rootElement, err = cp.load(a, nil)
|
||||
} else {
|
||||
cp.rootElement = &trueElement{}
|
||||
}
|
||||
cp.rootElement, err = cp.load(a, nil)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@ func TestCondLoader(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
err = cl.Parse(``)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCondKeyValue(t *testing.T) {
|
||||
@@ -68,6 +72,27 @@ func TestCondKeyValue(t *testing.T) {
|
||||
if check, err := cl.Check(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":6, "Other":false}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Other":true, "Field":{"*gt":5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(``)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCondKeyValuePointer(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user