mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-20 22:58:44 +05:00
Remove usage_multiply (can be done via dataConverter)
This commit is contained in:
committed by
Dan Christian Bogos
parent
3c07051385
commit
f97d1c6d03
@@ -133,19 +133,6 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
|
||||
if exportFormat == utils.DRYRUN {
|
||||
filePath = utils.DRYRUN
|
||||
}
|
||||
usageMultiplyFactor := exportTemplate.UsageMultiplyFactor
|
||||
if attr.DataUsageMultiplyFactor != nil && *attr.DataUsageMultiplyFactor != 0.0 {
|
||||
usageMultiplyFactor[utils.DATA] = *attr.DataUsageMultiplyFactor
|
||||
}
|
||||
if attr.SmsUsageMultiplyFactor != nil && *attr.SmsUsageMultiplyFactor != 0.0 {
|
||||
usageMultiplyFactor[utils.SMS] = *attr.SmsUsageMultiplyFactor
|
||||
}
|
||||
if attr.MmsUsageMultiplyFactor != nil && *attr.MmsUsageMultiplyFactor != 0.0 {
|
||||
usageMultiplyFactor[utils.MMS] = *attr.MmsUsageMultiplyFactor
|
||||
}
|
||||
if attr.GenericUsageMultiplyFactor != nil && *attr.GenericUsageMultiplyFactor != 0.0 {
|
||||
usageMultiplyFactor[utils.GENERIC] = *attr.GenericUsageMultiplyFactor
|
||||
}
|
||||
costMultiplyFactor := exportTemplate.CostMultiplyFactor
|
||||
if attr.CostMultiplyFactor != nil && *attr.CostMultiplyFactor != 0.0 {
|
||||
costMultiplyFactor = *attr.CostMultiplyFactor
|
||||
@@ -163,7 +150,7 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
|
||||
}
|
||||
cdrexp, err := engine.NewCDRExporter(cdrs, exportTemplate, exportFormat,
|
||||
filePath, utils.META_NONE, exportID, exportTemplate.Synchronous,
|
||||
exportTemplate.Attempts, fieldSep, usageMultiplyFactor, costMultiplyFactor,
|
||||
exportTemplate.Attempts, fieldSep, costMultiplyFactor,
|
||||
self.Config.GeneralCfg().RoundingDecimals,
|
||||
self.Config.GeneralCfg().HttpSkipTlsVerify, self.HTTPPoster, self.FilterS)
|
||||
if err != nil {
|
||||
@@ -211,7 +198,6 @@ type ArgExportCDRs struct {
|
||||
Synchronous *bool
|
||||
Attempts *int
|
||||
FieldSeparator *string
|
||||
UsageMultiplyFactor utils.FieldMultiplyFactor
|
||||
CostMultiplyFactor *float64
|
||||
ExportID *string // Optional exportid
|
||||
ExportFileName *string // If provided the output filename will be set to this
|
||||
@@ -295,10 +281,6 @@ func (self *ApierV1) ExportCDRs(arg ArgExportCDRs, reply *RplExportedCDRs) (err
|
||||
u.Path = path.Join(u.Path, fileName)
|
||||
filePath = u.String()
|
||||
}
|
||||
usageMultiplyFactor := exportTemplate.UsageMultiplyFactor
|
||||
for k, v := range arg.UsageMultiplyFactor {
|
||||
usageMultiplyFactor[k] = v
|
||||
}
|
||||
costMultiplyFactor := exportTemplate.CostMultiplyFactor
|
||||
if arg.CostMultiplyFactor != nil && *arg.CostMultiplyFactor != 0.0 {
|
||||
costMultiplyFactor = *arg.CostMultiplyFactor
|
||||
@@ -319,7 +301,7 @@ func (self *ApierV1) ExportCDRs(arg ArgExportCDRs, reply *RplExportedCDRs) (err
|
||||
}
|
||||
cdrexp, err := engine.NewCDRExporter(cdrs, exportTemplate, exportFormat,
|
||||
filePath, utils.META_NONE, exportID,
|
||||
synchronous, attempts, fieldSep, usageMultiplyFactor,
|
||||
synchronous, attempts, fieldSep,
|
||||
costMultiplyFactor, roundingDecimals,
|
||||
self.Config.GeneralCfg().HttpSkipTlsVerify,
|
||||
self.HTTPPoster, self.FilterS)
|
||||
|
||||
@@ -31,20 +31,16 @@ import (
|
||||
)
|
||||
|
||||
type AttrExportCdrsToFile struct {
|
||||
CdrFormat *string // Cdr output file format <utils.CdreCdrFormats>
|
||||
FieldSeparator *string // Separator used between fields
|
||||
ExportID *string // Optional exportid
|
||||
ExportDirectory *string // If provided it overwrites the configured export directory
|
||||
ExportFileName *string // If provided the output filename will be set to this
|
||||
ExportTemplate *string // Exported fields template <""|fld1,fld2|>
|
||||
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
|
||||
RoundingDecimals *int // force rounding to this value
|
||||
Verbose bool // Disable CgrIds reporting in reply/ExportedCgrIds and reply/UnexportedCgrIds
|
||||
utils.RPCCDRsFilter // Inherit the CDR filter attributes
|
||||
CdrFormat *string // Cdr output file format <utils.CdreCdrFormats>
|
||||
FieldSeparator *string // Separator used between fields
|
||||
ExportID *string // Optional exportid
|
||||
ExportDirectory *string // If provided it overwrites the configured export directory
|
||||
ExportFileName *string // If provided the output filename will be set to this
|
||||
ExportTemplate *string // Exported fields template <""|fld1,fld2|>
|
||||
CostMultiplyFactor *float64 // Multiply the cost before export, eg: apply VAT
|
||||
RoundingDecimals *int // force rounding to this value
|
||||
Verbose bool // Disable CgrIds reporting in reply/ExportedCgrIds and reply/UnexportedCgrIds
|
||||
utils.RPCCDRsFilter // Inherit the CDR filter attributes
|
||||
}
|
||||
|
||||
type ExportedFileCdrs struct {
|
||||
@@ -106,19 +102,6 @@ func (self *ApierV2) ExportCdrsToFile(attr AttrExportCdrsToFile, reply *Exported
|
||||
if exportFormat == utils.DRYRUN {
|
||||
filePath = utils.DRYRUN
|
||||
}
|
||||
usageMultiplyFactor := exportTemplate.UsageMultiplyFactor
|
||||
if attr.DataUsageMultiplyFactor != nil && *attr.DataUsageMultiplyFactor != 0.0 {
|
||||
usageMultiplyFactor[utils.DATA] = *attr.DataUsageMultiplyFactor
|
||||
}
|
||||
if attr.SMSUsageMultiplyFactor != nil && *attr.SMSUsageMultiplyFactor != 0.0 {
|
||||
usageMultiplyFactor[utils.SMS] = *attr.SMSUsageMultiplyFactor
|
||||
}
|
||||
if attr.MMSUsageMultiplyFactor != nil && *attr.MMSUsageMultiplyFactor != 0.0 {
|
||||
usageMultiplyFactor[utils.MMS] = *attr.MMSUsageMultiplyFactor
|
||||
}
|
||||
if attr.GenericUsageMultiplyFactor != nil && *attr.GenericUsageMultiplyFactor != 0.0 {
|
||||
usageMultiplyFactor[utils.GENERIC] = *attr.GenericUsageMultiplyFactor
|
||||
}
|
||||
costMultiplyFactor := exportTemplate.CostMultiplyFactor
|
||||
if attr.CostMultiplyFactor != nil && *attr.CostMultiplyFactor != 0.0 {
|
||||
costMultiplyFactor = *attr.CostMultiplyFactor
|
||||
@@ -140,7 +123,7 @@ func (self *ApierV2) ExportCdrsToFile(attr AttrExportCdrsToFile, reply *Exported
|
||||
}
|
||||
cdrexp, err := engine.NewCDRExporter(cdrs, exportTemplate, exportFormat,
|
||||
filePath, utils.META_NONE, exportID, exportTemplate.Synchronous,
|
||||
exportTemplate.Attempts, fieldSep, usageMultiplyFactor, costMultiplyFactor,
|
||||
exportTemplate.Attempts, fieldSep, costMultiplyFactor,
|
||||
roundingDecimals, self.Config.GeneralCfg().HttpSkipTlsVerify,
|
||||
self.HTTPPoster, self.FilterS)
|
||||
if err != nil {
|
||||
@@ -153,7 +136,8 @@ func (self *ApierV2) ExportCdrsToFile(attr AttrExportCdrsToFile, reply *Exported
|
||||
*reply = ExportedFileCdrs{ExportedFilePath: ""}
|
||||
return nil
|
||||
}
|
||||
*reply = ExportedFileCdrs{ExportedFilePath: filePath, TotalRecords: len(cdrs), TotalCost: cdrexp.TotalCost(), FirstOrderId: cdrexp.FirstOrderId(), LastOrderId: cdrexp.LastOrderId()}
|
||||
*reply = ExportedFileCdrs{ExportedFilePath: filePath, TotalRecords: len(cdrs),
|
||||
TotalCost: cdrexp.TotalCost(), FirstOrderId: cdrexp.FirstOrderId(), LastOrderId: cdrexp.LastOrderId()}
|
||||
if !attr.Verbose {
|
||||
reply.ExportedCgrIds = cdrexp.PositiveExports()
|
||||
reply.UnexportedCgrIds = cdrexp.NegativeExports()
|
||||
|
||||
@@ -18,24 +18,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// One instance of CdrExporter
|
||||
type CdreCfg struct {
|
||||
ExportFormat string
|
||||
ExportPath string
|
||||
Filters []string
|
||||
Tenant string
|
||||
Synchronous bool
|
||||
Attempts int
|
||||
FieldSeparator rune
|
||||
UsageMultiplyFactor utils.FieldMultiplyFactor
|
||||
CostMultiplyFactor float64
|
||||
HeaderFields []*FCTemplate
|
||||
ContentFields []*FCTemplate
|
||||
TrailerFields []*FCTemplate
|
||||
ExportFormat string
|
||||
ExportPath string
|
||||
Filters []string
|
||||
Tenant string
|
||||
Synchronous bool
|
||||
Attempts int
|
||||
FieldSeparator rune
|
||||
CostMultiplyFactor float64
|
||||
HeaderFields []*FCTemplate
|
||||
ContentFields []*FCTemplate
|
||||
TrailerFields []*FCTemplate
|
||||
}
|
||||
|
||||
func (self *CdreCfg) loadFromJsonCfg(jsnCfg *CdreJsonCfg, separator string) (err error) {
|
||||
@@ -67,14 +62,6 @@ func (self *CdreCfg) loadFromJsonCfg(jsnCfg *CdreJsonCfg, separator string) (err
|
||||
sepStr := *jsnCfg.Field_separator
|
||||
self.FieldSeparator = rune(sepStr[0])
|
||||
}
|
||||
if jsnCfg.Usage_multiply_factor != nil {
|
||||
if self.UsageMultiplyFactor == nil { // not yet initialized
|
||||
self.UsageMultiplyFactor = make(map[string]float64, len(*jsnCfg.Usage_multiply_factor))
|
||||
}
|
||||
for k, v := range *jsnCfg.Usage_multiply_factor {
|
||||
self.UsageMultiplyFactor[k] = v
|
||||
}
|
||||
}
|
||||
if jsnCfg.Cost_multiply_factor != nil {
|
||||
self.CostMultiplyFactor = *jsnCfg.Cost_multiply_factor
|
||||
}
|
||||
@@ -105,10 +92,6 @@ func (self *CdreCfg) Clone() *CdreCfg {
|
||||
clnCdre.Attempts = self.Attempts
|
||||
clnCdre.FieldSeparator = self.FieldSeparator
|
||||
clnCdre.Tenant = self.Tenant
|
||||
clnCdre.UsageMultiplyFactor = make(map[string]float64, len(self.UsageMultiplyFactor))
|
||||
for k, v := range self.UsageMultiplyFactor {
|
||||
clnCdre.UsageMultiplyFactor[k] = v
|
||||
}
|
||||
clnCdre.Filters = make([]string, len(self.Filters))
|
||||
for i, fltr := range self.Filters {
|
||||
clnCdre.Filters[i] = fltr
|
||||
|
||||
@@ -40,15 +40,11 @@ func TestCdreCfgClone(t *testing.T) {
|
||||
Value: runIdRsrs},
|
||||
}
|
||||
initCdreCfg := &CdreCfg{
|
||||
ExportFormat: utils.MetaFileCSV,
|
||||
ExportPath: "/var/spool/cgrates/cdre",
|
||||
Synchronous: true,
|
||||
Attempts: 2,
|
||||
FieldSeparator: rune(','),
|
||||
UsageMultiplyFactor: map[string]float64{
|
||||
utils.ANY: 1.0,
|
||||
utils.DATA: 1024,
|
||||
},
|
||||
ExportFormat: utils.MetaFileCSV,
|
||||
ExportPath: "/var/spool/cgrates/cdre",
|
||||
Synchronous: true,
|
||||
Attempts: 2,
|
||||
FieldSeparator: rune(','),
|
||||
CostMultiplyFactor: 1.0,
|
||||
ContentFields: initContentFlds,
|
||||
}
|
||||
@@ -63,16 +59,12 @@ func TestCdreCfgClone(t *testing.T) {
|
||||
Value: runIdRsrs},
|
||||
}
|
||||
eClnCdreCfg := &CdreCfg{
|
||||
ExportFormat: utils.MetaFileCSV,
|
||||
ExportPath: "/var/spool/cgrates/cdre",
|
||||
Synchronous: true,
|
||||
Attempts: 2,
|
||||
Filters: []string{},
|
||||
FieldSeparator: rune(','),
|
||||
UsageMultiplyFactor: map[string]float64{
|
||||
utils.ANY: 1.0,
|
||||
utils.DATA: 1024.0,
|
||||
},
|
||||
ExportFormat: utils.MetaFileCSV,
|
||||
ExportPath: "/var/spool/cgrates/cdre",
|
||||
Synchronous: true,
|
||||
Attempts: 2,
|
||||
Filters: []string{},
|
||||
FieldSeparator: rune(','),
|
||||
CostMultiplyFactor: 1.0,
|
||||
HeaderFields: emptyFields,
|
||||
ContentFields: eClnContentFlds,
|
||||
@@ -82,10 +74,6 @@ func TestCdreCfgClone(t *testing.T) {
|
||||
if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) {
|
||||
t.Errorf("Cloned result: %+v", clnCdreCfg)
|
||||
}
|
||||
initCdreCfg.UsageMultiplyFactor[utils.DATA] = 2048.0
|
||||
if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) { // MOdifying a field after clone should not affect cloned instance
|
||||
t.Errorf("Cloned result: %+v", clnCdreCfg)
|
||||
}
|
||||
initContentFlds[0].Tag = "Destination"
|
||||
if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) { // MOdifying a field after clone should not affect cloned instance
|
||||
t.Errorf("Cloned result: %+v", clnCdreCfg)
|
||||
@@ -119,9 +107,6 @@ func TestCdreCfgloadFromJsonCfg(t *testing.T) {
|
||||
"synchronous": false, // block processing until export has a result
|
||||
"attempts": 1, // Number of attempts if not success
|
||||
"field_separator": ",", // used field separator in some export formats, eg: *file_csv
|
||||
"usage_multiply_factor": {
|
||||
"*any": 1 // multiply usage based on ToR field or *any for all
|
||||
},
|
||||
"cost_multiply_factor": 1, // multiply cost before export, eg: add VAT
|
||||
"header_fields": [], // template of the exported header fields
|
||||
"content_fields": [ // template of the exported content fields
|
||||
@@ -136,15 +121,14 @@ func TestCdreCfgloadFromJsonCfg(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
expected = CdreCfg{
|
||||
ExportFormat: "*file_csv",
|
||||
ExportPath: "/var/spool/cgrates/cdre",
|
||||
Filters: []string{},
|
||||
Tenant: "cgrates.org",
|
||||
Attempts: 1,
|
||||
FieldSeparator: ',',
|
||||
UsageMultiplyFactor: map[string]float64{"*any": 1},
|
||||
CostMultiplyFactor: 1,
|
||||
HeaderFields: []*FCTemplate{},
|
||||
ExportFormat: "*file_csv",
|
||||
ExportPath: "/var/spool/cgrates/cdre",
|
||||
Filters: []string{},
|
||||
Tenant: "cgrates.org",
|
||||
Attempts: 1,
|
||||
FieldSeparator: ',',
|
||||
CostMultiplyFactor: 1,
|
||||
HeaderFields: []*FCTemplate{},
|
||||
ContentFields: []*FCTemplate{{
|
||||
Tag: "CGRID",
|
||||
Type: "*composed",
|
||||
|
||||
@@ -212,9 +212,6 @@ const CGRATES_CFG_JSON = `
|
||||
"synchronous": false, // block processing until export has a result
|
||||
"attempts": 1, // export attempts
|
||||
"field_separator": ",", // used field separator in some export formats, eg: *file_csv
|
||||
"usage_multiply_factor": {
|
||||
"*any": 1 // multiply usage based on ToR field or *any for all
|
||||
},
|
||||
"cost_multiply_factor": 1, // multiply cost before export, eg: add VAT
|
||||
"header_fields": [], // template of the exported header fields
|
||||
"content_fields": [ // template of the exported content fields
|
||||
|
||||
@@ -344,18 +344,17 @@ func TestDfCdreJsonCfgs(t *testing.T) {
|
||||
}
|
||||
eCfg := map[string]*CdreJsonCfg{
|
||||
utils.META_DEFAULT: {
|
||||
Export_format: utils.StringPointer(utils.MetaFileCSV),
|
||||
Export_path: utils.StringPointer("/var/spool/cgrates/cdre"),
|
||||
Synchronous: utils.BoolPointer(false),
|
||||
Attempts: utils.IntPointer(1),
|
||||
Tenant: utils.StringPointer(""),
|
||||
Field_separator: utils.StringPointer(","),
|
||||
Usage_multiply_factor: &map[string]float64{utils.ANY: 1.0},
|
||||
Cost_multiply_factor: utils.Float64Pointer(1.0),
|
||||
Header_fields: &eFields,
|
||||
Content_fields: &eContentFlds,
|
||||
Trailer_fields: &eFields,
|
||||
Filters: &[]string{},
|
||||
Export_format: utils.StringPointer(utils.MetaFileCSV),
|
||||
Export_path: utils.StringPointer("/var/spool/cgrates/cdre"),
|
||||
Synchronous: utils.BoolPointer(false),
|
||||
Attempts: utils.IntPointer(1),
|
||||
Tenant: utils.StringPointer(""),
|
||||
Field_separator: utils.StringPointer(","),
|
||||
Cost_multiply_factor: utils.Float64Pointer(1.0),
|
||||
Header_fields: &eFields,
|
||||
Content_fields: &eContentFlds,
|
||||
Trailer_fields: &eFields,
|
||||
Filters: &[]string{},
|
||||
},
|
||||
}
|
||||
if cfg, err := dfCgrJsonCfg.CdreJsonCfgs(); err != nil {
|
||||
|
||||
@@ -600,17 +600,16 @@ func TestCgrCfgJSONDefaultsCdreProfiles(t *testing.T) {
|
||||
}
|
||||
eCdreCfg := map[string]*CdreCfg{
|
||||
utils.MetaDefault: {
|
||||
ExportFormat: utils.MetaFileCSV,
|
||||
ExportPath: "/var/spool/cgrates/cdre",
|
||||
Filters: []string{},
|
||||
Synchronous: false,
|
||||
Attempts: 1,
|
||||
FieldSeparator: ',',
|
||||
UsageMultiplyFactor: map[string]float64{utils.ANY: 1.0},
|
||||
CostMultiplyFactor: 1.0,
|
||||
HeaderFields: eFields,
|
||||
ContentFields: eContentFlds,
|
||||
TrailerFields: eFields,
|
||||
ExportFormat: utils.MetaFileCSV,
|
||||
ExportPath: "/var/spool/cgrates/cdre",
|
||||
Filters: []string{},
|
||||
Synchronous: false,
|
||||
Attempts: 1,
|
||||
FieldSeparator: ',',
|
||||
CostMultiplyFactor: 1.0,
|
||||
HeaderFields: eFields,
|
||||
ContentFields: eContentFlds,
|
||||
TrailerFields: eFields,
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(cgrCfg.CdreProfiles, eCdreCfg) {
|
||||
|
||||
@@ -164,18 +164,17 @@ type CdrFieldJsonCfg struct {
|
||||
|
||||
// Cdre config section
|
||||
type CdreJsonCfg struct {
|
||||
Export_format *string
|
||||
Export_path *string
|
||||
Filters *[]string
|
||||
Tenant *string
|
||||
Synchronous *bool
|
||||
Attempts *int
|
||||
Field_separator *string
|
||||
Usage_multiply_factor *map[string]float64
|
||||
Cost_multiply_factor *float64
|
||||
Header_fields *[]*FcTemplateJsonCfg
|
||||
Content_fields *[]*FcTemplateJsonCfg
|
||||
Trailer_fields *[]*FcTemplateJsonCfg
|
||||
Export_format *string
|
||||
Export_path *string
|
||||
Filters *[]string
|
||||
Tenant *string
|
||||
Synchronous *bool
|
||||
Attempts *int
|
||||
Field_separator *string
|
||||
Cost_multiply_factor *float64
|
||||
Header_fields *[]*FcTemplateJsonCfg
|
||||
Content_fields *[]*FcTemplateJsonCfg
|
||||
Trailer_fields *[]*FcTemplateJsonCfg
|
||||
}
|
||||
|
||||
// Cdrc config section
|
||||
|
||||
@@ -140,11 +140,6 @@ func (cdr *CDR) ComputeCGRID() {
|
||||
cdr.CGRID = utils.Sha1(cdr.OriginID, cdr.OriginHost)
|
||||
}
|
||||
|
||||
// Used to multiply usage on export
|
||||
func (cdr *CDR) UsageMultiply(multiplyFactor float64, roundDecimals int) {
|
||||
cdr.Usage = time.Duration(int(utils.Round(float64(cdr.Usage.Nanoseconds())*multiplyFactor, roundDecimals, utils.ROUNDING_MIDDLE))) // Rounding down could introduce a slight loss here but only at nanoseconds level
|
||||
}
|
||||
|
||||
// Used to multiply cost on export
|
||||
func (cdr *CDR) CostMultiply(multiplyFactor float64, roundDecimals int) {
|
||||
cdr.Cost = utils.Round(cdr.Cost*multiplyFactor, roundDecimals, utils.ROUNDING_MIDDLE)
|
||||
|
||||
@@ -286,18 +286,6 @@ func TestFieldAsStringForCostDetails(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUsageMultiply(t *testing.T) {
|
||||
cdr := CDR{Usage: time.Duration(10) * time.Second}
|
||||
if cdr.UsageMultiply(1024.0, 0); cdr.Usage != time.Duration(10240)*time.Second {
|
||||
t.Errorf("Unexpected usage after multiply: %v", cdr.Usage.Nanoseconds())
|
||||
}
|
||||
cdr = CDR{Usage: time.Duration(10240) * time.Second} // Simulate conversion back, gives out a bit odd result but this can be rounded on export
|
||||
expectDuration, _ := time.ParseDuration("10.000005120s")
|
||||
if cdr.UsageMultiply(0.000976563, 0); cdr.Usage != expectDuration {
|
||||
t.Errorf("Unexpected usage after multiply: %v", cdr.Usage.Nanoseconds())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCostMultiply(t *testing.T) {
|
||||
cdr := CDR{Cost: 1.01}
|
||||
if cdr.CostMultiply(1.19, 4); cdr.Cost != 1.2019 {
|
||||
|
||||
@@ -51,48 +51,46 @@ const (
|
||||
)
|
||||
|
||||
func NewCDRExporter(cdrs []*CDR, exportTemplate *config.CdreCfg, exportFormat, exportPath, fallbackPath, exportID string,
|
||||
synchronous bool, attempts int, fieldSeparator rune, usageMultiplyFactor utils.FieldMultiplyFactor,
|
||||
costMultiplyFactor float64, roundingDecimals int, httpSkipTlsCheck bool, httpPoster *HTTPPoster, filterS *FilterS) (*CDRExporter, error) {
|
||||
synchronous bool, attempts int, fieldSeparator rune, costMultiplyFactor float64, roundingDecimals int,
|
||||
httpSkipTlsCheck bool, httpPoster *HTTPPoster, filterS *FilterS) (*CDRExporter, error) {
|
||||
if len(cdrs) == 0 { // Nothing to export
|
||||
return nil, nil
|
||||
}
|
||||
cdre := &CDRExporter{
|
||||
cdrs: cdrs,
|
||||
exportTemplate: exportTemplate,
|
||||
exportFormat: exportFormat,
|
||||
exportPath: exportPath,
|
||||
fallbackPath: fallbackPath,
|
||||
exportID: exportID,
|
||||
synchronous: synchronous,
|
||||
attempts: attempts,
|
||||
fieldSeparator: fieldSeparator,
|
||||
usageMultiplyFactor: usageMultiplyFactor,
|
||||
costMultiplyFactor: costMultiplyFactor,
|
||||
roundingDecimals: roundingDecimals,
|
||||
httpSkipTlsCheck: httpSkipTlsCheck,
|
||||
httpPoster: httpPoster,
|
||||
negativeExports: make(map[string]string),
|
||||
filterS: filterS,
|
||||
cdrs: cdrs,
|
||||
exportTemplate: exportTemplate,
|
||||
exportFormat: exportFormat,
|
||||
exportPath: exportPath,
|
||||
fallbackPath: fallbackPath,
|
||||
exportID: exportID,
|
||||
synchronous: synchronous,
|
||||
attempts: attempts,
|
||||
fieldSeparator: fieldSeparator,
|
||||
costMultiplyFactor: costMultiplyFactor,
|
||||
roundingDecimals: roundingDecimals,
|
||||
httpSkipTlsCheck: httpSkipTlsCheck,
|
||||
httpPoster: httpPoster,
|
||||
negativeExports: make(map[string]string),
|
||||
filterS: filterS,
|
||||
}
|
||||
return cdre, nil
|
||||
}
|
||||
|
||||
type CDRExporter struct {
|
||||
sync.RWMutex
|
||||
cdrs []*CDR
|
||||
exportTemplate *config.CdreCfg
|
||||
exportFormat string
|
||||
exportPath string
|
||||
fallbackPath string // folder where we save failed CDRs
|
||||
exportID string // Unique identifier or this export
|
||||
synchronous bool
|
||||
attempts int
|
||||
fieldSeparator rune
|
||||
usageMultiplyFactor utils.FieldMultiplyFactor
|
||||
costMultiplyFactor float64
|
||||
roundingDecimals int
|
||||
httpSkipTlsCheck bool
|
||||
httpPoster *HTTPPoster
|
||||
cdrs []*CDR
|
||||
exportTemplate *config.CdreCfg
|
||||
exportFormat string
|
||||
exportPath string
|
||||
fallbackPath string // folder where we save failed CDRs
|
||||
exportID string // Unique identifier or this export
|
||||
synchronous bool
|
||||
attempts int
|
||||
fieldSeparator rune
|
||||
costMultiplyFactor float64
|
||||
roundingDecimals int
|
||||
httpSkipTlsCheck bool
|
||||
httpPoster *HTTPPoster
|
||||
|
||||
header, trailer []string // Header and Trailer fields
|
||||
content [][]string // Rows of cdr fields
|
||||
@@ -298,13 +296,6 @@ func (cdre *CDRExporter) processCDR(cdr *CDR) (err error) {
|
||||
if cdr.ExtraFields == nil { // Avoid assignment in nil map if not initialized
|
||||
cdr.ExtraFields = make(map[string]string)
|
||||
}
|
||||
// Usage multiply, find config based on ToR field or *any
|
||||
for _, key := range []string{cdr.ToR, utils.ANY} {
|
||||
if uM, hasIt := cdre.usageMultiplyFactor[key]; hasIt && uM != 1.0 {
|
||||
cdr.UsageMultiply(uM, cdre.roundingDecimals)
|
||||
break
|
||||
}
|
||||
}
|
||||
if cdre.costMultiplyFactor != 0.0 {
|
||||
cdr.CostMultiply(cdre.costMultiplyFactor, cdre.roundingDecimals)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestCsvCdrWriter(t *testing.T) {
|
||||
}
|
||||
cdre, err := NewCDRExporter([]*CDR{storedCdr1},
|
||||
cfg.CdreProfiles[utils.MetaDefault], utils.MetaFileCSV, "", "", "firstexport",
|
||||
true, 1, ',', map[string]float64{}, 0.0, cfg.GeneralCfg().RoundingDecimals,
|
||||
true, 1, ',', 0.0, cfg.GeneralCfg().RoundingDecimals,
|
||||
cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
@@ -84,7 +84,7 @@ func TestAlternativeFieldSeparator(t *testing.T) {
|
||||
}
|
||||
cdre, err := NewCDRExporter([]*CDR{storedCdr1}, cfg.CdreProfiles[utils.MetaDefault],
|
||||
utils.MetaFileCSV, "", "", "firstexport", true, 1, '|',
|
||||
map[string]float64{}, 0.0, cfg.GeneralCfg().RoundingDecimals,
|
||||
0.0, cfg.GeneralCfg().RoundingDecimals,
|
||||
cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
@@ -179,7 +179,7 @@ func TestExportVoiceWithConvert(t *testing.T) {
|
||||
}
|
||||
cdre, err := NewCDRExporter([]*CDR{cdrVoice, cdrData, cdrSMS}, cdreCfg,
|
||||
utils.MetaFileCSV, "", "", "firstexport",
|
||||
true, 1, '|', map[string]float64{}, 0.0,
|
||||
true, 1, '|', 0.0,
|
||||
5, true, nil, &FilterS{cfg: cfg})
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
@@ -277,7 +277,7 @@ func TestExportWithFilter(t *testing.T) {
|
||||
}
|
||||
cdre, err := NewCDRExporter([]*CDR{cdrVoice, cdrData, cdrSMS}, cdreCfg,
|
||||
utils.MetaFileCSV, "", "", "firstexport",
|
||||
true, 1, '|', map[string]float64{}, 0.0,
|
||||
true, 1, '|', 0.0,
|
||||
5, true, nil, &FilterS{cfg: cfg})
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
@@ -374,7 +374,7 @@ func TestExportWithFilter2(t *testing.T) {
|
||||
}
|
||||
cdre, err := NewCDRExporter([]*CDR{cdrVoice, cdrData, cdrSMS}, cdreCfg,
|
||||
utils.MetaFileCSV, "", "", "firstexport",
|
||||
true, 1, '|', map[string]float64{}, 0.0,
|
||||
true, 1, '|', 0.0,
|
||||
5, true, nil, &FilterS{cfg: cfg})
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received: ", err)
|
||||
|
||||
@@ -282,7 +282,7 @@ func TestWriteCdr(t *testing.T) {
|
||||
}
|
||||
|
||||
cdre, err := NewCDRExporter([]*CDR{cdr}, cdreCfg, utils.MetaFileFWV, "", "", "fwv_1",
|
||||
true, 1, '|', map[string]float64{}, 0.0, cfg.GeneralCfg().RoundingDecimals,
|
||||
true, 1, '|', 0.0, cfg.GeneralCfg().RoundingDecimals,
|
||||
cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -369,7 +369,7 @@ func TestWriteCdrs(t *testing.T) {
|
||||
}
|
||||
cfg, _ := config.NewDefaultCGRConfig()
|
||||
cdre, err := NewCDRExporter([]*CDR{cdr1, cdr2, cdr3, cdr4}, cdreCfg,
|
||||
utils.MetaFileFWV, "", "", "fwv_1", true, 1, ',', map[string]float64{},
|
||||
utils.MetaFileFWV, "", "", "fwv_1", true, 1, ',',
|
||||
0.0, cfg.GeneralCfg().RoundingDecimals,
|
||||
cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -387,8 +387,7 @@ func (cdrS *CDRServer) exportCDRs(cdrs []*CDR) (err error) {
|
||||
if cdre, err = NewCDRExporter(cdrs, expTpl, expTpl.ExportFormat,
|
||||
expTpl.ExportPath, cdrS.cgrCfg.GeneralCfg().FailedPostsDir,
|
||||
"CDRSReplication", expTpl.Synchronous, expTpl.Attempts,
|
||||
expTpl.FieldSeparator, expTpl.UsageMultiplyFactor,
|
||||
expTpl.CostMultiplyFactor, cdrS.cgrCfg.GeneralCfg().RoundingDecimals,
|
||||
expTpl.FieldSeparator, expTpl.CostMultiplyFactor, cdrS.cgrCfg.GeneralCfg().RoundingDecimals,
|
||||
cdrS.cgrCfg.GeneralCfg().HttpSkipTlsVerify, cdrS.httpPoster,
|
||||
cdrS.filterS); err != nil {
|
||||
utils.Logger.Err(fmt.Sprintf("<CDRS> Building CDRExporter for online exports got error: <%s>", err.Error()))
|
||||
|
||||
@@ -524,35 +524,31 @@ type CacheKeys struct {
|
||||
}
|
||||
|
||||
type AttrExpFileCdrs struct {
|
||||
CdrFormat *string // Cdr output file format <CdreCdrFormats>
|
||||
FieldSeparator *string // Separator used between fields
|
||||
ExportId *string // Optional exportid
|
||||
ExportDir *string // If provided it overwrites the configured export directory
|
||||
ExportFileName *string // If provided the output filename will be set to this
|
||||
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
|
||||
CgrIds []string // If provided, it will filter based on the cgrids present in list
|
||||
MediationRunIds []string // If provided, it will filter on mediation runid
|
||||
TORs []string // If provided, filter on TypeOfRecord
|
||||
CdrHosts []string // If provided, it will filter cdrhost
|
||||
CdrSources []string // If provided, it will filter cdrsource
|
||||
ReqTypes []string // If provided, it will fiter reqtype
|
||||
Tenants []string // If provided, it will filter tenant
|
||||
Categories []string // If provided, it will filter çategory
|
||||
Accounts []string // If provided, it will filter account
|
||||
Subjects []string // If provided, it will filter the rating subject
|
||||
DestinationPrefixes []string // If provided, it will filter on destination prefix
|
||||
OrderIdStart *int64 // Export from this order identifier
|
||||
OrderIdEnd *int64 // Export smaller than this order identifier
|
||||
TimeStart string // If provided, it will represent the starting of the CDRs interval (>=)
|
||||
TimeEnd string // If provided, it will represent the end of the CDRs interval (<)
|
||||
SkipErrors bool // Do not export errored CDRs
|
||||
SkipRated bool // Do not export rated CDRs
|
||||
SuppressCgrIds bool // Disable CgrIds reporting in reply/ExportedCgrIds and reply/UnexportedCgrIds
|
||||
CdrFormat *string // Cdr output file format <CdreCdrFormats>
|
||||
FieldSeparator *string // Separator used between fields
|
||||
ExportId *string // Optional exportid
|
||||
ExportDir *string // If provided it overwrites the configured export directory
|
||||
ExportFileName *string // If provided the output filename will be set to this
|
||||
ExportTemplate *string // Exported fields template <""|fld1,fld2|*xml:instance_name>
|
||||
CostMultiplyFactor *float64 // Multiply the cost before export, eg: apply VAT
|
||||
CgrIds []string // If provided, it will filter based on the cgrids present in list
|
||||
MediationRunIds []string // If provided, it will filter on mediation runid
|
||||
TORs []string // If provided, filter on TypeOfRecord
|
||||
CdrHosts []string // If provided, it will filter cdrhost
|
||||
CdrSources []string // If provided, it will filter cdrsource
|
||||
ReqTypes []string // If provided, it will fiter reqtype
|
||||
Tenants []string // If provided, it will filter tenant
|
||||
Categories []string // If provided, it will filter çategory
|
||||
Accounts []string // If provided, it will filter account
|
||||
Subjects []string // If provided, it will filter the rating subject
|
||||
DestinationPrefixes []string // If provided, it will filter on destination prefix
|
||||
OrderIdStart *int64 // Export from this order identifier
|
||||
OrderIdEnd *int64 // Export smaller than this order identifier
|
||||
TimeStart string // If provided, it will represent the starting of the CDRs interval (>=)
|
||||
TimeEnd string // If provided, it will represent the end of the CDRs interval (<)
|
||||
SkipErrors bool // Do not export errored CDRs
|
||||
SkipRated bool // Do not export rated CDRs
|
||||
SuppressCgrIds bool // Disable CgrIds reporting in reply/ExportedCgrIds and reply/UnexportedCgrIds
|
||||
Paginator
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user