From 575259628a06dc21d3231d045c410ee15e4b6a84 Mon Sep 17 00:00:00 2001 From: DanB Date: Tue, 29 Dec 2020 20:41:48 +0100 Subject: [PATCH] AccountS - usageFactor implementation --- accounts/absolutebalance.go | 8 +++++-- accounts/concretebalance.go | 17 +++++++++++--- accounts/libaccounts.go | 44 ++++++++++++++++++++++++++++++++----- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/accounts/absolutebalance.go b/accounts/absolutebalance.go index cf4901be5..f0e41c7b4 100644 --- a/accounts/absolutebalance.go +++ b/accounts/absolutebalance.go @@ -21,18 +21,22 @@ package accounts import ( "time" + "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) // newAbstractBalance constructs an abstractBalanceOperator -func newAbstractBalanceOperator(blnCfg *utils.Balance, cncrtBlncs []balanceOperator) balanceOperator { - return &abstractBalance{blnCfg, cncrtBlncs} +func newAbstractBalanceOperator(blnCfg *utils.Balance, cncrtBlncs []balanceOperator, + fltrS *engine.FilterS, ralsConns []string) balanceOperator { + return &abstractBalance{blnCfg, cncrtBlncs, fltrS, ralsConns} } // abstractBalance is the operator for *abstract balance type type abstractBalance struct { blnCfg *utils.Balance cncrtBlncs []balanceOperator // paying balances + fltrS *engine.FilterS + ralsConns []string } // debit implements the balanceOperator interface diff --git a/accounts/concretebalance.go b/accounts/concretebalance.go index 00d10e994..a90633a45 100644 --- a/accounts/concretebalance.go +++ b/accounts/concretebalance.go @@ -21,21 +21,32 @@ package accounts import ( "time" + "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) // newConcreteBalance constructs a concreteBalanceOperator -func newConcreteBalanceOperator(blnCfg *utils.Balance) balanceOperator { - return &concreteBalance{blnCfg} +func newConcreteBalanceOperator(blnCfg *utils.Balance, + fltrS *engine.FilterS, ralsConns []string) balanceOperator { + return &concreteBalance{blnCfg, fltrS, ralsConns} } // concreteBalance is the operator for *concrete balance type type concreteBalance struct { - blnCfg *utils.Balance + blnCfg *utils.Balance + fltrS *engine.FilterS + ralsConns []string } // debit implements the balanceOperator interface func (cb *concreteBalance) debit(cgrEv *utils.CGREventWithOpts, startTime time.Time, usage float64) (ec *utils.EventCharges, err error) { + var uF float64 + if uF, err = usageFactor(cb.blnCfg, cb.fltrS, cgrEv); err != nil { + return + } + if uF != 1.0 { + usage = usage * uF + } return } diff --git a/accounts/libaccounts.go b/accounts/libaccounts.go index ab7a117e3..061f295db 100644 --- a/accounts/libaccounts.go +++ b/accounts/libaccounts.go @@ -39,7 +39,7 @@ func newAccountBalances(acnt *utils.AccountProfile, // populate cncrtBlncs acntBlncs.cncrtBlncs = make([]balanceOperator, len(acntBlncs.typIdx[utils.MetaConcrete])) for i, blncIdx := range acntBlncs.typIdx[utils.MetaConcrete] { - acntBlncs.cncrtBlncs[i] = newConcreteBalanceOperator(acntBlncs.blnCfgs[blncIdx]) + acntBlncs.cncrtBlncs[i] = newConcreteBalanceOperator(acntBlncs.blnCfgs[blncIdx], fltrS, ralsConns) acntBlncs.procs[acntBlncs.blnCfgs[blncIdx].ID] = acntBlncs.cncrtBlncs[i] } // populate procs @@ -48,7 +48,7 @@ func newAccountBalances(acnt *utils.AccountProfile, continue } if acntBlncs.procs[blnCfg.ID], err = newBalanceOperator(blnCfg, - acntBlncs.cncrtBlncs); err != nil { + acntBlncs.cncrtBlncs, fltrS, ralsConns); err != nil { return } } @@ -68,15 +68,15 @@ type accountBalances struct { // newBalanceOperator instantiates balanceOperator interface // cncrtBlncs are needed for abstract balance debits -func newBalanceOperator(blncCfg *utils.Balance, - cncrtBlncs []balanceOperator) (bP balanceOperator, err error) { +func newBalanceOperator(blncCfg *utils.Balance, cncrtBlncs []balanceOperator, + fltrS *engine.FilterS, ralsConns []string) (bP balanceOperator, err error) { switch blncCfg.Type { default: return nil, fmt.Errorf("unsupported balance type: <%s>", blncCfg.Type) case utils.MetaConcrete: - return newConcreteBalanceOperator(blncCfg), nil + return newConcreteBalanceOperator(blncCfg, fltrS, ralsConns), nil case utils.MetaAbstract: - return newAbstractBalanceOperator(blncCfg, cncrtBlncs), nil + return newAbstractBalanceOperator(blncCfg, cncrtBlncs, fltrS, ralsConns), nil } } @@ -85,3 +85,35 @@ type balanceOperator interface { debit(cgrEv *utils.CGREventWithOpts, startTime time.Time, usage float64) (ec *utils.EventCharges, err error) } + +// usageFactor returns the usage factor for the debit +// includes event filtering to avoid code duplication +func usageFactor(blnCfg *utils.Balance, fltrS *engine.FilterS, cgrEv *utils.CGREventWithOpts) (fctr float64, err error) { + fctr = 1.0 + if len(blnCfg.FilterIDs) == 0 && + len(blnCfg.UsageFactors) == 0 { + return + } + evNm := utils.MapStorage{ + utils.MetaOpts: cgrEv.Opts, + utils.MetaReq: cgrEv.Event, + } + // match the general balance filters + var pass bool + if pass, err = fltrS.Pass(cgrEv.CGREvent.Tenant, blnCfg.FilterIDs, evNm); err != nil { + return 0, err + } else if !pass { + return 0, utils.ErrFilterNotPassingNoCaps + } + // find out the factor + for _, uF := range blnCfg.UsageFactors { + if pass, err = fltrS.Pass(cgrEv.CGREvent.Tenant, uF.FilterIDs, evNm); err != nil { + return 0, err + } else if !pass { + continue + } + fctr = uF.Factor + break + } + return +}