diff --git a/engine/account.go b/engine/account.go index 4811e1899..cce870291 100644 --- a/engine/account.go +++ b/engine/account.go @@ -128,8 +128,7 @@ func (ub *Account) debitBalanceAction(a *Action) error { continue // we can clean expired balances balances here } if b.Equal(a.Balance) { - b.Value -= a.Balance.Value - b.Value = utils.Round(b.Value, roundingDecimals, utils.ROUNDING_MIDDLE) + b.SubstractAmount(a.Balance.Value) found = true break } @@ -195,11 +194,7 @@ func (ub *Account) debitCreditBalance(cc *CallCost, count bool) (err error) { usefulMoneyBalances := ub.getAlldBalancesForPrefix(cc.Destination, CREDIT+cc.Direction) // debit minutes for _, balance := range usefulMinuteBalances { - initialValue := balance.Value balance.DebitMinutes(cc, count, balance.account, usefulMoneyBalances) - if balance.Value != initialValue && balance.account != ub { - accountingStorage.SetAccount(balance.account) - } if cc.IsPaid() { goto CONNECT_FEE } @@ -218,11 +213,7 @@ func (ub *Account) debitCreditBalance(cc *CallCost, count bool) (err error) { } // debit money for _, balance := range usefulMoneyBalances { - initialValue := balance.Value balance.DebitMoney(cc, count, balance.account) - if balance.Value != initialValue && balance.account != ub { - accountingStorage.SetAccount(balance.account) - } if cc.IsPaid() { goto CONNECT_FEE } @@ -245,7 +236,7 @@ func (ub *Account) debitCreditBalance(cc *CallCost, count bool) (err error) { } for _, increment := range ts.Increments { cost := increment.Cost - ub.GetDefaultMoneyBalance(cc.Direction).Value -= cost + ub.GetDefaultMoneyBalance(cc.Direction).SubstractAmount(cost) if count { ub.countUnits(&Action{BalanceType: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: cost, DestinationId: cc.Destination}}) } @@ -259,8 +250,7 @@ CONNECT_FEE: connectFeePaid := false for _, b := range usefulMoneyBalances { if b.Value >= connectFee { - b.Value -= connectFee - b.Value = utils.Round(b.Value, roundingDecimals, utils.ROUNDING_MIDDLE) + b.SubstractAmount(connectFee) // the conect fee is not refundable! if count { ub.countUnits(&Action{BalanceType: CREDIT, Direction: cc.Direction, Balance: &Balance{Value: connectFee, DestinationId: cc.Destination}}) @@ -279,6 +269,9 @@ CONNECT_FEE: } } } + // save darty shared balances + usefulMoneyBalances.SaveDirtyBalances(ub) + usefulMinuteBalances.SaveDirtyBalances(ub) return } diff --git a/engine/balances.go b/engine/balances.go index 28944600b..78bbf9e26 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -38,6 +38,7 @@ type Balance struct { SharedGroup string precision int account *Account // used to store ub reference for shared balances + dirty bool } func (b *Balance) Equal(o *Balance) bool { @@ -136,6 +137,12 @@ func (b *Balance) GetCost(cd *CallDescriptor) (*CallCost, error) { return cc, nil } +func (b *Balance) SubstractAmount(amount float64) { + b.Value -= amount + b.Value = utils.Round(b.Value, roundingDecimals, utils.ROUNDING_MIDDLE) + b.dirty = true +} + func (b *Balance) DebitMinutes(cc *CallCost, count bool, ub *Account, moneyBalances BalanceChain) error { for tsIndex := 0; tsIndex < len(cc.Timespans); tsIndex++ { if b.Value <= 0 { @@ -195,8 +202,7 @@ func (b *Balance) DebitMinutes(cc *CallCost, count bool, ub *Account, moneyBalan cc.Timespans.RemoveOverlapedFromIndex(tsIndex) inc = newTs.Increments[0] } - b.Value -= amount - b.Value = utils.Round(b.Value, roundingDecimals, utils.ROUNDING_MIDDLE) + b.SubstractAmount(amount) inc.BalanceInfo.MinuteBalanceUuid = b.Uuid inc.BalanceInfo.AccountId = ub.Id inc.MinuteInfo = &MinuteInfo{cc.Destination, amount} @@ -236,9 +242,7 @@ func (b *Balance) DebitMinutes(cc *CallCost, count bool, ub *Account, moneyBalan } } if moneyBal != nil && b.Value >= seconds { - b.Value -= seconds - b.Value = utils.Round(b.Value, roundingDecimals, utils.ROUNDING_MIDDLE) - + b.SubstractAmount(seconds) nInc.BalanceInfo.MinuteBalanceUuid = b.Uuid nInc.BalanceInfo.AccountId = ub.Id nInc.MinuteInfo = &MinuteInfo{newCC.Destination, seconds} @@ -310,8 +314,7 @@ func (b *Balance) DebitMoney(cc *CallCost, count bool, ub *Account) error { if b.RateSubject == "" { amount := increment.Cost if b.Value >= amount { - b.Value -= amount - b.Value = utils.Round(b.Value, roundingDecimals, utils.ROUNDING_MIDDLE) + b.SubstractAmount(amount) increment.BalanceInfo.MoneyBalanceUuid = b.Uuid increment.BalanceInfo.AccountId = ub.Id increment.paid = true @@ -340,8 +343,7 @@ func (b *Balance) DebitMoney(cc *CallCost, count bool, ub *Account) error { // debit money amount := nInc.Cost if b.Value >= amount { - b.Value -= amount - b.Value = utils.Round(b.Value, roundingDecimals, utils.ROUNDING_MIDDLE) + b.SubstractAmount(amount) nInc.BalanceInfo.MoneyBalanceUuid = b.Uuid nInc.BalanceInfo.AccountId = ub.Id nInc.paid = true @@ -418,8 +420,7 @@ func (bc BalanceChain) Debit(amount float64) float64 { continue } if b.Value >= amount || i == len(bc)-1 { // if last one go negative - b.Value -= amount - b.Value = utils.Round(b.Value, roundingDecimals, utils.ROUNDING_MIDDLE) + b.SubstractAmount(amount) break } b.Value = 0 @@ -467,3 +468,11 @@ func (bc BalanceChain) HasBalance(balance *Balance) bool { } return false } + +func (bc BalanceChain) SaveDirtyBalances(acc *Account) { + for _, b := range bc { + if b.account != nil && b.account != acc && b.dirty { + accountingStorage.SetAccount(b.account) + } + } +}