mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Merge branch 'master' into stats
Conflicts: cmd/cgr-engine/cgr-engine.go engine/action_trigger.go utils/rsrfield.go
This commit is contained in:
@@ -59,7 +59,8 @@ func (self *ApierV1) ExportCdrsToFile(attr utils.AttrExpFileCdrs, reply *utils.E
|
||||
}
|
||||
} else {
|
||||
exportTemplate, _ = config.NewDefaultCdreConfig()
|
||||
if contentFlds, err := config.NewCdreCdrFieldsFromIds(strings.Split(*attr.ExportTemplate, string(utils.CSV_SEP))...); err != nil {
|
||||
if contentFlds, err := config.NewCdreCdrFieldsFromIds(exportTemplate.CdrFormat == utils.CDRE_FIXED_WIDTH,
|
||||
strings.Split(*attr.ExportTemplate, string(utils.CSV_SEP))...); err != nil {
|
||||
return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
|
||||
} else {
|
||||
exportTemplate.ContentFields = contentFlds
|
||||
|
||||
@@ -241,11 +241,9 @@ func (cdre *CdrExporter) composeHeader() error {
|
||||
return err
|
||||
}
|
||||
fmtOut := outVal
|
||||
if cdre.cdrFormat == utils.CDRE_FIXED_WIDTH {
|
||||
if fmtOut, err = FmtFieldWidth(outVal, cfgFld.Width, cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<CdreFw> Cannot export CDR header, field %s, error: %s", cfgFld.Name, err.Error()))
|
||||
return err
|
||||
}
|
||||
if fmtOut, err = FmtFieldWidth(outVal, cfgFld.Width, cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<CdreFw> Cannot export CDR header, field %s, error: %s", cfgFld.Name, err.Error()))
|
||||
return err
|
||||
}
|
||||
cdre.header = append(cdre.header, fmtOut)
|
||||
}
|
||||
@@ -272,11 +270,9 @@ func (cdre *CdrExporter) composeTrailer() error {
|
||||
return err
|
||||
}
|
||||
fmtOut := outVal
|
||||
if cdre.cdrFormat == utils.CDRE_FIXED_WIDTH {
|
||||
if fmtOut, err = FmtFieldWidth(outVal, cfgFld.Width, cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<CdreFw> Cannot export CDR trailer, field: %s, error: %s", cfgFld.Name, err.Error()))
|
||||
return err
|
||||
}
|
||||
if fmtOut, err = FmtFieldWidth(outVal, cfgFld.Width, cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<CdreFw> Cannot export CDR trailer, field: %s, error: %s", cfgFld.Name, err.Error()))
|
||||
return err
|
||||
}
|
||||
cdre.trailer = append(cdre.trailer, fmtOut)
|
||||
}
|
||||
@@ -338,11 +334,9 @@ func (cdre *CdrExporter) processCdr(cdr *utils.StoredCdr) error {
|
||||
return err
|
||||
}
|
||||
fmtOut := outVal
|
||||
if cdre.cdrFormat == utils.CDRE_FIXED_WIDTH {
|
||||
if fmtOut, err = FmtFieldWidth(outVal, cfgFld.Width, cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<CdreFw> Cannot export CDR with cgrid: %s, runid: %s, fieldName: %s, fieldValue: %s, error: %s", cdr.CgrId, cdr.MediationRunId, cfgFld.Name, outVal, err.Error()))
|
||||
return err
|
||||
}
|
||||
if fmtOut, err = FmtFieldWidth(outVal, cfgFld.Width, cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<CdreFw> Cannot export CDR with cgrid: %s, runid: %s, fieldName: %s, fieldValue: %s, error: %s", cdr.CgrId, cdr.MediationRunId, cfgFld.Name, outVal, err.Error()))
|
||||
return err
|
||||
}
|
||||
cdrRow[idx] += fmtOut
|
||||
}
|
||||
@@ -362,8 +356,10 @@ func (cdre *CdrExporter) processCdr(cdr *utils.StoredCdr) error {
|
||||
if !utils.IsSliceMember([]string{utils.DATA, utils.SMS}, cdr.TOR) { // Only count duration for non data cdrs
|
||||
cdre.totalDuration += cdr.Usage
|
||||
}
|
||||
cdre.totalCost += cdr.Cost
|
||||
cdre.totalCost = utils.Round(cdre.totalCost, cdre.roundDecimals, utils.ROUNDING_MIDDLE)
|
||||
if cdr.Cost != -1 {
|
||||
cdre.totalCost += cdr.Cost
|
||||
cdre.totalCost = utils.Round(cdre.totalCost, cdre.roundDecimals, utils.ROUNDING_MIDDLE)
|
||||
}
|
||||
if cdre.firstExpOrderId > cdr.OrderId || cdre.firstExpOrderId == 0 {
|
||||
cdre.firstExpOrderId = cdr.OrderId
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ func FmtFieldWidth(source string, width int, strip, padding string, mandatory bo
|
||||
if mandatory && len(source) == 0 {
|
||||
return "", errors.New("Empty source value")
|
||||
}
|
||||
if width == 0 { // Disable width processing if not defined
|
||||
return source, nil
|
||||
}
|
||||
if len(source) == width { // the source is exactly the maximum length
|
||||
return source, nil
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ func startMediator(responder *engine.Responder, loggerDb engine.LogStorage, cdrD
|
||||
var err error
|
||||
|
||||
for i := 0; i < cfg.MediatorRaterReconnects; i++ {
|
||||
client, err = rpcclient.NewRpcClient("tcp", cfg.MediatorRater, 0, 3, utils.GOB)
|
||||
client, err = rpcclient.NewRpcClient("tcp", cfg.MediatorRater, 0, cfg.MediatorRaterReconnects, utils.GOB)
|
||||
if err == nil { //Connected so no need to reiterate
|
||||
break
|
||||
}
|
||||
@@ -150,7 +150,7 @@ func startSessionManager(responder *engine.Responder, loggerDb engine.LogStorage
|
||||
var err error
|
||||
|
||||
for i := 0; i < cfg.SMRaterReconnects; i++ {
|
||||
client, err = rpcclient.NewRpcClient("tcp", cfg.SMRater, 0, 3, utils.GOB)
|
||||
client, err = rpcclient.NewRpcClient("tcp", cfg.SMRater, 0, cfg.SMRaterReconnects, utils.GOB)
|
||||
if err == nil { //Connected so no need to reiterate
|
||||
break
|
||||
}
|
||||
|
||||
@@ -24,15 +24,16 @@ import (
|
||||
)
|
||||
|
||||
// Converts a list of field identifiers into proper CDR field content
|
||||
func NewCdreCdrFieldsFromIds(fldsIds ...string) ([]*CdreCdrField, error) {
|
||||
func NewCdreCdrFieldsFromIds(withFixedWith bool, fldsIds ...string) ([]*CdreCdrField, error) {
|
||||
cdrFields := make([]*CdreCdrField, len(fldsIds))
|
||||
for idx, fldId := range fldsIds {
|
||||
if parsedRsr, err := utils.NewRSRField(fldId); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
cdrFld := &CdreCdrField{Name: fldId, Type: utils.CDRFIELD, Value: fldId, valueAsRsrField: parsedRsr}
|
||||
if err := cdrFld.setDefaultFixedWidthProperties(); err != nil { // Set default fixed width properties to be used later if needed
|
||||
if err := cdrFld.setDefaultFieldProperties(withFixedWith); err != nil { // Set default fixed width properties to be used later if needed
|
||||
return nil, err
|
||||
|
||||
}
|
||||
cdrFields[idx] = cdrFld
|
||||
}
|
||||
@@ -73,7 +74,7 @@ func (cdreCfg *CdreConfig) setDefaults() error {
|
||||
cdreCfg.MaskDestId = ""
|
||||
cdreCfg.MaskLength = 0
|
||||
cdreCfg.ExportDir = "/var/log/cgrates/cdre"
|
||||
if flds, err := NewCdreCdrFieldsFromIds(utils.CGRID, utils.MEDI_RUNID, utils.TOR, utils.ACCID, utils.REQTYPE, utils.DIRECTION, utils.TENANT,
|
||||
if flds, err := NewCdreCdrFieldsFromIds(false, utils.CGRID, utils.MEDI_RUNID, utils.TOR, utils.ACCID, utils.REQTYPE, utils.DIRECTION, utils.TENANT,
|
||||
utils.CATEGORY, utils.ACCOUNT, utils.SUBJECT, utils.DESTINATION, utils.SETUP_TIME, utils.ANSWER_TIME, utils.USAGE, utils.COST); err != nil {
|
||||
return err
|
||||
} else {
|
||||
@@ -100,125 +101,142 @@ func (cdrField *CdreCdrField) ValueAsRSRField() *utils.RSRField {
|
||||
}
|
||||
|
||||
// Should be called on .fwv configuration without providing default values for fixed with parameters
|
||||
func (cdrField *CdreCdrField) setDefaultFixedWidthProperties() error {
|
||||
func (cdrField *CdreCdrField) setDefaultFieldProperties(fixedWidth bool) error {
|
||||
if cdrField.valueAsRsrField == nil {
|
||||
return errors.New("Missing valueAsRsrField")
|
||||
}
|
||||
switch cdrField.valueAsRsrField.Id {
|
||||
case utils.CGRID:
|
||||
cdrField.Width = 40
|
||||
cdrField.Strip = ""
|
||||
cdrField.Padding = ""
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 40
|
||||
}
|
||||
case utils.ORDERID:
|
||||
cdrField.Width = 11
|
||||
cdrField.Strip = ""
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 11
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.TOR:
|
||||
cdrField.Width = 6
|
||||
cdrField.Strip = ""
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 6
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.ACCID:
|
||||
cdrField.Width = 36
|
||||
cdrField.Strip = "left"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 36
|
||||
cdrField.Strip = "left"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.CDRHOST:
|
||||
cdrField.Width = 15
|
||||
cdrField.Strip = "left"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 15
|
||||
cdrField.Strip = "left"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.CDRSOURCE:
|
||||
cdrField.Width = 15
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 15
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.REQTYPE:
|
||||
cdrField.Width = 13
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 13
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.DIRECTION:
|
||||
cdrField.Width = 4
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 4
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.TENANT:
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.CATEGORY:
|
||||
cdrField.Width = 10
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 10
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.ACCOUNT:
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.SUBJECT:
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.DESTINATION:
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.SETUP_TIME:
|
||||
cdrField.Width = 30
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = "2006-01-02T15:04:05Z07:00"
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 30
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = "2006-01-02T15:04:05Z07:00"
|
||||
}
|
||||
case utils.ANSWER_TIME:
|
||||
cdrField.Width = 30
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = "2006-01-02T15:04:05Z07:00"
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 30
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = "2006-01-02T15:04:05Z07:00"
|
||||
}
|
||||
case utils.USAGE:
|
||||
cdrField.Width = 30
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 30
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.MEDI_RUNID:
|
||||
cdrField.Width = 20
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 20
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
case utils.COST:
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = true
|
||||
if fixedWidth {
|
||||
cdrField.Width = 24
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
default:
|
||||
cdrField.Width = 30
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
cdrField.Layout = ""
|
||||
cdrField.Mandatory = false
|
||||
if fixedWidth {
|
||||
cdrField.Width = 30
|
||||
cdrField.Strip = "xright"
|
||||
cdrField.Padding = "left"
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestCdreCfgNewCdreCdrFieldsFromIds(t *testing.T) {
|
||||
valueAsRsrField: &utils.RSRField{Id: "extra1"},
|
||||
},
|
||||
}
|
||||
if cdreFlds, err := NewCdreCdrFieldsFromIds(utils.CGRID, "extra1"); err != nil {
|
||||
if cdreFlds, err := NewCdreCdrFieldsFromIds(true, utils.CGRID, "extra1"); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(expectedFlds, cdreFlds) {
|
||||
t.Errorf("Expected: %v, received: %v", expectedFlds, cdreFlds)
|
||||
@@ -86,7 +86,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.CGRID,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.CGRID,
|
||||
Width: 40,
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.CGRID},
|
||||
},
|
||||
@@ -94,9 +93,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.MEDI_RUNID,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.MEDI_RUNID,
|
||||
Width: 20,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.MEDI_RUNID},
|
||||
},
|
||||
@@ -104,8 +100,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.TOR,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.TOR,
|
||||
Width: 6,
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.TOR},
|
||||
},
|
||||
@@ -113,9 +107,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.ACCID,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.ACCID,
|
||||
Width: 36,
|
||||
Strip: "left",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.ACCID},
|
||||
},
|
||||
@@ -123,9 +114,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.REQTYPE,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.REQTYPE,
|
||||
Width: 13,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.REQTYPE},
|
||||
},
|
||||
@@ -133,9 +121,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.DIRECTION,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.DIRECTION,
|
||||
Width: 4,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.DIRECTION},
|
||||
},
|
||||
@@ -143,9 +128,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.TENANT,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.TENANT,
|
||||
Width: 24,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.TENANT},
|
||||
},
|
||||
@@ -153,9 +135,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.CATEGORY,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.CATEGORY,
|
||||
Width: 10,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.CATEGORY},
|
||||
},
|
||||
@@ -163,9 +142,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.ACCOUNT,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.ACCOUNT,
|
||||
Width: 24,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.ACCOUNT},
|
||||
},
|
||||
@@ -173,9 +149,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.SUBJECT,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.SUBJECT,
|
||||
Width: 24,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.SUBJECT},
|
||||
},
|
||||
@@ -183,9 +156,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.DESTINATION,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.DESTINATION,
|
||||
Width: 24,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.DESTINATION},
|
||||
},
|
||||
@@ -193,10 +163,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.SETUP_TIME,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.SETUP_TIME,
|
||||
Width: 30,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Layout: "2006-01-02T15:04:05Z07:00",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.SETUP_TIME},
|
||||
},
|
||||
@@ -204,10 +170,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.ANSWER_TIME,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.ANSWER_TIME,
|
||||
Width: 30,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Layout: "2006-01-02T15:04:05Z07:00",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.ANSWER_TIME},
|
||||
},
|
||||
@@ -215,9 +177,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.USAGE,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.USAGE,
|
||||
Width: 30,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.USAGE},
|
||||
},
|
||||
@@ -225,9 +184,6 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
Name: utils.COST,
|
||||
Type: utils.CDRFIELD,
|
||||
Value: utils.COST,
|
||||
Width: 24,
|
||||
Strip: "xright",
|
||||
Padding: "left",
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.COST},
|
||||
},
|
||||
@@ -239,7 +195,7 @@ func TestCdreCfgNewDefaultCdreConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
func TestCdreCfgSetDefaultFieldProperties(t *testing.T) {
|
||||
cdreCdrFld := &CdreCdrField{
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.CGRID},
|
||||
}
|
||||
@@ -248,7 +204,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.CGRID},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -262,7 +218,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.ORDERID},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -276,7 +232,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.TOR},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -291,7 +247,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.ACCID},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -306,7 +262,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.CDRHOST},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -321,7 +277,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.CDRSOURCE},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -336,7 +292,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.REQTYPE},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -351,7 +307,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.DIRECTION},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -366,7 +322,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.TENANT},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -381,7 +337,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.CATEGORY},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -396,7 +352,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.ACCOUNT},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -411,7 +367,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.SUBJECT},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -426,7 +382,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.DESTINATION},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -442,7 +398,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.SETUP_TIME},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -458,7 +414,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.ANSWER_TIME},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -473,7 +429,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.USAGE},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -488,7 +444,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.MEDI_RUNID},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -503,7 +459,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: true,
|
||||
valueAsRsrField: &utils.RSRField{Id: utils.COST},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
@@ -518,7 +474,7 @@ func TestCdreCfgSetDefaultFixedWidthProperties(t *testing.T) {
|
||||
Mandatory: false,
|
||||
valueAsRsrField: &utils.RSRField{Id: "extra_1"},
|
||||
}
|
||||
if err := cdreCdrFld.setDefaultFixedWidthProperties(); err != nil {
|
||||
if err := cdreCdrFld.setDefaultFieldProperties(true); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCdreCdrFld, cdreCdrFld) {
|
||||
t.Errorf("Expecting: %v, received: %v", eCdreCdrFld, cdreCdrFld)
|
||||
|
||||
@@ -423,7 +423,8 @@ func loadConfig(c *conf.ConfigFile) (*CGRConfig, error) {
|
||||
cfg.CdreDefaultInstance = xmlTemplates[exportTemplate[len(utils.XML_PROFILE_PREFIX):]].AsCdreConfig()
|
||||
}
|
||||
} else { // Not loading out of template
|
||||
if flds, err := NewCdreCdrFieldsFromIds(strings.Split(exportTemplate, string(utils.CSV_SEP))...); err != nil {
|
||||
if flds, err := NewCdreCdrFieldsFromIds(cfg.CdreDefaultInstance.CdrFormat == utils.CDRE_FIXED_WIDTH,
|
||||
strings.Split(exportTemplate, string(utils.CSV_SEP))...); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
cfg.CdreDefaultInstance.ContentFields = flds
|
||||
|
||||
@@ -214,7 +214,7 @@ func TestConfigFromFile(t *testing.T) {
|
||||
MaskDestId: "test",
|
||||
MaskLength: 99,
|
||||
ExportDir: "test"}
|
||||
eCfg.CdreDefaultInstance.ContentFields, _ = NewCdreCdrFieldsFromIds("test")
|
||||
eCfg.CdreDefaultInstance.ContentFields, _ = NewCdreCdrFieldsFromIds(false, "test")
|
||||
eCfg.CdrcEnabled = true
|
||||
eCfg.CdrcCdrs = "test"
|
||||
eCfg.CdrcRunDelay = time.Duration(99) * time.Second
|
||||
@@ -308,11 +308,11 @@ cdr_format = csv
|
||||
export_template = cgrid,mediation_runid,accid
|
||||
`)
|
||||
expectedFlds := []*CdreCdrField{
|
||||
&CdreCdrField{Name: "cgrid", Type: utils.CDRFIELD, Value: "cgrid", valueAsRsrField: &utils.RSRField{Id: "cgrid"}, Width: 40, Mandatory: true},
|
||||
&CdreCdrField{Name: "cgrid", Type: utils.CDRFIELD, Value: "cgrid", valueAsRsrField: &utils.RSRField{Id: "cgrid"}, Mandatory: true},
|
||||
&CdreCdrField{Name: "mediation_runid", Type: utils.CDRFIELD, Value: "mediation_runid", valueAsRsrField: &utils.RSRField{Id: "mediation_runid"},
|
||||
Width: 20, Strip: "xright", Padding: "left", Mandatory: true},
|
||||
Mandatory: true},
|
||||
&CdreCdrField{Name: "accid", Type: utils.CDRFIELD, Value: "accid", valueAsRsrField: &utils.RSRField{Id: "accid"},
|
||||
Width: 36, Strip: "left", Padding: "left", Mandatory: true},
|
||||
Mandatory: true},
|
||||
}
|
||||
expCdreCfg := &CdreConfig{CdrFormat: utils.CSV, CostRoundingDecimals: -1, ExportDir: "/var/log/cgrates/cdre", ContentFields: expectedFlds}
|
||||
if cfg, err := NewCGRConfigFromBytes(eFieldsCfg); err != nil {
|
||||
@@ -326,9 +326,9 @@ export_template = cgrid,~effective_caller_id_number:s/(\d+)/+$1/
|
||||
`)
|
||||
rsrField, _ := utils.NewRSRField(`~effective_caller_id_number:s/(\d+)/+$1/`)
|
||||
expectedFlds = []*CdreCdrField{
|
||||
&CdreCdrField{Name: "cgrid", Type: utils.CDRFIELD, Value: "cgrid", valueAsRsrField: &utils.RSRField{Id: "cgrid"}, Width: 40, Mandatory: true},
|
||||
&CdreCdrField{Name: `~effective_caller_id_number:s/(\d+)/+$1/`, Type: utils.CDRFIELD, Value: `~effective_caller_id_number:s/(\d+)/+$1/`, valueAsRsrField: rsrField,
|
||||
Width: 30, Strip: "xright", Padding: "left", Mandatory: false}}
|
||||
&CdreCdrField{Name: "cgrid", Type: utils.CDRFIELD, Value: "cgrid", valueAsRsrField: &utils.RSRField{Id: "cgrid"}, Mandatory: true},
|
||||
&CdreCdrField{Name: `~effective_caller_id_number:s/(\d+)/+$1/`, Type: utils.CDRFIELD, Value: `~effective_caller_id_number:s/(\d+)/+$1/`,
|
||||
valueAsRsrField: rsrField, Mandatory: false}}
|
||||
expCdreCfg.ContentFields = expectedFlds
|
||||
if cfg, err := NewCGRConfigFromBytes(eFieldsCfg); err != nil {
|
||||
t.Error("Could not parse the config", err.Error())
|
||||
|
||||
@@ -344,12 +344,12 @@ func (ub *Account) executeActionTriggers(a *Action) {
|
||||
if uc.BalanceType == at.BalanceType {
|
||||
for _, mb := range uc.Balances {
|
||||
if strings.Contains(at.ThresholdType, "*max") {
|
||||
if mb.MatchDestination(at.DestinationId) && mb.Value >= at.ThresholdValue {
|
||||
if mb.MatchActionTrigger(at) && mb.Value >= at.ThresholdValue {
|
||||
// run the actions
|
||||
at.Execute(ub)
|
||||
}
|
||||
} else { //MIN
|
||||
if mb.MatchDestination(at.DestinationId) && mb.Value <= at.ThresholdValue {
|
||||
if mb.MatchActionTrigger(at) && mb.Value <= at.ThresholdValue {
|
||||
// run the actions
|
||||
at.Execute(ub)
|
||||
}
|
||||
@@ -359,13 +359,16 @@ func (ub *Account) executeActionTriggers(a *Action) {
|
||||
}
|
||||
} else { // BALANCE
|
||||
for _, b := range ub.BalanceMap[at.BalanceType+at.Direction] {
|
||||
if !b.dirty { // do not check clean balances
|
||||
continue
|
||||
}
|
||||
if strings.Contains(at.ThresholdType, "*max") {
|
||||
if b.MatchDestination(at.DestinationId) && b.Value >= at.ThresholdValue {
|
||||
if b.MatchActionTrigger(at) && b.Value >= at.ThresholdValue {
|
||||
// run the actions
|
||||
at.Execute(ub)
|
||||
}
|
||||
} else { //MIN
|
||||
if b.MatchDestination(at.DestinationId) && b.Value <= at.ThresholdValue {
|
||||
if b.MatchActionTrigger(at) && b.Value <= at.ThresholdValue {
|
||||
// run the actions
|
||||
at.Execute(ub)
|
||||
}
|
||||
|
||||
@@ -33,15 +33,17 @@ type ActionTrigger struct {
|
||||
Direction string
|
||||
ThresholdType string //*min_counter, *max_counter, *min_balance, *max_balance
|
||||
// stats: *min_asr, *max_asr, *min_acd, *max_acd, *min_acc, *max_acc
|
||||
ThresholdValue float64
|
||||
Recurrent bool // reset eexcuted flag each run
|
||||
MinSleep time.Duration // Minimum duration between two executions in case of recurrent triggers
|
||||
DestinationId string
|
||||
Weight float64
|
||||
ActionsId string
|
||||
Executed bool
|
||||
MinQueuedItems int // Trigger actions only if this number is hit (stats only)
|
||||
lastExecutionTime time.Time
|
||||
ThresholdValue float64
|
||||
Recurrent bool // reset eexcuted flag each run
|
||||
MinSleep time.Duration // Minimum duration between two executions in case of recurrent triggers
|
||||
DestinationId string // filter for balance
|
||||
BalanceWeight float64 // filter for balance
|
||||
BalanceExpirationDate time.Time // filter for balance
|
||||
Weight float64
|
||||
ActionsId string
|
||||
Executed bool
|
||||
MinQueuedItems int // Trigger actions only if this number is hit (stats only)
|
||||
lastExecutionTime time.Time
|
||||
}
|
||||
|
||||
func (at *ActionTrigger) Execute(ub *Account) (err error) {
|
||||
@@ -51,7 +53,7 @@ func (at *ActionTrigger) Execute(ub *Account) (err error) {
|
||||
}
|
||||
at.lastExecutionTime = time.Now()
|
||||
if ub.Disabled {
|
||||
return fmt.Errorf("User %s is disabled", ub.Id)
|
||||
return fmt.Errorf("User %s is disabled and there are triggers in action!", ub.Id)
|
||||
}
|
||||
// does NOT need to Lock() because it is triggered from a method that took the Lock
|
||||
var aac Actions
|
||||
|
||||
@@ -827,7 +827,7 @@ func TestActionResetCounterMinutes(t *testing.T) {
|
||||
CREDIT: BalanceChain{&Balance{Value: 100}},
|
||||
MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, DestinationId: "NAT"}, &Balance{Weight: 10, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceType: CREDIT, Balances: BalanceChain{&Balance{Value: 1}}}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceType: CREDIT, ThresholdType: "*max_counter", ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceType: MINUTES}
|
||||
resetCounterAction(ub, a)
|
||||
@@ -840,14 +840,14 @@ func TestActionResetCounterMinutes(t *testing.T) {
|
||||
for _, b := range ub.UnitCounters[1].Balances {
|
||||
t.Logf("B: %+v", b)
|
||||
}
|
||||
t.Error("Reset counters action failed!", ub.UnitCounters[1])
|
||||
t.Errorf("Reset counters action failed: %+v", ub)
|
||||
}
|
||||
if len(ub.UnitCounters) < 2 || len(ub.UnitCounters[1].Balances) < 1 {
|
||||
t.FailNow()
|
||||
}
|
||||
mb := ub.UnitCounters[1].Balances[0]
|
||||
if mb.Weight != 20 || mb.Value != 0 || mb.DestinationId != "NAT" {
|
||||
t.Errorf("Balance cloned incorrectly: %v!", mb)
|
||||
t.Errorf("Balance cloned incorrectly: %+v!", mb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,20 @@ func (b *Balance) MatchDestination(destinationId string) bool {
|
||||
return !b.HasDestination() || b.DestinationId == destinationId
|
||||
}
|
||||
|
||||
func (b *Balance) MatchActionTrigger(at *ActionTrigger) bool {
|
||||
matchesExpirationDate := true
|
||||
if !at.BalanceExpirationDate.IsZero() {
|
||||
matchesExpirationDate = (at.BalanceExpirationDate.Equal(b.ExpirationDate))
|
||||
}
|
||||
matchesWeight := true
|
||||
if at.BalanceWeight > 0 {
|
||||
matchesWeight = (at.BalanceWeight == b.Weight)
|
||||
}
|
||||
return b.MatchDestination(at.DestinationId) &&
|
||||
matchesExpirationDate &&
|
||||
matchesWeight
|
||||
}
|
||||
|
||||
func (b *Balance) Clone() *Balance {
|
||||
return &Balance{
|
||||
Uuid: b.Uuid,
|
||||
|
||||
@@ -19,6 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/cgrates/cgrates/cache2go"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
@@ -36,6 +38,10 @@ type UnitsCounter struct {
|
||||
func (uc *UnitsCounter) initBalances(ats []*ActionTrigger) {
|
||||
uc.Balances = BalanceChain{&Balance{}} // general balance
|
||||
for _, at := range ats {
|
||||
if !strings.Contains(at.ThresholdType, "counter") {
|
||||
// only get actions fo counter type action triggers
|
||||
continue
|
||||
}
|
||||
acs, err := accountingStorage.GetActions(at.ActionsId, false)
|
||||
if err != nil {
|
||||
continue
|
||||
|
||||
@@ -48,17 +48,17 @@ func NewRSRField(fldStr string) (*RSRField, error) {
|
||||
spltRgxp := regexp.MustCompile(`:s\/`)
|
||||
spltRules := spltRgxp.Split(fldStr, -1)
|
||||
if len(spltRules) < 2 {
|
||||
return nil, fmt.Errorf("Invalid Search&Replace field rule. %s", fldStr)
|
||||
return nil, fmt.Errorf("Invalid Split of Search&Replace field rule. %s", fldStr)
|
||||
}
|
||||
rsrField := &RSRField{Id: spltRules[0][1:]} // Original id in form ~hdr_name
|
||||
rulesRgxp := regexp.MustCompile(`(?:(.+[^\\])\/(.+[^\\])*\/){1,}`)
|
||||
rulesRgxp := regexp.MustCompile(`(?:(.+[^\\])\/(.*[^\\])*\/){1,}`)
|
||||
for _, ruleStr := range spltRules[1:] { // :s/ already removed through split
|
||||
allMatches := rulesRgxp.FindStringSubmatch(ruleStr)
|
||||
if len(allMatches) != 3 {
|
||||
return nil, fmt.Errorf("Invalid Search&Replace field rule. %s", fldStr)
|
||||
return nil, fmt.Errorf("Not enough members in Search&Replace, ruleStr: %s, matches: %v, ", ruleStr, allMatches)
|
||||
}
|
||||
if srRegexp, err := regexp.Compile(allMatches[1]); err != nil {
|
||||
return nil, fmt.Errorf("Invalid Search&Replace field rule. %s", fldStr)
|
||||
return nil, fmt.Errorf("Invalid Search&Replace subfield rule: %s", allMatches[1])
|
||||
} else {
|
||||
rsrField.RSRules = append(rsrField.RSRules, &ReSearchReplace{SearchRegexp: srRegexp, ReplaceTemplate: allMatches[2]})
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@ func TestNewRSRFieldIvo(t *testing.T) {
|
||||
} else if !reflect.DeepEqual(rsrField, expectRSRField) {
|
||||
t.Errorf("Unexpected RSRField received: %v", rsrField)
|
||||
}
|
||||
if _, err := NewRSRField(`~account:s/^[A-Za-z0-9]*[c|a]\d{4}$/S/:s/^[A-Za-z0-9]*n\d{4}$/C/:s/^\d{10}$//`); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertPlusNationalAnd00(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user