mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-19 22:28:45 +05:00
started value formula
This commit is contained in:
@@ -127,7 +127,7 @@ func (acc *Account) setBalanceAction(a *Action) error {
|
||||
if a.Balance.ID != nil && *a.Balance.ID == utils.META_DEFAULT {
|
||||
balance.ID = utils.META_DEFAULT
|
||||
if a.Balance.Value != nil {
|
||||
balance.Value = *a.Balance.Value
|
||||
balance.Value = a.Balance.GetValue()
|
||||
}
|
||||
} else {
|
||||
a.Balance.ModifyBalance(balance)
|
||||
|
||||
@@ -856,7 +856,7 @@ func TestAccountdebitBalanceExists(t *testing.T) {
|
||||
BalanceMap: map[string]Balances{utils.SMS: Balances{&Balance{Value: 14}}, utils.DATA: Balances{&Balance{Value: 1024}}, utils.VOICE: Balances{&Balance{Value: 15, Weight: 20, DestinationIDs: utils.StringMap{"NAT": true}, Directions: utils.NewStringMap(utils.OUT)}, &Balance{Weight: 10, DestinationIDs: utils.StringMap{"RET": true}}}},
|
||||
}
|
||||
newMb := &BalanceFilter{
|
||||
Value: utils.Float64Pointer(-10),
|
||||
Value: &ValueFormula{Static: -10},
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Weight: utils.Float64Pointer(20),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
@@ -883,19 +883,19 @@ func TestAccountAddMinuteNil(t *testing.T) {
|
||||
|
||||
func TestAccountAddMinutBucketEmpty(t *testing.T) {
|
||||
mb1 := &BalanceFilter{
|
||||
Value: utils.Float64Pointer(-10),
|
||||
Value: &ValueFormula{Static: -10},
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
}
|
||||
mb2 := &BalanceFilter{
|
||||
Value: utils.Float64Pointer(-10),
|
||||
Value: &ValueFormula{Static: -10},
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"NAT": true}),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
}
|
||||
mb3 := &BalanceFilter{
|
||||
Value: utils.Float64Pointer(-10),
|
||||
Value: &ValueFormula{Static: -10},
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
DestinationIDs: utils.StringMapPointer(utils.StringMap{"OTHER": true}),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
|
||||
@@ -93,59 +93,36 @@ func (a *Action) Clone() *Action {
|
||||
type actionTypeFunc func(*Account, *StatsQueueTriggered, *Action, Actions) error
|
||||
|
||||
func getActionFunc(typ string) (actionTypeFunc, bool) {
|
||||
switch typ {
|
||||
case LOG:
|
||||
return logAction, true
|
||||
case CDRLOG:
|
||||
return cdrLogAction, true
|
||||
case RESET_TRIGGERS:
|
||||
return resetTriggersAction, true
|
||||
case SET_RECURRENT:
|
||||
return setRecurrentAction, true
|
||||
case UNSET_RECURRENT:
|
||||
return unsetRecurrentAction, true
|
||||
case ALLOW_NEGATIVE:
|
||||
return allowNegativeAction, true
|
||||
case DENY_NEGATIVE:
|
||||
return denyNegativeAction, true
|
||||
case RESET_ACCOUNT:
|
||||
return resetAccountAction, true
|
||||
case TOPUP_RESET:
|
||||
return topupResetAction, true
|
||||
case TOPUP:
|
||||
return topupAction, true
|
||||
case DEBIT_RESET:
|
||||
return debitResetAction, true
|
||||
case DEBIT:
|
||||
return debitAction, true
|
||||
case RESET_COUNTERS:
|
||||
return resetCountersAction, true
|
||||
case ENABLE_ACCOUNT:
|
||||
return enableUserAction, true
|
||||
case DISABLE_ACCOUNT:
|
||||
return disableUserAction, true
|
||||
//case ENABLE_DISABLE_BALANCE:
|
||||
// return enableDisableBalanceAction, true
|
||||
case CALL_URL:
|
||||
return callUrl, true
|
||||
case CALL_URL_ASYNC:
|
||||
return callUrlAsync, true
|
||||
case MAIL_ASYNC:
|
||||
return mailAsync, true
|
||||
case SET_DDESTINATIONS:
|
||||
return setddestinations, true
|
||||
case REMOVE_ACCOUNT:
|
||||
return removeAccountAction, true
|
||||
case REMOVE_BALANCE:
|
||||
return removeBalanceAction, true
|
||||
case SET_BALANCE:
|
||||
return setBalanceAction, true
|
||||
case TRANSFER_MONETARY_DEFAULT:
|
||||
return transferMonetaryDefaultAction, true
|
||||
case CGR_RPC:
|
||||
return cgrRPCAction, true
|
||||
actionFuncMap := map[string]actionTypeFunc{
|
||||
LOG: logAction,
|
||||
CDRLOG: cdrLogAction,
|
||||
RESET_TRIGGERS: resetTriggersAction,
|
||||
SET_RECURRENT: setRecurrentAction,
|
||||
UNSET_RECURRENT: unsetRecurrentAction,
|
||||
ALLOW_NEGATIVE: allowNegativeAction,
|
||||
DENY_NEGATIVE: denyNegativeAction,
|
||||
RESET_ACCOUNT: resetAccountAction,
|
||||
TOPUP_RESET: topupResetAction,
|
||||
TOPUP: topupAction,
|
||||
DEBIT_RESET: debitResetAction,
|
||||
DEBIT: debitAction,
|
||||
RESET_COUNTERS: resetCountersAction,
|
||||
ENABLE_ACCOUNT: enableUserAction,
|
||||
DISABLE_ACCOUNT: disableUserAction,
|
||||
//case ENABLE_DISABLE_BALANCE:
|
||||
// return enableDisableBalanceAction, true
|
||||
CALL_URL: callUrl,
|
||||
CALL_URL_ASYNC: callUrlAsync,
|
||||
MAIL_ASYNC: mailAsync,
|
||||
SET_DDESTINATIONS: setddestinations,
|
||||
REMOVE_ACCOUNT: removeAccountAction,
|
||||
REMOVE_BALANCE: removeBalanceAction,
|
||||
SET_BALANCE: setBalanceAction,
|
||||
TRANSFER_MONETARY_DEFAULT: transferMonetaryDefaultAction,
|
||||
CGR_RPC: cgrRPCAction,
|
||||
}
|
||||
return nil, false
|
||||
f, exists := actionFuncMap[typ]
|
||||
return f, exists
|
||||
}
|
||||
|
||||
func logAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) {
|
||||
|
||||
@@ -413,7 +413,7 @@ func TestActionPlanLogFunction(t *testing.T) {
|
||||
ActionType: "*log",
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer("test"),
|
||||
Value: utils.Float64Pointer(1.1),
|
||||
Value: &ValueFormula{Static: 1.1},
|
||||
},
|
||||
}
|
||||
at := &ActionTiming{
|
||||
@@ -430,7 +430,7 @@ func TestActionPlanFunctionNotAvailable(t *testing.T) {
|
||||
ActionType: "VALID_FUNCTION_TYPE",
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer("test"),
|
||||
Value: utils.Float64Pointer(1.1),
|
||||
Value: &ValueFormula{Static: 1.1},
|
||||
},
|
||||
}
|
||||
at := &ActionTiming{
|
||||
@@ -659,7 +659,7 @@ func TestActionTriggerMatchAll(t *testing.T) {
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
RatingSubject: utils.StringPointer("test1"),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
Value: utils.Float64Pointer(2),
|
||||
Value: &ValueFormula{Static: 2},
|
||||
Weight: utils.Float64Pointer(1.0),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
SharedGroups: utils.StringMapPointer(utils.NewStringMap("test2")),
|
||||
@@ -669,7 +669,7 @@ func TestActionTriggerMatchAll(t *testing.T) {
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
RatingSubject: utils.StringPointer("test1"),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
Value: utils.Float64Pointer(2),
|
||||
Value: &ValueFormula{Static: 2},
|
||||
Weight: utils.Float64Pointer(1.0),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
SharedGroups: utils.StringMapPointer(utils.NewStringMap("test2")),
|
||||
@@ -799,7 +799,7 @@ func TestActionTopupResetCredit(t *testing.T) {
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupResetAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 10 ||
|
||||
@@ -818,7 +818,7 @@ func TestActionTopupValueFactor(t *testing.T) {
|
||||
a := &Action{
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Value: utils.Float64Pointer(10),
|
||||
Value: &ValueFormula{Static: 10},
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
},
|
||||
ExtraParameters: `{"*monetary":2.0}`,
|
||||
@@ -839,7 +839,7 @@ func TestActionTopupResetCreditId(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), ID: utils.StringPointer("TEST_B"), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), ID: utils.StringPointer("TEST_B"), Value: &ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupResetAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 110 ||
|
||||
@@ -858,7 +858,7 @@ func TestActionTopupResetCreditNoId(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupResetAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 20 ||
|
||||
@@ -876,7 +876,7 @@ func TestActionTopupResetMinutes(t *testing.T) {
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: &ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupResetAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.VOICE].GetTotalValue() != 5 ||
|
||||
@@ -895,7 +895,7 @@ func TestActionTopupCredit(t *testing.T) {
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 110 ||
|
||||
@@ -913,7 +913,7 @@ func TestActionTopupMinutes(t *testing.T) {
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: &ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
topupAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.VOICE].GetTotalValue() != 15 ||
|
||||
@@ -932,7 +932,7 @@ func TestActionDebitCredit(t *testing.T) {
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1, Filter: &BalanceFilter{Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &ValueFormula{Static: 10}, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
debitAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.MONETARY].GetTotalValue() != 90 ||
|
||||
@@ -950,7 +950,7 @@ func TestActionDebitMinutes(t *testing.T) {
|
||||
UnitCounters: UnitCounters{utils.MONETARY: []*UnitCounter{&UnitCounter{Counters: CounterFilters{&CounterFilter{Value: 1}}}}},
|
||||
ActionTriggers: ActionTriggers{&ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}, &ActionTrigger{Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY)}, ThresholdValue: 2, ActionsID: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: utils.Float64Pointer(5), Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
a := &Action{Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Value: &ValueFormula{Static: 5}, Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT))}}
|
||||
debitAction(ub, nil, a, nil)
|
||||
if ub.AllowNegative ||
|
||||
ub.BalanceMap[utils.VOICE][0].GetValue() != 5 ||
|
||||
@@ -1119,7 +1119,7 @@ func TestActionPlanLogging(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActionMakeNegative(t *testing.T) {
|
||||
a := &Action{Balance: &BalanceFilter{Value: utils.Float64Pointer(10)}}
|
||||
a := &Action{Balance: &BalanceFilter{Value: &ValueFormula{Static: 10}}}
|
||||
genericMakeNegative(a)
|
||||
if a.Balance.GetValue() > 0 {
|
||||
t.Error("Failed to make negative: ", a)
|
||||
@@ -1153,7 +1153,7 @@ func TestTopupAction(t *testing.T) {
|
||||
initialUb, _ := accountingStorage.GetAccount("vdf:minu")
|
||||
a := &Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)},
|
||||
}
|
||||
|
||||
at := &ActionTiming{
|
||||
@@ -1174,7 +1174,7 @@ func TestTopupActionLoaded(t *testing.T) {
|
||||
initialUb, _ := accountingStorage.GetAccount("vdf:minitsboy")
|
||||
a := &Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20)},
|
||||
}
|
||||
|
||||
at := &ActionTiming{
|
||||
@@ -1201,7 +1201,7 @@ func TestActionCdrlogEmpty(t *testing.T) {
|
||||
err := cdrLogAction(acnt, nil, cdrlog, Actions{
|
||||
&Action{
|
||||
ActionType: DEBIT,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1223,11 +1223,11 @@ func TestActionCdrlogWithParams(t *testing.T) {
|
||||
err := cdrLogAction(acnt, nil, cdrlog, Actions{
|
||||
&Action{
|
||||
ActionType: DEBIT,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
&Action{
|
||||
ActionType: DEBIT_RESET,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1250,11 +1250,11 @@ func TestActionCdrLogParamsWithOverload(t *testing.T) {
|
||||
err := cdrLogAction(acnt, nil, cdrlog, Actions{
|
||||
&Action{
|
||||
ActionType: DEBIT,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
&Action{
|
||||
ActionType: DEBIT_RESET,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(25), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 25}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(20)},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1335,11 +1335,11 @@ func TestActionTransactionFuncType(t *testing.T) {
|
||||
actions: []*Action{
|
||||
&Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(1.1), Type: utils.StringPointer(utils.MONETARY)},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 1.1}, Type: utils.StringPointer(utils.MONETARY)},
|
||||
},
|
||||
&Action{
|
||||
ActionType: "VALID_FUNCTION_TYPE",
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(1.1), Type: utils.StringPointer("test")},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 1.1}, Type: utils.StringPointer("test")},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1371,7 +1371,7 @@ func TestActionTransactionBalanceType(t *testing.T) {
|
||||
actions: []*Action{
|
||||
&Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(1.1), Type: utils.StringPointer(utils.MONETARY)},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 1.1}, Type: utils.StringPointer(utils.MONETARY)},
|
||||
},
|
||||
&Action{
|
||||
ActionType: TOPUP,
|
||||
@@ -1407,7 +1407,7 @@ func TestActionTransactionBalanceNotType(t *testing.T) {
|
||||
actions: []*Action{
|
||||
&Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{Value: utils.Float64Pointer(1.1), Type: utils.StringPointer(utils.VOICE)},
|
||||
Balance: &BalanceFilter{Value: &ValueFormula{Static: 1.1}, Type: utils.StringPointer(utils.VOICE)},
|
||||
},
|
||||
&Action{
|
||||
ActionType: TOPUP,
|
||||
@@ -1445,14 +1445,14 @@ func TestActionWithExpireWithoutExpire(t *testing.T) {
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Value: utils.Float64Pointer(15),
|
||||
Value: &ValueFormula{Static: 15},
|
||||
},
|
||||
},
|
||||
&Action{
|
||||
ActionType: TOPUP,
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Value: utils.Float64Pointer(30),
|
||||
Value: &ValueFormula{Static: 30},
|
||||
ExpirationDate: utils.TimePointer(time.Date(2025, time.November, 11, 22, 39, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
@@ -1672,7 +1672,7 @@ func TestActionConditionalTopup(t *testing.T) {
|
||||
Filter: `{"Type":"*monetary","Value":1,"Weight":10}`,
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Value: utils.Float64Pointer(11),
|
||||
Value: &ValueFormula{Static: 11},
|
||||
Weight: utils.Float64Pointer(30),
|
||||
},
|
||||
}
|
||||
@@ -1736,7 +1736,7 @@ func TestActionConditionalTopupNoMatch(t *testing.T) {
|
||||
Filter: `{"Type":"*monetary","Value":2,"Weight":10}`,
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Value: utils.Float64Pointer(11),
|
||||
Value: &ValueFormula{Static: 11},
|
||||
Weight: utils.Float64Pointer(30),
|
||||
},
|
||||
}
|
||||
@@ -1800,7 +1800,7 @@ func TestActionConditionalTopupExistingBalance(t *testing.T) {
|
||||
Filter: `{"Type":"*voice","Value":{"*gte":100}}`,
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Value: utils.Float64Pointer(11),
|
||||
Value: &ValueFormula{Static: 11},
|
||||
Weight: utils.Float64Pointer(10),
|
||||
},
|
||||
}
|
||||
@@ -2021,7 +2021,7 @@ func TestActionSetBalance(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
ID: utils.StringPointer("m2"),
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Value: utils.Float64Pointer(11),
|
||||
Value: &ValueFormula{Static: 11},
|
||||
Weight: utils.Float64Pointer(10),
|
||||
},
|
||||
}
|
||||
@@ -2122,7 +2122,7 @@ func TestActionCdrlogBalanceValue(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
ID: utils.StringPointer("*default"),
|
||||
Uuid: utils.StringPointer("25a02c82-f09f-4c6e-bacf-8ed4b076475a"),
|
||||
Value: utils.Float64Pointer(1.1),
|
||||
Value: &ValueFormula{Static: 1.1},
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
},
|
||||
},
|
||||
@@ -2132,7 +2132,7 @@ func TestActionCdrlogBalanceValue(t *testing.T) {
|
||||
Balance: &BalanceFilter{
|
||||
ID: utils.StringPointer("*default"),
|
||||
Uuid: utils.StringPointer("25a02c82-f09f-4c6e-bacf-8ed4b076475a"),
|
||||
Value: utils.Float64Pointer(2.1),
|
||||
Value: &ValueFormula{Static: 2.1},
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
@@ -11,7 +14,7 @@ type BalanceFilter struct {
|
||||
Uuid *string
|
||||
ID *string
|
||||
Type *string
|
||||
Value *float64
|
||||
Value *ValueFormula
|
||||
Directions *utils.StringMap
|
||||
ExpirationDate *time.Time
|
||||
Weight *float64
|
||||
@@ -58,7 +61,7 @@ func (bf *BalanceFilter) Clone() *BalanceFilter {
|
||||
*result.ID = *bf.ID
|
||||
}
|
||||
if bf.Value != nil {
|
||||
result.Value = new(float64)
|
||||
result.Value = new(ValueFormula)
|
||||
*result.Value = *bf.Value
|
||||
}
|
||||
if bf.RatingSubject != nil {
|
||||
@@ -116,7 +119,7 @@ func (bf *BalanceFilter) LoadFromBalance(b *Balance) *BalanceFilter {
|
||||
bf.ID = &b.ID
|
||||
}
|
||||
if b.Value != 0 {
|
||||
bf.Value = &b.Value
|
||||
bf.Value.Static = b.Value
|
||||
}
|
||||
if !b.Directions.IsEmpty() {
|
||||
bf.Directions = &b.Directions
|
||||
@@ -173,14 +176,22 @@ func (bp *BalanceFilter) GetValue() float64 {
|
||||
if bp == nil || bp.Value == nil {
|
||||
return 0.0
|
||||
}
|
||||
return *bp.Value
|
||||
if bp.Value.Method == "" {
|
||||
return bp.Value.Static
|
||||
}
|
||||
// calculate using formula
|
||||
formula, exists := valueFormulas[bp.Value.Method]
|
||||
if !exists {
|
||||
return 0.0
|
||||
}
|
||||
return formula(bp.Value.Params)
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) SetValue(v float64) {
|
||||
if bp.Value == nil {
|
||||
bp.Value = new(float64)
|
||||
bp.Value = new(ValueFormula)
|
||||
}
|
||||
*bp.Value = v
|
||||
bp.Value.Static = v
|
||||
}
|
||||
|
||||
func (bp *BalanceFilter) GetUuid() string {
|
||||
@@ -292,7 +303,7 @@ func (bf *BalanceFilter) ModifyBalance(b *Balance) {
|
||||
b.Directions = *bf.Directions
|
||||
}
|
||||
if bf.Value != nil {
|
||||
b.Value = *bf.Value
|
||||
b.Value = bf.GetValue()
|
||||
}
|
||||
if bf.ExpirationDate != nil {
|
||||
b.ExpirationDate = *bf.ExpirationDate
|
||||
@@ -323,3 +334,37 @@ func (bf *BalanceFilter) ModifyBalance(b *Balance) {
|
||||
}
|
||||
b.SetDirty() // Mark the balance as dirty since we have modified and it should be checked by action triggers
|
||||
}
|
||||
|
||||
//for computing a dynamic value for Value field
|
||||
type ValueFormula struct {
|
||||
Method string
|
||||
Params map[string]interface{}
|
||||
Static float64
|
||||
}
|
||||
|
||||
func ParseBalanceFilterValue(val string) (*ValueFormula, error) {
|
||||
u, err := strconv.ParseFloat(val, 64)
|
||||
if err == nil {
|
||||
return &ValueFormula{Static: u}, err
|
||||
}
|
||||
var vf ValueFormula
|
||||
err = json.Unmarshal([]byte(val), &vf)
|
||||
if err == nil {
|
||||
return &vf, err
|
||||
}
|
||||
return nil, errors.New("Invalid value: " + val)
|
||||
}
|
||||
|
||||
type valueFormula func(map[string]interface{}) float64
|
||||
|
||||
const (
|
||||
PERIODIC = "*periodic"
|
||||
)
|
||||
|
||||
var valueFormulas = map[string]valueFormula{
|
||||
PERIODIC: periodicFormula,
|
||||
}
|
||||
|
||||
func periodicFormula(params map[string]interface{}) float64 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ func init() {
|
||||
|
||||
func populateDB() {
|
||||
ats := []*Action{
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10)}},
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Weight: utils.Float64Pointer(20), Value: utils.Float64Pointer(10), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT"))}},
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &ValueFormula{Static: 10}}},
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.VOICE), Weight: utils.Float64Pointer(20), Value: &ValueFormula{Static: 10}, DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT"))}},
|
||||
}
|
||||
|
||||
ats1 := []*Action{
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: utils.Float64Pointer(10)}, Weight: 10},
|
||||
&Action{ActionType: "*topup", Balance: &BalanceFilter{Type: utils.StringPointer(utils.MONETARY), Value: &ValueFormula{Static: 10}}, Weight: 10},
|
||||
&Action{ActionType: "*reset_account", Weight: 20},
|
||||
}
|
||||
|
||||
|
||||
@@ -840,7 +840,7 @@ func TestLoadActions(t *testing.T) {
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Uuid: as1[0].Balance.Uuid,
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
Value: utils.Float64Pointer(10),
|
||||
Value: &ValueFormula{Static: 10},
|
||||
Weight: utils.Float64Pointer(10),
|
||||
DestinationIDs: nil,
|
||||
TimingIDs: nil,
|
||||
@@ -860,7 +860,7 @@ func TestLoadActions(t *testing.T) {
|
||||
Type: utils.StringPointer(utils.VOICE),
|
||||
Uuid: as1[1].Balance.Uuid,
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
Value: utils.Float64Pointer(100),
|
||||
Value: &ValueFormula{Static: 100},
|
||||
Weight: utils.Float64Pointer(10),
|
||||
RatingSubject: utils.StringPointer("test"),
|
||||
DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")),
|
||||
@@ -873,7 +873,7 @@ func TestLoadActions(t *testing.T) {
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(as1, expected) {
|
||||
t.Errorf("Error loading action1: %+v", as1[0].Balance)
|
||||
t.Errorf("Error loading action1: %s", utils.ToIJSON(as1))
|
||||
}
|
||||
as2 := csvr.actions["SHARED"]
|
||||
expected = []*Action{
|
||||
@@ -887,7 +887,7 @@ func TestLoadActions(t *testing.T) {
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
DestinationIDs: nil,
|
||||
Uuid: as2[0].Balance.Uuid,
|
||||
Value: utils.Float64Pointer(100),
|
||||
Value: &ValueFormula{Static: 100},
|
||||
Weight: utils.Float64Pointer(10),
|
||||
SharedGroups: utils.StringMapPointer(utils.NewStringMap("SG1")),
|
||||
TimingIDs: nil,
|
||||
@@ -898,7 +898,7 @@ func TestLoadActions(t *testing.T) {
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(as2, expected) {
|
||||
t.Errorf("Error loading action: %+v", as2[0].Balance)
|
||||
t.Errorf("Error loading action: %s", utils.ToIJSON(as2))
|
||||
}
|
||||
as3 := csvr.actions["DEFEE"]
|
||||
expected = []*Action{
|
||||
|
||||
@@ -531,11 +531,11 @@ func (tpr *TpReader) LoadActions() (err error) {
|
||||
}
|
||||
|
||||
if tpact.Units != "" && tpact.Units != utils.ANY {
|
||||
u, err := strconv.ParseFloat(tpact.Units, 64)
|
||||
vf, err := ParseBalanceFilterValue(tpact.Units)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
acts[idx].Balance.Value = utils.Float64Pointer(u)
|
||||
acts[idx].Balance.Value = vf
|
||||
}
|
||||
|
||||
if tpact.BalanceWeight != "" && tpact.BalanceWeight != utils.ANY {
|
||||
@@ -1007,11 +1007,11 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
|
||||
}
|
||||
|
||||
if tpact.Units != "" && tpact.Units != utils.ANY {
|
||||
u, err := strconv.ParseFloat(tpact.Units, 64)
|
||||
vf, err := ParseBalanceFilterValue(tpact.Units)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
acts[idx].Balance.Value = utils.Float64Pointer(u)
|
||||
acts[idx].Balance.Value = vf
|
||||
}
|
||||
|
||||
if tpact.BalanceWeight != "" && tpact.BalanceWeight != utils.ANY {
|
||||
@@ -1355,11 +1355,11 @@ func (tpr *TpReader) LoadCdrStatsFiltered(tag string, save bool) (err error) {
|
||||
}
|
||||
|
||||
if tpact.Units != "" && tpact.Units != utils.ANY {
|
||||
u, err := strconv.ParseFloat(tpact.Units, 64)
|
||||
vf, err := ParseBalanceFilterValue(tpact.Units)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
acts[idx].Balance.Value = utils.Float64Pointer(u)
|
||||
acts[idx].Balance.Value = vf
|
||||
}
|
||||
|
||||
if tpact.BalanceWeight != "" && tpact.BalanceWeight != utils.ANY {
|
||||
|
||||
Reference in New Issue
Block a user