mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-21 07:08:45 +05:00
EventCost - generic RatingMatchedFilters, TestNewEventCostFromCallCost
This commit is contained in:
@@ -24,10 +24,10 @@ import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type RatingFilters map[string]*RatingMatchedFilters // so we can define search methods
|
||||
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
|
||||
func (rfs RatingFilters) GetUUIDWithSet(rmf *RatingMatchedFilters) string {
|
||||
func (rfs RatingFilters) GetUUIDWithSet(rmf RatingMatchedFilters) string {
|
||||
for k, v := range rfs {
|
||||
if v.Equals(rmf) {
|
||||
return k
|
||||
@@ -112,8 +112,8 @@ func NewEventCostFromCallCost(cc *CallCost, cgrID, runID string) (ec *EventCost)
|
||||
}
|
||||
for i, ts := range cc.Timespans {
|
||||
cIl := &ChargingInterval{StartTime: ts.TimeStart, CompressFactor: ts.CompressFactor}
|
||||
rf := &RatingMatchedFilters{Subject: ts.MatchedSubject, DestinationPrefix: ts.MatchedPrefix,
|
||||
DestinationID: ts.MatchedDestId, RatingPlanID: ts.RatingPlanId}
|
||||
rf := RatingMatchedFilters{"Subject": ts.MatchedSubject, "DestinationPrefix": ts.MatchedPrefix,
|
||||
"DestinationID": ts.MatchedDestId, "RatingPlanID": ts.RatingPlanId}
|
||||
cIl.RatingUUID = ec.ratingUUIDForRateInterval(ts.RateInterval, rf)
|
||||
if len(ts.Increments) != 0 {
|
||||
cIl.Increments = make([]*ChargingIncrement, len(ts.Increments))
|
||||
@@ -177,7 +177,7 @@ type EventCost struct {
|
||||
Timings ChargedTimings
|
||||
}
|
||||
|
||||
func (ec *EventCost) ratingUUIDForRateInterval(ri *RateInterval, rf *RatingMatchedFilters) string {
|
||||
func (ec *EventCost) ratingUUIDForRateInterval(ri *RateInterval, rf RatingMatchedFilters) string {
|
||||
if ri == nil || ri.Rating == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -267,10 +267,10 @@ func (ec *EventCost) AsCallCost(ToR, Tenant, Direction, Category, Account, Subje
|
||||
if cIl.RatingUUID != "" {
|
||||
if ec.Rating[cIl.RatingUUID].RatingFiltersUUID != "" {
|
||||
rfs := ec.RatingFilters[ec.Rating[cIl.RatingUUID].RatingFiltersUUID]
|
||||
ts.MatchedSubject = rfs.Subject
|
||||
ts.MatchedPrefix = rfs.DestinationPrefix
|
||||
ts.MatchedDestId = rfs.DestinationID
|
||||
ts.RatingPlanId = rfs.RatingPlanID
|
||||
ts.MatchedSubject = rfs["Subject"].(string)
|
||||
ts.MatchedPrefix = rfs["DestinationPrefix"].(string)
|
||||
ts.MatchedDestId = rfs["DestinationID"].(string)
|
||||
ts.RatingPlanId = rfs["RatingPlanID"].(string)
|
||||
}
|
||||
}
|
||||
ts.RateInterval = ec.rateIntervalForRatingUUID(cIl.RatingUUID)
|
||||
@@ -302,18 +302,16 @@ func (ec *EventCost) AsCallCost(ToR, Tenant, Direction, Category, Account, Subje
|
||||
// ChargingInterval represents one interval out of Usage providing charging info
|
||||
// eg: PEAK vs OFFPEAK
|
||||
type ChargingInterval struct {
|
||||
StartTime time.Time
|
||||
IntervalDetailsUUID string // reference to CIntervDetails
|
||||
RatingUUID string // reference to RatingUnit
|
||||
Increments []*ChargingIncrement // specific increments applied to this interval
|
||||
CompressFactor int
|
||||
usage *time.Duration // cache usage computation for this interval
|
||||
cost *float64 // cache cost calculation on this interval
|
||||
StartTime time.Time
|
||||
RatingUUID string // reference to RatingUnit
|
||||
Increments []*ChargingIncrement // specific increments applied to this interval
|
||||
CompressFactor int
|
||||
usage *time.Duration // cache usage computation for this interval
|
||||
cost *float64 // cache cost calculation on this interval
|
||||
}
|
||||
|
||||
func (cIl *ChargingInterval) Equals(oCIl *ChargingInterval) (equals bool) {
|
||||
if equals = cIl.StartTime.Equal(oCIl.StartTime) &&
|
||||
cIl.IntervalDetailsUUID == oCIl.IntervalDetailsUUID &&
|
||||
cIl.RatingUUID == oCIl.RatingUUID &&
|
||||
len(cIl.Increments) == len(oCIl.Increments); !equals {
|
||||
return
|
||||
@@ -383,18 +381,17 @@ func (bc *BalanceCharge) Equals(oBC *BalanceCharge) bool {
|
||||
bc.ExtraChargeUUID == oBC.ExtraChargeUUID
|
||||
}
|
||||
|
||||
type RatingMatchedFilters struct {
|
||||
Subject string // matched subject
|
||||
DestinationPrefix string // matched destination prefix
|
||||
DestinationID string // matched destinationID
|
||||
RatingPlanID string // matched ratingPlanID
|
||||
}
|
||||
type RatingMatchedFilters map[string]interface{}
|
||||
|
||||
func (rf *RatingMatchedFilters) Equals(oRF *RatingMatchedFilters) bool {
|
||||
return rf.Subject == oRF.Subject &&
|
||||
rf.DestinationPrefix == oRF.DestinationPrefix &&
|
||||
rf.DestinationID == oRF.DestinationID &&
|
||||
rf.RatingPlanID == oRF.RatingPlanID
|
||||
func (rf RatingMatchedFilters) Equals(oRF RatingMatchedFilters) (equals bool) {
|
||||
equals = true
|
||||
for k := range rf {
|
||||
if rf[k] != oRF[k] {
|
||||
equals = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ChargedTiming represents one timing attached to a charge
|
||||
@@ -433,5 +430,6 @@ func (ru *RatingUnit) Equals(oRU *RatingUnit) bool {
|
||||
ru.MaxCost == oRU.MaxCost &&
|
||||
ru.MaxCostStrategy == oRU.MaxCostStrategy &&
|
||||
ru.TimingUUID == oRU.TimingUUID &&
|
||||
ru.RatesUUID == oRU.RatesUUID
|
||||
ru.RatesUUID == oRU.RatesUUID &&
|
||||
ru.RatingFiltersUUID == oRU.RatingFiltersUUID
|
||||
}
|
||||
|
||||
340
engine/eventcost_test.go
Normal file
340
engine/eventcost_test.go
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package engine
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func TestNewEventCostFromCallCost(t *testing.T) {
|
||||
cc := &CallCost{
|
||||
Direction: utils.META_OUT,
|
||||
Category: "call",
|
||||
Tenant: "cgrates.org",
|
||||
Subject: "dan",
|
||||
Account: "dan",
|
||||
Destination: "+4986517174963",
|
||||
TOR: utils.VOICE,
|
||||
Cost: 0.85,
|
||||
RatedUsage: 120.0,
|
||||
Timespans: TimeSpans{
|
||||
&TimeSpan{
|
||||
TimeStart: time.Date(2017, 1, 9, 16, 18, 21, 0, time.UTC),
|
||||
TimeEnd: time.Date(2017, 1, 9, 16, 19, 21, 0, time.UTC),
|
||||
Cost: 0.25,
|
||||
RateInterval: &RateInterval{ // standard rating
|
||||
Timing: &RITiming{
|
||||
StartTime: "00:00:00",
|
||||
},
|
||||
Rating: &RIRate{
|
||||
ConnectFee: 0.1,
|
||||
RoundingMethod: "*up",
|
||||
RoundingDecimals: 5,
|
||||
Rates: RateGroups{
|
||||
&Rate{
|
||||
GroupIntervalStart: time.Duration(0),
|
||||
Value: 0.01,
|
||||
RateUnit: time.Duration(1 * time.Second),
|
||||
RateIncrement: time.Duration(1 * time.Minute),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DurationIndex: time.Duration(1 * time.Minute),
|
||||
MatchedSubject: "*out:cgrates.org:call:*any",
|
||||
MatchedPrefix: "+49",
|
||||
MatchedDestId: "GERMANY",
|
||||
RatingPlanId: "RPL_RETAIL1",
|
||||
CompressFactor: 1,
|
||||
Increments: Increments{
|
||||
&Increment{ // ConnectFee
|
||||
Cost: 0.1,
|
||||
BalanceInfo: &DebitInfo{
|
||||
Monetary: &MonetaryInfo{UUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
|
||||
ID: utils.META_DEFAULT,
|
||||
Value: 9.9},
|
||||
AccountID: "cgrates.org:dan",
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
&Increment{ // First 30 seconds free
|
||||
Duration: time.Duration(1 * time.Second),
|
||||
Cost: 0,
|
||||
BalanceInfo: &DebitInfo{
|
||||
Unit: &UnitInfo{
|
||||
UUID: "9d54a9e9-d610-4c82-bcb5-a315b9a65089",
|
||||
ID: "free_mins",
|
||||
Value: 0,
|
||||
Consumed: 1.0,
|
||||
TOR: utils.VOICE,
|
||||
},
|
||||
AccountID: "cgrates.org:dan",
|
||||
},
|
||||
CompressFactor: 30,
|
||||
},
|
||||
&Increment{ // Minutes with special price
|
||||
Duration: time.Duration(1 * time.Second),
|
||||
Cost: 0.005,
|
||||
BalanceInfo: &DebitInfo{
|
||||
Unit: &UnitInfo{ // Minutes with special price
|
||||
UUID: "7a54a9e9-d610-4c82-bcb5-a315b9a65010",
|
||||
ID: "discounted_mins",
|
||||
Value: 0,
|
||||
Consumed: 1.0,
|
||||
TOR: utils.VOICE,
|
||||
RateInterval: &RateInterval{
|
||||
Timing: &RITiming{
|
||||
StartTime: "00:00:00",
|
||||
},
|
||||
Rating: &RIRate{
|
||||
ConnectFee: 0,
|
||||
RoundingMethod: "*up",
|
||||
RoundingDecimals: 5,
|
||||
Rates: RateGroups{
|
||||
&Rate{
|
||||
GroupIntervalStart: time.Duration(0),
|
||||
Value: 0.005,
|
||||
RateUnit: time.Duration(1 * time.Second),
|
||||
RateIncrement: time.Duration(1 * time.Second),
|
||||
},
|
||||
&Rate{
|
||||
GroupIntervalStart: time.Duration(60 * time.Second),
|
||||
Value: 0.005,
|
||||
RateUnit: time.Duration(1 * time.Second),
|
||||
RateIncrement: time.Duration(1 * time.Second),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Monetary: &MonetaryInfo{
|
||||
UUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
|
||||
ID: utils.META_DEFAULT,
|
||||
Value: 9.75},
|
||||
AccountID: "cgrates.org:dan",
|
||||
},
|
||||
CompressFactor: 30,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&TimeSpan{
|
||||
TimeStart: time.Date(2017, 1, 9, 16, 19, 21, 0, time.UTC),
|
||||
TimeEnd: time.Date(2017, 1, 9, 16, 20, 21, 0, time.UTC),
|
||||
Cost: 0.01,
|
||||
RateInterval: &RateInterval{ // standard rating
|
||||
Timing: &RITiming{
|
||||
StartTime: "00:00:00",
|
||||
},
|
||||
Rating: &RIRate{
|
||||
ConnectFee: 0.1,
|
||||
RoundingMethod: "*up",
|
||||
RoundingDecimals: 5,
|
||||
Rates: RateGroups{
|
||||
&Rate{
|
||||
GroupIntervalStart: time.Duration(0),
|
||||
Value: 0.01,
|
||||
RateUnit: time.Duration(1 * time.Second),
|
||||
RateIncrement: time.Duration(1 * time.Minute),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DurationIndex: time.Duration(1 * time.Minute),
|
||||
MatchedSubject: "*out:cgrates.org:call:*any",
|
||||
MatchedPrefix: "+49",
|
||||
MatchedDestId: "GERMANY",
|
||||
RatingPlanId: "RPL_RETAIL1",
|
||||
CompressFactor: 1,
|
||||
Increments: Increments{
|
||||
&Increment{
|
||||
Cost: 0.01,
|
||||
Duration: time.Duration(1 * time.Second),
|
||||
BalanceInfo: &DebitInfo{
|
||||
Monetary: &MonetaryInfo{UUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
|
||||
ID: utils.META_DEFAULT,
|
||||
Value: 9.15},
|
||||
AccountID: "cgrates.org:dan",
|
||||
},
|
||||
CompressFactor: 60,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
eEC := &EventCost{
|
||||
CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41",
|
||||
RunID: utils.META_DEFAULT,
|
||||
Cost: utils.Float64Pointer(0.85),
|
||||
Usage: utils.DurationPointer(time.Duration(2 * time.Minute)),
|
||||
Charges: []*ChargingInterval{
|
||||
&ChargingInterval{
|
||||
StartTime: time.Date(2017, 1, 9, 16, 18, 21, 0, time.UTC),
|
||||
RatingUUID: "bebf80cf-cba5-4e36-89dc-86673cff8cc4",
|
||||
Increments: []*ChargingIncrement{
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(0),
|
||||
Cost: 0.1,
|
||||
BalanceChargeUUID: "716a278d-9ca5-451a-aa59-b6a43f4fb4ef",
|
||||
CompressFactor: 1,
|
||||
},
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(1 * time.Second),
|
||||
Cost: 0,
|
||||
BalanceChargeUUID: "8ee1f8ee-5783-487b-87e3-cb1bb6fd8f9f",
|
||||
CompressFactor: 30,
|
||||
},
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(1 * time.Second),
|
||||
Cost: 0.005,
|
||||
BalanceChargeUUID: "77c904d4-c579-4687-8c28-a1561e39dae2",
|
||||
CompressFactor: 30,
|
||||
},
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
&ChargingInterval{
|
||||
StartTime: time.Date(2017, 1, 9, 16, 19, 21, 0, time.UTC),
|
||||
RatingUUID: "bebf80cf-cba5-4e36-89dc-86673cff8cc4",
|
||||
Increments: []*ChargingIncrement{
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(0),
|
||||
Cost: 0.01,
|
||||
BalanceChargeUUID: "79463f6e-d70f-41ac-9345-76bd21714759",
|
||||
CompressFactor: 60,
|
||||
},
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
},
|
||||
Rating: Rating{
|
||||
"bebf80cf-cba5-4e36-89dc-86673cff8cc4": &RatingUnit{
|
||||
ConnectFee: 0.1,
|
||||
RoundingMethod: "*up",
|
||||
RoundingDecimals: 5,
|
||||
TimingUUID: "3e4c7dd1-10f9-4fdc-b7df-8833724933dd",
|
||||
RatesUUID: "5f04c792-5c79-4873-ba39-413342671595",
|
||||
RatingFiltersUUID: "8fa45f23-5bb1-44ee-867c-ad09b2bae981",
|
||||
},
|
||||
"2b7333c0-479c-4e5d-8d72-d089e93b2b6a": &RatingUnit{
|
||||
RoundingMethod: "*up",
|
||||
RoundingDecimals: 5,
|
||||
TimingUUID: "3e4c7dd1-10f9-4fdc-b7df-8833724933dd",
|
||||
RatesUUID: "3246cb23-ef2e-4080-ba5b-45300cbede3f",
|
||||
RatingFiltersUUID: "8fa45f23-5bb1-44ee-867c-ad09b2bae981",
|
||||
},
|
||||
},
|
||||
Accounting: Accounting{
|
||||
"2afef931-eb94-46df-8fb4-3509954e771c": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
|
||||
Units: 0.005,
|
||||
},
|
||||
"716a278d-9ca5-451a-aa59-b6a43f4fb4ef": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
|
||||
Units: 0.1,
|
||||
},
|
||||
"77c904d4-c579-4687-8c28-a1561e39dae2": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "7a54a9e9-d610-4c82-bcb5-a315b9a65010",
|
||||
RatingUUID: "2b7333c0-479c-4e5d-8d72-d089e93b2b6a",
|
||||
Units: 1,
|
||||
ExtraChargeUUID: "2afef931-eb94-46df-8fb4-3509954e771c",
|
||||
},
|
||||
"79463f6e-d70f-41ac-9345-76bd21714759": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
|
||||
Units: 0.01,
|
||||
},
|
||||
"8ee1f8ee-5783-487b-87e3-cb1bb6fd8f9f": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "9d54a9e9-d610-4c82-bcb5-a315b9a65089",
|
||||
Units: 1,
|
||||
ExtraChargeUUID: "*none",
|
||||
},
|
||||
},
|
||||
RatingFilters: RatingFilters{
|
||||
"8fa45f23-5bb1-44ee-867c-ad09b2bae981": RatingMatchedFilters{
|
||||
"DestinationID": "GERMANY",
|
||||
"DestinationPrefix": "+49",
|
||||
"RatingPlanID": "RPL_RETAIL1",
|
||||
"Subject": "*out:cgrates.org:call:*any",
|
||||
},
|
||||
},
|
||||
Rates: ChargedRates{
|
||||
"3246cb23-ef2e-4080-ba5b-45300cbede3f": RateGroups{
|
||||
&Rate{
|
||||
GroupIntervalStart: time.Duration(0),
|
||||
Value: 0.01,
|
||||
RateIncrement: time.Duration(1 * time.Minute),
|
||||
RateUnit: time.Duration(1 * time.Second)},
|
||||
},
|
||||
"5f04c792-5c79-4873-ba39-413342671595": RateGroups{
|
||||
&Rate{
|
||||
GroupIntervalStart: time.Duration(0),
|
||||
Value: 0.005,
|
||||
RateIncrement: time.Duration(1 * time.Second),
|
||||
RateUnit: time.Duration(1 * time.Second)},
|
||||
&Rate{
|
||||
GroupIntervalStart: time.Duration(60 * time.Second),
|
||||
Value: 0.005,
|
||||
RateIncrement: time.Duration(1 * time.Second),
|
||||
RateUnit: time.Duration(1 * time.Second)},
|
||||
},
|
||||
},
|
||||
Timings: ChargedTimings{
|
||||
"3e4c7dd1-10f9-4fdc-b7df-8833724933dd": &ChargedTiming{
|
||||
StartTime: "00:00:00",
|
||||
},
|
||||
},
|
||||
}
|
||||
ec := NewEventCostFromCallCost(cc, "164b0422fdc6a5117031b427439482c6a4f90e41", utils.META_DEFAULT)
|
||||
if cost := ec.ComputeCost(); cost != cc.Cost {
|
||||
t.Errorf("Expecting: %f, received: %f", cc.Cost, cost)
|
||||
}
|
||||
eUsage := time.Duration(int64(cc.RatedUsage * 1000000000))
|
||||
if usage := ec.ComputeUsage(); usage != eUsage {
|
||||
t.Errorf("Expecting: %v, received: %v", eUsage, usage)
|
||||
}
|
||||
if len(ec.Charges) != len(eEC.Charges) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eEC, ec)
|
||||
}
|
||||
for i := range eEC.Charges {
|
||||
if len(eEC.Charges[i].Increments) != len(ec.Charges[i].Increments) {
|
||||
t.Errorf("At index %d, expecting: %+v, received: %+v", eEC.Charges[i].Increments, ec.Charges[i].Increments)
|
||||
}
|
||||
}
|
||||
if len(ec.Rating) != len(eEC.Rating) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eEC, ec)
|
||||
}
|
||||
if len(ec.Accounting) != len(eEC.Accounting) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eEC, ec)
|
||||
}
|
||||
if len(ec.Rates) != len(eEC.Rates) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eEC, ec)
|
||||
}
|
||||
if len(ec.Timings) != len(eEC.Timings) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eEC, ec)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user