added mms tor type

This commit is contained in:
Radu Ioan Fericean
2016-01-19 22:01:03 +02:00
parent 4e784b6ef5
commit 54f6d5b02f
14 changed files with 52 additions and 25 deletions

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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/"},
],

View File

@@ -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

View File

@@ -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),

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -148,6 +148,7 @@ const (
HDR_VAL_SEP = "/"
MONETARY = "*monetary"
SMS = "*sms"
MMS = "*mms"
GENERIC = "*generic"
DATA = "*data"
VOICE = "*voice"