mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Added FieldAsInterface for EventCost
This commit is contained in:
committed by
Dan Christian Bogos
parent
2f8b7dc53e
commit
ff5f5f2d21
@@ -31,10 +31,8 @@ import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
/*
|
||||
Structure containing information about user's credit (minutes, cents, sms...).'
|
||||
This can represent a user or a shared group.
|
||||
*/
|
||||
// Account structure containing information about user's credit (minutes, cents, sms...).'
|
||||
// This can represent a user or a shared group.
|
||||
type Account struct {
|
||||
ID string
|
||||
BalanceMap map[string]Balances
|
||||
@@ -47,17 +45,17 @@ type Account struct {
|
||||
}
|
||||
|
||||
// User's available minutes for the specified destination
|
||||
func (ub *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duration, credit float64, balances Balances) {
|
||||
creditBalances := ub.getBalancesForPrefix(cd.Destination, cd.Category, utils.MONETARY, "", cd.TimeStart)
|
||||
func (acc *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duration, credit float64, balances Balances) {
|
||||
creditBalances := acc.getBalancesForPrefix(cd.Destination, cd.Category, utils.MONETARY, "", cd.TimeStart)
|
||||
|
||||
unitBalances := ub.getBalancesForPrefix(cd.Destination, cd.Category, cd.ToR, "", cd.TimeStart)
|
||||
unitBalances := acc.getBalancesForPrefix(cd.Destination, cd.Category, cd.ToR, "", cd.TimeStart)
|
||||
// gather all balances from shared groups
|
||||
var extendedCreditBalances Balances
|
||||
for _, cb := range creditBalances {
|
||||
if len(cb.SharedGroups) > 0 {
|
||||
for sg := range cb.SharedGroups {
|
||||
if sharedGroup, _ := dm.GetSharedGroup(sg, false, utils.NonTransactional); sharedGroup != nil {
|
||||
sgb := sharedGroup.GetBalances(cd.Destination, cd.Category, utils.MONETARY, ub, cd.TimeStart)
|
||||
sgb := sharedGroup.GetBalances(cd.Destination, cd.Category, utils.MONETARY, acc, cd.TimeStart)
|
||||
sgb = sharedGroup.SortBalancesByStrategy(cb, sgb)
|
||||
extendedCreditBalances = append(extendedCreditBalances, sgb...)
|
||||
}
|
||||
@@ -71,7 +69,7 @@ func (ub *Account) getCreditForPrefix(cd *CallDescriptor) (duration time.Duratio
|
||||
if len(mb.SharedGroups) > 0 {
|
||||
for sg := range mb.SharedGroups {
|
||||
if sharedGroup, _ := dm.GetSharedGroup(sg, false, utils.NonTransactional); sharedGroup != nil {
|
||||
sgb := sharedGroup.GetBalances(cd.Destination, cd.Category, cd.ToR, ub, cd.TimeStart)
|
||||
sgb := sharedGroup.GetBalances(cd.Destination, cd.Category, cd.ToR, acc, cd.TimeStart)
|
||||
sgb = sharedGroup.SortBalancesByStrategy(mb, sgb)
|
||||
extendedMinuteBalances = append(extendedMinuteBalances, sgb...)
|
||||
}
|
||||
@@ -186,7 +184,7 @@ func (acc *Account) setBalanceAction(a *Action) error {
|
||||
|
||||
// Debits some amount of user's specified balance adding the balance if it does not exists.
|
||||
// Returns the remaining credit in user's balance.
|
||||
func (ub *Account) debitBalanceAction(a *Action, reset, resetIfNegative bool) error {
|
||||
func (acc *Account) debitBalanceAction(a *Action, reset, resetIfNegative bool) error {
|
||||
if a == nil {
|
||||
return errors.New("nil action")
|
||||
}
|
||||
@@ -195,16 +193,16 @@ func (ub *Account) debitBalanceAction(a *Action, reset, resetIfNegative bool) er
|
||||
if bClone == nil {
|
||||
return errors.New("nil balance in action")
|
||||
}
|
||||
if ub.BalanceMap == nil {
|
||||
ub.BalanceMap = make(map[string]Balances)
|
||||
if acc.BalanceMap == nil {
|
||||
acc.BalanceMap = make(map[string]Balances)
|
||||
}
|
||||
found := false
|
||||
balanceType := a.Balance.GetType()
|
||||
for _, b := range ub.BalanceMap[balanceType] {
|
||||
for _, b := range acc.BalanceMap[balanceType] {
|
||||
if b.IsExpiredAt(time.Now()) {
|
||||
continue // just to be safe (cleaned expired balances above)
|
||||
}
|
||||
b.account = ub
|
||||
b.account = acc
|
||||
if b.MatchFilter(a.Balance, false, false) {
|
||||
if reset || (resetIfNegative && b.Value < 0) {
|
||||
b.SetValue(0)
|
||||
@@ -242,23 +240,23 @@ func (ub *Account) debitBalanceAction(a *Action, reset, resetIfNegative bool) er
|
||||
utils.Logger.Warning(fmt.Sprintf("Could load value factor from actions: extra parametrs: %s", a.ExtraParameters))
|
||||
}
|
||||
}
|
||||
ub.BalanceMap[balanceType] = append(ub.BalanceMap[balanceType], bClone)
|
||||
acc.BalanceMap[balanceType] = append(acc.BalanceMap[balanceType], bClone)
|
||||
_, err := guardian.Guardian.Guard(func() (interface{}, error) {
|
||||
sgs := make([]string, len(bClone.SharedGroups))
|
||||
i := 0
|
||||
for sgId := range bClone.SharedGroups {
|
||||
for sgID := range bClone.SharedGroups {
|
||||
// add shared group member
|
||||
sg, err := dm.GetSharedGroup(sgId, false, utils.NonTransactional)
|
||||
sg, err := dm.GetSharedGroup(sgID, false, utils.NonTransactional)
|
||||
if err != nil || sg == nil {
|
||||
//than is problem
|
||||
utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgId))
|
||||
utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID))
|
||||
} else {
|
||||
if _, found := sg.MemberIds[ub.ID]; !found {
|
||||
if _, found := sg.MemberIds[acc.ID]; !found {
|
||||
// add member and save
|
||||
if sg.MemberIds == nil {
|
||||
sg.MemberIds = make(utils.StringMap)
|
||||
}
|
||||
sg.MemberIds[ub.ID] = true
|
||||
sg.MemberIds[acc.ID] = true
|
||||
dm.SetSharedGroup(sg, utils.NonTransactional)
|
||||
}
|
||||
}
|
||||
@@ -271,17 +269,17 @@ func (ub *Account) debitBalanceAction(a *Action, reset, resetIfNegative bool) er
|
||||
return err
|
||||
}
|
||||
}
|
||||
ub.InitCounters()
|
||||
ub.ExecuteActionTriggers(nil)
|
||||
acc.InitCounters()
|
||||
acc.ExecuteActionTriggers(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ub *Account) getBalancesForPrefix(prefix, category, tor,
|
||||
func (acc *Account) getBalancesForPrefix(prefix, category, tor,
|
||||
sharedGroup string, aTime time.Time) Balances {
|
||||
var balances Balances
|
||||
balances = append(balances, ub.BalanceMap[tor]...)
|
||||
balances = append(balances, acc.BalanceMap[tor]...)
|
||||
if tor != utils.MONETARY && tor != utils.GENERIC {
|
||||
balances = append(balances, ub.BalanceMap[utils.GENERIC]...)
|
||||
balances = append(balances, acc.BalanceMap[utils.GENERIC]...)
|
||||
}
|
||||
|
||||
var usefulBalances Balances
|
||||
@@ -298,15 +296,15 @@ func (ub *Account) getBalancesForPrefix(prefix, category, tor,
|
||||
if !b.MatchCategory(category) {
|
||||
continue
|
||||
}
|
||||
b.account = ub
|
||||
b.account = acc
|
||||
|
||||
if len(b.DestinationIDs) > 0 && b.DestinationIDs[utils.ANY] == false {
|
||||
for _, p := range utils.SplitPrefix(prefix, MIN_PREFIX_MATCH) {
|
||||
if destIDs, err := dm.GetReverseDestination(p, false, utils.NonTransactional); err == nil {
|
||||
foundResult := false
|
||||
allInclude := true // whether it is excluded or included
|
||||
for _, dId := range destIDs {
|
||||
inclDest, found := b.DestinationIDs[dId]
|
||||
for _, dID := range destIDs {
|
||||
inclDest, found := b.DestinationIDs[dID]
|
||||
if found {
|
||||
foundResult = true
|
||||
allInclude = allInclude && inclDest
|
||||
@@ -348,18 +346,18 @@ func (ub *Account) getBalancesForPrefix(prefix, category, tor,
|
||||
}
|
||||
|
||||
// like getBalancesForPrefix but expanding shared balances
|
||||
func (account *Account) getAlldBalancesForPrefix(destination, category,
|
||||
func (acc *Account) getAlldBalancesForPrefix(destination, category,
|
||||
balanceType string, aTime time.Time) (bc Balances) {
|
||||
balances := account.getBalancesForPrefix(destination, category, balanceType, "", aTime)
|
||||
balances := acc.getBalancesForPrefix(destination, category, balanceType, "", aTime)
|
||||
for _, b := range balances {
|
||||
if len(b.SharedGroups) > 0 {
|
||||
for sgId := range b.SharedGroups {
|
||||
sharedGroup, err := dm.GetSharedGroup(sgId, false, utils.NonTransactional)
|
||||
for sgID := range b.SharedGroups {
|
||||
sharedGroup, err := dm.GetSharedGroup(sgID, false, utils.NonTransactional)
|
||||
if err != nil || sharedGroup == nil {
|
||||
utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgId))
|
||||
utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID))
|
||||
continue
|
||||
}
|
||||
sharedBalances := sharedGroup.GetBalances(destination, category, balanceType, account, aTime)
|
||||
sharedBalances := sharedGroup.GetBalances(destination, category, balanceType, acc, aTime)
|
||||
sharedBalances = sharedGroup.SortBalancesByStrategy(b, sharedBalances)
|
||||
bc = append(bc, sharedBalances...)
|
||||
}
|
||||
@@ -370,9 +368,9 @@ func (account *Account) getAlldBalancesForPrefix(destination, category,
|
||||
return
|
||||
}
|
||||
|
||||
func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun bool, goNegative bool) (cc *CallCost, err error) {
|
||||
usefulUnitBalances := ub.getAlldBalancesForPrefix(cd.Destination, cd.Category, cd.ToR, cd.TimeStart)
|
||||
usefulMoneyBalances := ub.getAlldBalancesForPrefix(cd.Destination, cd.Category, utils.MONETARY, cd.TimeStart)
|
||||
func (acc *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun bool, goNegative bool) (cc *CallCost, err error) {
|
||||
usefulUnitBalances := acc.getAlldBalancesForPrefix(cd.Destination, cd.Category, cd.ToR, cd.TimeStart)
|
||||
usefulMoneyBalances := acc.getAlldBalancesForPrefix(cd.Destination, cd.Category, utils.MONETARY, cd.TimeStart)
|
||||
var leftCC *CallCost
|
||||
cc = cd.CreateCallCost()
|
||||
var hadBalanceSubj bool
|
||||
@@ -478,7 +476,7 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo
|
||||
if inc.BalanceInfo == nil {
|
||||
inc.BalanceInfo = &DebitInfo{}
|
||||
}
|
||||
inc.BalanceInfo.AccountID = ub.ID
|
||||
inc.BalanceInfo.AccountID = acc.ID
|
||||
}
|
||||
}
|
||||
cc.Timespans = append(cc.Timespans, leftCC.Timespans...)
|
||||
@@ -493,12 +491,12 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo
|
||||
|
||||
if initialLength == 0 {
|
||||
// this is the first add, debit the connect fee
|
||||
ok, debitedConnectFeeBalance = ub.DebitConnectionFee(cc, usefulMoneyBalances, count, true)
|
||||
ok, debitedConnectFeeBalance = acc.DebitConnectionFee(cc, usefulMoneyBalances, count, true)
|
||||
}
|
||||
//log.Printf("Left CC: %+v ", leftCC)
|
||||
// get the default money balanance
|
||||
// and go negative on it with the amount still unpaid
|
||||
if len(leftCC.Timespans) > 0 && leftCC.Cost > 0 && !ub.AllowNegative && !dryRun {
|
||||
if len(leftCC.Timespans) > 0 && leftCC.Cost > 0 && !acc.AllowNegative && !dryRun {
|
||||
utils.Logger.Warning(fmt.Sprintf("<Rater> Going negative on account %s with AllowNegative: false", cd.GetAccountKey()))
|
||||
}
|
||||
leftCC.Timespans.Decompress()
|
||||
@@ -518,7 +516,7 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo
|
||||
ID: debitedConnectFeeBalance.ID,
|
||||
Value: debitedConnectFeeBalance.Value,
|
||||
},
|
||||
AccountID: ub.ID,
|
||||
AccountID: acc.ID,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -534,11 +532,11 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo
|
||||
}
|
||||
|
||||
cost := increment.Cost
|
||||
defaultBalance := ub.GetDefaultMoneyBalance()
|
||||
defaultBalance := acc.GetDefaultMoneyBalance()
|
||||
defaultBalance.SubstractValue(cost)
|
||||
//send default balance to thresholdS to be processed
|
||||
if len(config.CgrConfig().RalsCfg().ThresholdSConns) != 0 {
|
||||
acntTnt := utils.NewTenantID(ub.ID)
|
||||
acntTnt := utils.NewTenantID(acc.ID)
|
||||
thEv := &ArgsProcessEvent{
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: acntTnt.Tenant,
|
||||
@@ -564,10 +562,10 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo
|
||||
ID: defaultBalance.ID,
|
||||
Value: defaultBalance.Value,
|
||||
}
|
||||
increment.BalanceInfo.AccountID = ub.ID
|
||||
increment.BalanceInfo.AccountID = acc.ID
|
||||
increment.paid = true
|
||||
if count {
|
||||
ub.countUnits(
|
||||
acc.countUnits(
|
||||
cost,
|
||||
utils.MONETARY,
|
||||
leftCC,
|
||||
@@ -583,15 +581,16 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo
|
||||
COMMIT:
|
||||
if !dryRun {
|
||||
// save darty shared balances
|
||||
usefulMoneyBalances.SaveDirtyBalances(ub)
|
||||
usefulUnitBalances.SaveDirtyBalances(ub)
|
||||
usefulMoneyBalances.SaveDirtyBalances(acc)
|
||||
usefulUnitBalances.SaveDirtyBalances(acc)
|
||||
}
|
||||
//log.Printf("Final CC: %+v", cc)
|
||||
return
|
||||
}
|
||||
|
||||
func (ub *Account) GetDefaultMoneyBalance() *Balance {
|
||||
for _, balance := range ub.BalanceMap[utils.MONETARY] {
|
||||
// GetDefaultMoneyBalance returns the defaultmoney balance
|
||||
func (acc *Account) GetDefaultMoneyBalance() *Balance {
|
||||
for _, balance := range acc.BalanceMap[utils.MONETARY] {
|
||||
if balance.IsDefault() {
|
||||
return balance
|
||||
}
|
||||
@@ -601,14 +600,14 @@ func (ub *Account) GetDefaultMoneyBalance() *Balance {
|
||||
Uuid: utils.GenUUID(),
|
||||
ID: utils.MetaDefault,
|
||||
} // minimum weight
|
||||
if ub.BalanceMap == nil {
|
||||
ub.BalanceMap = make(map[string]Balances)
|
||||
if acc.BalanceMap == nil {
|
||||
acc.BalanceMap = make(map[string]Balances)
|
||||
}
|
||||
ub.BalanceMap[utils.MONETARY] = append(ub.BalanceMap[utils.MONETARY], defaultBalance)
|
||||
acc.BalanceMap[utils.MONETARY] = append(acc.BalanceMap[utils.MONETARY], defaultBalance)
|
||||
return defaultBalance
|
||||
}
|
||||
|
||||
// Scans the action triggers and execute the actions for which trigger is met
|
||||
// ExecuteActionTriggers scans the action triggers and execute the actions for which trigger is met
|
||||
func (acc *Account) ExecuteActionTriggers(a *Action) {
|
||||
if acc.executingTriggers {
|
||||
return
|
||||
@@ -685,7 +684,7 @@ func (acc *Account) ExecuteActionTriggers(a *Action) {
|
||||
acc.CleanExpiredStuff()
|
||||
}
|
||||
|
||||
// Mark all action trigers as ready for execution
|
||||
// ResetActionTriggers marks all action trigers as ready for execution
|
||||
// If the action is not nil it acts like a filter
|
||||
func (acc *Account) ResetActionTriggers(a *Action) {
|
||||
for _, at := range acc.ActionTriggers {
|
||||
@@ -697,7 +696,7 @@ func (acc *Account) ResetActionTriggers(a *Action) {
|
||||
acc.ExecuteActionTriggers(a)
|
||||
}
|
||||
|
||||
// Sets/Unsets recurrent flag for action triggers
|
||||
// SetRecurrent sets/unsets recurrent flag for action triggers
|
||||
func (acc *Account) SetRecurrent(a *Action, recurrent bool) {
|
||||
for _, at := range acc.ActionTriggers {
|
||||
if !at.Match(a) {
|
||||
@@ -713,7 +712,7 @@ func (acc *Account) countUnits(amount float64, kind string, cc *CallCost, b *Bal
|
||||
acc.ExecuteActionTriggers(nil)
|
||||
}
|
||||
|
||||
// Create counters for all triggered actions
|
||||
// InitCounters creates counters for all triggered actions
|
||||
func (acc *Account) InitCounters() {
|
||||
oldUcs := acc.UnitCounters
|
||||
acc.UnitCounters = make(UnitCounters)
|
||||
@@ -766,6 +765,7 @@ func (acc *Account) InitCounters() {
|
||||
}
|
||||
}
|
||||
|
||||
// CleanExpiredStuff removed expired balances and actiontriggers
|
||||
func (acc *Account) CleanExpiredStuff() {
|
||||
if config.CgrConfig().RalsCfg().RemoveExpired {
|
||||
for key, bm := range acc.BalanceMap {
|
||||
@@ -797,7 +797,7 @@ func (acc *Account) allBalancesExpired() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// returns the shared groups that this user balance belnongs to
|
||||
// GetSharedGroups returns the shared groups that this user balance belnongs to
|
||||
func (acc *Account) GetSharedGroups() (groups []string) {
|
||||
for _, balanceChain := range acc.BalanceMap {
|
||||
for _, b := range balanceChain {
|
||||
@@ -809,10 +809,11 @@ func (acc *Account) GetSharedGroups() (groups []string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (account *Account) GetUniqueSharedGroupMembers(cd *CallDescriptor) (utils.StringMap, error) { // ToDo: make sure we return accountIDs
|
||||
// GetUniqueSharedGroupMembers returns the acounts from the group
|
||||
func (acc *Account) GetUniqueSharedGroupMembers(cd *CallDescriptor) (utils.StringMap, error) { // ToDo: make sure we return accountIDs
|
||||
var balances []*Balance
|
||||
balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, utils.MONETARY, "", cd.TimeStart)...)
|
||||
balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, cd.ToR, "", cd.TimeStart)...)
|
||||
balances = append(balances, acc.getBalancesForPrefix(cd.Destination, cd.Category, utils.MONETARY, "", cd.TimeStart)...)
|
||||
balances = append(balances, acc.getBalancesForPrefix(cd.Destination, cd.Category, cd.ToR, "", cd.TimeStart)...)
|
||||
// gather all shared group ids
|
||||
var sharedGroupIds []string
|
||||
for _, b := range balances {
|
||||
@@ -834,6 +835,7 @@ func (account *Account) GetUniqueSharedGroupMembers(cd *CallDescriptor) (utils.S
|
||||
return memberIds, nil
|
||||
}
|
||||
|
||||
// Clone creates a copy of the account
|
||||
func (acc *Account) Clone() *Account {
|
||||
newAcc := &Account{
|
||||
ID: acc.ID,
|
||||
@@ -856,6 +858,7 @@ func (acc *Account) Clone() *Account {
|
||||
return newAcc
|
||||
}
|
||||
|
||||
// DebitConnectionFee debits the connection fee
|
||||
func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balances, count bool, block bool) (bool, Balance) {
|
||||
var debitedBalance Balance
|
||||
|
||||
@@ -919,6 +922,7 @@ func (acc *Account) matchActionFilter(condition string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// GetID returns the account ID
|
||||
func (acc *Account) GetID() string {
|
||||
split := strings.Split(acc.ID, utils.CONCATENATED_KEY_SEP)
|
||||
if len(split) != 2 {
|
||||
@@ -927,7 +931,7 @@ func (acc *Account) GetID() string {
|
||||
return split[1]
|
||||
}
|
||||
|
||||
// used in some api for transition
|
||||
// AsOldStructure used in some api for transition
|
||||
func (acc *Account) AsOldStructure() interface{} {
|
||||
type Balance struct {
|
||||
Uuid string //system wide unique
|
||||
@@ -1069,6 +1073,7 @@ func (acc *Account) AsOldStructure() interface{} {
|
||||
return result
|
||||
}
|
||||
|
||||
// AsAccountSummary converts the account into AccountSummary
|
||||
func (acc *Account) AsAccountSummary() *AccountSummary {
|
||||
idSplt := strings.Split(acc.ID, utils.CONCATENATED_KEY_SEP)
|
||||
ad := &AccountSummary{AllowNegative: acc.AllowNegative, Disabled: acc.Disabled}
|
||||
@@ -1091,8 +1096,9 @@ func (acc *Account) AsAccountSummary() *AccountSummary {
|
||||
return ad
|
||||
}
|
||||
|
||||
func (acnt *Account) Publish() {
|
||||
acntTnt := utils.NewTenantID(acnt.ID)
|
||||
// Publish sends the account to stats and threshold
|
||||
func (acc *Account) Publish() {
|
||||
acntTnt := utils.NewTenantID(acc.ID)
|
||||
cgrEv := &utils.CGREvent{
|
||||
Tenant: acntTnt.Tenant,
|
||||
ID: utils.GenUUID(),
|
||||
@@ -1100,8 +1106,8 @@ func (acnt *Account) Publish() {
|
||||
utils.EventType: utils.AccountUpdate,
|
||||
utils.EventSource: utils.AccountService,
|
||||
utils.Account: acntTnt.ID,
|
||||
utils.AllowNegative: acnt.AllowNegative,
|
||||
utils.Disabled: acnt.Disabled}}
|
||||
utils.AllowNegative: acc.AllowNegative,
|
||||
utils.Disabled: acc.Disabled}}
|
||||
if len(config.CgrConfig().RalsCfg().StatSConns) != 0 {
|
||||
go func() {
|
||||
var reply []string
|
||||
@@ -1128,17 +1134,18 @@ func (acnt *Account) Publish() {
|
||||
}
|
||||
}
|
||||
|
||||
func (acnt *Account) AsNavigableMap(_ []*config.FCTemplate) (*config.NavigableMap, error) {
|
||||
// AsNavigableMap converts the Account to NavigableMap
|
||||
func (acc *Account) AsNavigableMap(_ []*config.FCTemplate) (*config.NavigableMap, error) {
|
||||
mpIface := map[string]interface{}{
|
||||
"ID": acnt.ID,
|
||||
"ID": acc.ID,
|
||||
//"UnitCounters": acnt.UnitCounters,
|
||||
"ActionTriggers": acnt.ActionTriggers,
|
||||
"AllowNegative": acnt.AllowNegative,
|
||||
"Disabled": acnt.Disabled,
|
||||
"ActionTriggers": acc.ActionTriggers,
|
||||
"AllowNegative": acc.AllowNegative,
|
||||
"Disabled": acc.Disabled,
|
||||
}
|
||||
|
||||
balanceMap := make(map[string]interface{}, len(acnt.BalanceMap))
|
||||
for key, balances := range acnt.BalanceMap {
|
||||
balanceMap := make(map[string]interface{}, len(acc.BalanceMap))
|
||||
for key, balances := range acc.BalanceMap {
|
||||
balSls := make([]*config.NavigableMap, len(balances))
|
||||
for i, balance := range balances {
|
||||
balSls[i], _ = balance.AsNavigableMap(nil)
|
||||
@@ -1151,6 +1158,7 @@ func (acnt *Account) AsNavigableMap(_ []*config.FCTemplate) (*config.NavigableMa
|
||||
|
||||
}
|
||||
|
||||
// NewAccountSummaryFromJSON creates a new AcccountSummary from a json string
|
||||
func NewAccountSummaryFromJSON(jsn string) (acntSummary *AccountSummary, err error) {
|
||||
if !utils.SliceHasMember([]string{"", "null"}, jsn) { // Unmarshal only when content
|
||||
json.Unmarshal([]byte(jsn), &acntSummary)
|
||||
@@ -1167,6 +1175,7 @@ type AccountSummary struct {
|
||||
Disabled bool
|
||||
}
|
||||
|
||||
// Clone creates a copy of the structure
|
||||
func (as *AccountSummary) Clone() (cln *AccountSummary) {
|
||||
cln = new(AccountSummary)
|
||||
cln.Tenant = as.Tenant
|
||||
@@ -1184,11 +1193,58 @@ func (as *AccountSummary) Clone() (cln *AccountSummary) {
|
||||
}
|
||||
|
||||
// GetBalanceWithID returns a Balance given balance type and balance ID
|
||||
func (acnt *Account) GetBalanceWithID(blcType, blcID string) (blc *Balance) {
|
||||
for _, blc = range acnt.BalanceMap[blcType] {
|
||||
func (acc *Account) GetBalanceWithID(blcType, blcID string) (blc *Balance) {
|
||||
for _, blc = range acc.BalanceMap[blcType] {
|
||||
if blc.ID == blcID {
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (as *AccountSummary) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
opath, indx := utils.GetPathIndex(fldPath[0])
|
||||
if opath == utils.BalanceSummaries && indx != nil {
|
||||
if len(as.BalanceSummaries) < *indx {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
bl := as.BalanceSummaries[*indx]
|
||||
if len(fldPath) == 1 {
|
||||
return bl, nil
|
||||
}
|
||||
return bl.FieldAsInterface(fldPath[1:])
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
case utils.Tenant:
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return as.Tenant, nil
|
||||
case utils.ID:
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return as.ID, nil
|
||||
case utils.BalanceSummaries:
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return as.BalanceSummaries, nil
|
||||
case utils.AllowNegative:
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return as.AllowNegative, nil
|
||||
case utils.Disabled:
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return as.Disabled, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -892,7 +892,7 @@ func (f ValueFactor) GetValue(tor string) float64 {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
// BalanceDigest represents compressed information about a balance
|
||||
// BalanceSummary represents compressed information about a balance
|
||||
type BalanceSummary struct {
|
||||
UUID string // Balance UUID
|
||||
ID string // Balance ID if not defined
|
||||
@@ -901,9 +901,10 @@ type BalanceSummary struct {
|
||||
Disabled bool
|
||||
}
|
||||
|
||||
// BalanceSummaries is a list of BalanceSummaries
|
||||
type BalanceSummaries []*BalanceSummary
|
||||
|
||||
// GetBalanceSummary returns a BalanceSummary based on an UUID
|
||||
// BalanceSummaryWithUUD returns a BalanceSummary based on an UUID
|
||||
func (bs BalanceSummaries) BalanceSummaryWithUUD(bsUUID string) (b *BalanceSummary) {
|
||||
for _, blc := range bs {
|
||||
if blc.UUID == bsUUID {
|
||||
@@ -913,3 +914,24 @@ func (bs BalanceSummaries) BalanceSummaryWithUUD(bsUUID string) (b *BalanceSumma
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (bl *BalanceSummary) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
case utils.UUID:
|
||||
return bl.UUID, nil
|
||||
case utils.ID:
|
||||
return bl.ID, nil
|
||||
case utils.Type:
|
||||
return bl.Type, nil
|
||||
case utils.Value:
|
||||
return bl.Value, nil
|
||||
case utils.Disabled:
|
||||
return bl.Disabled, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ package engine
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -840,48 +840,28 @@ func (ec *EventCost) Trim(atUsage time.Duration) (srplusEC *EventCost, err error
|
||||
return
|
||||
}
|
||||
|
||||
// getIndex returns the path and index if index present
|
||||
// path[index]=>path,index
|
||||
// path=>path,nil
|
||||
func getIndex(spath string) (opath string, idx *int) {
|
||||
idxStart := strings.Index(spath, utils.IdxStart)
|
||||
if idxStart == -1 || !strings.HasSuffix(spath, utils.IdxEnd) {
|
||||
return spath, nil
|
||||
}
|
||||
slctr := spath[idxStart+1 : len(spath)-1]
|
||||
opath = spath[:idxStart]
|
||||
if strings.HasPrefix(slctr, utils.DynamicDataPrefix) {
|
||||
return
|
||||
}
|
||||
idxVal, err := strconv.Atoi(slctr)
|
||||
if err != nil {
|
||||
return spath, nil
|
||||
}
|
||||
return opath, &idxVal
|
||||
}
|
||||
|
||||
// FieldAsInterface func to implement DataProvider
|
||||
func (ec *EventCost) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default: //"Charges [1]"
|
||||
opath, indx := getIndex(fldPath[0])
|
||||
default: // "Charges[1]"
|
||||
opath, indx := utils.GetPathIndex(fldPath[0])
|
||||
if opath != utils.Charges {
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", opath)
|
||||
}
|
||||
if indx != nil {
|
||||
chr := ec.Charges[*indx]
|
||||
if len(fldPath) == 1 {
|
||||
return chr, nil
|
||||
}
|
||||
if fldPath[1] == utils.Rating {
|
||||
return ec.getRatingForPath(fldPath[2:], ec.Rating[chr.RatingID])
|
||||
if len(ec.Charges) < *indx {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return ec.getChargesForPath(fldPath[1:], ec.Charges[*indx])
|
||||
}
|
||||
case utils.Charges: // not needed?
|
||||
// return ec.Charges.FieldAsInterface(fldPath[1:])
|
||||
case utils.Charges:
|
||||
if len(fldPath) != 1 { // slice has no members
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return ec.Charges, nil
|
||||
case utils.CGRID:
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
@@ -908,21 +888,57 @@ func (ec *EventCost) FieldAsInterface(fldPath []string) (val interface{}, err er
|
||||
}
|
||||
return ec.Cost, nil
|
||||
case utils.AccountSummary:
|
||||
// return ec.AccountSummary.FieldAsInterface(fldPath[1:])
|
||||
case utils.Timings: // not needed?
|
||||
// return ec.Timings.FieldAsInterface(fldPath[1:])
|
||||
case utils.Rates: // not needed?
|
||||
// return ec.Rates.FieldAsInterface(fldPath[1:])
|
||||
case utils.RatingFilters: // not needed?
|
||||
// return ec.RatingFilters.FieldAsInterface(fldPath[1:])
|
||||
case utils.Accounting: // not needed?
|
||||
// return ec.Accounting.FieldAsInterface(fldPath[1:])
|
||||
case utils.Rating: // not needed?
|
||||
// return ec.Rating.FieldAsInterface(fldPath[1:])
|
||||
return ec.AccountSummary.FieldAsInterface(fldPath[1:])
|
||||
case utils.Timings:
|
||||
return ec.Timings.FieldAsInterface(fldPath[1:])
|
||||
case utils.Rates:
|
||||
return ec.Rates.FieldAsInterface(fldPath[1:])
|
||||
case utils.RatingFilters:
|
||||
return ec.RatingFilters.FieldAsInterface(fldPath[1:])
|
||||
case utils.Accounting:
|
||||
return ec.Accounting.FieldAsInterface(fldPath[1:])
|
||||
case utils.Rating:
|
||||
return ec.Rating.FieldAsInterface(fldPath[1:])
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
}
|
||||
|
||||
func (ec *EventCost) getChargesForPath(fldPath []string, chr *ChargingInterval) (val interface{}, err error) {
|
||||
if chr == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if len(fldPath) == 0 {
|
||||
return chr, nil
|
||||
}
|
||||
if fldPath[0] == utils.CompressFactor {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return chr.CompressFactor, nil
|
||||
}
|
||||
if fldPath[0] == utils.Rating {
|
||||
return ec.getRatingForPath(fldPath[1:], ec.Rating[chr.RatingID])
|
||||
}
|
||||
opath, indx := utils.GetPathIndex(fldPath[0])
|
||||
if opath != utils.Increments {
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", opath)
|
||||
}
|
||||
if indx == nil {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return chr.Increments, nil
|
||||
}
|
||||
incr := chr.Increments[*indx]
|
||||
if len(fldPath) == 1 {
|
||||
return incr, nil
|
||||
}
|
||||
if fldPath[1] == utils.Accounting {
|
||||
return ec.getAcountingForPath(fldPath[3:], ec.Accounting[incr.AccountingID])
|
||||
}
|
||||
return incr.FieldAsInterface(fldPath)
|
||||
}
|
||||
|
||||
func (ec *EventCost) getRatingForPath(fldPath []string, rating *RatingUnit) (val interface{}, err error) {
|
||||
if rating == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
@@ -933,7 +949,7 @@ func (ec *EventCost) getRatingForPath(fldPath []string, rating *RatingUnit) (val
|
||||
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
opath, indx := getIndex(fldPath[0])
|
||||
opath, indx := utils.GetPathIndex(fldPath[0])
|
||||
if opath != utils.Rates {
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", opath)
|
||||
}
|
||||
@@ -978,3 +994,49 @@ func (ec *EventCost) getRatingForPath(fldPath []string, rating *RatingUnit) (val
|
||||
}
|
||||
return rating.FieldAsInterface(fldPath)
|
||||
}
|
||||
|
||||
func (ec *EventCost) getAcountingForPath(fldPath []string, bc *BalanceCharge) (val interface{}, err error) {
|
||||
if bc == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if len(fldPath) == 0 {
|
||||
return bc, nil
|
||||
}
|
||||
|
||||
if fldPath[0] == utils.Balance {
|
||||
bl := ec.AccountSummary.BalanceSummaries.BalanceSummaryWithUUD(bc.BalanceUUID)
|
||||
if bl == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if len(fldPath) == 1 {
|
||||
return bl, nil
|
||||
}
|
||||
return bl.FieldAsInterface(fldPath[1:])
|
||||
|
||||
}
|
||||
return bc.FieldAsInterface(fldPath)
|
||||
}
|
||||
|
||||
// String to implement Dataprovider
|
||||
func (ec *EventCost) String() string {
|
||||
return utils.ToJSON(ec)
|
||||
}
|
||||
|
||||
// FieldAsString to implement Dataprovider
|
||||
func (ec *EventCost) FieldAsString(fldPath []string) (string, error) {
|
||||
ival, err := ec.FieldAsInterface(fldPath)
|
||||
if err != nil {
|
||||
return utils.EmptyString, err
|
||||
}
|
||||
return utils.IfaceAsString(ival), nil
|
||||
}
|
||||
|
||||
// AsNavigableMap to implement Dataprovider
|
||||
func (ec *EventCost) AsNavigableMap([]*config.FCTemplate) (*config.NavigableMap, error) {
|
||||
return nil, utils.ErrNotImplemented
|
||||
}
|
||||
|
||||
// RemoteHost to implement Dataprovider
|
||||
func (ec *EventCost) RemoteHost() net.Addr {
|
||||
return utils.LocalAddr()
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ func (cIl *ChargingInterval) Cost() float64 {
|
||||
return *cIl.cost
|
||||
}
|
||||
|
||||
// TotalCost returns the cost of charges
|
||||
func (cIl *ChargingInterval) TotalCost() float64 {
|
||||
return utils.Round((cIl.Cost() * float64(cIl.CompressFactor)),
|
||||
globalRoundingDecimals, utils.ROUNDING_MIDDLE)
|
||||
@@ -131,6 +132,7 @@ type ChargingIncrement struct {
|
||||
CompressFactor int
|
||||
}
|
||||
|
||||
// Equals returns if the structure has the same value
|
||||
func (cIt *ChargingIncrement) Equals(oCIt *ChargingIncrement) bool {
|
||||
return cIt.Usage == oCIt.Usage &&
|
||||
cIt.Cost == oCIt.Cost &&
|
||||
@@ -145,6 +147,7 @@ func (cIt *ChargingIncrement) PartiallyEquals(oCIt *ChargingIncrement) bool {
|
||||
cIt.AccountingID == oCIt.AccountingID
|
||||
}
|
||||
|
||||
// Clone creates a copy of ChargingIncrement
|
||||
func (cIt *ChargingIncrement) Clone() (cln *ChargingIncrement) {
|
||||
cln = new(ChargingIncrement)
|
||||
*cln = *cIt
|
||||
@@ -156,10 +159,30 @@ func (cIt *ChargingIncrement) TotalUsage() time.Duration {
|
||||
return time.Duration(cIt.Usage.Nanoseconds() * int64(cIt.CompressFactor))
|
||||
}
|
||||
|
||||
// TotalCost returns the cost of the increment
|
||||
func (cIt *ChargingIncrement) TotalCost() float64 {
|
||||
return cIt.Cost * float64(cIt.CompressFactor)
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (cIt *ChargingIncrement) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
case utils.Usage:
|
||||
return cIt.Usage, nil
|
||||
case utils.Cost:
|
||||
return cIt.Cost, nil
|
||||
case utils.AccountingID:
|
||||
return cIt.AccountingID, nil
|
||||
case utils.CompressFactor:
|
||||
return cIt.CompressFactor, nil
|
||||
}
|
||||
}
|
||||
|
||||
// BalanceCharge represents one unit charged to a balance
|
||||
type BalanceCharge struct {
|
||||
AccountID string // keep reference for shared balances
|
||||
@@ -169,6 +192,28 @@ type BalanceCharge struct {
|
||||
ExtraChargeID string // used in cases when paying *voice with *monetary
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (bc *BalanceCharge) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
case utils.AccountID:
|
||||
return bc.AccountID, nil
|
||||
case utils.BalanceUUID:
|
||||
return bc.BalanceUUID, nil
|
||||
case utils.RatingID:
|
||||
return bc.RatingID, nil
|
||||
case utils.Units:
|
||||
return bc.Units, nil
|
||||
case utils.ExtraChargeID:
|
||||
return bc.ExtraChargeID, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Equals returns if the structure have the same fields
|
||||
func (bc *BalanceCharge) Equals(oBC *BalanceCharge) bool {
|
||||
bcExtraChargeID := bc.ExtraChargeID
|
||||
if bcExtraChargeID == "" {
|
||||
@@ -185,14 +230,17 @@ func (bc *BalanceCharge) Equals(oBC *BalanceCharge) bool {
|
||||
bcExtraChargeID == oBCExtraChargerID
|
||||
}
|
||||
|
||||
// Clone creates a copy of BalanceCharge
|
||||
func (bc *BalanceCharge) Clone() *BalanceCharge {
|
||||
clnBC := new(BalanceCharge)
|
||||
*clnBC = *bc
|
||||
return clnBC
|
||||
}
|
||||
|
||||
// RatingMatchedFilters a rating filter
|
||||
type RatingMatchedFilters map[string]interface{}
|
||||
|
||||
// Equals returns if the RatingMatchedFilters are equal
|
||||
func (rf RatingMatchedFilters) Equals(oRF RatingMatchedFilters) bool {
|
||||
for k := range rf {
|
||||
if rf[k] != oRF[k] {
|
||||
@@ -202,6 +250,7 @@ func (rf RatingMatchedFilters) Equals(oRF RatingMatchedFilters) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Clone creates a copy of RatingMatchedFilters
|
||||
func (rf RatingMatchedFilters) Clone() (cln map[string]interface{}) {
|
||||
if rf == nil {
|
||||
return nil
|
||||
@@ -213,6 +262,18 @@ func (rf RatingMatchedFilters) Clone() (cln map[string]interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (rf *RatingMatchedFilters) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
ct, has := (*rf)[fldPath[0]]
|
||||
if !has || ct == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return ct, nil
|
||||
}
|
||||
|
||||
// ChargedTiming represents one timing attached to a charge
|
||||
type ChargedTiming struct {
|
||||
Years utils.Years
|
||||
@@ -222,6 +283,7 @@ type ChargedTiming struct {
|
||||
StartTime string
|
||||
}
|
||||
|
||||
// Equals returns if the timings are equal
|
||||
func (ct *ChargedTiming) Equals(oCT *ChargedTiming) bool {
|
||||
return ct.Years.Equals(oCT.Years) &&
|
||||
ct.Months.Equals(oCT.Months) &&
|
||||
@@ -230,12 +292,34 @@ func (ct *ChargedTiming) Equals(oCT *ChargedTiming) bool {
|
||||
ct.StartTime == oCT.StartTime
|
||||
}
|
||||
|
||||
// Clone creates a copy of ChargedTiming
|
||||
func (ct *ChargedTiming) Clone() (cln *ChargedTiming) {
|
||||
cln = new(ChargedTiming)
|
||||
*cln = *ct
|
||||
return
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (ct *ChargedTiming) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
case utils.YearsFieldName:
|
||||
return ct.Years, nil
|
||||
case utils.MonthsFieldName:
|
||||
return ct.Months, nil
|
||||
case utils.MonthDaysFieldName:
|
||||
return ct.MonthDays, nil
|
||||
case utils.WeekDaysFieldName:
|
||||
return ct.WeekDays, nil
|
||||
case utils.StartTime:
|
||||
return ct.StartTime, nil
|
||||
}
|
||||
}
|
||||
|
||||
// RatingUnit represents one unit out of RatingPlan matching for an event
|
||||
type RatingUnit struct {
|
||||
ConnectFee float64
|
||||
@@ -248,6 +332,7 @@ type RatingUnit struct {
|
||||
RatingFiltersID string
|
||||
}
|
||||
|
||||
// Equals returns if RatingUnit is equal to the other
|
||||
func (ru *RatingUnit) Equals(oRU *RatingUnit) bool {
|
||||
return ru.ConnectFee == oRU.ConnectFee &&
|
||||
ru.RoundingMethod == oRU.RoundingMethod &&
|
||||
@@ -259,15 +344,44 @@ func (ru *RatingUnit) Equals(oRU *RatingUnit) bool {
|
||||
ru.RatingFiltersID == oRU.RatingFiltersID
|
||||
}
|
||||
|
||||
// Clone creates a copy of RatingUnit
|
||||
func (ru *RatingUnit) Clone() (cln *RatingUnit) {
|
||||
cln = new(RatingUnit)
|
||||
*cln = *ru
|
||||
return
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (ru *RatingUnit) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
case utils.ConnectFee:
|
||||
return ru.ConnectFee, nil
|
||||
case utils.RoundingMethod:
|
||||
return ru.RoundingMethod, nil
|
||||
case utils.RoundingDecimals:
|
||||
return ru.RoundingDecimals, nil
|
||||
case utils.MaxCost:
|
||||
return ru.MaxCost, nil
|
||||
case utils.MaxCostStrategy:
|
||||
return ru.MaxCostStrategy, nil
|
||||
case utils.TimingID:
|
||||
return ru.TimingID, nil
|
||||
case utils.RatesID:
|
||||
return ru.RatesID, nil
|
||||
case utils.RatingFiltersID:
|
||||
return ru.RatingFiltersID, nil
|
||||
}
|
||||
}
|
||||
|
||||
// RatingFilters the map of rating filters
|
||||
type RatingFilters map[string]RatingMatchedFilters // so we can define search methods
|
||||
|
||||
// GetWithSet attempts to retrieve the UUID of a matching data or create a new one
|
||||
// GetIDWithSet attempts to retrieve the UUID of a matching data or create a new one
|
||||
func (rfs RatingFilters) GetIDWithSet(rmf RatingMatchedFilters) string {
|
||||
if rmf == nil || len(rmf) == 0 {
|
||||
return ""
|
||||
@@ -283,6 +397,7 @@ func (rfs RatingFilters) GetIDWithSet(rmf RatingMatchedFilters) string {
|
||||
return uuid
|
||||
}
|
||||
|
||||
// Clone creates a copy of RatingFilters
|
||||
func (rfs RatingFilters) Clone() (cln RatingFilters) {
|
||||
cln = make(RatingFilters, len(rfs))
|
||||
for k, v := range rfs {
|
||||
@@ -291,6 +406,22 @@ func (rfs RatingFilters) Clone() (cln RatingFilters) {
|
||||
return
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (rfs *RatingFilters) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
ct, has := (*rfs)[fldPath[0]]
|
||||
if !has || ct == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if len(fldPath) == 1 {
|
||||
return ct, nil
|
||||
}
|
||||
return ct.FieldAsInterface(fldPath[1:])
|
||||
}
|
||||
|
||||
// Rating the map of rating units
|
||||
type Rating map[string]*RatingUnit
|
||||
|
||||
// GetIDWithSet attempts to retrieve the UUID of a matching data or create a new one
|
||||
@@ -309,6 +440,7 @@ func (crus Rating) GetIDWithSet(cru *RatingUnit) string {
|
||||
return uuid
|
||||
}
|
||||
|
||||
// Clone creates a copy of Rating
|
||||
func (crus Rating) Clone() (cln Rating) {
|
||||
cln = make(Rating, len(crus))
|
||||
for k, v := range crus {
|
||||
@@ -317,8 +449,50 @@ func (crus Rating) Clone() (cln Rating) {
|
||||
return
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (crus *Rating) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
rt, has := (*crus)[fldPath[0]]
|
||||
if !has || rt == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if len(fldPath) == 1 {
|
||||
return rt, nil
|
||||
}
|
||||
return rt.FieldAsInterface(fldPath[1:])
|
||||
}
|
||||
|
||||
// ChargedRates the map with rateGroups
|
||||
type ChargedRates map[string]RateGroups
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (crs *ChargedRates) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
opath, indx := utils.GetPathIndex(fldPath[0])
|
||||
cr, has := (*crs)[opath]
|
||||
if !has || cr == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if indx != nil {
|
||||
if len(cr) < *indx {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
rg := cr[*indx]
|
||||
if len(fldPath) == 1 {
|
||||
return rg, nil
|
||||
}
|
||||
return rg.FieldAsInterface(fldPath[1:])
|
||||
}
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return cr, nil
|
||||
}
|
||||
|
||||
// GetIDWithSet attempts to retrieve the UUID of a matching data or create a new one
|
||||
func (crs ChargedRates) GetIDWithSet(rg RateGroups) string {
|
||||
if rg == nil || len(rg) == 0 {
|
||||
@@ -335,6 +509,7 @@ func (crs ChargedRates) GetIDWithSet(rg RateGroups) string {
|
||||
return uuid
|
||||
}
|
||||
|
||||
// Clone creates a copy of ChargedRates
|
||||
func (crs ChargedRates) Clone() (cln ChargedRates) {
|
||||
cln = make(ChargedRates, len(crs))
|
||||
for k, v := range crs {
|
||||
@@ -343,8 +518,24 @@ func (crs ChargedRates) Clone() (cln ChargedRates) {
|
||||
return
|
||||
}
|
||||
|
||||
// ChargedTimings the map of ChargedTiming
|
||||
type ChargedTimings map[string]*ChargedTiming
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (cts *ChargedTimings) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
ct, has := (*cts)[fldPath[0]]
|
||||
if !has || ct == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if len(fldPath) == 1 {
|
||||
return ct, nil
|
||||
}
|
||||
return ct.FieldAsInterface(fldPath[1:])
|
||||
}
|
||||
|
||||
// GetIDWithSet attempts to retrieve the UUID of a matching data or create a new one
|
||||
func (cts ChargedTimings) GetIDWithSet(ct *ChargedTiming) string {
|
||||
if ct == nil {
|
||||
@@ -361,6 +552,7 @@ func (cts ChargedTimings) GetIDWithSet(ct *ChargedTiming) string {
|
||||
return uuid
|
||||
}
|
||||
|
||||
// Clone creates a copy of ChargedTimings
|
||||
func (cts ChargedTimings) Clone() (cln ChargedTimings) {
|
||||
cln = make(ChargedTimings, len(cts))
|
||||
for k, v := range cts {
|
||||
@@ -369,6 +561,7 @@ func (cts ChargedTimings) Clone() (cln ChargedTimings) {
|
||||
return
|
||||
}
|
||||
|
||||
// Accounting the map of debited balances
|
||||
type Accounting map[string]*BalanceCharge
|
||||
|
||||
// GetIDWithSet attempts to retrieve the UUID of a matching data or create a new one
|
||||
@@ -387,6 +580,7 @@ func (cbs Accounting) GetIDWithSet(cb *BalanceCharge) string {
|
||||
return uuid
|
||||
}
|
||||
|
||||
// Clone creates a copy of Accounting
|
||||
func (cbs Accounting) Clone() (cln Accounting) {
|
||||
cln = make(Accounting, len(cbs))
|
||||
for k, v := range cbs {
|
||||
@@ -395,6 +589,21 @@ func (cbs Accounting) Clone() (cln Accounting) {
|
||||
return
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (cbs *Accounting) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
ac, has := (*cbs)[fldPath[0]]
|
||||
if !has || ac == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if len(fldPath) == 1 {
|
||||
return ac, nil
|
||||
}
|
||||
return ac.FieldAsInterface(fldPath[1:])
|
||||
}
|
||||
|
||||
// IfaceAsEventCost converts an interface to EventCost
|
||||
func IfaceAsEventCost(itm interface{}) (ec *EventCost, err error) {
|
||||
switch otm := itm.(type) {
|
||||
|
||||
@@ -233,6 +233,25 @@ type Rate struct {
|
||||
RateUnit time.Duration
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (r *Rate) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
||||
if len(fldPath) != 1 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
switch fldPath[0] {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
||||
case utils.GroupIntervalStart:
|
||||
return r.GroupIntervalStart, nil
|
||||
case utils.Value:
|
||||
return r.Value, nil
|
||||
case utils.RateIncrement:
|
||||
return r.RateIncrement, nil
|
||||
case utils.RateUnit:
|
||||
return r.RateUnit, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Rate) Stringify() string {
|
||||
return utils.Sha1(fmt.Sprintf("%v", r))[:8]
|
||||
}
|
||||
|
||||
@@ -497,6 +497,29 @@ const (
|
||||
Accounting = "Accounting"
|
||||
Rating = "Rating"
|
||||
Charges = "Charges"
|
||||
CompressFactor = "CompressFactor"
|
||||
Increments = "Increments"
|
||||
Balance = "Balance"
|
||||
BalanceSummaries = "BalanceSummaries"
|
||||
Type = "Type"
|
||||
YearsFieldName = "Years"
|
||||
MonthsFieldName = "Months"
|
||||
MonthDaysFieldName = "MonthDays"
|
||||
WeekDaysFieldName = "WeekDays"
|
||||
GroupIntervalStart = "GroupIntervalStart"
|
||||
RateIncrement = "RateIncrement"
|
||||
RateUnit = "RateUnit"
|
||||
BalanceUUID = "BalanceUUID"
|
||||
RatingID = "RatingID"
|
||||
ExtraChargeID = "ExtraChargeID"
|
||||
ConnectFee = "ConnectFee"
|
||||
RoundingMethod = "RoundingMethod"
|
||||
RoundingDecimals = "RoundingDecimals"
|
||||
MaxCostStrategy = "MaxCostStrategy"
|
||||
TimingID = "TimingID"
|
||||
RatesID = "RatesID"
|
||||
RatingFiltersID = "RatingFiltersID"
|
||||
AccountingID = "AccountingID"
|
||||
MetaSessionS = "*sessions"
|
||||
MetaDefault = "*default"
|
||||
Error = "Error"
|
||||
|
||||
@@ -892,3 +892,23 @@ func CastRPCErr(err error) error {
|
||||
func RandomInteger(min, max int) int {
|
||||
return math_rand.Intn(max-min) + min
|
||||
}
|
||||
|
||||
// GetPathIndex returns the path and index if index present
|
||||
// path[index]=>path,index
|
||||
// path=>path,nil
|
||||
func GetPathIndex(spath string) (opath string, idx *int) {
|
||||
idxStart := strings.Index(spath, IdxStart)
|
||||
if idxStart == -1 || !strings.HasSuffix(spath, IdxEnd) {
|
||||
return spath, nil
|
||||
}
|
||||
slctr := spath[idxStart+1 : len(spath)-1]
|
||||
opath = spath[:idxStart]
|
||||
// if strings.HasPrefix(slctr, DynamicDataPrefix) {
|
||||
// return
|
||||
// }
|
||||
idxVal, err := strconv.Atoi(slctr)
|
||||
if err != nil {
|
||||
return spath, nil
|
||||
}
|
||||
return opath, &idxVal
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user