Remove RoundingDecimals from CDRC ( can be set explicit for the field you want)

This commit is contained in:
TeoV
2019-06-04 17:33:23 +03:00
committed by Dan Christian Bogos
parent a5f9be607e
commit 89bf087bc6
10 changed files with 48 additions and 81 deletions

View File

@@ -147,7 +147,6 @@ 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,
self.Config.GeneralCfg().RoundingDecimals,
self.Config.GeneralCfg().HttpSkipTlsVerify, self.HTTPPoster, self.FilterS)
if err != nil {
return utils.NewErrServerError(err)
@@ -196,7 +195,6 @@ type ArgExportCDRs struct {
FieldSeparator *string
ExportID *string // Optional exportid
ExportFileName *string // If provided the output filename will be set to this
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
}
@@ -276,10 +274,6 @@ func (self *ApierV1) ExportCDRs(arg ArgExportCDRs, reply *RplExportedCDRs) (err
u.Path = path.Join(u.Path, fileName)
filePath = u.String()
}
roundingDecimals := self.Config.GeneralCfg().RoundingDecimals
if arg.RoundingDecimals != nil {
roundingDecimals = *arg.RoundingDecimals
}
cdrsFltr, err := arg.RPCCDRsFilter.AsCDRsFilter(self.Config.GeneralCfg().DefaultTimezone)
if err != nil {
return utils.NewErrServerError(err)
@@ -292,7 +286,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, roundingDecimals,
synchronous, attempts, fieldSep,
self.Config.GeneralCfg().HttpSkipTlsVerify,
self.HTTPPoster, self.FilterS)
if err != nil {

View File

@@ -37,7 +37,6 @@ type AttrExportCdrsToFile struct {
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|>
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
}
@@ -112,14 +111,9 @@ func (self *ApierV2) ExportCdrsToFile(attr AttrExportCdrsToFile, reply *Exported
*reply = ExportedFileCdrs{ExportedFilePath: ""}
return nil
}
roundingDecimals := self.Config.GeneralCfg().RoundingDecimals
if attr.RoundingDecimals != nil {
roundingDecimals = *attr.RoundingDecimals
}
cdrexp, err := engine.NewCDRExporter(cdrs, exportTemplate, exportFormat,
filePath, utils.META_NONE, exportID, exportTemplate.Synchronous,
exportTemplate.Attempts, fieldSep,
roundingDecimals, self.Config.GeneralCfg().HttpSkipTlsVerify,
exportTemplate.Attempts, fieldSep, self.Config.GeneralCfg().HttpSkipTlsVerify,
self.HTTPPoster, self.FilterS)
if err != nil {
return utils.NewErrServerError(err)

View File

@@ -78,7 +78,7 @@ func (prc *PartialRecordsCache) dumpPartialRecords(originID string) {
csvWriter.Comma = prc.csvSep
for _, cdr := range prc.partialRecords[originID].cdrs {
expRec, err := cdr.AsExportRecord(prc.partialRecords[originID].cacheDumpFields,
prc.httpSkipTlsCheck, nil, prc.roundDecimals, prc.filterS)
prc.httpSkipTlsCheck, nil, prc.filterS)
if err != nil {
return nil, err
}

View File

@@ -63,7 +63,7 @@
{"tag": "SetupTime", "type": "*composed", "value": "~SetupTime", "layout": "2006-01-02T15:04:05Z07:00"},
{"tag": "AnswerTime", "type": "*composed", "value": "~AnswerTime", "layout": "2006-01-02T15:04:05Z07:00"},
{"tag": "Usage", "type": "*composed", "value": "~Usage"},
{"tag": "Cost", "type": "*composed", "value": "~Cost"},
{"tag": "Cost", "type": "*composed", "value": "~Cost","rounding_decimals":5},
],
},
{

View File

@@ -332,16 +332,14 @@ func (cdr *CDR) exportFieldValue(cfgCdrFld *config.FCTemplate, filterS *FilterS)
cfgCdrFld.RoundingDecimals)
case utils.SetupTime:
if cfgCdrFld.Layout == "" {
cdrVal = cdr.SetupTime.Format(time.RFC3339)
} else {
cdrVal = cdr.SetupTime.Format(cfgCdrFld.Layout)
cfgCdrFld.Layout = time.RFC3339
}
cdrVal = cdr.SetupTime.Format(cfgCdrFld.Layout)
case utils.AnswerTime: // Format time based on layout
if cfgCdrFld.Layout == "" {
cdrVal = cdr.AnswerTime.Format(time.RFC3339)
} else {
cdrVal = cdr.AnswerTime.Format(cfgCdrFld.Layout)
cfgCdrFld.Layout = time.RFC3339
}
cdrVal = cdr.AnswerTime.Format(cfgCdrFld.Layout)
case utils.Destination:
cdrVal, err = cdr.FieldAsString(rsrFld)
if err != nil {
@@ -379,10 +377,9 @@ func (cdr *CDR) formatField(cfgFld *config.FCTemplate, httpSkipTlsCheck bool,
return "", err
} else {
if cfgFld.Layout == "" {
outVal = dtFld.Format(time.RFC3339)
} else {
outVal = dtFld.Format(cfgFld.Layout)
cfgFld.Layout = time.RFC3339
}
outVal = dtFld.Format(cfgFld.Layout)
}
case utils.META_HTTP_POST:
var outValByte []byte
@@ -423,7 +420,7 @@ func (cdr *CDR) formatField(cfgFld *config.FCTemplate, httpSkipTlsCheck bool,
// Used in place where we need to export the CDR based on an export template
// ExportRecord is a []string to keep it compatible with encoding/csv Writer
func (cdr *CDR) AsExportRecord(exportFields []*config.FCTemplate,
httpSkipTlsCheck bool, groupedCDRs []*CDR, roundingDecs int, filterS *FilterS) (expRecord []string, err error) {
httpSkipTlsCheck bool, groupedCDRs []*CDR, filterS *FilterS) (expRecord []string, err error) {
for _, cfgFld := range exportFields {
if pass, err := filterS.Pass(cdr.Tenant,
cfgFld.Filters, config.NewNavigableMap(cdr.AsMapStringIface())); err != nil {
@@ -431,12 +428,6 @@ func (cdr *CDR) AsExportRecord(exportFields []*config.FCTemplate,
} else if !pass {
continue
}
if roundingDecs != 0 {
clnFld := new(config.FCTemplate) // Clone so we can modify the rounding decimals without affecting the template
*clnFld = *cfgFld
clnFld.RoundingDecimals = roundingDecs
cfgFld = clnFld
}
if fmtOut, err := cdr.formatField(cfgFld, httpSkipTlsCheck, groupedCDRs, filterS); err != nil {
utils.Logger.Warning(fmt.Sprintf("<CDR> error: %s exporting field: %s, CDR: %s\n",
err.Error(), utils.ToJSON(cfgFld), utils.ToJSON(cdr)))
@@ -451,7 +442,7 @@ func (cdr *CDR) AsExportRecord(exportFields []*config.FCTemplate,
// AsExportMap converts the CDR into a map[string]string based on export template
// Used in real-time replication as well as remote exports
func (cdr *CDR) AsExportMap(exportFields []*config.FCTemplate, httpSkipTlsCheck bool,
groupedCDRs []*CDR, roundingDecs int, filterS *FilterS) (expMap map[string]string, err error) {
groupedCDRs []*CDR, filterS *FilterS) (expMap map[string]string, err error) {
expMap = make(map[string]string)
for _, cfgFld := range exportFields {
if pass, err := filterS.Pass(cdr.Tenant,
@@ -460,12 +451,6 @@ func (cdr *CDR) AsExportMap(exportFields []*config.FCTemplate, httpSkipTlsCheck
} else if !pass {
continue
}
if roundingDecs != 0 {
clnFld := new(config.FCTemplate) // Clone so we can modify the rounding decimals without affecting the template
*clnFld = *cfgFld
clnFld.RoundingDecimals = roundingDecs
cfgFld = clnFld
}
if fmtOut, err := cdr.formatField(cfgFld, httpSkipTlsCheck, groupedCDRs, filterS); err != nil {
utils.Logger.Warning(fmt.Sprintf("<CDR> error: %s exporting field: %s, CDR: %s\n",
err.Error(), utils.ToJSON(cfgFld), utils.ToJSON(cdr)))

View File

@@ -614,7 +614,7 @@ func TestCDRAsExportRecord(t *testing.T) {
prsr := config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+utils.Destination, true, utils.INFIELD_SEP)
cfgCdrFld := &config.FCTemplate{Tag: "destination", Type: utils.META_COMPOSED,
FieldId: utils.Destination, Value: prsr, Timezone: "UTC"}
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, nil); err != nil {
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, nil); err != nil {
t.Error(err)
} else if expRecord[0] != cdr.Destination {
t.Errorf("Expecting:\n%s\nReceived:\n%s", cdr.Destination, expRecord)
@@ -627,7 +627,7 @@ func TestCDRAsExportRecord(t *testing.T) {
cfgCdrFld = &config.FCTemplate{Tag: "Destination", Type: utils.META_COMPOSED,
FieldId: utils.Destination, Value: prsr, MaskDestID: "MASKED_DESTINATIONS", MaskLen: 3}
eDst := "+4986517174***"
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, nil); err != nil {
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, nil); err != nil {
t.Error(err)
} else if expRecord[0] != eDst {
t.Errorf("Expecting:\n%s\nReceived:\n%s", eDst, expRecord[0])
@@ -635,7 +635,7 @@ func TestCDRAsExportRecord(t *testing.T) {
cfgCdrFld = &config.FCTemplate{Tag: "MaskedDest", Type: utils.MetaMaskedDestination,
Value: prsr, MaskDestID: "MASKED_DESTINATIONS"}
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, nil); err != nil {
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, nil); err != nil {
t.Error(err)
} else if expRecord[0] != "1" {
t.Errorf("Expecting:\n%s\nReceived:\n%s", "1", expRecord[0])
@@ -649,7 +649,7 @@ func TestCDRAsExportRecord(t *testing.T) {
cfgCdrFld = &config.FCTemplate{Tag: "destination", Type: utils.META_COMPOSED,
FieldId: utils.Destination, Value: prsr, Filters: []string{"*string:Tenant:itsyscom.com"}, Timezone: "UTC"}
if rcrd, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, &FilterS{dm: dmForCDR, cfg: defaultCfg}); err != nil {
if rcrd, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, &FilterS{dm: dmForCDR, cfg: defaultCfg}); err != nil {
t.Error(err)
} else if len(rcrd) != 0 {
t.Error("failed using filter")
@@ -660,7 +660,7 @@ func TestCDRAsExportRecord(t *testing.T) {
layout := "2006-01-02 15:04:05"
cfgCdrFld = &config.FCTemplate{Tag: "stop_time", Type: utils.MetaDateTime,
FieldId: "stop_time", Value: prsr, Layout: layout, Timezone: "UTC"}
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, &FilterS{dm: dmForCDR, cfg: defaultCfg}); err != nil {
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, &FilterS{dm: dmForCDR, cfg: defaultCfg}); err != nil {
t.Error(err)
} else if expRecord[0] != "2014-06-11 19:19:00" {
t.Error("Expecting: 2014-06-11 19:19:00, got: ", expRecord[0])
@@ -670,7 +670,7 @@ func TestCDRAsExportRecord(t *testing.T) {
cfgCdrFld = &config.FCTemplate{Tag: "stop_time", Type: utils.MetaDateTime,
FieldId: "stop_time", Value: prsr, Filters: []string{"*string:Tenant:itsyscom.com"},
Layout: layout, Timezone: "UTC"}
if rcrd, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, &FilterS{dm: dmForCDR, cfg: defaultCfg}); err != nil {
if rcrd, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, &FilterS{dm: dmForCDR, cfg: defaultCfg}); err != nil {
t.Error(err)
} else if len(rcrd) != 0 {
t.Error("failed using filter")
@@ -680,14 +680,14 @@ func TestCDRAsExportRecord(t *testing.T) {
cfgCdrFld = &config.FCTemplate{Tag: "stop_time", Type: utils.MetaDateTime,
FieldId: "stop_time", Value: prsr, Layout: layout, Timezone: "UTC"}
// Test time parse error
if _, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, nil); err == nil {
if _, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, nil); err == nil {
t.Error("Should give error here, got none.")
}
prsr = config.NewRSRParsersMustCompile("~CostDetails.CGRID", true, utils.INFIELD_SEP)
cfgCdrFld = &config.FCTemplate{Tag: "CGRIDFromCostDetails", Type: utils.META_COMPOSED,
FieldId: "CGRIDFromCostDetails", Value: prsr}
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, nil); err != nil {
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, nil); err != nil {
t.Error(err)
} else if expRecord[0] != cdr.CostDetails.CGRID {
t.Errorf("Expecting:\n%s\nReceived:\n%s", cdr.CostDetails.CGRID, expRecord)
@@ -695,7 +695,7 @@ func TestCDRAsExportRecord(t *testing.T) {
prsr = config.NewRSRParsersMustCompile("~CostDetails.AccountSummary.ID", true, utils.INFIELD_SEP)
cfgCdrFld = &config.FCTemplate{Tag: "AccountID", Type: utils.META_COMPOSED,
FieldId: "CustomAccountID", Value: prsr}
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, nil); err != nil {
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, nil); err != nil {
t.Error(err)
} else if expRecord[0] != cdr.CostDetails.AccountSummary.ID {
t.Errorf("Expecting:\n%s\nReceived:\n%s", cdr.CostDetails.AccountSummary.ID, expRecord)
@@ -705,7 +705,7 @@ func TestCDRAsExportRecord(t *testing.T) {
prsr = config.NewRSRParsersMustCompile("~CostDetails.RatingFilters", true, utils.INFIELD_SEP)
cfgCdrFld = &config.FCTemplate{Tag: "DestinationID", Type: utils.META_COMPOSED,
FieldId: "CustomDestinationID", Value: prsr}
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, 0, nil); err != nil {
if expRecord, err := cdr.AsExportRecord([]*config.FCTemplate{cfgCdrFld}, false, nil, nil); err != nil {
t.Error(err)
} else if expRecord[0] != expected {
t.Errorf("Expecting: <%q>,\n Received: <%q>", expected, expRecord[0])
@@ -737,7 +737,7 @@ func TestCDRAsExportMap(t *testing.T) {
&config.FCTemplate{FieldId: "FieldExtra1", Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+"field_extr1", true, utils.INFIELD_SEP)},
}
if cdrMp, err := cdr.AsExportMap(expFlds, false, nil, 0, nil); err != nil {
if cdrMp, err := cdr.AsExportMap(expFlds, false, nil, nil); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCDRMp, cdrMp) {
t.Errorf("Expecting: %+v, received: %+v", eCDRMp, cdrMp)

View File

@@ -51,7 +51,7 @@ const (
)
func NewCDRExporter(cdrs []*CDR, exportTemplate *config.CdreCfg, exportFormat, exportPath, fallbackPath, exportID string,
synchronous bool, attempts int, fieldSeparator rune, roundingDecimals int,
synchronous bool, attempts int, fieldSeparator rune,
httpSkipTlsCheck bool, httpPoster *HTTPPoster, filterS *FilterS) (*CDRExporter, error) {
if len(cdrs) == 0 { // Nothing to export
return nil, nil
@@ -66,7 +66,6 @@ func NewCDRExporter(cdrs []*CDR, exportTemplate *config.CdreCfg, exportFormat, e
synchronous: synchronous,
attempts: attempts,
fieldSeparator: fieldSeparator,
roundingDecimals: roundingDecimals,
httpSkipTlsCheck: httpSkipTlsCheck,
httpPoster: httpPoster,
negativeExports: make(map[string]string),
@@ -86,7 +85,6 @@ type CDRExporter struct {
synchronous bool
attempts int
fieldSeparator rune
roundingDecimals int
httpSkipTlsCheck bool
httpPoster *HTTPPoster
@@ -135,7 +133,7 @@ func (cdre *CDRExporter) metaHandler(tag, arg string) (string, error) {
return cdr.FieldAsString(&config.RSRParser{Rules: "~" + utils.Usage, AllFiltersMatch: true})
case META_COSTCDRS:
return strconv.FormatFloat(utils.Round(cdre.totalCost,
cdre.roundingDecimals, utils.ROUNDING_MIDDLE), 'f', -1, 64), nil
globalRoundingDecimals, utils.ROUNDING_MIDDLE), 'f', -1, 64), nil
default:
return "", fmt.Errorf("Unsupported METATAG: %s", tag)
}
@@ -243,7 +241,7 @@ func (cdre *CDRExporter) postCdr(cdr *CDR) (err error) {
}
body = jsn
case utils.MetaHTTPjsonMap, utils.MetaAMQPjsonMap, utils.MetaAWSjsonMap, utils.MetaSQSjsonMap:
expMp, err := cdr.AsExportMap(cdre.exportTemplate.ContentFields, cdre.httpSkipTlsCheck, nil, cdre.roundingDecimals, cdre.filterS)
expMp, err := cdr.AsExportMap(cdre.exportTemplate.ContentFields, cdre.httpSkipTlsCheck, nil, cdre.filterS)
if err != nil {
return err
}
@@ -253,7 +251,7 @@ func (cdre *CDRExporter) postCdr(cdr *CDR) (err error) {
}
body = jsn
case utils.META_HTTP_POST:
expMp, err := cdr.AsExportMap(cdre.exportTemplate.ContentFields, cdre.httpSkipTlsCheck, nil, cdre.roundingDecimals, cdre.filterS)
expMp, err := cdr.AsExportMap(cdre.exportTemplate.ContentFields, cdre.httpSkipTlsCheck, nil, cdre.filterS)
if err != nil {
return err
}
@@ -297,7 +295,7 @@ func (cdre *CDRExporter) processCDR(cdr *CDR) (err error) {
switch cdre.exportFormat {
case utils.MetaFileFWV, utils.MetaFileCSV:
var cdrRow []string
cdrRow, err = cdr.AsExportRecord(cdre.exportTemplate.ContentFields, cdre.httpSkipTlsCheck, cdre.cdrs, cdre.roundingDecimals, cdre.filterS)
cdrRow, err = cdr.AsExportRecord(cdre.exportTemplate.ContentFields, cdre.httpSkipTlsCheck, cdre.cdrs, cdre.filterS)
if len(cdrRow) == 0 && err == nil { // No CDR data, most likely no configuration fields defined
return
} else {
@@ -339,7 +337,7 @@ func (cdre *CDRExporter) processCDR(cdr *CDR) (err error) {
}
if cdr.Cost != -1 {
cdre.totalCost += cdr.Cost
cdre.totalCost = utils.Round(cdre.totalCost, cdre.roundingDecimals, utils.ROUNDING_MIDDLE)
cdre.totalCost = utils.Round(cdre.totalCost, globalRoundingDecimals, utils.ROUNDING_MIDDLE)
}
if cdre.firstExpOrderId > cdr.OrderID || cdre.firstExpOrderId == 0 {
cdre.firstExpOrderId = cdr.OrderID

View File

@@ -45,8 +45,7 @@ func TestCsvCdrWriter(t *testing.T) {
}
cdre, err := NewCDRExporter([]*CDR{storedCdr1},
cfg.CdreProfiles[utils.MetaDefault], utils.MetaFileCSV, "", "", "firstexport",
true, 1, ',', cfg.GeneralCfg().RoundingDecimals,
cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
true, 1, ',', cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
if err != nil {
t.Error("Unexpected error received: ", err)
}
@@ -57,7 +56,7 @@ func TestCsvCdrWriter(t *testing.T) {
if err := cdre.writeCsv(csvWriter); err != nil {
t.Error("Unexpected error: ", err)
}
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6,*default,*voice,dsafdsaf,*rated,cgrates.org,call,1001,1001,1002,2013-11-07T08:42:25Z,2013-11-07T08:42:26Z,10s,1.01000`
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6,*default,*voice,dsafdsaf,*rated,cgrates.org,call,1001,1001,1002,2013-11-07T08:42:25Z,2013-11-07T08:42:26Z,10s,1.0100`
result := strings.TrimSpace(writer.String())
if result != expected {
t.Errorf("Expected: \n%s \n received: \n%s.", expected, result)
@@ -84,7 +83,6 @@ func TestAlternativeFieldSeparator(t *testing.T) {
}
cdre, err := NewCDRExporter([]*CDR{storedCdr1}, cfg.CdreProfiles[utils.MetaDefault],
utils.MetaFileCSV, "", "", "firstexport", true, 1, '|',
cfg.GeneralCfg().RoundingDecimals,
cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
if err != nil {
t.Error("Unexpected error received: ", err)
@@ -96,7 +94,7 @@ func TestAlternativeFieldSeparator(t *testing.T) {
if err := cdre.writeCsv(csvWriter); err != nil {
t.Error("Unexpected error: ", err)
}
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6|*default|*voice|dsafdsaf|*rated|cgrates.org|call|1001|1001|1002|2013-11-07T08:42:25Z|2013-11-07T08:42:26Z|10s|1.01000`
expected := `dbafe9c8614c785a65aabd116dd3959c3c56f7f6|*default|*voice|dsafdsaf|*rated|cgrates.org|call|1001|1001|1002|2013-11-07T08:42:25Z|2013-11-07T08:42:26Z|10s|1.0100`
result := strings.TrimSpace(writer.String())
if result != expected {
t.Errorf("Expected: \n%s received: \n%s.", expected, result)
@@ -139,7 +137,7 @@ func TestExportVoiceWithConvert(t *testing.T) {
Value: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+"Usage{*duration_nanoseconds}", true, utils.INFIELD_SEP)},
{Tag: "Cost", Type: "*composed",
Value: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+"Cost", true, utils.INFIELD_SEP),
RoundingDecimals: 4},
RoundingDecimals: 5},
}
cdrVoice := &CDR{
CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()),
@@ -179,7 +177,7 @@ func TestExportVoiceWithConvert(t *testing.T) {
}
cdre, err := NewCDRExporter([]*CDR{cdrVoice, cdrData, cdrSMS}, cdreCfg,
utils.MetaFileCSV, "", "", "firstexport",
true, 1, '|', 5, true, nil, &FilterS{cfg: cfg})
true, 1, '|', true, nil, &FilterS{cfg: cfg})
if err != nil {
t.Error("Unexpected error received: ", err)
}
@@ -236,7 +234,7 @@ func TestExportWithFilter(t *testing.T) {
Value: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+"Usage{*duration_nanoseconds}", true, utils.INFIELD_SEP)},
{Tag: "Cost", Type: "*composed",
Value: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+"Cost", true, utils.INFIELD_SEP),
RoundingDecimals: 4},
RoundingDecimals: 5},
}
cdrVoice := &CDR{
CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()),
@@ -276,7 +274,7 @@ func TestExportWithFilter(t *testing.T) {
}
cdre, err := NewCDRExporter([]*CDR{cdrVoice, cdrData, cdrSMS}, cdreCfg,
utils.MetaFileCSV, "", "", "firstexport",
true, 1, '|', 5, true, nil, &FilterS{cfg: cfg})
true, 1, '|', true, nil, &FilterS{cfg: cfg})
if err != nil {
t.Error("Unexpected error received: ", err)
}
@@ -332,7 +330,7 @@ func TestExportWithFilter2(t *testing.T) {
Value: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+"Usage{*duration_nanoseconds}", true, utils.INFIELD_SEP)},
{Tag: "Cost", Type: "*composed",
Value: config.NewRSRParsersMustCompile(utils.DynamicDataPrefix+"Cost", true, utils.INFIELD_SEP),
RoundingDecimals: 4},
RoundingDecimals: 5},
}
cdrVoice := &CDR{
CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()),
@@ -372,7 +370,7 @@ func TestExportWithFilter2(t *testing.T) {
}
cdre, err := NewCDRExporter([]*CDR{cdrVoice, cdrData, cdrSMS}, cdreCfg,
utils.MetaFileCSV, "", "", "firstexport",
true, 1, '|', 5, true, nil, &FilterS{cfg: cfg})
true, 1, '|', true, nil, &FilterS{cfg: cfg})
if err != nil {
t.Error("Unexpected error received: ", err)
}

View File

@@ -183,11 +183,12 @@ var contentJsnCfgFlds = []*config.FcTemplateJsonCfg{
Strip: utils.StringPointer("right"),
Padding: utils.StringPointer("right")},
{
Tag: utils.StringPointer("Cost"),
Type: utils.StringPointer(utils.META_COMPOSED),
Width: utils.IntPointer(9),
Value: utils.StringPointer("~" + utils.COST),
Padding: utils.StringPointer("zeroleft")},
Tag: utils.StringPointer("Cost"),
Type: utils.StringPointer(utils.META_COMPOSED),
Width: utils.IntPointer(9),
Value: utils.StringPointer("~" + utils.COST),
Padding: utils.StringPointer("zeroleft"),
Rounding_decimals: utils.IntPointer(5)},
{
Tag: utils.StringPointer("DestinationPrivacy"),
Type: utils.StringPointer(utils.MetaMaskedDestination),
@@ -282,8 +283,7 @@ func TestWriteCdr(t *testing.T) {
}
cdre, err := NewCDRExporter([]*CDR{cdr}, cdreCfg, utils.MetaFileFWV, "", "", "fwv_1",
true, 1, '|', cfg.GeneralCfg().RoundingDecimals,
cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
true, 1, '|', cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
if err != nil {
t.Error(err)
}
@@ -314,7 +314,7 @@ func TestWriteCdr(t *testing.T) {
t.Error("Unexpected number of records in the stats: ", cdre.numberOfRecords)
} else if cdre.totalDuration != cdr.Usage {
t.Error("Unexpected total duration in the stats: ", cdre.totalDuration)
} else if cdre.totalCost != utils.Round(cdr.Cost, cdre.roundingDecimals, utils.ROUNDING_MIDDLE) {
} else if cdre.totalCost != utils.Round(cdr.Cost, 5, utils.ROUNDING_MIDDLE) {
t.Error("Unexpected total cost in the stats: ", cdre.totalCost)
}
@@ -324,7 +324,7 @@ func TestWriteCdr(t *testing.T) {
if cdre.LastOrderId() != 1 {
t.Error("Unexpected LastOrderId", cdre.LastOrderId())
}
if cdre.TotalCost() != utils.Round(cdr.Cost, cdre.roundingDecimals, utils.ROUNDING_MIDDLE) {
if cdre.TotalCost() != utils.Round(cdr.Cost, 5, utils.ROUNDING_MIDDLE) {
t.Error("Unexpected TotalCost: ", cdre.TotalCost())
}
}
@@ -370,7 +370,6 @@ func TestWriteCdrs(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
cdre, err := NewCDRExporter([]*CDR{cdr1, cdr2, cdr3, cdr4}, cdreCfg,
utils.MetaFileFWV, "", "", "fwv_1", true, 1, ',',
cfg.GeneralCfg().RoundingDecimals,
cfg.GeneralCfg().HttpSkipTlsVerify, nil, nil)
if err != nil {
t.Error(err)

View File

@@ -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, cdrS.cgrCfg.GeneralCfg().RoundingDecimals,
cdrS.cgrCfg.GeneralCfg().HttpSkipTlsVerify, cdrS.httpPoster,
expTpl.FieldSeparator, 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()))
continue