Added EventCost to DataProvider for filters.Fixes #1910

This commit is contained in:
Trial97
2020-02-05 15:09:43 +02:00
committed by Dan Christian Bogos
parent ff5f5f2d21
commit 1ee5fa0720
7 changed files with 207 additions and 9 deletions

View File

@@ -153,7 +153,10 @@ func (cdr *CDR) FormatCost(shiftDecimals, roundDecimals int) string {
// FieldAsString is used to retrieve fields as string, primary fields are const labeled
func (cdr *CDR) FieldAsString(rsrPrs *config.RSRParser) (parsed string, err error) {
parsed, err = rsrPrs.ParseDataProviderWithInterfaces(
config.NewNavigableMap(map[string]interface{}{utils.MetaReq: cdr.AsMapStringIface()}), utils.NestingSep)
config.NewNavigableMap(map[string]interface{}{
utils.MetaReq: cdr.AsMapStringIface(),
utils.MetaEC: cdr.CostDetails,
}), utils.NestingSep)
if err != nil {
return
}
@@ -163,7 +166,10 @@ func (cdr *CDR) FieldAsString(rsrPrs *config.RSRParser) (parsed string, err erro
// FieldsAsString concatenates values of multiple fields defined in template, used eg in CDR templates
func (cdr *CDR) FieldsAsString(rsrFlds config.RSRParsers) string {
outVal, err := rsrFlds.ParseDataProviderWithInterfaces(
config.NewNavigableMap(map[string]interface{}{utils.MetaReq: cdr.AsMapStringIface()}), utils.NestingSep)
config.NewNavigableMap(map[string]interface{}{
utils.MetaReq: cdr.AsMapStringIface(),
utils.MetaEC: cdr.CostDetails,
}), utils.NestingSep)
if err != nil {
return ""
}
@@ -403,7 +409,10 @@ func (cdr *CDR) formatField(cfgFld *config.FCTemplate, httpSkipTLSCheck bool,
// ExportRecord is a []string to keep it compatible with encoding/csv Writer
func (cdr *CDR) AsExportRecord(exportFields []*config.FCTemplate,
httpSkipTLSCheck bool, groupedCDRs []*CDR, filterS *FilterS) (expRecord []string, err error) {
nM := config.NewNavigableMap(map[string]interface{}{utils.MetaReq: cdr.AsMapStringIface()})
nM := config.NewNavigableMap(map[string]interface{}{
utils.MetaReq: cdr.AsMapStringIface(),
utils.MetaEC: cdr.CostDetails,
})
for _, cfgFld := range exportFields {
if !strings.HasPrefix(cfgFld.Path, utils.MetaExp) {
continue
@@ -430,7 +439,10 @@ func (cdr *CDR) AsExportRecord(exportFields []*config.FCTemplate,
func (cdr *CDR) AsExportMap(exportFields []*config.FCTemplate, httpSkipTLSCheck bool,
groupedCDRs []*CDR, filterS *FilterS) (expMap map[string]string, err error) {
expMap = make(map[string]string)
nM := config.NewNavigableMap(map[string]interface{}{utils.MetaReq: cdr.AsMapStringIface()})
nM := config.NewNavigableMap(map[string]interface{}{
utils.MetaReq: cdr.AsMapStringIface(),
utils.MetaEC: cdr.CostDetails,
})
for _, cfgFld := range exportFields {
if !strings.HasPrefix(cfgFld.Path, utils.MetaExp+utils.NestingSep) {
continue

View File

@@ -390,7 +390,10 @@ func (cdre *CDRExporter) processCDRs() (err error) {
continue
}
if len(cdre.exportTemplate.Filters) != 0 {
cgrDp := config.NewNavigableMap(map[string]interface{}{utils.MetaReq: cdr.AsMapStringIface()})
cgrDp := config.NewNavigableMap(map[string]interface{}{
utils.MetaReq: cdr.AsMapStringIface(),
utils.MetaEC: cdr.CostDetails,
})
if pass, err := cdre.filterS.Pass(cdre.exportTemplate.Tenant,
cdre.exportTemplate.Filters, cgrDp); err != nil || !pass {
continue // Not passes filters, ignore this CDR

View File

@@ -934,7 +934,7 @@ func (ec *EventCost) getChargesForPath(fldPath []string, chr *ChargingInterval)
return incr, nil
}
if fldPath[1] == utils.Accounting {
return ec.getAcountingForPath(fldPath[3:], ec.Accounting[incr.AccountingID])
return ec.getAcountingForPath(fldPath[2:], ec.Accounting[incr.AccountingID])
}
return incr.FieldAsInterface(fldPath)
}

View File

@@ -484,7 +484,8 @@ func (fS *FilterS) getFieldNameDataProvider(initialDP config.DataProvider,
strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaCgrep),
strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaRep),
strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaCGRAReq),
strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaAct):
strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaAct),
strings.HasPrefix(fieldName, utils.DynamicDataPrefix+utils.MetaEC):
dp = initialDP
// don't need to take out the prefix because the navigable map have ~*req prefix
case fieldName == utils.EmptyString:

View File

@@ -1017,3 +1017,167 @@ func TestPassFilterMissingField(t *testing.T) {
t.Errorf("Expecting: false , received: %+v", pass)
}
}
func TestEventCostFilter(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
data := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items)
dmFilterPass := NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
filterS := FilterS{
cfg: cfg,
dm: dmFilterPass,
}
cd := &EventCost{
Cost: utils.Float64Pointer(0.264933),
CGRID: "d8534def2b7067f4f5ad4f7ec7bbcc94bb46111a",
Rates: ChargedRates{
"3db483c": RateGroups{
{
Value: 0.1574,
RateUnit: 60000000000,
RateIncrement: 30000000000,
GroupIntervalStart: 0,
},
{
Value: 0.1574,
RateUnit: 60000000000,
RateIncrement: 1000000000,
GroupIntervalStart: 30000000000,
},
},
},
RunID: "*default",
Usage: utils.DurationPointer(101 * time.Second),
Rating: Rating{
"7f3d423": &RatingUnit{
MaxCost: 40,
RatesID: "3db483c",
TimingID: "128e970",
ConnectFee: 0,
RoundingMethod: "*up",
MaxCostStrategy: "*disconnect",
RatingFiltersID: "f8e95f2",
RoundingDecimals: 4,
},
},
Charges: []*ChargingInterval{
{
RatingID: "7f3d423",
Increments: []*ChargingIncrement{
{
Cost: 0.0787,
Usage: 30000000000,
AccountingID: "fee8a3a",
CompressFactor: 1,
},
},
CompressFactor: 1,
},
{
RatingID: "7f3d423",
Increments: []*ChargingIncrement{
{
Cost: 0.002623,
Usage: 1000000000,
AccountingID: "3463957",
CompressFactor: 71,
},
},
CompressFactor: 1,
},
},
Timings: ChargedTimings{
"128e970": &ChargedTiming{
StartTime: "00:00:00",
},
},
StartTime: time.Date(2019, 12, 06, 11, 57, 32, 0, time.UTC),
Accounting: Accounting{
"3463957": &BalanceCharge{
Units: 0.002623,
RatingID: "",
AccountID: "cgrates.org:1001",
BalanceUUID: "154419f2-45e0-4629-a203-06034ccb493f",
ExtraChargeID: "",
},
"fee8a3a": &BalanceCharge{
Units: 0.0787,
RatingID: "",
AccountID: "cgrates.org:1001",
BalanceUUID: "154419f2-45e0-4629-a203-06034ccb493f",
ExtraChargeID: "",
},
},
RatingFilters: RatingFilters{
"f8e95f2": RatingMatchedFilters{
"Subject": "*out:cgrates.org:mo_call_UK_Mobile_O2_GBRCN:*any",
"RatingPlanID": "RP_MO_CALL_44800",
"DestinationID": "DST_44800",
"DestinationPrefix": "44800",
},
},
AccountSummary: &AccountSummary{
ID: "234189200129930",
Tenant: "cgrates.org",
Disabled: false,
AllowNegative: false,
BalanceSummaries: BalanceSummaries{
&BalanceSummary{
ID: "MOBILE_DATA",
Type: "*data",
UUID: "08a05723-5849-41b9-b6a9-8ee362539280",
Value: 3221225472,
Disabled: false,
},
&BalanceSummary{
ID: "MOBILE_SMS",
Type: "*sms",
UUID: "06a87f20-3774-4eeb-826e-a79c5f175fd3",
Value: 247,
Disabled: false,
},
&BalanceSummary{
ID: "MOBILE_VOICE",
Type: "*voice",
UUID: "4ad16621-6e22-4e35-958e-5e1ff93ad7b7",
Value: 14270000000000,
Disabled: false,
},
&BalanceSummary{
ID: "MONETARY_POSTPAID",
Type: "*monetary",
UUID: "154419f2-45e0-4629-a203-06034ccb493f",
Value: 50,
Disabled: false,
},
},
},
}
cgrDp := config.NewNavigableMap(map[string]interface{}{utils.MetaEC: cd})
if pass, err := filterS.Pass("cgrates.org",
[]string{"*string:~*ec.Charges[0].Increments[0].Accounting.Balance.Value:50"}, cgrDp); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: true , received: %+v", pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*string:~*ec.Charges[0].Increments[0].Accounting.AccountID:cgrates.org:1001"}, cgrDp); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: true , received: %+v", pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*string:~*ec.Charges[0].Rating.Rates[0].Value:0.1574"}, cgrDp); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: true , received: %+v", pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*string:~*ec.Charges[0].Increments[0].Accounting.Balance.ID:MONETARY_POSTPAID"}, cgrDp); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: true , received: %+v", pass)
}
}