diff --git a/rates/librates.go b/rates/librates.go index 797366d58..920e7eea4 100644 --- a/rates/librates.go +++ b/rates/librates.go @@ -203,7 +203,7 @@ func getRateIntervalIDFromIncrement(cstRts map[string]*utils.IntervalRate, intRt // computeRateSIntervals will give out the cost projection for the given orderedRates and usage func computeRateSIntervals(rts []*orderedRate, intervalStart, usage *decimal.Big, - cstRts map[string]*utils.IntervalRate) (rtIvls []*utils.RateSIntervalCost, err error) { + cstRts map[string]*utils.IntervalRate) (rtIvls []*utils.RateSInterval, err error) { totalUsage := usage if intervalStart.Cmp(decimal.New(0, 0)) != 0 { totalUsage = utils.SumBig(usage, intervalStart) @@ -216,7 +216,7 @@ func computeRateSIntervals(rts []*orderedRate, intervalStart, usage *decimal.Big } else { rtUsageEIdx = totalUsage } - var rIcmts []*utils.RateSIncrementCost + var rIcmts []*utils.RateSIncrement iRtUsageSIdx := intervalStart iRtUsageEIdx := rtUsageEIdx for j, iRt := range rt.IntervalRates { @@ -238,7 +238,7 @@ func computeRateSIntervals(rts []*orderedRate, intervalStart, usage *decimal.Big return nil, fmt.Errorf("zero increment to be charged within rate: <%s>", rt.UID()) } if rt.IntervalRates[j].FixedFee != nil && rt.IntervalRates[j].FixedFee.Cmp(decimal.New(0, 0)) != 0 { // Add FixedFee - rIcmts = append(rIcmts, &utils.RateSIncrementCost{ + rIcmts = append(rIcmts, &utils.RateSIncrement{ IncrementStart: &utils.Decimal{iRtUsageSIdx}, IntervalRateIndex: j, RateID: getRateIntervalIDFromIncrement(cstRts, rt.IntervalRates[j]), @@ -268,7 +268,7 @@ func computeRateSIntervals(rts []*orderedRate, intervalStart, usage *decimal.Big if !ok { return nil, fmt.Errorf("<%s> cannot convert <%+v> increment to Int64", utils.RateS, cmpFactor) } - rIcmts = append(rIcmts, &utils.RateSIncrementCost{ + rIcmts = append(rIcmts, &utils.RateSIncrement{ IncrementStart: &utils.Decimal{iRtUsageSIdx}, RateID: getRateIntervalIDFromIncrement(cstRts, rt.IntervalRates[j]), CompressFactor: cmpFactorInt, @@ -283,7 +283,7 @@ func computeRateSIntervals(rts []*orderedRate, intervalStart, usage *decimal.Big if len(rIcmts) == 0 { // no match found continue } - rtIvls = append(rtIvls, &utils.RateSIntervalCost{ + rtIvls = append(rtIvls, &utils.RateSInterval{ IntervalStart: &utils.Decimal{usageStart}, Increments: rIcmts, CompressFactor: 1, diff --git a/rates/rates.go b/rates/rates.go index 9754360d8..95bf1740d 100644 --- a/rates/rates.go +++ b/rates/rates.go @@ -187,12 +187,17 @@ func (rS *RateS) rateProfileCostForEvent(ctx *context.Context, rtPfl *utils.Rate if ivalStart, err = args.IntervalStart(); err != nil { return } - if rpCost.CostIntervals, err = computeRateSIntervals(ordRts, ivalStart, usage, rpCost.Rates); err != nil { + var costIntervals []*utils.RateSInterval + if costIntervals, err = computeRateSIntervals(ordRts, ivalStart, usage, rpCost.Rates); err != nil { return nil, err } - // in case we have error it is returned in the function from above - // this came up in coverage tests - rpCost.Cost = &utils.Decimal{utils.CostForIntervals(rpCost.CostIntervals, rpCost.Rates)} + rpCost.CostIntervals = make([]*utils.RateSIntervalCost, len(costIntervals)) + finalCost := new(decimal.Big) + for idx, costInt := range costIntervals { + finalCost = utils.SumBig(finalCost, costInt.Cost(rpCost.Rates)) // CostForIntervals sums the costs for all intervals + rpCost.CostIntervals[idx] = costInt.AsRatesIntervalsCost() //this does not contains IncrementStart and IntervalStart so we convert in RatesIntervalCosts + } + rpCost.Cost = &utils.Decimal{finalCost} return } diff --git a/utils/librates.go b/utils/librates.go index b70198c76..86bd958f6 100644 --- a/utils/librates.go +++ b/utils/librates.go @@ -360,6 +360,24 @@ type ExtRateSInterval struct { cost *float64 // unexported total interval cost } +// AsRatesIntervalsCost converts RateSInterval to RateSIntervalCost +// The difference between this 2 is that RateSIntervalCost don't need IntervalStart +func (rI *RateSInterval) AsRatesIntervalsCost() (rIc *RateSIntervalCost) { + rIc = &RateSIntervalCost{ + CompressFactor: rI.CompressFactor, + } + if rI.cost != nil { + rIc.cost = rI.cost + } + if rI.Increments != nil { + rIc.Increments = make([]*RateSIncrementCost, len(rI.Increments)) + for idx, incr := range rI.Increments { + rIc.Increments[idx] = incr.AsRateSIncrementCost() + } + } + return +} + // AsExtRateSInterval converts RateSInterval to ExtRateSInterval func (rI *RateSInterval) AsExtRateSInterval() (eRi *ExtRateSInterval, err error) { eRi = &ExtRateSInterval{ @@ -430,7 +448,7 @@ type ExtRateSIncrement struct { cost *float64 // unexported total increment cost } -// AsExtRateSIncrement converts RateSIncrement to ExtRateSIncrement +//AsExtRateSIncrement converts RateSIncrement to ExtRateSIncrement func (rI *RateSIncrement) AsExtRateSIncrement() (eRi *ExtRateSIncrement, err error) { eRi = &ExtRateSIncrement{ IntervalRateIndex: rI.IntervalRateIndex, @@ -524,7 +542,6 @@ type RateProfileCost struct { // RateSIntervalCost is used in the RateProfileCost to reflect the RateSInterval used type RateSIntervalCost struct { - IntervalStart *Decimal Increments []*RateSIncrementCost CompressFactor int64 @@ -533,7 +550,6 @@ type RateSIntervalCost struct { // RateSIncrementCost is used in the RateProfileCost to reflect RateSIncrement type RateSIncrementCost struct { - IncrementStart *Decimal Usage *Decimal RateID string IntervalRateIndex int @@ -542,6 +558,24 @@ type RateSIncrementCost struct { cost *decimal.Big // unexported total increment cost } +// AsRateSIncrementCost converts RateSIncrement to RateSIncrementCost +// The difference between this 2 is that RateSIncrementCost don't need IncrementStart +func (rI *RateSIncrement) AsRateSIncrementCost() (rIc *RateSIncrementCost) { + rIc = &RateSIncrementCost{ + IntervalRateIndex: rI.IntervalRateIndex, + CompressFactor: rI.CompressFactor, + RateID: rI.RateID, + } + if rI.Usage != nil { + rIc.Usage = rI.Usage + } + if rI.cost != nil { + rIc.cost = rI.cost + } + return + +} + // Equals returns the equality between two RateSIntervalCost func (rIC *RateSIntervalCost) Equals(nRIc *RateSIntervalCost, rIlRef, nRilRef map[string]*IntervalRate) (eq bool) { if (rIC.Increments != nil && rIC.Increments == nil || @@ -598,9 +632,18 @@ func (rpC *RateProfileCost) SynchronizeRateKeys(nRpCt *RateProfileCost) { // Equals returns the equality between two RateProfileCost func (rpC *RateProfileCost) Equals(nRpCt *RateProfileCost) (eq bool) { if rpC.ID != nRpCt.ID || - rpC.Cost != nRpCt.Cost || - rpC.MinCost != nRpCt.MinCost || - rpC.MaxCost != nRpCt.MaxCost || + (rpC.Cost == nil && nRpCt.Cost != nil) || + (rpC.Cost != nil && nRpCt.Cost == nil) || + (rpC.Cost != nil && nRpCt.Cost != nil && + rpC.Cost.Compare(nRpCt.Cost) != 0) || + (rpC.MinCost == nil && nRpCt.MinCost != nil) || + (rpC.MinCost != nil && nRpCt.MinCost == nil) || + (rpC.MinCost != nil && nRpCt.MinCost != nil && + rpC.MinCost.Compare(nRpCt.MinCost) != 0) || + (rpC.MaxCost == nil && nRpCt.MaxCost != nil) || + (rpC.MaxCost != nil && nRpCt.MaxCost == nil) || + (rpC.MaxCost != nil && nRpCt.MaxCost != nil && + rpC.MaxCost.Compare(nRpCt.MaxCost) != 0) || rpC.MaxCostStrategy != nRpCt.MaxCostStrategy || (rpC.CostIntervals != nil && nRpCt.CostIntervals == nil || rpC.CostIntervals == nil && nRpCt.CostIntervals != nil || @@ -665,7 +708,7 @@ func (rIv *RateSInterval) CompressEquals(rIv2 *RateSInterval) (eq bool) { return true } -func (rIv *RateSIntervalCost) Cost(rts map[string]*IntervalRate) (cost *decimal.Big) { +func (rIv *RateSInterval) Cost(rts map[string]*IntervalRate) (cost *decimal.Big) { if rIv.cost == nil { rIv.cost = new(decimal.Big) for _, incrm := range rIv.Increments { @@ -683,7 +726,7 @@ func (rIcr *RateSIncrement) CompressEquals(rIcr2 *RateSIncrement) (eq bool) { } // Cost computes the Cost on RateSIncrement -func (rIcr *RateSIncrementCost) Cost(rts map[string]*IntervalRate) (cost *decimal.Big) { +func (rIcr *RateSIncrement) Cost(rts map[string]*IntervalRate) (cost *decimal.Big) { if rIcr.cost == nil { icrRt, has := rts[rIcr.RateID] if !has { @@ -709,7 +752,7 @@ func (rIcr *RateSIncrementCost) Cost(rts map[string]*IntervalRate) (cost *decima } // CostForIntervals sums the costs for all intervals -func CostForIntervals(rtIvls []*RateSIntervalCost, rts map[string]*IntervalRate) (cost *decimal.Big) { +func CostForIntervals(rtIvls []*RateSInterval, rts map[string]*IntervalRate) (cost *decimal.Big) { cost = new(decimal.Big) for _, rtIvl := range rtIvls { cost = SumBig(cost, rtIvl.Cost(rts))