diff --git a/engine/account.go b/engine/account.go index 45497e32f..b356a8ab3 100644 --- a/engine/account.go +++ b/engine/account.go @@ -190,6 +190,7 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error { b.SubstractValue(bClone.GetValue()) b.dirty = true found = true + a.balanceValue = b.GetValue() } } // if it is not found then we add it to the list @@ -207,7 +208,7 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error { } } bClone.dirty = true // Mark the balance as dirty since we have modified and it should be checked by action triggers - + a.balanceValue = bClone.GetValue() bClone.Uuid = utils.GenUUID() // alway overwrite the uuid for consistency // load ValueFactor if defined in extra parametrs if a.ExtraParameters != "" { diff --git a/engine/action.go b/engine/action.go index 07152a58d..62ca439dd 100644 --- a/engine/action.go +++ b/engine/action.go @@ -45,6 +45,7 @@ type Action struct { ExpirationString string // must stay as string because it can have relative values like 1month Weight float64 Balance *BalanceFilter + balanceValue float64 // balance value after action execution, used with cdrlog } const ( @@ -181,6 +182,8 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action) parsedValue += rsrFld.ParseValue(action.Id) case "ActionType": parsedValue += rsrFld.ParseValue(action.ActionType) + case "ActionValue": + parsedValue += rsrFld.ParseValue(strconv.FormatFloat(b.GetValue(), 'f', -1, 64)) case "BalanceType": parsedValue += rsrFld.ParseValue(action.Balance.GetType()) case "BalanceUUID": @@ -188,7 +191,7 @@ func parseTemplateValue(rsrFlds utils.RSRFields, acnt *Account, action *Action) case "BalanceID": parsedValue += rsrFld.ParseValue(b.ID) case "BalanceValue": - parsedValue += rsrFld.ParseValue(strconv.FormatFloat(b.GetValue(), 'f', -1, 64)) + parsedValue += rsrFld.ParseValue(strconv.FormatFloat(action.balanceValue, 'f', -1, 64)) case "DestinationIDs": parsedValue += rsrFld.ParseValue(b.DestinationIDs.String()) case "ExtraParameters": @@ -215,7 +218,7 @@ func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) utils.TENANT: utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP), utils.ACCOUNT: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP), utils.SUBJECT: utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP), - utils.COST: utils.ParseRSRFieldsMustCompile("BalanceValue", utils.INFIELD_SEP), + utils.COST: utils.ParseRSRFieldsMustCompile("ActionValue", utils.INFIELD_SEP), } template := make(map[string]string) @@ -329,7 +332,9 @@ func topupResetAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actio } c := a.Clone() genericMakeNegative(c) - return genericDebit(ub, c, true) + err = genericDebit(ub, c, true) + a.balanceValue = c.balanceValue + return } func topupAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) { @@ -338,7 +343,9 @@ func topupAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) ( } c := a.Clone() genericMakeNegative(c) - return genericDebit(ub, c, false) + err = genericDebit(ub, c, false) + a.balanceValue = c.balanceValue + return } func debitResetAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) { diff --git a/engine/actions_test.go b/engine/actions_test.go index 1fea3f47d..bead47620 100644 --- a/engine/actions_test.go +++ b/engine/actions_test.go @@ -2097,6 +2097,53 @@ func TestActionExpNoExp(t *testing.T) { } } +func TestActionCdrlogBalanceValue(t *testing.T) { + err := accountingStorage.SetAccount(&Account{ + ID: "cgrates.org:bv", + BalanceMap: map[string]Balances{ + utils.MONETARY: Balances{&Balance{ + Value: 10, + }}, + }, + }) + if err != nil { + t.Error("Error setting account: ", err) + } + at := &ActionTiming{ + accountIDs: utils.StringMap{"cgrates.org:bv": true}, + Timing: &RateInterval{}, + actions: []*Action{ + &Action{ + ActionType: TOPUP, + Balance: &BalanceFilter{Value: utils.Float64Pointer(1.1), Type: utils.StringPointer(utils.MONETARY)}, + }, + &Action{ + ActionType: DEBIT, + Balance: &BalanceFilter{Value: utils.Float64Pointer(2.1), Type: utils.StringPointer(utils.MONETARY)}, + }, + &Action{ + ActionType: CDRLOG, + ExtraParameters: `{"BalanceValue":"BalanceValue"}`, + }, + }, + } + err = at.Execute() + acc, err := accountingStorage.GetAccount("cgrates.org:bv") + if err != nil || acc == nil { + t.Error("Error getting account: ", acc, err) + } + if acc.BalanceMap[utils.MONETARY][0].Value != 9 { + t.Errorf("Transaction didn't work: %v", acc.BalanceMap[utils.MONETARY][0].Value) + } + cdrs := make([]*CDR, 0) + json.Unmarshal([]byte(at.actions[2].ExpirationString), &cdrs) + if len(cdrs) != 2 || + cdrs[0].ExtraFields["BalanceValue"] != "11.1" || + cdrs[1].ExtraFields["BalanceValue"] != "9" { + t.Errorf("Wrong cdrlogs: %+v", cdrs[1]) + } +} + /**************** Benchmarks ********************************/ func BenchmarkUUID(b *testing.B) {