mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 02:26:26 +05:00
Added *sessionChargeable session option. Fixes #1702
This commit is contained in:
committed by
Dan Christian Bogos
parent
a2688b9536
commit
d2e04360bd
@@ -102,7 +102,7 @@ func processAttributeS(connMgr *engine.ConnManager, cgrEv *utils.CGREvent,
|
||||
attrArgs := &engine.AttrArgsProcessEvent{
|
||||
Context: utils.StringPointer(utils.FirstNonEmpty(
|
||||
engine.MapEvent(cgrEv.Opts).GetStringIgnoreErrors(utils.OptsContext),
|
||||
utils.MetaAccountS)),
|
||||
utils.MetaAccounts)),
|
||||
CGREvent: cgrEv,
|
||||
AttributeIDs: attrIDs,
|
||||
ProcessRuns: procRuns,
|
||||
|
||||
@@ -54,15 +54,16 @@ func NewEventCostFromCallCost(cc *CallCost, cgrID, runID string) (ec *EventCost)
|
||||
cIl := &ChargingInterval{CompressFactor: ts.CompressFactor}
|
||||
rf := RatingMatchedFilters{"Subject": ts.MatchedSubject, "DestinationPrefix": ts.MatchedPrefix,
|
||||
"DestinationID": ts.MatchedDestId, "RatingPlanID": ts.RatingPlanId}
|
||||
cIl.RatingID = ec.ratingIDForRateInterval(ts.RateInterval, rf)
|
||||
isPause := ts.RatingPlanId == utils.MetaPause
|
||||
cIl.RatingID = ec.ratingIDForRateInterval(ts.RateInterval, rf, isPause)
|
||||
if len(ts.Increments) != 0 {
|
||||
cIl.Increments = make([]*ChargingIncrement, 0, len(ts.Increments)+1)
|
||||
}
|
||||
for _, incr := range ts.Increments {
|
||||
cIl.Increments = append(cIl.Increments, ec.newChargingIncrement(incr, rf, false))
|
||||
cIl.Increments = append(cIl.Increments, ec.newChargingIncrement(incr, rf, false, isPause))
|
||||
}
|
||||
if ts.RoundIncrement != nil {
|
||||
rIncr := ec.newChargingIncrement(ts.RoundIncrement, rf, true)
|
||||
rIncr := ec.newChargingIncrement(ts.RoundIncrement, rf, true, false)
|
||||
rIncr.Cost = -rIncr.Cost
|
||||
cIl.Increments = append(cIl.Increments, rIncr)
|
||||
}
|
||||
@@ -73,7 +74,7 @@ func NewEventCostFromCallCost(cc *CallCost, cgrID, runID string) (ec *EventCost)
|
||||
|
||||
// newChargingIncrement creates ChargingIncrement from a Increment
|
||||
// special case if is the roundIncrement the rateID is *rounding
|
||||
func (ec *EventCost) newChargingIncrement(incr *Increment, rf RatingMatchedFilters, roundedIncrement bool) (cIt *ChargingIncrement) {
|
||||
func (ec *EventCost) newChargingIncrement(incr *Increment, rf RatingMatchedFilters, roundedIncrement, isPause bool) (cIt *ChargingIncrement) {
|
||||
cIt = &ChargingIncrement{
|
||||
Usage: incr.Duration,
|
||||
Cost: incr.Cost,
|
||||
@@ -82,6 +83,9 @@ func (ec *EventCost) newChargingIncrement(incr *Increment, rf RatingMatchedFilte
|
||||
if incr.BalanceInfo == nil {
|
||||
return
|
||||
}
|
||||
if roundedIncrement {
|
||||
isPause = false
|
||||
}
|
||||
rateID := utils.MetaRounding
|
||||
//AccountingID
|
||||
if incr.BalanceInfo.Unit != nil {
|
||||
@@ -89,40 +93,53 @@ func (ec *EventCost) newChargingIncrement(incr *Increment, rf RatingMatchedFilte
|
||||
ecUUID := utils.MetaNone // populate no matter what due to Unit not nil
|
||||
if incr.BalanceInfo.Monetary != nil {
|
||||
if !roundedIncrement {
|
||||
rateID = ec.ratingIDForRateInterval(incr.BalanceInfo.Monetary.RateInterval, rf)
|
||||
rateID = ec.ratingIDForRateInterval(incr.BalanceInfo.Monetary.RateInterval, rf, isPause)
|
||||
}
|
||||
if uuid := ec.Accounting.GetIDWithSet(
|
||||
&BalanceCharge{
|
||||
AccountID: incr.BalanceInfo.AccountID,
|
||||
BalanceUUID: incr.BalanceInfo.Monetary.UUID,
|
||||
Units: incr.Cost,
|
||||
RatingID: rateID,
|
||||
}); uuid != "" {
|
||||
ecUUID = uuid
|
||||
}
|
||||
}
|
||||
if !roundedIncrement {
|
||||
rateID = ec.ratingIDForRateInterval(incr.BalanceInfo.Unit.RateInterval, rf)
|
||||
}
|
||||
cIt.AccountingID = ec.Accounting.GetIDWithSet(
|
||||
&BalanceCharge{
|
||||
AccountID: incr.BalanceInfo.AccountID,
|
||||
BalanceUUID: incr.BalanceInfo.Unit.UUID,
|
||||
Units: incr.BalanceInfo.Unit.Consumed,
|
||||
RatingID: rateID,
|
||||
ExtraChargeID: ecUUID,
|
||||
})
|
||||
} else if incr.BalanceInfo.Monetary != nil { // Only monetary
|
||||
if !roundedIncrement {
|
||||
rateID = ec.ratingIDForRateInterval(incr.BalanceInfo.Monetary.RateInterval, rf)
|
||||
}
|
||||
cIt.AccountingID = ec.Accounting.GetIDWithSet(
|
||||
&BalanceCharge{
|
||||
bc := &BalanceCharge{
|
||||
AccountID: incr.BalanceInfo.AccountID,
|
||||
BalanceUUID: incr.BalanceInfo.Monetary.UUID,
|
||||
Units: incr.Cost,
|
||||
RatingID: rateID,
|
||||
})
|
||||
}
|
||||
if isPause {
|
||||
ecUUID = utils.MetaPause
|
||||
ec.Accounting[ecUUID] = bc
|
||||
} else {
|
||||
ecUUID = ec.Accounting.GetIDWithSet(bc)
|
||||
}
|
||||
}
|
||||
if !roundedIncrement {
|
||||
rateID = ec.ratingIDForRateInterval(incr.BalanceInfo.Unit.RateInterval, rf, isPause)
|
||||
}
|
||||
bc := &BalanceCharge{
|
||||
AccountID: incr.BalanceInfo.AccountID,
|
||||
BalanceUUID: incr.BalanceInfo.Unit.UUID,
|
||||
Units: incr.BalanceInfo.Unit.Consumed,
|
||||
RatingID: rateID,
|
||||
ExtraChargeID: ecUUID,
|
||||
}
|
||||
if isPause {
|
||||
cIt.AccountingID = utils.MetaPause
|
||||
ec.Accounting[utils.MetaPause] = bc
|
||||
} else {
|
||||
cIt.AccountingID = ec.Accounting.GetIDWithSet(bc)
|
||||
}
|
||||
} else if incr.BalanceInfo.Monetary != nil { // Only monetary
|
||||
if !roundedIncrement {
|
||||
rateID = ec.ratingIDForRateInterval(incr.BalanceInfo.Monetary.RateInterval, rf, isPause)
|
||||
}
|
||||
bc := &BalanceCharge{
|
||||
AccountID: incr.BalanceInfo.AccountID,
|
||||
BalanceUUID: incr.BalanceInfo.Monetary.UUID,
|
||||
Units: incr.Cost,
|
||||
RatingID: rateID,
|
||||
}
|
||||
if isPause {
|
||||
cIt.AccountingID = utils.MetaPause
|
||||
ec.Accounting[utils.MetaPause] = bc
|
||||
} else {
|
||||
cIt.AccountingID = ec.Accounting.GetIDWithSet(bc)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -151,39 +168,54 @@ func (ec *EventCost) initCache() {
|
||||
}
|
||||
}
|
||||
|
||||
func (ec *EventCost) ratingIDForRateInterval(ri *RateInterval, rf RatingMatchedFilters) string {
|
||||
func (ec *EventCost) ratingIDForRateInterval(ri *RateInterval, rf RatingMatchedFilters, isPause bool) string {
|
||||
if ri == nil || ri.Rating == nil {
|
||||
return ""
|
||||
}
|
||||
var rfUUID string
|
||||
if rf != nil {
|
||||
rfUUID = ec.RatingFilters.GetIDWithSet(rf)
|
||||
if isPause {
|
||||
rfUUID = utils.MetaPause
|
||||
ec.RatingFilters[rfUUID] = rf
|
||||
} else {
|
||||
rfUUID = ec.RatingFilters.GetIDWithSet(rf)
|
||||
}
|
||||
}
|
||||
var tmID string
|
||||
if ri.Timing != nil {
|
||||
tmID = ec.Timings.GetIDWithSet(
|
||||
&ChargedTiming{
|
||||
Years: ri.Timing.Years,
|
||||
Months: ri.Timing.Months,
|
||||
MonthDays: ri.Timing.MonthDays,
|
||||
WeekDays: ri.Timing.WeekDays,
|
||||
StartTime: ri.Timing.StartTime})
|
||||
// timingID can have random UUID to be reused by other Rates from EventCost
|
||||
tmID = ec.Timings.GetIDWithSet(&ChargedTiming{
|
||||
Years: ri.Timing.Years,
|
||||
Months: ri.Timing.Months,
|
||||
MonthDays: ri.Timing.MonthDays,
|
||||
WeekDays: ri.Timing.WeekDays,
|
||||
StartTime: ri.Timing.StartTime,
|
||||
})
|
||||
}
|
||||
var rtUUID string
|
||||
if len(ri.Rating.Rates) != 0 {
|
||||
rtUUID = ec.Rates.GetIDWithSet(ri.Rating.Rates)
|
||||
if isPause {
|
||||
rtUUID = utils.MetaPause
|
||||
ec.Rates[rtUUID] = ri.Rating.Rates
|
||||
} else {
|
||||
rtUUID = ec.Rates.GetIDWithSet(ri.Rating.Rates)
|
||||
}
|
||||
}
|
||||
return ec.Rating.GetIDWithSet(
|
||||
&RatingUnit{
|
||||
ConnectFee: ri.Rating.ConnectFee,
|
||||
RoundingMethod: ri.Rating.RoundingMethod,
|
||||
RoundingDecimals: ri.Rating.RoundingDecimals,
|
||||
MaxCost: ri.Rating.MaxCost,
|
||||
MaxCostStrategy: ri.Rating.MaxCostStrategy,
|
||||
TimingID: tmID,
|
||||
RatesID: rtUUID,
|
||||
RatingFiltersID: rfUUID,
|
||||
})
|
||||
ru := &RatingUnit{
|
||||
ConnectFee: ri.Rating.ConnectFee,
|
||||
RoundingMethod: ri.Rating.RoundingMethod,
|
||||
RoundingDecimals: ri.Rating.RoundingDecimals,
|
||||
MaxCost: ri.Rating.MaxCost,
|
||||
MaxCostStrategy: ri.Rating.MaxCostStrategy,
|
||||
TimingID: tmID,
|
||||
RatesID: rtUUID,
|
||||
RatingFiltersID: rfUUID,
|
||||
}
|
||||
if isPause {
|
||||
ec.Rating[utils.MetaPause] = ru
|
||||
return utils.MetaPause
|
||||
}
|
||||
return ec.Rating.GetIDWithSet(ru)
|
||||
}
|
||||
|
||||
func (ec *EventCost) rateIntervalForRatingID(ratingID string) (ri *RateInterval) {
|
||||
@@ -459,8 +491,18 @@ func (ec *EventCost) newIntervalFromCharge(cInc *ChargingIncrement) (incr *Incre
|
||||
|
||||
// ratingGetIDFomEventCost retrieves UUID based on data from another EventCost
|
||||
func (ec *EventCost) ratingGetIDFomEventCost(oEC *EventCost, oRatingID string) string {
|
||||
if oRatingID == "" {
|
||||
return ""
|
||||
if oRatingID == utils.EmptyString {
|
||||
return utils.EmptyString
|
||||
} else if oRatingID == utils.MetaPause {
|
||||
oCIlRating := oEC.Rating[oRatingID].Clone() // clone so we don't influence the original data
|
||||
oCIlRating.TimingID = utils.MetaPause
|
||||
ec.Timings[utils.MetaPause] = oEC.Timings[oCIlRating.TimingID]
|
||||
oCIlRating.RatingFiltersID = utils.MetaPause
|
||||
ec.RatingFilters[utils.MetaPause] = oEC.RatingFilters[oCIlRating.RatingFiltersID]
|
||||
oCIlRating.RatesID = utils.MetaPause
|
||||
ec.Rates[utils.MetaPause] = oEC.Rates[oCIlRating.RatesID]
|
||||
ec.Rating[utils.MetaPause] = oCIlRating
|
||||
return utils.MetaPause
|
||||
}
|
||||
oCIlRating := oEC.Rating[oRatingID].Clone() // clone so we don't influence the original data
|
||||
oCIlRating.TimingID = ec.Timings.GetIDWithSet(oEC.Timings[oCIlRating.TimingID])
|
||||
@@ -473,6 +515,11 @@ func (ec *EventCost) ratingGetIDFomEventCost(oEC *EventCost, oRatingID string) s
|
||||
func (ec *EventCost) accountingGetIDFromEventCost(oEC *EventCost, oAccountingID string) string {
|
||||
if oAccountingID == "" || oAccountingID == utils.MetaNone {
|
||||
return ""
|
||||
} else if oAccountingID == utils.MetaPause { // *pause represent a pause in debited session
|
||||
oBC := oEC.Accounting[oAccountingID].Clone()
|
||||
oBC.RatingID = ec.ratingGetIDFomEventCost(oEC, oBC.RatingID)
|
||||
ec.Accounting[utils.MetaPause] = oBC
|
||||
return utils.MetaPause
|
||||
}
|
||||
oBC := oEC.Accounting[oAccountingID].Clone()
|
||||
oBC.RatingID = ec.ratingGetIDFomEventCost(oEC, oBC.RatingID)
|
||||
|
||||
@@ -632,11 +632,11 @@ func NewFreeEventCost(cgrID, runID, account string, tStart time.Time, usage time
|
||||
StartTime: tStart,
|
||||
Cost: utils.Float64Pointer(0),
|
||||
Charges: []*ChargingInterval{{
|
||||
RatingID: "*free",
|
||||
RatingID: utils.MetaPause,
|
||||
Increments: []*ChargingIncrement{
|
||||
{
|
||||
Usage: usage,
|
||||
AccountingID: "*free",
|
||||
AccountingID: utils.MetaPause,
|
||||
CompressFactor: 1,
|
||||
},
|
||||
},
|
||||
@@ -644,39 +644,40 @@ func NewFreeEventCost(cgrID, runID, account string, tStart time.Time, usage time
|
||||
}},
|
||||
|
||||
Rating: Rating{
|
||||
"*free": {
|
||||
utils.MetaPause: {
|
||||
RoundingMethod: "*up",
|
||||
RoundingDecimals: 5,
|
||||
RatesID: "*free",
|
||||
RatingFiltersID: "*free",
|
||||
TimingID: "*free",
|
||||
RatesID: utils.MetaPause,
|
||||
RatingFiltersID: utils.MetaPause,
|
||||
TimingID: utils.MetaPause,
|
||||
},
|
||||
},
|
||||
Accounting: Accounting{
|
||||
"*free": {
|
||||
utils.MetaPause: {
|
||||
AccountID: account,
|
||||
// BalanceUUID: "",
|
||||
RatingID: "*free",
|
||||
RatingID: utils.MetaPause,
|
||||
},
|
||||
},
|
||||
RatingFilters: RatingFilters{
|
||||
"*free": {
|
||||
utils.MetaPause: {
|
||||
utils.Subject: "",
|
||||
utils.DestinationPrefixName: "",
|
||||
utils.DestinationID: "",
|
||||
utils.RatingPlanID: "",
|
||||
utils.RatingPlanID: utils.MetaPause,
|
||||
},
|
||||
},
|
||||
Rates: ChargedRates{
|
||||
"*free": {
|
||||
utils.MetaPause: {
|
||||
{
|
||||
RateIncrement: usage,
|
||||
RateUnit: usage,
|
||||
RateIncrement: 1,
|
||||
RateUnit: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
Timings: ChargedTimings{
|
||||
"*free": {
|
||||
utils.MetaPause: {
|
||||
|
||||
StartTime: "00:00:00",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -285,3 +285,16 @@ func (me MapEvent) AsCDR(cfg *config.CGRConfig, tnt, tmz string) (cdr *CDR, err
|
||||
func (me MapEvent) Data() map[string]interface{} {
|
||||
return me
|
||||
}
|
||||
|
||||
// GetBoolOrDefault returns the value as a bool or dflt if not present in map
|
||||
func (me MapEvent) GetBoolOrDefault(fldName string, dflt bool) (out bool) {
|
||||
fldIface, has := me[fldName]
|
||||
if !has {
|
||||
return dflt
|
||||
}
|
||||
out, err := utils.IfaceAsBool(fldIface)
|
||||
if err != nil {
|
||||
return dflt
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
367
general_tests/session5_it_test.go
Normal file
367
general_tests/session5_it_test.go
Normal file
@@ -0,0 +1,367 @@
|
||||
// +build integration
|
||||
|
||||
/*
|
||||
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 general_tests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/rpc"
|
||||
"path"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/sessions"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
ses5CfgDir string
|
||||
ses5CfgPath string
|
||||
ses5Cfg *config.CGRConfig
|
||||
ses5RPC *rpc.Client
|
||||
|
||||
ses5Tests = []func(t *testing.T){
|
||||
testSes5ItLoadConfig,
|
||||
testSes5ItResetDataDB,
|
||||
testSes5ItResetStorDb,
|
||||
testSes5ItStartEngine,
|
||||
testSes5ItRPCConn,
|
||||
testSes5ItLoadFromFolder,
|
||||
|
||||
testSes5ItAllPause,
|
||||
|
||||
testSes5ItStopCgrEngine,
|
||||
}
|
||||
)
|
||||
|
||||
func TestSes5ItSessions(t *testing.T) {
|
||||
switch *dbType {
|
||||
case utils.MetaInternal:
|
||||
ses5CfgDir = "tutinternal"
|
||||
case utils.MetaMySQL:
|
||||
ses5CfgDir = "tutmysql"
|
||||
case utils.MetaMongo:
|
||||
ses5CfgDir = "tutmongo"
|
||||
case utils.MetaPostgres:
|
||||
t.SkipNow()
|
||||
default:
|
||||
t.Fatal("Unknown Database type")
|
||||
}
|
||||
for _, stest := range ses5Tests {
|
||||
t.Run(ses5CfgDir, stest)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItLoadConfig(t *testing.T) {
|
||||
ses5CfgPath = path.Join(*dataDir, "conf", "samples", ses5CfgDir)
|
||||
if ses5Cfg, err = config.NewCGRConfigFromPath(ses5CfgPath); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItResetDataDB(t *testing.T) {
|
||||
if err := engine.InitDataDb(ses5Cfg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItResetStorDb(t *testing.T) {
|
||||
if err := engine.InitStorDb(ses5Cfg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItStartEngine(t *testing.T) {
|
||||
if _, err := engine.StopStartEngine(ses5CfgPath, *waitRater); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItRPCConn(t *testing.T) {
|
||||
var err error
|
||||
ses5RPC, err = newRPCClient(ses5Cfg.ListenCfg())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItLoadFromFolder(t *testing.T) {
|
||||
var reply string
|
||||
attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")}
|
||||
if err := ses5RPC.Call(utils.APIerSv1LoadTariffPlanFromFolder, attrs, &reply); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
func testSes5ItInitSession(t *testing.T, chargeable bool) {
|
||||
args1 := &sessions.V1InitSessionArgs{
|
||||
InitSession: true,
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
Event: map[string]interface{}{
|
||||
utils.Category: utils.Call,
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.OriginID: "TestDebitIterval",
|
||||
utils.RequestType: utils.MetaPrepaid,
|
||||
utils.AccountField: "1001",
|
||||
utils.Subject: "1001",
|
||||
utils.Destination: "1002",
|
||||
utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC),
|
||||
utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC),
|
||||
utils.Usage: time.Second,
|
||||
},
|
||||
Opts: map[string]interface{}{
|
||||
utils.OptsDebitInterval: "0s",
|
||||
utils.OptsChargeable: chargeable,
|
||||
},
|
||||
},
|
||||
}
|
||||
var rply1 sessions.V1InitSessionReply
|
||||
if err := ses5RPC.Call(utils.SessionSv1InitiateSession,
|
||||
args1, &rply1); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
} else if rply1.MaxUsage != nil && *rply1.MaxUsage != time.Second {
|
||||
t.Errorf("Unexpected MaxUsage: %v", rply1.MaxUsage)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItUpdateSession(t *testing.T, chargeable bool) {
|
||||
usage := 2 * time.Second
|
||||
updtArgs := &sessions.V1UpdateSessionArgs{
|
||||
UpdateSession: true,
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
Event: map[string]interface{}{
|
||||
utils.Category: utils.Call,
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.OriginID: "TestDebitIterval",
|
||||
utils.RequestType: utils.MetaPrepaid,
|
||||
utils.AccountField: "1001",
|
||||
utils.Subject: "1001",
|
||||
utils.Destination: "1002",
|
||||
utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC),
|
||||
utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC),
|
||||
utils.Usage: usage,
|
||||
},
|
||||
Opts: map[string]interface{}{
|
||||
utils.OptsChargeable: chargeable,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var updtRpl sessions.V1UpdateSessionReply
|
||||
if err := ses5RPC.Call(utils.SessionSv1UpdateSession, updtArgs, &updtRpl); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if updtRpl.MaxUsage == nil || *updtRpl.MaxUsage != usage {
|
||||
t.Errorf("Expecting : %+v, received: %+v", usage, updtRpl.MaxUsage)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItTerminateSession(t *testing.T, chargeable bool) {
|
||||
args := &sessions.V1TerminateSessionArgs{
|
||||
TerminateSession: true,
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
Event: map[string]interface{}{
|
||||
utils.Category: utils.Call,
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.OriginID: "TestDebitIterval",
|
||||
utils.RequestType: utils.MetaPrepaid,
|
||||
utils.AccountField: "1001",
|
||||
utils.Subject: "1002",
|
||||
utils.Destination: "1002",
|
||||
utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC),
|
||||
utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC),
|
||||
utils.Usage: 5 * time.Second,
|
||||
},
|
||||
Opts: map[string]interface{}{
|
||||
utils.OptsChargeable: chargeable,
|
||||
},
|
||||
},
|
||||
}
|
||||
var rply string
|
||||
if err := ses5RPC.Call(utils.SessionSv1TerminateSession,
|
||||
args, &rply); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if rply != utils.OK {
|
||||
t.Errorf("Unexpected reply: %s", rply)
|
||||
}
|
||||
if err := ses5RPC.Call(utils.SessionSv1ProcessCDR, &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "testSes5ItProccesCDR",
|
||||
Event: map[string]interface{}{
|
||||
utils.Category: utils.Call,
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.OriginID: "TestDebitIterval",
|
||||
utils.RequestType: utils.MetaPrepaid,
|
||||
utils.AccountField: "1001",
|
||||
utils.Subject: "1002",
|
||||
utils.Destination: "1002",
|
||||
utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC),
|
||||
utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC),
|
||||
utils.Usage: 5 * time.Second,
|
||||
},
|
||||
}, &rply); err != nil {
|
||||
t.Error(err)
|
||||
} else if rply != utils.OK {
|
||||
t.Errorf("Received reply: %s", rply)
|
||||
}
|
||||
}
|
||||
|
||||
func testSes5ItAllPause(t *testing.T) {
|
||||
testSes5ItInitSession(t, false)
|
||||
testSes5ItUpdateSession(t, false)
|
||||
testSes5ItTerminateSession(t, false)
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
var cdrs []*engine.ExternalCDR
|
||||
req := utils.RPCCDRsFilter{RequestTypes: []string{utils.MetaPrepaid}}
|
||||
if err := ses5RPC.Call(utils.APIerSv2GetCDRs, &req, &cdrs); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
}
|
||||
|
||||
exp := []*engine.ExternalCDR{{
|
||||
CGRID: "1b676c7583ceb27ad7c991ded73b2417faa29a6a",
|
||||
RunID: "*default",
|
||||
OrderID: 0,
|
||||
OriginHost: "",
|
||||
Source: "",
|
||||
OriginID: "TestDebitIterval",
|
||||
ToR: "*voice",
|
||||
RequestType: "*prepaid",
|
||||
Tenant: "cgrates.org",
|
||||
Category: "call",
|
||||
Account: "1001",
|
||||
Subject: "1001",
|
||||
Destination: "1002",
|
||||
SetupTime: "2018-01-07T19:00:00+02:00",
|
||||
AnswerTime: "2018-01-07T19:00:10+02:00",
|
||||
Usage: "5s",
|
||||
ExtraFields: map[string]string{},
|
||||
CostSource: "*sessions",
|
||||
Cost: 0,
|
||||
CostDetails: "",
|
||||
ExtraInfo: "",
|
||||
PreRated: false,
|
||||
}}
|
||||
if len(cdrs) == 0 {
|
||||
t.Fatal("No cdrs returned")
|
||||
}
|
||||
cdrs[0].OrderID = 0
|
||||
cdString := cdrs[0].CostDetails
|
||||
cdrs[0].CostDetails = ""
|
||||
if !reflect.DeepEqual(exp, cdrs) {
|
||||
t.Errorf("Expected %s \n received: %s", utils.ToJSON(exp), utils.ToJSON(cdrs))
|
||||
}
|
||||
|
||||
var cd engine.EventCost
|
||||
if err := json.Unmarshal([]byte(cdString), &cd); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
evCost := engine.EventCost{
|
||||
CGRID: "1b676c7583ceb27ad7c991ded73b2417faa29a6a",
|
||||
RunID: "*default",
|
||||
StartTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC),
|
||||
Usage: utils.DurationPointer(5 * time.Second),
|
||||
Cost: utils.Float64Pointer(0),
|
||||
Charges: []*engine.ChargingInterval{{
|
||||
RatingID: utils.MetaPause,
|
||||
Increments: []*engine.ChargingIncrement{{
|
||||
Usage: time.Second,
|
||||
Cost: 0,
|
||||
AccountingID: utils.MetaPause,
|
||||
CompressFactor: 1,
|
||||
}},
|
||||
CompressFactor: 1,
|
||||
}, {
|
||||
RatingID: utils.MetaPause,
|
||||
Increments: []*engine.ChargingIncrement{{
|
||||
Usage: 2 * time.Second,
|
||||
Cost: 0,
|
||||
AccountingID: utils.MetaPause,
|
||||
CompressFactor: 1,
|
||||
}},
|
||||
CompressFactor: 2,
|
||||
}},
|
||||
Rating: engine.Rating{
|
||||
utils.MetaPause: {
|
||||
ConnectFee: 0,
|
||||
RoundingMethod: "*up",
|
||||
RoundingDecimals: 5,
|
||||
MaxCost: 0,
|
||||
MaxCostStrategy: "",
|
||||
TimingID: "",
|
||||
RatesID: utils.MetaPause,
|
||||
RatingFiltersID: utils.MetaPause,
|
||||
},
|
||||
},
|
||||
Accounting: engine.Accounting{
|
||||
utils.MetaPause: {
|
||||
AccountID: "1001",
|
||||
BalanceUUID: "",
|
||||
RatingID: utils.MetaPause,
|
||||
Units: 0,
|
||||
ExtraChargeID: "",
|
||||
},
|
||||
},
|
||||
RatingFilters: engine.RatingFilters{
|
||||
utils.MetaPause: {
|
||||
utils.DestinationID: "",
|
||||
utils.DestinationPrefixName: "",
|
||||
utils.RatingPlanID: utils.MetaPause,
|
||||
utils.Subject: "",
|
||||
},
|
||||
},
|
||||
Rates: engine.ChargedRates{
|
||||
utils.MetaPause: {{
|
||||
GroupIntervalStart: 0,
|
||||
Value: 0,
|
||||
RateIncrement: 1,
|
||||
RateUnit: 1,
|
||||
}},
|
||||
},
|
||||
Timings: engine.ChargedTimings{
|
||||
"": {
|
||||
StartTime: "00:00:00",
|
||||
},
|
||||
},
|
||||
}
|
||||
// the Timings are not relevant for this test
|
||||
for _, r := range cd.Rating {
|
||||
r.TimingID = ""
|
||||
}
|
||||
cd.Timings = evCost.Timings
|
||||
if !reflect.DeepEqual(evCost, cd) {
|
||||
t.Errorf("Expected %s \n received: %s", utils.ToJSON(evCost), utils.ToJSON(cd))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testSes5ItStopCgrEngine(t *testing.T) {
|
||||
if err := engine.KillEngine(100); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -142,6 +142,7 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium
|
||||
* [FilterS] Optimized the automated index fields matching
|
||||
* [AgentS] Added *cfg as DataProvider for AgentRequest
|
||||
* [AgentS] Added *routes_maxcost flag
|
||||
* [SessionS] Added *sessionChargeable session option to control session charging
|
||||
|
||||
-- DanB <danb@cgrates.org> Wed, 19 Feb 2020 13:25:52 +0200
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ type Session struct {
|
||||
|
||||
debitStop chan struct{}
|
||||
sTerminator *sTerminator // automatic timeout for the session
|
||||
chargeable bool
|
||||
}
|
||||
|
||||
// Lock exported function from sync.RWMutex
|
||||
|
||||
@@ -425,6 +425,11 @@ func (sS *SessionS) debitSession(s *Session, sRunIdx int, dur time.Duration,
|
||||
return
|
||||
}
|
||||
sr := s.SRuns[sRunIdx]
|
||||
if !s.chargeable {
|
||||
sS.pause(sr, dur)
|
||||
sr.TotalUsage += sr.LastUsage
|
||||
return dur, nil
|
||||
}
|
||||
rDur := sr.debitReserve(dur, lastUsed) // debit out of reserve, rDur is still to be debited
|
||||
if rDur == time.Duration(0) {
|
||||
return dur, nil // complete debit out of reserve
|
||||
@@ -498,6 +503,27 @@ func (sS *SessionS) debitSession(s *Session, sRunIdx int, dur time.Duration,
|
||||
return
|
||||
}
|
||||
|
||||
func (sS *SessionS) pause(sr *SRun, dur time.Duration) {
|
||||
if sr.CD.LoopIndex > 0 {
|
||||
sr.CD.TimeStart = sr.CD.TimeEnd
|
||||
}
|
||||
sr.CD.TimeEnd = sr.CD.TimeStart.Add(dur)
|
||||
sr.CD.DurationIndex += dur
|
||||
ec := engine.NewFreeEventCost(sr.CD.CgrID, sr.CD.RunID, sr.CD.Account, sr.CD.TimeStart, dur)
|
||||
sr.LastUsage = dur
|
||||
sr.CD.LoopIndex++
|
||||
if sr.EventCost == nil { // is the first increment
|
||||
// when we start the call with debit interval 0
|
||||
// but later we update this value with one greater than 0
|
||||
sr.EventCost = ec
|
||||
} else { // we already debited something
|
||||
// copy the old AccountSummary as in Merge the old one is overwriten by the new one
|
||||
ec.AccountSummary = sr.EventCost.AccountSummary
|
||||
// similar to the debit merge the event costs
|
||||
sr.EventCost.Merge(ec)
|
||||
}
|
||||
}
|
||||
|
||||
// debitLoopSession will periodically debit sessions, ie: automatic prepaid
|
||||
// threadSafe since it will run into it's own goroutine
|
||||
func (sS *SessionS) debitLoopSession(s *Session, sRunIdx int,
|
||||
@@ -1121,6 +1147,7 @@ func (sS *SessionS) newSession(cgrEv *utils.CGREvent, resID, clntConnID string,
|
||||
ClientConnID: clntConnID,
|
||||
DebitInterval: dbtItval,
|
||||
}
|
||||
s.chargeable = s.OptsStart.GetBoolOrDefault(utils.OptsChargeable, true)
|
||||
if !isMsg && sS.isIndexed(s, false) { // check if already exists
|
||||
return nil, utils.ErrExists
|
||||
}
|
||||
@@ -1367,7 +1394,7 @@ func (sS *SessionS) initSessionDebitLoops(s *Session) {
|
||||
return
|
||||
}
|
||||
for i, sr := range s.SRuns {
|
||||
if s.DebitInterval != 0 &&
|
||||
if s.DebitInterval > 0 &&
|
||||
sr.Event.GetStringIgnoreErrors(utils.RequestType) == utils.MetaPrepaid {
|
||||
if s.debitStop == nil { // init the debitStop only for the first sRun with DebitInterval and RequestType MetaPrepaid
|
||||
s.debitStop = make(chan struct{})
|
||||
@@ -1450,6 +1477,7 @@ func (sS *SessionS) updateSession(s *Session, updtEv, opts engine.MapEvent, isMs
|
||||
s.updateSRuns(updtEv, sS.cgrCfg.SessionSCfg().AlterableFields)
|
||||
sS.setSTerminator(s, opts) // reset the terminator
|
||||
}
|
||||
s.chargeable = opts.GetBoolOrDefault(utils.OptsChargeable, true)
|
||||
//init has no updtEv
|
||||
if updtEv == nil {
|
||||
updtEv = engine.MapEvent(s.EventStart.Clone())
|
||||
@@ -1517,20 +1545,24 @@ func (sS *SessionS) endSession(s *Session, tUsage, lastUsage *time.Duration,
|
||||
if sr.EventCost != nil {
|
||||
if !isMsg { // in case of one time charge there is no need of corrections
|
||||
if notCharged := sUsage - sr.EventCost.GetUsage(); notCharged > 0 { // we did not charge enough, make a manual debit here
|
||||
if sr.CD.LoopIndex > 0 {
|
||||
sr.CD.TimeStart = sr.CD.TimeEnd
|
||||
}
|
||||
sr.CD.TimeEnd = sr.CD.TimeStart.Add(notCharged)
|
||||
sr.CD.DurationIndex += notCharged
|
||||
cc := new(engine.CallCost)
|
||||
if err = sS.connMgr.Call(sS.cgrCfg.SessionSCfg().RALsConns, nil, utils.ResponderDebit,
|
||||
&engine.CallDescriptorWithOpts{
|
||||
CallDescriptor: sr.CD,
|
||||
Opts: s.OptsStart,
|
||||
}, cc); err == nil {
|
||||
sr.EventCost.Merge(
|
||||
engine.NewEventCostFromCallCost(cc, s.CGRID,
|
||||
sr.Event.GetStringIgnoreErrors(utils.RunID)))
|
||||
if !s.chargeable {
|
||||
sS.pause(sr, notCharged)
|
||||
} else {
|
||||
if sr.CD.LoopIndex > 0 {
|
||||
sr.CD.TimeStart = sr.CD.TimeEnd
|
||||
}
|
||||
sr.CD.TimeEnd = sr.CD.TimeStart.Add(notCharged)
|
||||
sr.CD.DurationIndex += notCharged
|
||||
cc := new(engine.CallCost)
|
||||
if err = sS.connMgr.Call(sS.cgrCfg.SessionSCfg().RALsConns, nil, utils.ResponderDebit,
|
||||
&engine.CallDescriptorWithOpts{
|
||||
CallDescriptor: sr.CD,
|
||||
Opts: s.OptsStart,
|
||||
}, cc); err == nil {
|
||||
sr.EventCost.Merge(
|
||||
engine.NewEventCostFromCallCost(cc, s.CGRID,
|
||||
sr.Event.GetStringIgnoreErrors(utils.RunID)))
|
||||
}
|
||||
}
|
||||
} else if notCharged < 0 { // charged too much, try refund
|
||||
if err = sS.refundSession(s, sRunIdx, -notCharged); err != nil {
|
||||
@@ -2585,7 +2617,7 @@ func (sS *SessionS) BiRPCv1TerminateSession(clnt rpcclient.ClientConnector,
|
||||
dbtItvl, isMsg, args.ForceDuration); err != nil {
|
||||
return utils.NewErrRALs(err)
|
||||
}
|
||||
if _, err = sS.updateSession(s, ev, args.Opts, isMsg); err != nil {
|
||||
if _, err = sS.updateSession(s, ev, opts, isMsg); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
@@ -2593,6 +2625,9 @@ func (sS *SessionS) BiRPCv1TerminateSession(clnt rpcclient.ClientConnector,
|
||||
if !isMsg {
|
||||
s.UpdateSRuns(ev, sS.cgrCfg.SessionSCfg().AlterableFields)
|
||||
}
|
||||
s.Lock()
|
||||
s.chargeable = opts.GetBoolOrDefault(utils.OptsChargeable, true)
|
||||
s.Unlock()
|
||||
if err = sS.terminateSession(s,
|
||||
ev.GetDurationPtrIgnoreErrors(utils.Usage),
|
||||
ev.GetDurationPtrIgnoreErrors(utils.LastUsed),
|
||||
@@ -3396,6 +3431,10 @@ func (sS *SessionS) BiRPCv1ProcessEvent(clnt rpcclient.ClientConnector,
|
||||
dbtItvl, false, ralsOpts.Has(utils.MetaFD)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
s.Lock()
|
||||
s.chargeable = opts.GetBoolOrDefault(utils.OptsChargeable, true)
|
||||
s.Unlock()
|
||||
}
|
||||
if err = sS.terminateSession(s,
|
||||
ev.GetDurationPtrIgnoreErrors(utils.Usage),
|
||||
@@ -3637,7 +3676,6 @@ func (sS *SessionS) BiRPCv1DeactivateSessions(clnt rpcclient.ClientConnector,
|
||||
}
|
||||
|
||||
func (sS *SessionS) processCDR(cgrEv *utils.CGREvent, flags []string, rply *string, clnb bool) (err error) {
|
||||
|
||||
ev := engine.MapEvent(cgrEv.Event)
|
||||
cgrID := GetSetCGRID(ev)
|
||||
s := sS.getRelocateSession(cgrID,
|
||||
|
||||
@@ -308,6 +308,7 @@ func testForceSTerminatorManualTermination(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
@@ -348,6 +349,7 @@ func testForceSTerminatorPostCDRs(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
expected := "INTERNALLY_DISCONNECTED"
|
||||
@@ -384,6 +386,7 @@ func testForceSTerminatorReleaseSession(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
expected := "MANDATORY_IE_MISSING: [connIDs]"
|
||||
@@ -432,6 +435,7 @@ func testForceSTerminatorClientCall(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
expected := "MANDATORY_IE_MISSING: [connIDs]"
|
||||
@@ -464,6 +468,7 @@ func testDebitSession(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
//RunIdx cannot be higher than the length of sessions runs
|
||||
@@ -551,6 +556,7 @@ func testDebitSessionResponderMaxDebit(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
if maxDur, err := sessions.debitSession(ss, 0, 5*time.Second,
|
||||
@@ -614,6 +620,7 @@ func testDebitSessionResponderMaxDebitError(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
if maxDur, err := sessions.debitSession(ss, 0, 5*time.Minute,
|
||||
@@ -668,6 +675,7 @@ func testInitSessionDebitLoops(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
sessions.initSessionDebitLoops(ss)
|
||||
@@ -713,6 +721,7 @@ func testDebitLoopSessionErrorDebiting(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
// session already closed
|
||||
@@ -800,6 +809,7 @@ func testDebitLoopSession(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
go func() {
|
||||
if _, err := sessions.debitLoopSession(ss, 0, time.Second); err != nil {
|
||||
@@ -860,6 +870,7 @@ func testDebitLoopSessionFrcDiscLowerDbtInterval(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
go func() {
|
||||
if _, err := sessions.debitLoopSession(ss, 0, time.Second); err != nil {
|
||||
@@ -913,6 +924,7 @@ func testDebitLoopSessionLowBalance(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
sessions.cgrCfg.SessionSCfg().MinDurLowBalance = 10 * time.Second
|
||||
@@ -970,6 +982,7 @@ func testDebitLoopSessionWarningSessions(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
// will disconnect faster, MinDurLowBalance higher than the debit interval
|
||||
@@ -1031,6 +1044,7 @@ func testDebitLoopSessionDisconnectSession(t *testing.T) {
|
||||
NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
// will disconnect faster
|
||||
@@ -1085,6 +1099,7 @@ func testStoreSCost(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
if err := sessions.storeSCost(ss, 0); err != nil {
|
||||
@@ -1132,6 +1147,7 @@ func testRefundSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
expectedErr := "no event cost"
|
||||
@@ -1266,6 +1282,7 @@ func testRoundCost(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
//mocking an error API Call
|
||||
@@ -1288,6 +1305,7 @@ func testDisconnectSession(t *testing.T) {
|
||||
TotalUsage: time.Minute,
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
sTestMock := &testMockClientConn{}
|
||||
@@ -1410,6 +1428,7 @@ func testNewSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
if rcv, err := sessions.newSession(cgrEv, "resourceID", "clientConnID",
|
||||
time.Second, false, false); err != nil {
|
||||
@@ -2080,6 +2099,7 @@ func testEndSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
|
||||
activationTime := time.Date(2020, 21, 07, 10, 0, 0, 0, time.UTC)
|
||||
@@ -2196,6 +2216,7 @@ func testBiRPCv1GetActivePassiveSessions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
chargeable: true,
|
||||
}
|
||||
sr2[utils.ToR] = utils.MetaSMS
|
||||
sr2[utils.Subject] = "subject2"
|
||||
|
||||
@@ -370,6 +370,7 @@ const (
|
||||
MetaMaxCostFree = "*free"
|
||||
MetaMaxCostDisconnect = "*disconnect"
|
||||
MetaOut = "*out"
|
||||
MetaPause = "*pause"
|
||||
|
||||
MetaVoice = "*voice"
|
||||
ACD = "ACD"
|
||||
@@ -989,7 +990,6 @@ const (
|
||||
MetaActionProfiles = "*action_profiles"
|
||||
MetaAccountProfiles = "*account_profiles"
|
||||
MetaLoadIDs = "*load_ids"
|
||||
MetaAccountS = "*accounts"
|
||||
)
|
||||
|
||||
// MetaMetrics
|
||||
@@ -2500,11 +2500,12 @@ var (
|
||||
)
|
||||
|
||||
// CGROptionsSet the possible cgr options
|
||||
var CGROptionsSet = NewStringSet([]string{OptsRatesStartTime, OptsRatesUsage, OptsSessionTTL, OptsSessionTTLMaxDelay,
|
||||
OptsSessionTTLLastUsed, OptsSessionTTLLastUsage, OptsSessionTTLUsage, OptsDebitInterval, OptsStirATest,
|
||||
OptsStirPayloadMaxDuration, OptsStirIdentity, OptsStirOriginatorTn, OptsStirOriginatorURI,
|
||||
OptsStirDestinationTn, OptsStirDestinationURI, OptsStirPublicKeyPath, OptsStirPrivateKeyPath,
|
||||
OptsAPIKey, OptsRouteID, OptsContext, OptsAttributesProcessRuns, OptsRoutesLimit, OptsRoutesOffset})
|
||||
var CGROptionsSet = NewStringSet([]string{OptsRatesStartTime, OptsRatesUsage, OptsSessionTTL,
|
||||
OptsSessionTTLMaxDelay, OptsSessionTTLLastUsed, OptsSessionTTLLastUsage, OptsSessionTTLUsage,
|
||||
OptsDebitInterval, OptsStirATest, OptsStirPayloadMaxDuration, OptsStirIdentity,
|
||||
OptsStirOriginatorTn, OptsStirOriginatorURI, OptsStirDestinationTn, OptsStirDestinationURI,
|
||||
OptsStirPublicKeyPath, OptsStirPrivateKeyPath, OptsAPIKey, OptsRouteID, OptsContext,
|
||||
OptsAttributesProcessRuns, OptsRoutesLimit, OptsRoutesOffset, OptsChargeable})
|
||||
|
||||
// EventExporter metrics
|
||||
const (
|
||||
@@ -2536,6 +2537,7 @@ const (
|
||||
OptsSessionTTLLastUsage = "*sessionTTLLastUsage"
|
||||
OptsSessionTTLUsage = "*sessionTTLUsage"
|
||||
OptsDebitInterval = "*sessionDebitInterval"
|
||||
OptsChargeable = "*sessionChargeable"
|
||||
// STIR
|
||||
OptsStirATest = "*stirATest"
|
||||
OptsStirPayloadMaxDuration = "*stirPayloadMaxDuration"
|
||||
|
||||
Reference in New Issue
Block a user