mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
RateS - return ErrNotFound in case of no profile matched, AccountS - testAccountSv1MaxUsage
This commit is contained in:
@@ -93,7 +93,6 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal,
|
||||
// will use special rounding to 0 since otherwise we go negative (ie: 0.05 as increment)
|
||||
usage.Big = roundedUsageWithIncrements(aB.blnCfg.Units.Big, costIcrm.Increment.Big)
|
||||
}
|
||||
|
||||
// attempt to debit usage with cost
|
||||
if ec, err = maxDebitUsageFromConcretes(aB.cncrtBlncs, usage,
|
||||
aB.connMgr, cgrEv,
|
||||
|
||||
@@ -176,17 +176,20 @@ func (aS *AccountS) accountProcessEvent(acnt *utils.AccountProfile,
|
||||
} else {
|
||||
usage.Big = decimal.New(int64(usgEv), 0)
|
||||
}
|
||||
|
||||
for _, blncOper := range blncOpers {
|
||||
for i, blncOper := range blncOpers {
|
||||
if i == 0 {
|
||||
ec = utils.NewEventCharges()
|
||||
}
|
||||
if usage.Big.Cmp(decimal.New(0, 0)) == 0 {
|
||||
return // no more debit
|
||||
}
|
||||
var ecDbt *utils.EventCharges
|
||||
if ec, err = blncOper.debitUsage(usage, cgrEv); err != nil {
|
||||
if ecDbt, err = blncOper.debitUsage(usage.Clone(), cgrEv); err != nil {
|
||||
if err == utils.ErrFilterNotPassingNoCaps {
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
usage.Big = utils.SubstractBig(usage.Big, ecDbt.Usage)
|
||||
ec.Merge(ecDbt)
|
||||
@@ -209,7 +212,7 @@ func (aS *AccountS) V1AccountProfileForEvent(args *utils.ArgsAccountForEvent, ap
|
||||
}
|
||||
|
||||
// V1MaxUsage returns the maximum usage for the event, based on matching Account
|
||||
func (aS *AccountS) V1MaxUsage(args *utils.ArgsAccountForEvent, ec *utils.EventCharges) (err error) {
|
||||
func (aS *AccountS) V1MaxUsage(args *utils.ArgsAccountForEvent, eEc *utils.ExtEventCharges) (err error) {
|
||||
var acnt *utils.AccountProfile
|
||||
var lkID string
|
||||
if acnt, lkID, err = aS.matchingAccountForEvent(args.CGREvent.Tenant,
|
||||
@@ -225,13 +228,16 @@ func (aS *AccountS) V1MaxUsage(args *utils.ArgsAccountForEvent, ec *utils.EventC
|
||||
if procEC, err = aS.accountProcessEvent(acnt, args.CGREvent); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
*ec = *procEC
|
||||
var rcvEec *utils.ExtEventCharges
|
||||
if rcvEec, err = procEC.AsExtEventCharges(); err != nil {
|
||||
return
|
||||
}
|
||||
*eEc = *rcvEec
|
||||
return
|
||||
}
|
||||
|
||||
// V1DebitUsage performs debit for the provided event
|
||||
func (aS *AccountS) V1DebitUsage(args *utils.ArgsAccountForEvent, ec *utils.EventCharges) (err error) {
|
||||
func (aS *AccountS) V1DebitUsage(args *utils.ArgsAccountForEvent, eEc *utils.ExtEventCharges) (err error) {
|
||||
var acnt *utils.AccountProfile
|
||||
var lkID string
|
||||
if acnt, lkID, err = aS.matchingAccountForEvent(args.CGREvent.Tenant,
|
||||
@@ -248,10 +254,15 @@ func (aS *AccountS) V1DebitUsage(args *utils.ArgsAccountForEvent, ec *utils.Even
|
||||
return
|
||||
}
|
||||
|
||||
var rcvEec *utils.ExtEventCharges
|
||||
if rcvEec, err = procEC.AsExtEventCharges(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = aS.dm.SetAccountProfile(acnt, false); err != nil {
|
||||
return // no need of revert since we did not save
|
||||
}
|
||||
|
||||
*ec = *procEC
|
||||
*eEc = *rcvEec
|
||||
return
|
||||
}
|
||||
|
||||
@@ -112,7 +112,6 @@ func (cB *concreteBalance) debitUnits(dUnts *utils.Decimal, tnt string,
|
||||
// debit implements the balanceOperator interface
|
||||
func (cB *concreteBalance) debitUsage(usage *utils.Decimal,
|
||||
cgrEv *utils.CGREvent) (ec *utils.EventCharges, err error) {
|
||||
|
||||
evNm := utils.MapStorage{
|
||||
utils.MetaOpts: cgrEv.Opts,
|
||||
utils.MetaReq: cgrEv.Event,
|
||||
|
||||
@@ -40,13 +40,19 @@ func newAccountBalanceOperators(acnt *utils.AccountProfile,
|
||||
}
|
||||
blnCfgs.Sort()
|
||||
|
||||
var cncrtBlncs []*concreteBalance
|
||||
blncOpers = make([]balanceOperator, len(blnCfgs))
|
||||
for i, blnCfg := range blnCfgs {
|
||||
var cncrtBlncs []*concreteBalance
|
||||
for i, blnCfg := range blnCfgs { // build the concrete balances
|
||||
if blnCfg.Type != utils.MetaConcrete {
|
||||
continue
|
||||
}
|
||||
blncOpers[i] = newConcreteBalanceOperator(blnCfg,
|
||||
fltrS, connMgr, attrSConns, rateSConns)
|
||||
cncrtBlncs = append(cncrtBlncs, blncOpers[i].(*concreteBalance))
|
||||
}
|
||||
|
||||
for i, blnCfg := range blnCfgs { // build the abstract balances
|
||||
if blnCfg.Type == utils.MetaConcrete {
|
||||
blncOpers[i] = newConcreteBalanceOperator(blnCfg,
|
||||
fltrS, connMgr, attrSConns, rateSConns)
|
||||
cncrtBlncs = append(cncrtBlncs, blncOpers[i].(*concreteBalance))
|
||||
continue
|
||||
}
|
||||
if blncOpers[i], err = newBalanceOperator(blnCfg, cncrtBlncs, fltrS, connMgr,
|
||||
@@ -189,6 +195,7 @@ func debitUsageFromConcretes(cncrtBlncs []*concreteBalance, usage *utils.Decimal
|
||||
costIcrm.FixedFee == nil {
|
||||
var rplyCost *engine.RateProfileCost
|
||||
if rplyCost, err = rateSCostForEvent(connMgr, cgrEv, rateSConns, rpIDs); err != nil {
|
||||
err = utils.NewErrRateS(err)
|
||||
return
|
||||
}
|
||||
costIcrm = costIcrm.Clone() // so we don't modify the original
|
||||
@@ -235,7 +242,6 @@ func maxDebitUsageFromConcretes(cncrtBlncs []*concreteBalance, usage *utils.Deci
|
||||
connMgr *engine.ConnManager, cgrEv *utils.CGREvent,
|
||||
attrSConns, attributeIDs, rateSConns, rpIDs []string,
|
||||
costIcrm *utils.CostIncrement) (ec *utils.EventCharges, err error) {
|
||||
|
||||
// process AttributeS if needed
|
||||
if costIcrm.RecurrentFee.Cmp(decimal.New(-1, 0)) == 0 &&
|
||||
costIcrm.FixedFee == nil &&
|
||||
|
||||
@@ -166,12 +166,12 @@ func (aSv1 *AccountSv1) AccountProfileForEvent(args *utils.ArgsAccountForEvent,
|
||||
|
||||
// MaxUsage returns the maximum usage for the event, based on matching Account
|
||||
func (aSv1 *AccountSv1) MaxUsage(args *utils.ArgsAccountForEvent,
|
||||
ec *utils.EventCharges) (err error) {
|
||||
return aSv1.aS.V1MaxUsage(args, ec)
|
||||
eEc *utils.ExtEventCharges) (err error) {
|
||||
return aSv1.aS.V1MaxUsage(args, eEc)
|
||||
}
|
||||
|
||||
// DebitUsage performs debit for the provided event
|
||||
func (aSv1 *AccountSv1) DebitUsage(args *utils.ArgsAccountForEvent,
|
||||
ec *utils.EventCharges) (err error) {
|
||||
return aSv1.aS.V1DebitUsage(args, ec)
|
||||
eEc *utils.ExtEventCharges) (err error) {
|
||||
return aSv1.aS.V1DebitUsage(args, eEc)
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ func TestAccountSv1IT(t *testing.T) {
|
||||
testAccountSv1RPCConn,
|
||||
testAccountSv1LoadFromFolder,
|
||||
testAccountSv1AccountProfileForEvent,
|
||||
testAccountSv1MaxUsage,
|
||||
}
|
||||
switch *dbType {
|
||||
case utils.MetaInternal:
|
||||
@@ -144,13 +145,9 @@ func testAccountSv1AccountProfileForEvent(t *testing.T) {
|
||||
AttributeIDs: []string{},
|
||||
RateProfileIDs: []string{},
|
||||
UnitFactors: []*utils.UnitFactor{
|
||||
&utils.UnitFactor{
|
||||
FilterIDs: []string{"*string:~*req.ToR:*voice"},
|
||||
Factor: &utils.Decimal{decimal.New(int64(time.Second), 0)},
|
||||
},
|
||||
&utils.UnitFactor{
|
||||
FilterIDs: []string{"*string:~*req.ToR:*data"},
|
||||
Factor: &utils.Decimal{decimal.New(int64(1024*time.Second), 0)},
|
||||
Factor: &utils.Decimal{decimal.New(1024, 3)},
|
||||
},
|
||||
},
|
||||
Units: &utils.Decimal{decimal.New(int64(time.Hour), 0)},
|
||||
@@ -180,11 +177,18 @@ func testAccountSv1AccountProfileForEvent(t *testing.T) {
|
||||
Units: &utils.Decimal{decimal.New(5, 0)},
|
||||
},
|
||||
"MonetaryBalance2": &utils.Balance{
|
||||
ID: "MonetaryBalance2",
|
||||
FilterIDs: []string{},
|
||||
Weight: 10,
|
||||
Type: utils.MetaConcrete,
|
||||
CostIncrements: []*utils.CostIncrement{},
|
||||
ID: "MonetaryBalance2",
|
||||
FilterIDs: []string{},
|
||||
Weight: 10,
|
||||
Type: utils.MetaConcrete,
|
||||
CostIncrements: []*utils.CostIncrement{
|
||||
&utils.CostIncrement{
|
||||
FilterIDs: []string{"*string:~*req.ToR:*voice"},
|
||||
Increment: &utils.Decimal{decimal.New(int64(time.Second), 0)},
|
||||
FixedFee: &utils.Decimal{decimal.New(0, 0)},
|
||||
RecurrentFee: &utils.Decimal{decimal.New(1, 0)},
|
||||
},
|
||||
},
|
||||
AttributeIDs: []string{},
|
||||
RateProfileIDs: []string{},
|
||||
UnitFactors: []*utils.UnitFactor{},
|
||||
@@ -206,3 +210,20 @@ func testAccountSv1AccountProfileForEvent(t *testing.T) {
|
||||
t.Errorf("Expecting : %s \n received: %s", utils.ToJSON(eAcnt), utils.ToJSON(acnt))
|
||||
}
|
||||
}
|
||||
|
||||
func testAccountSv1MaxUsage(t *testing.T) {
|
||||
var eEc *utils.ExtEventCharges
|
||||
if err := acntSRPC.Call(utils.AccountSv1MaxUsage,
|
||||
&utils.ArgsAccountForEvent{CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "testAccountSv1MaxUsage",
|
||||
Event: map[string]interface{}{
|
||||
utils.AccountField: "1001",
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.Usage: "15m",
|
||||
}}}, &eEc); err != nil {
|
||||
t.Error(err)
|
||||
} else if eEc.Usage == nil || *eEc.Usage != 800000000000.0 { // 500s from first monetary + 300s from last monetary
|
||||
t.Errorf("received usage: %v", *eEc.Usage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#Tenant,ID,FilterIDs,ActivationInterval,Weight,BalanceID,BalanceFilterIDs,BalanceWeight,BalanceBlocker,BalanceType,BalanceOpts,BalanceCostIncrements,BalanceAttributeIDs,BalanceRateProfileIDs,BalanceUnitFactors,BalanceUnits,ThresholdIDs
|
||||
cgrates.org,1001,*string:~*req.Account:1001,,,MonetaryBalance1,,30,,*concrete,,*string:~*req.ToR:*voice;1000000000;0;0.01;*string:~*req.ToR:*data;1024;0;0.01,,,,5,*none
|
||||
cgrates.org,1001,,,,GenericBalance1,,20,,*abstract,,*string:~*req.ToR:*voice;1000000000;0;0.01;*string:~*req.ToR:*data;1024;0;0.01,,,*string:~*req.ToR:*voice;1000000000;*string:~*req.ToR:*data;1024000000000,3600000000000,
|
||||
cgrates.org,1001,,,,MonetaryBalance2,,10,,*concrete,,,,,,3,
|
||||
cgrates.org,1001,,,,GenericBalance1,,20,,*abstract,,*string:~*req.ToR:*voice;1000000000;0;0.01;*string:~*req.ToR:*data;1024;0;0.01,,,*string:~*req.ToR:*data;1.024,3600000000000,
|
||||
cgrates.org,1001,,,,MonetaryBalance2,,10,,*concrete,,*string:~*req.ToR:*voice;1000000000;0;1,,,,3,
|
||||
cgrates.org,1002,*string:~*req.Account:1002,,10,MonetaryBalance1,,,,*concrete,,*string:~*req.ToR:*voice;1000000000;0;0.01;;1;0;1,,,,10,*none
|
||||
|
||||
|
@@ -198,10 +198,16 @@ func (rS *RateS) V1CostForEvent(args *utils.ArgsCostForEvent, rpCost *engine.Rat
|
||||
}
|
||||
var rtPrl *engine.RateProfile
|
||||
if rtPrl, err = rS.matchingRateProfileForEvent(args.Tenant, rPfIDs, args); err != nil {
|
||||
return utils.NewErrServerError(err)
|
||||
if err != utils.ErrNotFound {
|
||||
err = utils.NewErrServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if rcvCost, errCost := rS.rateProfileCostForEvent(rtPrl, args, rS.cfg.RateSCfg().Verbosity); errCost != nil {
|
||||
return utils.NewErrServerError(errCost)
|
||||
if errCost != utils.ErrNotFound {
|
||||
errCost = utils.NewErrServerError(err)
|
||||
}
|
||||
return errCost
|
||||
} else {
|
||||
*rpCost = *rcvCost
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ var (
|
||||
ErrNotConnected = errors.New("NOT_CONNECTED")
|
||||
RalsErrorPrfx = "RALS_ERROR"
|
||||
DispatcherErrorPrefix = "DISPATCHER_ERROR"
|
||||
RateSErrPrfx = "RATES_ERROR"
|
||||
ErrUnsupportedFormat = errors.New("UNSUPPORTED_FORMAT")
|
||||
ErrNoDatabaseConn = errors.New("NO_DATA_BASE_CONNECTION")
|
||||
ErrMaxIncrementsExceeded = errors.New("MAX_INCREMENTS_EXCEEDED")
|
||||
@@ -204,6 +205,10 @@ func NewErrDispatcherS(err error) error {
|
||||
return fmt.Errorf("%s:%s", DispatcherErrorPrefix, err.Error())
|
||||
}
|
||||
|
||||
func NewErrRateS(err error) error {
|
||||
return fmt.Errorf("%s:%s", RateSErrPrfx, err.Error())
|
||||
}
|
||||
|
||||
// Centralized returns for APIs
|
||||
func APIErrorHandler(errIn error) (err error) {
|
||||
cgrErr, ok := errIn.(*CGRError)
|
||||
|
||||
@@ -24,6 +24,12 @@ import (
|
||||
"github.com/ericlagergren/decimal"
|
||||
)
|
||||
|
||||
// NewEventChargers instantiates the EventChargers in a central place
|
||||
func NewEventCharges() (ec *EventCharges) {
|
||||
ec = new(EventCharges)
|
||||
return
|
||||
}
|
||||
|
||||
// EventCharges records the charges applied to an Event
|
||||
type EventCharges struct {
|
||||
Usage *decimal.Big
|
||||
|
||||
Reference in New Issue
Block a user