mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-16 05:39:54 +05:00
Decimal NewDecimalFromUsage accepting empty string
This commit is contained in:
@@ -36,7 +36,7 @@ type SortedRoute struct {
|
||||
sortingDataF64 map[string]float64 // only the data we sort after
|
||||
}
|
||||
|
||||
// SortedRoutes is returned as part of GetRoutes call
|
||||
// SortedRoutes represents all viable routes inside one routing profile
|
||||
type SortedRoutes struct {
|
||||
ProfileID string // Profile matched
|
||||
Sorting string // Sorting algorithm
|
||||
|
||||
@@ -183,91 +183,22 @@ func (rpS *RouteService) matchingRouteProfilesForEvent(ctx *context.Context, tnt
|
||||
|
||||
// costForEvent will compute cost out of accounts and rating plans for event
|
||||
// returns map[string]interface{} with cost and relevant matching information inside
|
||||
func (rpS *RouteService) costForEvent(ev *utils.CGREvent,
|
||||
func (rpS *RouteService) costForEvent(ctx *context.Context, ev *utils.CGREvent,
|
||||
acntIDs, rpIDs []string) (costData map[string]interface{}, err error) {
|
||||
costData = make(map[string]interface{})
|
||||
if err = ev.CheckMandatoryFields([]string{utils.AccountField,
|
||||
utils.Destination, utils.SetupTime}); err != nil {
|
||||
return
|
||||
}
|
||||
// var acnt , subj, dst string
|
||||
// if acnt, err = ev.FieldAsString(utils.AccountField); err != nil {
|
||||
// return
|
||||
// }
|
||||
// if subj, err = ev.FieldAsString(utils.Subject); err != nil {
|
||||
// if err != utils.ErrNotFound {
|
||||
// return
|
||||
// }
|
||||
// subj = acnt
|
||||
// }
|
||||
// if dst, err = ev.FieldAsString(utils.Destination); err != nil {
|
||||
// return
|
||||
// }
|
||||
var sTime time.Time
|
||||
if sTime, err = ev.FieldAsTime(utils.SetupTime, rpS.cgrcfg.GeneralCfg().DefaultTimezone); err != nil {
|
||||
return
|
||||
}
|
||||
var usage time.Duration
|
||||
if usage, err = ev.FieldAsDuration(utils.Usage); err != nil {
|
||||
if err != utils.ErrNotFound {
|
||||
return
|
||||
}
|
||||
// in case usage is missing from event we decide to use 1 minute as default
|
||||
usage = time.Duration(1 * time.Minute)
|
||||
err = nil
|
||||
}
|
||||
var accountMaxUsage time.Duration
|
||||
var acntCost map[string]interface{}
|
||||
var initialUsage time.Duration
|
||||
if len(acntIDs) != 0 {
|
||||
// if err := rpS.connMgr.Call(rpS.cgrcfg.RouteSCfg().RALsConns, nil, utils.ResponderGetMaxSessionTimeOnAccounts,
|
||||
// &utils.GetMaxSessionTimeOnAccountsArgs{
|
||||
// Tenant: ev.Tenant,
|
||||
// Subject: subj,
|
||||
// Destination: dst,
|
||||
// SetupTime: sTime,
|
||||
// Usage: usage,
|
||||
// AccountIDs: acntIDs,
|
||||
// }, &acntCost); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
if ifaceMaxUsage, has := acntCost[utils.CapMaxUsage]; has {
|
||||
if accountMaxUsage, err = utils.IfaceAsDuration(ifaceMaxUsage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if usage > accountMaxUsage {
|
||||
// remain usage needs to be covered by rating plans
|
||||
if len(rpIDs) == 0 {
|
||||
return nil, fmt.Errorf("no rating plans defined for remaining usage")
|
||||
}
|
||||
// update the setup time and the usage
|
||||
sTime = sTime.Add(accountMaxUsage)
|
||||
initialUsage = usage
|
||||
}
|
||||
for k, v := range acntCost { // update the costData with the infos from AccountS
|
||||
costData[k] = v
|
||||
}
|
||||
}
|
||||
var rpCost utils.RateProfileCost
|
||||
if err = rpS.connMgr.Call(ctx, rpS.cgrcfg.RouteSCfg().RateSConns,
|
||||
utils.RateSv1CostForEvent,
|
||||
&utils.ArgsCostForEvent{
|
||||
RateProfileIDs: rpIDs,
|
||||
CGREvent: ev,
|
||||
}, &rpCost); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
costData[utils.Cost], _ = rpCost.Cost.Float64()
|
||||
costData[utils.RatingPlanID] = rpCost.ID
|
||||
}
|
||||
|
||||
if accountMaxUsage == 0 || accountMaxUsage < initialUsage {
|
||||
var rpCost map[string]interface{}
|
||||
// if err := rpS.connMgr.Call(rpS.cgrcfg.RouteSCfg().RALsConns, nil, utils.ResponderGetCostOnRatingPlans,
|
||||
// &utils.GetCostOnRatingPlansArgs{
|
||||
// Tenant: ev.Tenant,
|
||||
// Account: acnt,
|
||||
// Subject: subj,
|
||||
// Destination: dst,
|
||||
// SetupTime: sTime,
|
||||
// Usage: usage,
|
||||
// RateProfileIDs: rpIDs,
|
||||
// }, &rpCost); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
for k, v := range rpCost { // do not overwrite the return map
|
||||
costData[k] = v
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -379,7 +310,7 @@ func (rpS *RouteService) populateSortingData(ctx *context.Context, ev *utils.CGR
|
||||
}
|
||||
//calculate costData if we have fields
|
||||
if len(route.AccountIDs) != 0 || len(route.RateProfileIDs) != 0 {
|
||||
costData, err := rpS.costForEvent(ev, route.AccountIDs, route.RateProfileIDs)
|
||||
costData, err := rpS.costForEvent(ctx, ev, route.AccountIDs, route.RateProfileIDs)
|
||||
if err != nil {
|
||||
if extraOpts.ignoreErrors {
|
||||
utils.Logger.Warning(
|
||||
@@ -675,7 +606,7 @@ func (rpS *RouteService) sortedRoutesForProfile(ctx *context.Context, tnt string
|
||||
return
|
||||
}
|
||||
|
||||
// sortedRoutesForEvent will return the list of valid route IDs
|
||||
// sortedRoutesForEvent will return the list of sortedRoutes
|
||||
// for event based on filters and sorting algorithms
|
||||
func (rpS *RouteService) sortedRoutesForEvent(ctx *context.Context, tnt string, args *ArgsGetRoutes) (sortedRoutes SortedRoutesList, err error) {
|
||||
if _, has := args.CGREvent.Event[utils.Usage]; !has {
|
||||
|
||||
@@ -106,6 +106,9 @@ func NewDecimalFromFloat64(f float64) *Decimal {
|
||||
// NewDecimalFromUsage is a constructor for Decimal out of unit represents as string
|
||||
func NewDecimalFromUsage(u string) (d *Decimal, err error) {
|
||||
switch {
|
||||
// There was no duration present, equivalent of 0 decimal
|
||||
case u == EmptyString:
|
||||
d = NewDecimal(0, 0)
|
||||
//"ns", "us" (or "µs"), "ms", "s", "m", "h"
|
||||
case strings.HasSuffix(u, NsSuffix), strings.HasSuffix(u, UsSuffix), strings.HasSuffix(u, µSuffix), strings.HasSuffix(u, MsSuffix),
|
||||
strings.HasSuffix(u, SSuffix), strings.HasSuffix(u, MSuffix), strings.HasSuffix(u, HSuffix):
|
||||
@@ -114,16 +117,14 @@ func NewDecimalFromUsage(u string) (d *Decimal, err error) {
|
||||
return
|
||||
}
|
||||
d = NewDecimal(int64(tm), 0)
|
||||
return
|
||||
default:
|
||||
var i int64
|
||||
if i, err = strconv.ParseInt(u, 10, 64); err != nil {
|
||||
return
|
||||
}
|
||||
d = NewDecimal(i, 0)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NewDecimal is a constructor for Decimal, following the one of decimal.Big
|
||||
@@ -200,3 +201,8 @@ func (d *Decimal) Round(rndDec int) *Decimal {
|
||||
ctx.Precision = rndDec
|
||||
return &Decimal{ctx.Round(d.Big)}
|
||||
}
|
||||
|
||||
// Float64 returns the decimal as float64 number or !ok otherwise
|
||||
func (d *Decimal) Float64() (f float64, ok bool) {
|
||||
return d.Big.Float64()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user