EventCost.SyncKeys method with tests

This commit is contained in:
DanB
2019-02-28 19:30:01 +01:00
parent 1525797b08
commit 43296dd9e8
5 changed files with 370 additions and 4 deletions

View File

@@ -53,6 +53,7 @@ var sTestsAlsPrf = []func(t *testing.T){
testAttributeSGetAttributeForEventNotFound,
testAttributeSGetAttributeForEventWithMetaAnyContext,
testAttributeSProcessEvent,
testAttributeSProcessEventNotFound,
testAttributeSProcessEventMissing,
testAttributeSProcessEventWithNoneSubstitute,
testAttributeSProcessEventWithNoneSubstitute2,
@@ -356,6 +357,26 @@ func testAttributeSProcessEvent(t *testing.T) {
}
}
func testAttributeSProcessEventNotFound(t *testing.T) {
ev := &engine.AttrArgsProcessEvent{
Context: utils.StringPointer(utils.MetaSessionS),
CGREvent: utils.CGREvent{
Tenant: "cgrates.org",
ID: "testAttributeSProcessEventNotFound",
Event: map[string]interface{}{
utils.Account: "Inexistent",
utils.Destination: "+491511231234",
},
},
}
var rplyEv engine.AttrSProcessEventReply
if err := attrSRPC.Call(utils.AttributeSv1ProcessEvent,
ev, &rplyEv); err == nil ||
err.Error() != utils.ErrNotFound.Error() {
t.Error(err)
}
}
func testAttributeSProcessEventMissing(t *testing.T) {
ev := &engine.AttrArgsProcessEvent{
Context: utils.StringPointer(utils.MetaSessionS),
@@ -369,10 +390,10 @@ func testAttributeSProcessEventMissing(t *testing.T) {
},
},
}
var rplyEv engine.AttrSProcessEventReply
if err := attrSRPC.Call(utils.AttributeSv1ProcessEvent,
ev, &rplyEv); err == nil && err != utils.ErrMandatoryIeMissing {
ev, &rplyEv); err == nil ||
err.Error() != utils.ErrMandatoryIeMissing.Error() {
t.Error(err)
}
}
@@ -652,7 +673,8 @@ func testAttributeSProcessEventWithHeader(t *testing.T) {
func testAttributeSGetAttPrfIDs(t *testing.T) {
expected := []string{"ATTR_2", "ATTR_1", "ATTR_3", "ATTR_Header", "AttributeWithNonSubstitute"}
var result []string
if err := attrSRPC.Call("ApierV1.GetAttributeProfileIDs", "", &result); err == nil || err.Error() != utils.NewErrMandatoryIeMissing("Tenant").Error() {
if err := attrSRPC.Call("ApierV1.GetAttributeProfileIDs", "", &result); err == nil ||
err.Error() != utils.NewErrMandatoryIeMissing("Tenant").Error() {
t.Errorf("Expected error recived reply %+v with err=%v", result, err)
}
if err := attrSRPC.Call("ApierV1.GetAttributeProfileIDs", "cgrates.org", &result); err != nil {

View File

@@ -397,6 +397,107 @@ func (ec *EventCost) appendChargingIntervalFromEventCost(oEC *EventCost, cIlIdx
}
}
// SyncKeys will sync the keys present into ec with the ones in refEC
func (ec *EventCost) SyncKeys(refEC *EventCost) {
// sync RatingFilters
sncedRFilterIDs := make(map[string]string)
for key, rf := range ec.RatingFilters {
for refKey, refRf := range refEC.RatingFilters {
if rf.Equals(refRf) {
delete(ec.RatingFilters, key)
sncedRFilterIDs[key] = refKey
ec.RatingFilters[refKey] = rf
break
}
}
}
// sync Rates
sncedRateIDs := make(map[string]string)
for key, rt := range ec.Rates {
for refKey, refRt := range refEC.Rates {
if rt.Equals(refRt) {
delete(ec.Rates, key)
sncedRateIDs[key] = refKey
ec.Rates[refKey] = rt
break
}
}
}
// sync Timings
sncedTimingIDs := make(map[string]string)
for key, tm := range ec.Timings {
for refKey, refTm := range refEC.Timings {
if tm.Equals(refTm) {
delete(ec.Timings, key)
sncedTimingIDs[key] = refKey
ec.Timings[refKey] = tm
break
}
}
}
// sync Rating
sncedRatingIDs := make(map[string]string)
for key, ru := range ec.Rating {
if tmRefKey, has := sncedTimingIDs[ru.TimingID]; has {
ru.TimingID = tmRefKey
}
if rtRefID, has := sncedRateIDs[ru.RatesID]; has {
ru.RatesID = rtRefID
}
if rfRefID, has := sncedRFilterIDs[ru.RatingFiltersID]; has {
ru.RatingFiltersID = rfRefID
}
for refKey, refRU := range refEC.Rating {
if ru.Equals(refRU) {
delete(ec.Rating, key)
sncedRatingIDs[key] = refKey
ec.Rating[refKey] = ru
break
}
}
}
// sync Accounting
sncedAcntIDs := make(map[string]string)
for key, acnt := range ec.Accounting {
for refKey, refAcnt := range refEC.Accounting {
if acnt.Equals(refAcnt) {
delete(ec.Accounting, key)
sncedAcntIDs[key] = refKey
ec.Accounting[refKey] = acnt
break
}
}
}
// correct the ExtraCharge
for _, acnt := range ec.Accounting {
if acntRefID, has := sncedAcntIDs[acnt.ExtraChargeID]; has {
acnt.ExtraChargeID = acntRefID
}
}
// need another sync for the corrected ExtraChargeIDs
for key, acnt := range ec.Accounting {
for refKey, refAcnt := range refEC.Accounting {
if acnt.Equals(refAcnt) {
delete(ec.Accounting, key)
sncedAcntIDs[key] = refKey
ec.Accounting[refKey] = acnt
break
}
}
}
// sync Charges
for _, ci := range ec.Charges {
if refRatingID, has := sncedRatingIDs[ci.RatingID]; has {
ci.RatingID = refRatingID
}
for _, cIcrmt := range ci.Increments {
if refAcntID, has := sncedAcntIDs[cIcrmt.AccountingID]; has {
cIcrmt.AccountingID = refAcntID
}
}
}
}
// Merge will merge a list of EventCosts into this one
func (ec *EventCost) Merge(ecs ...*EventCost) {
for _, newEC := range ecs {

View File

@@ -2030,3 +2030,244 @@ func TestECAppendCIlFromEC(t *testing.T) {
t.Errorf("expecting: %s, received: %s", utils.ToJSON(eEC), utils.ToJSON(ec))
}
}
func TestECSyncKeys(t *testing.T) {
ec := testEC.Clone()
refEC := &EventCost{
Rating: Rating{
"21a5ab9": &RatingUnit{
ConnectFee: 0.1,
RoundingMethod: "*up",
RoundingDecimals: 5,
TimingID: "2f324ab",
RatesID: "2c1a177",
RatingFiltersID: "23e77dc",
},
},
Accounting: Accounting{
"2012888": &BalanceCharge{
AccountID: "cgrates.org:dan",
BalanceUUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
Units: 0.01,
},
"288bfa6": &BalanceCharge{
AccountID: "cgrates.org:dan",
BalanceUUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
Units: 0.005,
},
"24d6c02": &BalanceCharge{
AccountID: "cgrates.org:dan",
BalanceUUID: "7a54a9e9-d610-4c82-bcb5-a315b9a65010",
RatingID: "3cd6425",
Units: 1,
ExtraChargeID: "288bfa6",
},
},
RatingFilters: RatingFilters{
"23e77dc": RatingMatchedFilters{
"DestinationID": "GERMANY",
"DestinationPrefix": "+49",
"RatingPlanID": "RPL_RETAIL1",
"Subject": "*out:cgrates.org:call:*any",
},
},
Timings: ChargedTimings{
"2f324ab": &ChargedTiming{
StartTime: "00:00:00",
},
},
Rates: ChargedRates{
"2c1a177": RateGroups{
&Rate{
GroupIntervalStart: time.Duration(0),
Value: 0.01,
RateIncrement: time.Duration(1 * time.Minute),
RateUnit: time.Duration(1 * time.Second)},
},
},
}
eEC := &EventCost{
CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41",
RunID: utils.META_DEFAULT,
StartTime: time.Date(2017, 1, 9, 16, 18, 21, 0, time.UTC),
Charges: []*ChargingInterval{
&ChargingInterval{
RatingID: "21a5ab9",
Increments: []*ChargingIncrement{
&ChargingIncrement{
Usage: time.Duration(0),
Cost: 0.1,
AccountingID: "9bdad10",
CompressFactor: 1,
},
&ChargingIncrement{
Usage: time.Duration(1 * time.Second),
Cost: 0,
AccountingID: "3455b83",
CompressFactor: 10,
},
&ChargingIncrement{
Usage: time.Duration(10 * time.Second),
Cost: 0.01,
AccountingID: "2012888",
CompressFactor: 2,
},
&ChargingIncrement{
Usage: time.Duration(1 * time.Second),
Cost: 0.005,
AccountingID: "24d6c02",
CompressFactor: 30,
},
},
CompressFactor: 1,
},
&ChargingInterval{
RatingID: "21a5ab9",
Increments: []*ChargingIncrement{
&ChargingIncrement{
Usage: time.Duration(1 * time.Second),
Cost: 0.01,
AccountingID: "2012888",
CompressFactor: 60,
},
},
CompressFactor: 4,
},
&ChargingInterval{
RatingID: "21a5ab9",
Increments: []*ChargingIncrement{
&ChargingIncrement{
Usage: time.Duration(1 * time.Second),
Cost: 0,
AccountingID: "3455b83",
CompressFactor: 10,
},
&ChargingIncrement{
Usage: time.Duration(10 * time.Second),
Cost: 0.01,
AccountingID: "2012888",
CompressFactor: 2,
},
&ChargingIncrement{
Usage: time.Duration(1 * time.Second),
Cost: 0.005,
AccountingID: "24d6c02",
CompressFactor: 30,
},
},
CompressFactor: 5,
},
},
AccountSummary: &AccountSummary{
Tenant: "cgrates.org",
ID: "dan",
BalanceSummaries: []*BalanceSummary{
&BalanceSummary{
Type: "*monetary",
Value: 50,
Disabled: false},
&BalanceSummary{
ID: "4b8b53d7-c1a1-4159-b845-4623a00a0165",
Type: "*monetary",
Value: 25,
Disabled: false},
&BalanceSummary{
Type: "*voice",
Value: 200,
Disabled: false,
},
},
AllowNegative: false,
Disabled: false,
},
Rating: Rating{
"3cd6425": &RatingUnit{
RoundingMethod: "*up",
RoundingDecimals: 5,
TimingID: "2f324ab",
RatesID: "4910ecf",
RatingFiltersID: "23e77dc",
},
"21a5ab9": &RatingUnit{
ConnectFee: 0.1,
RoundingMethod: "*up",
RoundingDecimals: 5,
TimingID: "2f324ab",
RatesID: "2c1a177",
RatingFiltersID: "23e77dc",
},
},
Accounting: Accounting{
"2012888": &BalanceCharge{
AccountID: "cgrates.org:dan",
BalanceUUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
Units: 0.01,
},
"288bfa6": &BalanceCharge{
AccountID: "cgrates.org:dan",
BalanceUUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
Units: 0.005,
},
"9bdad10": &BalanceCharge{
AccountID: "cgrates.org:dan",
BalanceUUID: "8c54a9e9-d610-4c82-bcb5-a315b9a65010",
Units: 0.1,
},
"24d6c02": &BalanceCharge{
AccountID: "cgrates.org:dan",
BalanceUUID: "7a54a9e9-d610-4c82-bcb5-a315b9a65010",
RatingID: "3cd6425",
Units: 1,
ExtraChargeID: "288bfa6",
},
"3455b83": &BalanceCharge{
AccountID: "cgrates.org:dan",
BalanceUUID: "9d54a9e9-d610-4c82-bcb5-a315b9a65089",
Units: 1,
ExtraChargeID: "*none",
},
},
RatingFilters: RatingFilters{
"23e77dc": RatingMatchedFilters{
"DestinationID": "GERMANY",
"DestinationPrefix": "+49",
"RatingPlanID": "RPL_RETAIL1",
"Subject": "*out:cgrates.org:call:*any",
},
},
Rates: ChargedRates{
"2c1a177": RateGroups{
&Rate{
GroupIntervalStart: time.Duration(0),
Value: 0.01,
RateIncrement: time.Duration(1 * time.Minute),
RateUnit: time.Duration(1 * time.Second)},
},
"4910ecf": 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{
"2f324ab": &ChargedTiming{
StartTime: "00:00:00",
},
},
}
ec.SyncKeys(refEC)
if !reflect.DeepEqual(eEC, ec) {
t.Errorf("expecting: %s \nreceived: %s",
utils.ToIJSON(eEC), utils.ToIJSON(ec))
}
}

View File

@@ -460,7 +460,7 @@ func (sS *SessionS) debitSession(s *Session, sRunIdx int, dur time.Duration,
cd := sr.CD.Clone()
s.Unlock()
cc := new(engine.CallCost)
if err := sS.ralS.Call("Responder.MaxDebit", cd, cc); err != nil {
if err := sS.ralS.Call(utils.ResponderMaxDebit, cd, cc); err != nil {
s.Lock()
sr.ExtraDuration += dbtRsrv
s.Unlock()
@@ -489,6 +489,7 @@ func (sS *SessionS) debitSession(s *Session, sRunIdx int, dur time.Duration,
sr.EventCost = ec
}
} else {
ec.SyncKeys(sr.EventCost)
sr.EventCost.Merge(ec)
}
maxDur = sr.LastUsage

View File

@@ -785,6 +785,7 @@ const (
ResponderRefundIncrements = "Responder.RefundIncrements"
ResponderGetMaxSessionTime = "Responder.GetMaxSessionTime"
ResponderStatus = "Responder.Status"
ResponderMaxDebit = "Responder.MaxDebit"
)
// DispatcherS APIs