From 54f6d5b02f6739ceab6091e350d6fca8aada5f17 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Tue, 19 Jan 2016 22:01:03 +0200 Subject: [PATCH] added mms tor type --- apier/v1/cdre.go | 7 +++++-- apier/v2/cdre.go | 7 +++++-- cdre/cdrexporter.go | 34 ++++++++++++++++++++++------------ cdre/cdrexporter_test.go | 2 +- cdre/csv_test.go | 4 ++-- cdre/fixedwidth_test.go | 4 ++-- config/cdreconfig.go | 5 +++++ config/cfg_data.json | 2 +- config/config_defaults.go | 1 + config/config_json_test.go | 5 +++-- config/libconfig_json.go | 1 + engine/cdr.go | 2 +- utils/apitpdata.go | 2 ++ utils/consts.go | 1 + 14 files changed, 52 insertions(+), 25 deletions(-) diff --git a/apier/v1/cdre.go b/apier/v1/cdre.go index fe77a03d1..224058cfc 100644 --- a/apier/v1/cdre.go +++ b/apier/v1/cdre.go @@ -144,6 +144,10 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E if attr.SmsUsageMultiplyFactor != nil && *attr.SmsUsageMultiplyFactor != 0.0 { smsUsageMultiplyFactor = *attr.SmsUsageMultiplyFactor } + mmsUsageMultiplyFactor := exportTemplate.MMSUsageMultiplyFactor + if attr.MmsUsageMultiplyFactor != nil && *attr.MmsUsageMultiplyFactor != 0.0 { + mmsUsageMultiplyFactor = *attr.MmsUsageMultiplyFactor + } genericUsageMultiplyFactor := exportTemplate.GenericUsageMultiplyFactor if attr.GenericUsageMultiplyFactor != nil && *attr.GenericUsageMultiplyFactor != 0.0 { genericUsageMultiplyFactor = *attr.GenericUsageMultiplyFactor @@ -179,8 +183,7 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E *reply = utils.ExportedFileCdrs{ExportedFilePath: ""} return nil } - cdrexp, err := cdre.NewCdrExporter(cdrs, self.CdrDb, exportTemplate, cdrFormat, fieldSep, exportId, dataUsageMultiplyFactor, smsUsageMultiplyFactor, genericUsageMultiplyFactor, - costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen, self.Config.HttpSkipTlsVerify, self.Config.DefaultTimezone) + cdrexp, err := cdre.NewCdrExporter(cdrs, self.CdrDb, exportTemplate, cdrFormat, fieldSep, exportId, dataUsageMultiplyFactor, smsUsageMultiplyFactor, mmsUsageMultiplyFactor, genericUsageMultiplyFactor, costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen, self.Config.HttpSkipTlsVerify, self.Config.DefaultTimezone) if err != nil { return utils.NewErrServerError(err) } diff --git a/apier/v2/cdre.go b/apier/v2/cdre.go index d4e0d81bb..31ea8f43e 100644 --- a/apier/v2/cdre.go +++ b/apier/v2/cdre.go @@ -80,6 +80,10 @@ func (self *ApierV2) ExportCdrsToFile(attr utils.AttrExportCdrsToFile, reply *ut if attr.SMSUsageMultiplyFactor != nil && *attr.SMSUsageMultiplyFactor != 0.0 { SMSUsageMultiplyFactor = *attr.SMSUsageMultiplyFactor } + MMSUsageMultiplyFactor := exportTemplate.MMSUsageMultiplyFactor + if attr.MMSUsageMultiplyFactor != nil && *attr.MMSUsageMultiplyFactor != 0.0 { + MMSUsageMultiplyFactor = *attr.MMSUsageMultiplyFactor + } genericUsageMultiplyFactor := exportTemplate.GenericUsageMultiplyFactor if attr.GenericUsageMultiplyFactor != nil && *attr.GenericUsageMultiplyFactor != 0.0 { genericUsageMultiplyFactor = *attr.GenericUsageMultiplyFactor @@ -115,8 +119,7 @@ func (self *ApierV2) ExportCdrsToFile(attr utils.AttrExportCdrsToFile, reply *ut *reply = utils.ExportedFileCdrs{ExportedFilePath: ""} return nil } - cdrexp, err := cdre.NewCdrExporter(cdrs, self.CdrDb, exportTemplate, cdrFormat, fieldSep, ExportID, dataUsageMultiplyFactor, SMSUsageMultiplyFactor, genericUsageMultiplyFactor, - costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen, self.Config.HttpSkipTlsVerify, self.Config.DefaultTimezone) + cdrexp, err := cdre.NewCdrExporter(cdrs, self.CdrDb, exportTemplate, cdrFormat, fieldSep, ExportID, dataUsageMultiplyFactor, SMSUsageMultiplyFactor, MMSUsageMultiplyFactor, genericUsageMultiplyFactor, costMultiplyFactor, costShiftDigits, roundingDecimals, self.Config.RoundingDecimals, maskDestId, maskLen, self.Config.HttpSkipTlsVerify, self.Config.DefaultTimezone) if err != nil { return utils.NewErrServerError(err) } diff --git a/cdre/cdrexporter.go b/cdre/cdrexporter.go index 00fbe67d9..a98a26c95 100644 --- a/cdre/cdrexporter.go +++ b/cdre/cdrexporter.go @@ -43,6 +43,7 @@ const ( META_NRCDRS = "*cdrs_number" META_DURCDRS = "*cdrs_duration" META_SMSUSAGE = "*sms_usage" + META_MMSUSAGE = "*mms_usage" META_GENERICUSAGE = "*generic_usage" META_DATAUSAGE = "*data_usage" META_COSTCDRS = "*cdrs_cost" @@ -53,7 +54,7 @@ const ( var err error func NewCdrExporter(cdrs []*engine.CDR, cdrDb engine.CdrStorage, exportTpl *config.CdreConfig, cdrFormat string, fieldSeparator rune, exportId string, - dataUsageMultiplyFactor, smsUsageMultiplyFactor, genericUsageMultiplyFactor, costMultiplyFactor float64, + dataUsageMultiplyFactor, smsUsageMultiplyFactor, mmsUsageMultiplyFactor, genericUsageMultiplyFactor, costMultiplyFactor float64, costShiftDigits, roundDecimals, cgrPrecision int, maskDestId string, maskLen int, httpSkipTlsCheck bool, timezone string) (*CdrExporter, error) { if len(cdrs) == 0 { // Nothing to export return nil, nil @@ -66,7 +67,7 @@ func NewCdrExporter(cdrs []*engine.CDR, cdrDb engine.CdrStorage, exportTpl *conf fieldSeparator: fieldSeparator, exportId: exportId, dataUsageMultiplyFactor: dataUsageMultiplyFactor, - smsUsageMultiplyFactor: smsUsageMultiplyFactor, + mmsUsageMultiplyFactor: mmsUsageMultiplyFactor, costMultiplyFactor: costMultiplyFactor, costShiftDigits: costShiftDigits, roundDecimals: roundDecimals, @@ -92,18 +93,19 @@ type CdrExporter struct { exportId string // Unique identifier or this export dataUsageMultiplyFactor, smsUsageMultiplyFactor, // Multiply the SMS usage (eg: some billing systems billing them as minutes) + mmsUsageMultiplyFactor, genericUsageMultiplyFactor, costMultiplyFactor float64 - costShiftDigits, roundDecimals, cgrPrecision int - maskDestId string - maskLen int - httpSkipTlsCheck bool - timezone string - header, trailer []string // Header and Trailer fields - content [][]string // Rows of cdr fields - firstCdrATime, lastCdrATime time.Time - numberOfRecords int - totalDuration, totalDataUsage, totalSmsUsage, totalGenericUsage time.Duration + costShiftDigits, roundDecimals, cgrPrecision int + maskDestId string + maskLen int + httpSkipTlsCheck bool + timezone string + header, trailer []string // Header and Trailer fields + content [][]string // Rows of cdr fields + firstCdrATime, lastCdrATime time.Time + numberOfRecords int + totalDuration, totalDataUsage, totalSmsUsage, totalMmsUsage, totalGenericUsage time.Duration totalCost float64 firstExpOrderId, lastExpOrderId int64 @@ -234,6 +236,9 @@ func (cdre *CdrExporter) metaHandler(tag, arg string) (string, error) { case META_SMSUSAGE: emulatedCdr := &engine.CDR{ToR: utils.SMS, Usage: cdre.totalSmsUsage} return emulatedCdr.FormatUsage(arg), nil + case META_MMSUSAGE: + emulatedCdr := &engine.CDR{ToR: utils.MMS, Usage: cdre.totalMmsUsage} + return emulatedCdr.FormatUsage(arg), nil case META_GENERICUSAGE: emulatedCdr := &engine.CDR{ToR: utils.GENERIC, Usage: cdre.totalGenericUsage} return emulatedCdr.FormatUsage(arg), nil @@ -322,6 +327,8 @@ func (cdre *CdrExporter) processCdr(cdr *engine.CDR) error { cdr.UsageMultiply(cdre.dataUsageMultiplyFactor, cdre.cgrPrecision) } else if cdre.smsUsageMultiplyFactor != 0 && cdr.ToR == utils.SMS { cdr.UsageMultiply(cdre.smsUsageMultiplyFactor, cdre.cgrPrecision) + } else if cdre.mmsUsageMultiplyFactor != 0 && cdr.ToR == utils.MMS { + cdr.UsageMultiply(cdre.mmsUsageMultiplyFactor, cdre.cgrPrecision) } else if cdre.genericUsageMultiplyFactor != 0 && cdr.ToR == utils.GENERIC { cdr.UsageMultiply(cdre.genericUsageMultiplyFactor, cdre.cgrPrecision) } @@ -392,6 +399,9 @@ func (cdre *CdrExporter) processCdr(cdr *engine.CDR) error { if cdr.ToR == utils.SMS { // Count usage for SMS cdre.totalSmsUsage += cdr.Usage } + if cdr.ToR == utils.MMS { // Count usage for MMS + cdre.totalMmsUsage += cdr.Usage + } if cdr.ToR == utils.GENERIC { // Count usage for GENERIC cdre.totalGenericUsage += cdr.Usage } diff --git a/cdre/cdrexporter_test.go b/cdre/cdrexporter_test.go index 0960c8b8f..045fc0e4b 100644 --- a/cdre/cdrexporter_test.go +++ b/cdre/cdrexporter_test.go @@ -52,7 +52,7 @@ func TestCdreGetCombimedCdrFieldVal(t *testing.T) { Usage: time.Duration(10) * time.Second, RunID: "RETAIL1", Cost: 5.01}, } cdre, err := NewCdrExporter(cdrs, nil, cfg.CdreProfiles["*default"], cfg.CdreProfiles["*default"].CdrFormat, cfg.CdreProfiles["*default"].FieldSeparator, - "firstexport", 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "") + "firstexport", 0.0, 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "") if err != nil { t.Error("Unexpected error received: ", err) } diff --git a/cdre/csv_test.go b/cdre/csv_test.go index 0990c7a80..c69c140b9 100644 --- a/cdre/csv_test.go +++ b/cdre/csv_test.go @@ -40,7 +40,7 @@ func TestCsvCdrWriter(t *testing.T) { Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01, } - cdre, err := NewCdrExporter([]*engine.CDR{storedCdr1}, nil, cfg.CdreProfiles["*default"], utils.CSV, ',', "firstexport", 0.0, 0.0, 0.0, 0.0, 0, 4, + cdre, err := NewCdrExporter([]*engine.CDR{storedCdr1}, nil, cfg.CdreProfiles["*default"], utils.CSV, ',', "firstexport", 0.0, 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "") if err != nil { t.Error("Unexpected error received: ", err) @@ -69,7 +69,7 @@ func TestAlternativeFieldSeparator(t *testing.T) { ExtraFields: map[string]string{"extra1": "val_extra1", "extra2": "val_extra2", "extra3": "val_extra3"}, Cost: 1.01, } cdre, err := NewCdrExporter([]*engine.CDR{storedCdr1}, nil, cfg.CdreProfiles["*default"], utils.CSV, '|', - "firstexport", 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "") + "firstexport", 0.0, 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "") if err != nil { t.Error("Unexpected error received: ", err) } diff --git a/cdre/fixedwidth_test.go b/cdre/fixedwidth_test.go index ffdd1f747..ef5f5137e 100644 --- a/cdre/fixedwidth_test.go +++ b/cdre/fixedwidth_test.go @@ -127,7 +127,7 @@ func TestWriteCdr(t *testing.T) { Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 2.34567, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } - cdre, err := NewCdrExporter([]*engine.CDR{cdr}, nil, cdreCfg, utils.CDRE_FIXED_WIDTH, ',', "fwv_1", 0.0, 0.0, 0.0, 0.0, 0, 4, + cdre, err := NewCdrExporter([]*engine.CDR{cdr}, nil, cdreCfg, utils.CDRE_FIXED_WIDTH, ',', "fwv_1", 0.0, 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify, "") if err != nil { t.Error(err) @@ -203,7 +203,7 @@ func TestWriteCdrs(t *testing.T) { } cfg, _ := config.NewDefaultCGRConfig() cdre, err := NewCdrExporter([]*engine.CDR{cdr1, cdr2, cdr3, cdr4}, nil, cdreCfg, utils.CDRE_FIXED_WIDTH, ',', - "fwv_1", 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify, "") + "fwv_1", 0.0, 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", -1, cfg.HttpSkipTlsVerify, "") if err != nil { t.Error(err) } diff --git a/config/cdreconfig.go b/config/cdreconfig.go index 55a98c3b5..f55bad28e 100644 --- a/config/cdreconfig.go +++ b/config/cdreconfig.go @@ -24,6 +24,7 @@ type CdreConfig struct { FieldSeparator rune DataUsageMultiplyFactor float64 SMSUsageMultiplyFactor float64 + MMSUsageMultiplyFactor float64 GenericUsageMultiplyFactor float64 CostMultiplyFactor float64 CostRoundingDecimals int @@ -54,6 +55,9 @@ func (self *CdreConfig) loadFromJsonCfg(jsnCfg *CdreJsonCfg) error { if jsnCfg.Sms_usage_multiply_factor != nil { self.SMSUsageMultiplyFactor = *jsnCfg.Sms_usage_multiply_factor } + if jsnCfg.Mms_usage_multiply_factor != nil { + self.MMSUsageMultiplyFactor = *jsnCfg.Mms_usage_multiply_factor + } if jsnCfg.Generic_usage_multiply_factor != nil { self.GenericUsageMultiplyFactor = *jsnCfg.Generic_usage_multiply_factor } @@ -100,6 +104,7 @@ func (self *CdreConfig) Clone() *CdreConfig { clnCdre.FieldSeparator = self.FieldSeparator clnCdre.DataUsageMultiplyFactor = self.DataUsageMultiplyFactor clnCdre.SMSUsageMultiplyFactor = self.SMSUsageMultiplyFactor + clnCdre.MMSUsageMultiplyFactor = self.MMSUsageMultiplyFactor clnCdre.GenericUsageMultiplyFactor = self.GenericUsageMultiplyFactor clnCdre.CostMultiplyFactor = self.CostMultiplyFactor clnCdre.CostRoundingDecimals = self.CostRoundingDecimals diff --git a/config/cfg_data.json b/config/cfg_data.json index 77f20a7da..f5eb4a811 100644 --- a/config/cfg_data.json +++ b/config/cfg_data.json @@ -33,7 +33,7 @@ "run_delay": 1, "cdr_source_id": "csv2", // free form field, tag identifying the source of the CDRs within CDRS database "content_fields":[ // import template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value - {"field_id": "ToR", "value": "~7:s/^(voice|data|sms|generic)$/*$1/"}, + {"field_id": "ToR", "value": "~7:s/^(voice|data|sms|mms|generic)$/*$1/"}, {"field_id": "AnswerTime", "value": "1"}, {"field_id": "Usage", "value": "~9:s/^(\\d+)$/${1}s/"}, ], diff --git a/config/config_defaults.go b/config/config_defaults.go index 837c8ecd0..0cedd84f0 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -132,6 +132,7 @@ const CGRATES_CFG_JSON = ` "field_separator": ",", "data_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from KBytes to Bytes) "sms_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from SMS unit to call duration in some billing systems) + "mms_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from MMS unit to call duration in some billing systems) "generic_usage_multiply_factor": 1, // multiply data usage before export (eg: convert from GENERIC unit to call duration in some billing systems) "cost_multiply_factor": 1, // multiply cost before export, eg: add VAT "cost_rounding_decimals": -1, // rounding decimals for Cost values. -1 to disable rounding diff --git a/config/config_json_test.go b/config/config_json_test.go index c7317f93d..2548ec5c4 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -249,6 +249,7 @@ func TestDfCdreJsonCfgs(t *testing.T) { Field_separator: utils.StringPointer(","), Data_usage_multiply_factor: utils.Float64Pointer(1.0), Sms_usage_multiply_factor: utils.Float64Pointer(1.0), + Mms_usage_multiply_factor: utils.Float64Pointer(1.0), Generic_usage_multiply_factor: utils.Float64Pointer(1.0), Cost_multiply_factor: utils.Float64Pointer(1.0), Cost_rounding_decimals: utils.IntPointer(-1), @@ -591,7 +592,7 @@ func TestNewCgrJsonCfgFromFile(t *testing.T) { t.Error("Received: ", gCfg) } cdrFields := []*CdrFieldJsonCfg{ - &CdrFieldJsonCfg{Field_id: utils.StringPointer(utils.TOR), Value: utils.StringPointer("~7:s/^(voice|data|sms|generic)$/*$1/")}, + &CdrFieldJsonCfg{Field_id: utils.StringPointer(utils.TOR), Value: utils.StringPointer("~7:s/^(voice|data|sms|mms|generic)$/*$1/")}, &CdrFieldJsonCfg{Field_id: utils.StringPointer(utils.ANSWER_TIME), Value: utils.StringPointer("1")}, &CdrFieldJsonCfg{Field_id: utils.StringPointer(utils.USAGE), Value: utils.StringPointer(`~9:s/^(\d+)$/${1}s/`)}, } @@ -615,7 +616,7 @@ func TestNewCgrJsonCfgFromFile(t *testing.T) { if cfg, err := cgrJsonCfg.CdrcJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfgCdrc, cfg) { - t.Error("Received: ", cfg["CDRC-CSV2"]) + t.Error("Received: ", utils.ToIJSON(cfg["CDRC-CSV2"])) } eCfgSmFs := &SmFsJsonCfg{ Enabled: utils.BoolPointer(true), diff --git a/config/libconfig_json.go b/config/libconfig_json.go index fdf261f00..fba619846 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -127,6 +127,7 @@ type CdreJsonCfg struct { Field_separator *string Data_usage_multiply_factor *float64 Sms_usage_multiply_factor *float64 + Mms_usage_multiply_factor *float64 Generic_usage_multiply_factor *float64 Cost_multiply_factor *float64 Cost_rounding_decimals *int diff --git a/engine/cdr.go b/engine/cdr.go index ca0893832..de741ed3e 100644 --- a/engine/cdr.go +++ b/engine/cdr.go @@ -126,7 +126,7 @@ func (cdr *CDR) FormatCost(shiftDecimals, roundDecimals int) string { // Formats usage on export func (cdr *CDR) FormatUsage(layout string) string { - if utils.IsSliceMember([]string{utils.DATA, utils.SMS, utils.GENERIC}, cdr.ToR) { + if utils.IsSliceMember([]string{utils.DATA, utils.SMS, utils.MMS, utils.GENERIC}, cdr.ToR) { return strconv.FormatFloat(utils.Round(cdr.Usage.Seconds(), 0, utils.ROUNDING_MIDDLE), 'f', -1, 64) } switch layout { diff --git a/utils/apitpdata.go b/utils/apitpdata.go index dd3c1c246..9a2c63d31 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -597,6 +597,7 @@ type AttrExpFileCdrs struct { ExportTemplate *string // Exported fields template <""|fld1,fld2|*xml:instance_name> DataUsageMultiplyFactor *float64 // Multiply data usage before export (eg: convert from KBytes to Bytes) SmsUsageMultiplyFactor *float64 // Multiply sms usage before export (eg: convert from SMS unit to call duration for some billing systems) + MmsUsageMultiplyFactor *float64 // Multiply mms usage before export (eg: convert from MMS unit to call duration for some billing systems) GenericUsageMultiplyFactor *float64 // Multiply generic usage before export (eg: convert from GENERIC unit to call duration for some billing systems) CostMultiplyFactor *float64 // Multiply the cost before export, eg: apply VAT CostShiftDigits *int // If defined it will shift cost digits before applying rouding (eg: convert from Eur->cents), -1 to use general config ones @@ -1089,6 +1090,7 @@ type AttrExportCdrsToFile struct { ExportTemplate *string // Exported fields template <""|fld1,fld2|*xml:instance_name> DataUsageMultiplyFactor *float64 // Multiply data usage before export (eg: convert from KBytes to Bytes) SMSUsageMultiplyFactor *float64 // Multiply sms usage before export (eg: convert from SMS unit to call duration for some billing systems) + MMSUsageMultiplyFactor *float64 // Multiply mms usage before export (eg: convert from MMS unit to call duration for some billing systems) GenericUsageMultiplyFactor *float64 // Multiply generic usage before export (eg: convert from GENERIC unit to call duration for some billing systems) CostMultiplyFactor *float64 // Multiply the cost before export, eg: apply VAT CostShiftDigits *int // If defined it will shift cost digits before applying rouding (eg: convert from Eur->cents), -1 to use general config ones diff --git a/utils/consts.go b/utils/consts.go index 345408b29..6f413f1f3 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -148,6 +148,7 @@ const ( HDR_VAL_SEP = "/" MONETARY = "*monetary" SMS = "*sms" + MMS = "*mms" GENERIC = "*generic" DATA = "*data" VOICE = "*voice"