mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
EventCost compressing at ChargingIncrement level during Merge
This commit is contained in:
@@ -344,18 +344,46 @@ func (ec *EventCost) accountingGetIDFromEventCost(oEC *EventCost, oAccountingID
|
||||
return ec.Accounting.GetIDWithSet(oBC)
|
||||
}
|
||||
|
||||
// appendCIl appends a ChargingInterval to existing chargers, no compression done
|
||||
// appendCIl appends a ChargingInterval to existing chargers
|
||||
// no compression done at ChargingInterval level, attempted on ChargingIncrement level
|
||||
func (ec *EventCost) appendCIlFromEC(oEC *EventCost, cIlIdx int) {
|
||||
cIl := oEC.Charges[cIlIdx]
|
||||
cIl.RatingID = ec.ratingGetIDFomEventCost(oEC, cIl.RatingID)
|
||||
for _, cIt := range cIl.Increments {
|
||||
cIt.AccountingID = ec.accountingGetIDFromEventCost(oEC, cIt.AccountingID)
|
||||
lastCIl := ec.Charges[len(ec.Charges)-1]
|
||||
lastCIt := lastCIl.Increments[len(lastCIl.Increments)-1]
|
||||
appendChargingIncrement := lastCIl.CompressFactor == 1 &&
|
||||
lastCIl.RatingID == cIl.RatingID // attempt compressing of the ChargingIncrements
|
||||
var idxFirstCIt *int // keep here the reference towards last not appended charging increment so we can create separate ChargingInterval
|
||||
var idxLastCF *int // reference towards last compress not absorbed by ec.Charges
|
||||
for cF := cIl.CompressFactor; cF > 0; cF-- {
|
||||
for i, cIt := range cIl.Increments {
|
||||
cIt.AccountingID = ec.accountingGetIDFromEventCost(oEC, cIt.AccountingID)
|
||||
if idxFirstCIt != nil {
|
||||
continue
|
||||
}
|
||||
if !appendChargingIncrement ||
|
||||
!lastCIt.PartiallyEquals(cIt) {
|
||||
idxFirstCIt = utils.IntPointer(i)
|
||||
idxLastCF = utils.IntPointer(cF)
|
||||
continue
|
||||
}
|
||||
lastCIt.CompressFactor += cIt.CompressFactor // compress the iterated ChargingIncrement
|
||||
}
|
||||
}
|
||||
if idxFirstCIt != nil { // CIt was not completely absorbed
|
||||
cIlCln := cIl.Clone()
|
||||
cIlCln.CompressFactor = 1
|
||||
cIlCln.Increments = cIlCln.Increments[*idxFirstCIt:]
|
||||
ec.Charges = append(ec.Charges, cIlCln)
|
||||
if *idxLastCF > 1 { // add the remaining part out of original ChargingInterval
|
||||
cIl.CompressFactor = *idxLastCF - 1
|
||||
ec.Charges = append(ec.Charges, cIl)
|
||||
}
|
||||
}
|
||||
ec.Charges = append(ec.Charges, cIl)
|
||||
}
|
||||
|
||||
// AppendChargingInterval appends or compresses a &ChargingInterval to existing ec.Chargers
|
||||
func (ec *EventCost) AppendChargingIntervalFromEventCost(oEC *EventCost, cIlIdx int) {
|
||||
func (ec *EventCost) appendChargingIntervalFromEventCost(oEC *EventCost, cIlIdx int) {
|
||||
lenChargers := len(ec.Charges)
|
||||
if lenChargers != 0 && ec.Charges[lenChargers-1].PartiallyEquals(oEC.Charges[cIlIdx]) {
|
||||
ec.Charges[lenChargers-1].CompressFactor += 1
|
||||
@@ -369,7 +397,7 @@ func (ec *EventCost) Merge(ecs ...*EventCost) {
|
||||
for _, newEC := range ecs {
|
||||
ec.AccountSummary = newEC.AccountSummary // updated AccountSummary information
|
||||
for cIlIdx := range newEC.Charges {
|
||||
ec.AppendChargingIntervalFromEventCost(newEC, cIlIdx)
|
||||
ec.appendChargingIntervalFromEventCost(newEC, cIlIdx)
|
||||
}
|
||||
}
|
||||
ec.ResetCounters()
|
||||
|
||||
@@ -1225,18 +1225,6 @@ func TestECTrimMUsage(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
/*
|
||||
|
||||
ec = testEC.Clone()
|
||||
atUsage = time.Duration(61 * time.Second)
|
||||
srplsEC, _ = ec.Trim(atUsage)
|
||||
if ec.GetUsage() != atUsage {
|
||||
t.Errorf("Wrongly trimmed EC: %s", utils.ToJSON(ec))
|
||||
}
|
||||
if srplsEC.GetUsage() != time.Duration(239*time.Second) {
|
||||
t.Errorf("Wrong surplusEC: %s", utils.ToJSON(srplsEC))
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1290,3 +1278,327 @@ func TestECMerge(t *testing.T) {
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func TestECMergeGT(t *testing.T) {
|
||||
// InitialEventCost
|
||||
ecGT := &EventCost{
|
||||
CGRID: "7636f3f1a06dffa038ba7900fb57f52d28830a24",
|
||||
RunID: utils.META_DEFAULT,
|
||||
StartTime: time.Date(2018, 7, 27, 0, 59, 21, 0, time.UTC),
|
||||
Charges: []*ChargingInterval{
|
||||
&ChargingInterval{
|
||||
RatingID: "cc68da4",
|
||||
Increments: []*ChargingIncrement{
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(102400),
|
||||
AccountingID: "0d87a64",
|
||||
CompressFactor: 103,
|
||||
},
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
},
|
||||
AccountSummary: &AccountSummary{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "dan",
|
||||
BalanceSummaries: []*BalanceSummary{
|
||||
&BalanceSummary{
|
||||
UUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
ID: "addon_data",
|
||||
Type: utils.DATA,
|
||||
Value: 10726871040},
|
||||
},
|
||||
},
|
||||
Rating: Rating{
|
||||
"cc68da4": &RatingUnit{
|
||||
RatesID: "06dee2e",
|
||||
RatingFiltersID: "216b0a5",
|
||||
},
|
||||
},
|
||||
Accounting: Accounting{
|
||||
"0d87a64": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
Units: 102400,
|
||||
ExtraChargeID: utils.META_NONE,
|
||||
},
|
||||
},
|
||||
RatingFilters: RatingFilters{
|
||||
"216b0a5": RatingMatchedFilters{
|
||||
"DestinationID": utils.META_ANY,
|
||||
"DestinationPrefix": "42502",
|
||||
"RatingPlanID": utils.META_NONE,
|
||||
"Subject": "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
},
|
||||
},
|
||||
Rates: ChargedRates{
|
||||
"06dee2e": RateGroups{
|
||||
&Rate{
|
||||
RateIncrement: time.Duration(102400),
|
||||
RateUnit: time.Duration(102400)},
|
||||
},
|
||||
},
|
||||
}
|
||||
ecGTUpdt := &EventCost{
|
||||
CGRID: "7636f3f1a06dffa038ba7900fb57f52d28830a24",
|
||||
RunID: utils.META_DEFAULT,
|
||||
StartTime: time.Date(2018, 7, 27, 0, 59, 38, 0105472, time.UTC),
|
||||
Charges: []*ChargingInterval{
|
||||
&ChargingInterval{
|
||||
RatingID: "6a83227",
|
||||
Increments: []*ChargingIncrement{
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(102400),
|
||||
AccountingID: "9288f93",
|
||||
CompressFactor: 84,
|
||||
},
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
},
|
||||
AccountSummary: &AccountSummary{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "dan",
|
||||
BalanceSummaries: []*BalanceSummary{
|
||||
&BalanceSummary{
|
||||
UUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
ID: "addon_data",
|
||||
Type: utils.DATA,
|
||||
Value: 10718269440},
|
||||
},
|
||||
},
|
||||
Rating: Rating{
|
||||
"6a83227": &RatingUnit{
|
||||
RatesID: "52f8b0f",
|
||||
RatingFiltersID: "17f7216",
|
||||
},
|
||||
},
|
||||
Accounting: Accounting{
|
||||
"9288f93": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
Units: 102400,
|
||||
ExtraChargeID: utils.META_NONE,
|
||||
},
|
||||
},
|
||||
RatingFilters: RatingFilters{
|
||||
"17f7216": RatingMatchedFilters{
|
||||
"DestinationID": utils.META_ANY,
|
||||
"DestinationPrefix": "42502",
|
||||
"RatingPlanID": utils.META_NONE,
|
||||
"Subject": "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
},
|
||||
},
|
||||
Rates: ChargedRates{
|
||||
"52f8b0f": RateGroups{
|
||||
&Rate{
|
||||
RateIncrement: time.Duration(102400),
|
||||
RateUnit: time.Duration(102400)},
|
||||
},
|
||||
},
|
||||
}
|
||||
ecGT.Merge(ecGTUpdt)
|
||||
ecExpct := &EventCost{
|
||||
CGRID: "7636f3f1a06dffa038ba7900fb57f52d28830a24",
|
||||
RunID: utils.META_DEFAULT,
|
||||
StartTime: time.Date(2018, 7, 27, 0, 59, 21, 0, time.UTC),
|
||||
Charges: []*ChargingInterval{
|
||||
&ChargingInterval{
|
||||
RatingID: "cc68da4",
|
||||
Increments: []*ChargingIncrement{
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(102400),
|
||||
AccountingID: "0d87a64",
|
||||
CompressFactor: 187,
|
||||
},
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
},
|
||||
AccountSummary: &AccountSummary{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "dan",
|
||||
BalanceSummaries: []*BalanceSummary{
|
||||
&BalanceSummary{
|
||||
UUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
ID: "addon_data",
|
||||
Type: utils.DATA,
|
||||
Value: 10718269440},
|
||||
},
|
||||
},
|
||||
Rating: Rating{
|
||||
"cc68da4": &RatingUnit{
|
||||
RatesID: "06dee2e",
|
||||
RatingFiltersID: "216b0a5",
|
||||
},
|
||||
},
|
||||
Accounting: Accounting{
|
||||
"0d87a64": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
Units: 102400,
|
||||
ExtraChargeID: utils.META_NONE,
|
||||
},
|
||||
},
|
||||
RatingFilters: RatingFilters{
|
||||
"216b0a5": RatingMatchedFilters{
|
||||
"DestinationID": utils.META_ANY,
|
||||
"DestinationPrefix": "42502",
|
||||
"RatingPlanID": utils.META_NONE,
|
||||
"Subject": "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
},
|
||||
},
|
||||
Rates: ChargedRates{
|
||||
"06dee2e": RateGroups{
|
||||
&Rate{
|
||||
RateIncrement: time.Duration(102400),
|
||||
RateUnit: time.Duration(102400)},
|
||||
},
|
||||
},
|
||||
}
|
||||
if len(ecGT.Charges) != len(ecExpct.Charges) ||
|
||||
!reflect.DeepEqual(ecGT.Charges[0].TotalUsage(), ecExpct.Charges[0].TotalUsage()) ||
|
||||
!reflect.DeepEqual(ecGT.Charges[0].TotalCost(), ecExpct.Charges[0].TotalCost()) {
|
||||
t.Errorf("expecting: %s\n\n, received: %s",
|
||||
utils.ToJSON(ecExpct), utils.ToJSON(ecGT))
|
||||
}
|
||||
}
|
||||
|
||||
func TestECAppendCIlFromEC(t *testing.T) {
|
||||
ec := &EventCost{
|
||||
Charges: []*ChargingInterval{
|
||||
&ChargingInterval{
|
||||
RatingID: "cc68da4",
|
||||
Increments: []*ChargingIncrement{
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(102400),
|
||||
AccountingID: "0d87a64",
|
||||
CompressFactor: 103,
|
||||
},
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
},
|
||||
Rating: Rating{
|
||||
"cc68da4": &RatingUnit{
|
||||
RatesID: "06dee2e",
|
||||
RatingFiltersID: "216b0a5",
|
||||
},
|
||||
},
|
||||
Accounting: Accounting{
|
||||
"0d87a64": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
Units: 102400,
|
||||
ExtraChargeID: utils.META_NONE,
|
||||
},
|
||||
},
|
||||
RatingFilters: RatingFilters{
|
||||
"216b0a5": RatingMatchedFilters{
|
||||
"DestinationID": utils.META_ANY,
|
||||
"DestinationPrefix": "42502",
|
||||
"RatingPlanID": utils.META_NONE,
|
||||
"Subject": "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
},
|
||||
},
|
||||
Rates: ChargedRates{
|
||||
"06dee2e": RateGroups{
|
||||
&Rate{
|
||||
RateIncrement: time.Duration(102400),
|
||||
RateUnit: time.Duration(102400)},
|
||||
},
|
||||
},
|
||||
}
|
||||
oEC := &EventCost{
|
||||
Charges: []*ChargingInterval{
|
||||
&ChargingInterval{
|
||||
RatingID: "6a83227",
|
||||
Increments: []*ChargingIncrement{
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(102400),
|
||||
AccountingID: "9288f93",
|
||||
CompressFactor: 84,
|
||||
},
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
},
|
||||
Rating: Rating{
|
||||
"6a83227": &RatingUnit{
|
||||
RatesID: "52f8b0f",
|
||||
RatingFiltersID: "17f7216",
|
||||
},
|
||||
},
|
||||
Accounting: Accounting{
|
||||
"9288f93": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
Units: 102400,
|
||||
ExtraChargeID: utils.META_NONE,
|
||||
},
|
||||
},
|
||||
RatingFilters: RatingFilters{
|
||||
"17f7216": RatingMatchedFilters{
|
||||
"DestinationID": utils.META_ANY,
|
||||
"DestinationPrefix": "42502",
|
||||
"RatingPlanID": utils.META_NONE,
|
||||
"Subject": "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
},
|
||||
},
|
||||
Rates: ChargedRates{
|
||||
"52f8b0f": RateGroups{
|
||||
&Rate{
|
||||
RateIncrement: time.Duration(102400),
|
||||
RateUnit: time.Duration(102400)},
|
||||
},
|
||||
},
|
||||
}
|
||||
ec.appendCIlFromEC(oEC, 0)
|
||||
eEC := &EventCost{
|
||||
Charges: []*ChargingInterval{
|
||||
&ChargingInterval{
|
||||
RatingID: "cc68da4",
|
||||
Increments: []*ChargingIncrement{
|
||||
&ChargingIncrement{
|
||||
Usage: time.Duration(102400),
|
||||
AccountingID: "0d87a64",
|
||||
CompressFactor: 187,
|
||||
},
|
||||
},
|
||||
CompressFactor: 1,
|
||||
},
|
||||
},
|
||||
Rating: Rating{
|
||||
"cc68da4": &RatingUnit{
|
||||
RatesID: "06dee2e",
|
||||
RatingFiltersID: "216b0a5",
|
||||
},
|
||||
},
|
||||
Accounting: Accounting{
|
||||
"0d87a64": &BalanceCharge{
|
||||
AccountID: "cgrates.org:dan",
|
||||
BalanceUUID: "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
Units: 102400,
|
||||
ExtraChargeID: utils.META_NONE,
|
||||
},
|
||||
},
|
||||
RatingFilters: RatingFilters{
|
||||
"216b0a5": RatingMatchedFilters{
|
||||
"DestinationID": utils.META_ANY,
|
||||
"DestinationPrefix": "42502",
|
||||
"RatingPlanID": utils.META_NONE,
|
||||
"Subject": "9a767726-fe69-4940-b7bd-f43de9f0f8a5",
|
||||
},
|
||||
},
|
||||
Rates: ChargedRates{
|
||||
"06dee2e": RateGroups{
|
||||
&Rate{
|
||||
RateIncrement: time.Duration(102400),
|
||||
RateUnit: time.Duration(102400)},
|
||||
},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(eEC, ec) {
|
||||
t.Errorf("expecting: %s, received: %s", utils.ToJSON(eEC), utils.ToJSON(ec))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,18 +36,17 @@ type ChargingInterval struct {
|
||||
}
|
||||
|
||||
// PartiallyEquals does not compare CompressFactor, usefull for Merge
|
||||
func (cIl *ChargingInterval) PartiallyEquals(oCIl *ChargingInterval) (equals bool) {
|
||||
if equals = cIl.RatingID == oCIl.RatingID &&
|
||||
func (cIl *ChargingInterval) PartiallyEquals(oCIl *ChargingInterval) bool {
|
||||
if equals := cIl.RatingID == oCIl.RatingID &&
|
||||
len(cIl.Increments) == len(oCIl.Increments); !equals {
|
||||
return
|
||||
return false
|
||||
}
|
||||
for i := range cIl.Increments {
|
||||
if !cIl.Increments[i].Equals(oCIl.Increments[i]) {
|
||||
equals = false
|
||||
break
|
||||
return false
|
||||
}
|
||||
}
|
||||
return
|
||||
return true
|
||||
}
|
||||
|
||||
// Usage computes the total usage of this ChargingInterval, ignoring CompressFactor
|
||||
@@ -136,6 +135,13 @@ func (cIt *ChargingIncrement) Equals(oCIt *ChargingIncrement) bool {
|
||||
cIt.CompressFactor == oCIt.CompressFactor
|
||||
}
|
||||
|
||||
// PartiallyEquals ignores the CompressFactor when comparing
|
||||
func (cIt *ChargingIncrement) PartiallyEquals(oCIt *ChargingIncrement) bool {
|
||||
return cIt.Usage == oCIt.Usage &&
|
||||
cIt.Cost == oCIt.Cost &&
|
||||
cIt.AccountingID == oCIt.AccountingID
|
||||
}
|
||||
|
||||
func (cIt *ChargingIncrement) Clone() (cln *ChargingIncrement) {
|
||||
cln = new(ChargingIncrement)
|
||||
*cln = *cIt
|
||||
@@ -161,11 +167,19 @@ type BalanceCharge struct {
|
||||
}
|
||||
|
||||
func (bc *BalanceCharge) Equals(oBC *BalanceCharge) bool {
|
||||
bcExtraChargeID := bc.ExtraChargeID
|
||||
if bcExtraChargeID == "" {
|
||||
bcExtraChargeID = utils.META_NONE
|
||||
}
|
||||
oBCExtraChargerID := oBC.ExtraChargeID
|
||||
if oBCExtraChargerID == "" { // so we can compare them properly
|
||||
oBCExtraChargerID = utils.META_NONE
|
||||
}
|
||||
return bc.AccountID == oBC.AccountID &&
|
||||
bc.BalanceUUID == oBC.BalanceUUID &&
|
||||
bc.RatingID == oBC.RatingID &&
|
||||
bc.Units == oBC.Units &&
|
||||
bc.ExtraChargeID == oBC.ExtraChargeID
|
||||
bcExtraChargeID == oBCExtraChargerID
|
||||
}
|
||||
|
||||
func (bc *BalanceCharge) Clone() *BalanceCharge {
|
||||
@@ -176,15 +190,13 @@ func (bc *BalanceCharge) Clone() *BalanceCharge {
|
||||
|
||||
type RatingMatchedFilters map[string]interface{}
|
||||
|
||||
func (rf RatingMatchedFilters) Equals(oRF RatingMatchedFilters) (equals bool) {
|
||||
equals = true
|
||||
func (rf RatingMatchedFilters) Equals(oRF RatingMatchedFilters) bool {
|
||||
for k := range rf {
|
||||
if rf[k] != oRF[k] {
|
||||
equals = false
|
||||
break
|
||||
return false
|
||||
}
|
||||
}
|
||||
return
|
||||
return true
|
||||
}
|
||||
|
||||
func (rf RatingMatchedFilters) Clone() (cln map[string]interface{}) {
|
||||
|
||||
Reference in New Issue
Block a user