mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-20 06:38:45 +05:00
AccountS - restore concrete balances on errors
This commit is contained in:
@@ -156,6 +156,7 @@ func (aB *abstractBalance) debitUsageFromConcrete(cBs []*concreteBalance, usage
|
||||
tCost = utils.SumBig(tCost, rcrntCost)
|
||||
}
|
||||
}
|
||||
clnedUnts := cloneUnitsFromConcretes(cBs)
|
||||
for _, cB := range cBs {
|
||||
ev := utils.MapStorage{
|
||||
utils.MetaOpts: cgrEv.Opts,
|
||||
@@ -163,13 +164,16 @@ func (aB *abstractBalance) debitUsageFromConcrete(cBs []*concreteBalance, usage
|
||||
}
|
||||
var dbted *utils.Decimal
|
||||
if dbted, _, err = cB.debitUnits(&utils.Decimal{tCost}, cgrEv.Tenant, ev); err != nil {
|
||||
restoreUnitsFromClones(cBs, clnedUnts)
|
||||
return
|
||||
}
|
||||
tCost = utils.SubstractBig(tCost, dbted.Big)
|
||||
if tCost.Cmp(decimal.New(0, 0)) <= 0 {
|
||||
return // have debitted all, total is smaller or equal to 0
|
||||
return // have debited all, total is smaller or equal to 0
|
||||
}
|
||||
}
|
||||
// we could not debit all, put back what we have debited
|
||||
restoreUnitsFromClones(cBs, clnedUnts)
|
||||
return utils.ErrInsufficientCredit
|
||||
}
|
||||
|
||||
@@ -207,30 +211,35 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time,
|
||||
}
|
||||
}
|
||||
|
||||
blcVal := aB.blnCfg.Units
|
||||
origBlclVal := new(decimal.Big).Copy(aB.blnCfg.Units.Big) // so we can restore on errors
|
||||
|
||||
// balanceLimit
|
||||
var hasLmt bool
|
||||
blncLmt := aB.balanceLimit()
|
||||
if blncLmt != nil && blncLmt.Cmp(decimal.New(0, 0)) != 0 {
|
||||
blcVal = utils.SubstractDecimal(blcVal, blncLmt)
|
||||
aB.blnCfg.Units.Big = utils.SubstractBig(aB.blnCfg.Units.Big, blncLmt.Big)
|
||||
hasLmt = true
|
||||
}
|
||||
// balance smaller than usage, correct usage
|
||||
if blcVal.Compare(usage) == -1 && blncLmt != nil {
|
||||
// will use special rounding to 0 since otherwise we go negative (ie: 0.05 as increment)
|
||||
maxIncrm := &utils.Decimal{
|
||||
decimal.WithContext(
|
||||
decimal.Context{RoundingMode: decimal.ToZero}).Quo(blcVal.Big,
|
||||
costIcrm.Increment.Big).RoundToInt()}
|
||||
usage = utils.MultiplyDecimal(maxIncrm, costIcrm.Increment) // decrease the usage to match the maximum increments
|
||||
}
|
||||
|
||||
// unitFactor
|
||||
var uF *utils.UnitFactor
|
||||
if uF, err = aB.unitFactor(cgrEv.Tenant, evNm); err != nil {
|
||||
return
|
||||
}
|
||||
var hasUF bool
|
||||
if uF != nil && uF.Factor.Cmp(decimal.New(1, 0)) != 0 {
|
||||
usage.Big = utils.MultiplyBig(usage.Big, uF.Factor.Big)
|
||||
hasUF = true
|
||||
}
|
||||
|
||||
// balance smaller than usage, correct usage
|
||||
if aB.blnCfg.Units.Compare(usage) == -1 {
|
||||
// will use special rounding to 0 since otherwise we go negative (ie: 0.05 as increment)
|
||||
maxIncrm := decimal.WithContext(
|
||||
decimal.Context{RoundingMode: decimal.ToZero}).Quo(aB.blnCfg.Units.Big,
|
||||
costIcrm.Increment.Big).RoundToInt()
|
||||
usage.Big = utils.MultiplyBig(maxIncrm, costIcrm.Increment.Big) // decrease the usage to match the maximum increments
|
||||
}
|
||||
|
||||
// attempt to debit usage with cost
|
||||
// fix the maximum number of iterations
|
||||
@@ -238,7 +247,8 @@ func (aB *abstractBalance) debitUsage(usage *utils.Decimal, startTime time.Time,
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("costIcrm: %+v, blncLmt: %+v, hasLmt: %+v, uF: %+v", costIcrm, blncLmt, hasLmt, uF)
|
||||
fmt.Printf("costIcrm: %+v, blncLmt: %+v, hasLmt: %+v, uF: %+v, origBlclVal: %s, hasUF: %v",
|
||||
costIcrm, blncLmt, hasLmt, uF, origBlclVal, hasUF)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -98,9 +98,9 @@ func TestABDebitUsageFromConcrete(t *testing.T) {
|
||||
RecurrentFee: utils.NewDecimal(1, 0)},
|
||||
new(utils.CGREvent)); err == nil || err != utils.ErrInsufficientCredit {
|
||||
t.Error(err)
|
||||
} else if cBs[0].blnCfg.Units.Compare(utils.NewDecimal(-200, 0)) != 0 {
|
||||
} else if cBs[0].blnCfg.Units.Compare(utils.NewDecimal(500, 0)) != 0 {
|
||||
t.Errorf("Unexpected units in first balance: %s", cBs[0].blnCfg.Units)
|
||||
} else if cBs[1].blnCfg.Units.Compare(utils.NewDecimal(-1, 0)) != 0 {
|
||||
} else if cBs[1].blnCfg.Units.Compare(utils.NewDecimal(125, 2)) != 0 {
|
||||
t.Errorf("Unexpected units in first balance: %s", cBs[1].blnCfg.Units)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,13 +159,19 @@ func (cB *concreteBalance) debitUnits(dUnts *utils.Decimal, tnt string,
|
||||
}
|
||||
|
||||
// cloneUnitsFromConcretes returns cloned units from the concrete balances passed as parameters
|
||||
func cloneUnitsFromConcretes(cBs []*concreteBalance) (clnUnits []*utils.Decimal) {
|
||||
func cloneUnitsFromConcretes(cBs []*concreteBalance) (clnedUnts []*utils.Decimal) {
|
||||
if cBs == nil {
|
||||
return
|
||||
}
|
||||
clnUnits = make([]*utils.Decimal, len(cBs))
|
||||
clnedUnts = make([]*utils.Decimal, len(cBs))
|
||||
for i := range cBs {
|
||||
clnUnits[i] = cBs[i].blnCfg.Units.Clone()
|
||||
clnedUnts[i] = cBs[i].blnCfg.Units.Clone()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func restoreUnitsFromClones(cBs []*concreteBalance, clnedUnts []*utils.Decimal) {
|
||||
for i, clnedUnt := range clnedUnts {
|
||||
cBs[i].blnCfg.Units.Big = clnedUnt.Big
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user