Esempio n. 1
0
func TestSearchExtraField(t *testing.T) {
	fsCdr, _ := NewFSCdr(body, fsCdrCfg)
	rsrSt1, _ := utils.NewRSRField("^injected_value")
	rsrSt2, _ := utils.NewRSRField("^injected_hdr::injected_value/")
	fsCdrCfg.CDRSExtraFields = []*utils.RSRField{&utils.RSRField{Id: "caller_id_name"}, rsrSt1, rsrSt2}
	extraFields := fsCdr.getExtraFields()
	if len(extraFields) != 3 || extraFields["caller_id_name"] != "1001" ||
		extraFields["injected_value"] != "injected_value" ||
		extraFields["injected_hdr"] != "injected_value" {
		t.Error("Error parsing extra fields: ", extraFields)
	}
}
Esempio n. 2
0
func TestPassesFieldFilterDn1(t *testing.T) {
	cdr := &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "futurem0005",
		ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
	}
	acntPrefxFltr, _ := utils.NewRSRField(`~Account:s/^\w+[shmp]\d{4}$//`)
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); !pass {
		t.Error("Not passing valid filter")
	}

	cdr = &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "futurem00005",
		ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
	}
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Should not pass filter")
	}
	cdr = &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "0402129281",
		ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
	}
	acntPrefxFltr, _ = utils.NewRSRField(`~Account:s/^0\d{9}$//`)
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); !pass {
		t.Error("Not passing valid filter")
	}
	acntPrefxFltr, _ = utils.NewRSRField(`~Account:s/^0(\d{9})$/placeholder/`)
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Should not pass filter")
	}
	cdr = &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "04021292812",
		ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
	}
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Should not pass filter")
	}
	cdr = &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), Account: "0162447222",
		ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
	}
	if acntPrefxFltr, err := utils.NewRSRField(`~Account:s/^0\d{9}$//`); err != nil {
		t.Error("Unexpected parse error", err)
	} else if acntPrefxFltr == nil {
		t.Error("Failed parsing rule")
	} else if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); !pass {
		t.Error("Not passing valid filter")
	}
	if acntPrefxFltr, err := utils.NewRSRField(`~Account:s/^\w+[shmp]\d{4}$//`); err != nil {
		t.Error("Unexpected parse error", err)
	} else if acntPrefxFltr == nil {
		t.Error("Failed parsing rule")
	} else if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Should not pass filter")
	}
}
Esempio n. 3
0
func TestPassesFieldFilterDn1(t *testing.T) {
	body := `Event-Name: RE_SCHEDULE
Core-UUID: 792e181c-b6e6-499c-82a1-52a778e7d82d
FreeSWITCH-Hostname: h1.ip-switch.net
FreeSWITCH-Switchname: h1.ip-switch.net
FreeSWITCH-IPv4: 88.198.12.156
Caller-Username: futurem0005`
	ev := new(FSEvent).AsEvent(body)
	acntPrefxFltr, _ := utils.NewRSRField(`~Account:s/^\w+[shmp]\d{4}$//`)
	if pass, _ := ev.PassesFieldFilter(acntPrefxFltr); !pass {
		t.Error("Not passing valid filter")
	}
	body = `Event-Name: RE_SCHEDULE
Core-UUID: 792e181c-b6e6-499c-82a1-52a778e7d82d
FreeSWITCH-Hostname: h1.ip-switch.net
FreeSWITCH-Switchname: h1.ip-switch.net
FreeSWITCH-IPv4: 88.198.12.156
Caller-Username: futurem00005`
	ev = new(FSEvent).AsEvent(body)
	if pass, _ := ev.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Should not pass filter")
	}
	body = `Event-Name: RE_SCHEDULE
Core-UUID: 792e181c-b6e6-499c-82a1-52a778e7d82d
FreeSWITCH-Hostname: h1.ip-switch.net
FreeSWITCH-Switchname: h1.ip-switch.net
FreeSWITCH-IPv4: 88.198.12.156
Caller-Username: 0402129281`
	ev = new(FSEvent).AsEvent(body)
	acntPrefxFltr, _ = utils.NewRSRField(`~Account:s/^0\d{9}$//`)
	if pass, _ := ev.PassesFieldFilter(acntPrefxFltr); !pass {
		t.Error("Not passing valid filter")
	}
	acntPrefxFltr, _ = utils.NewRSRField(`~account:s/^0(\d{9})$/placeholder/`)
	if pass, _ := ev.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Should not pass filter")
	}
	body = `Event-Name: RE_SCHEDULE
Core-UUID: 792e181c-b6e6-499c-82a1-52a778e7d82d
FreeSWITCH-Hostname: h1.ip-switch.net
FreeSWITCH-Switchname: h1.ip-switch.net
FreeSWITCH-IPv4: 88.198.12.156
Caller-Username: 04021292812`
	ev = new(FSEvent).AsEvent(body)
	if pass, _ := ev.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Should not pass filter")
	}
}
Esempio n. 4
0
func TestCdreCdrFieldValue(t *testing.T) {
	cdre := new(CdrExporter)
	cdr := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
		ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
		Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
		Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.01}
	fltrRule, _ := utils.NewRSRField("~tenant:s/(.+)/cgrates.org/")
	if val, err := cdre.cdrFieldValue(cdr, fltrRule, &utils.RSRField{Id: "destination"}, ""); err != nil {
		t.Error(err)
	} else if val != cdr.Destination {
		t.Errorf("Expecting: %s, received: %s", cdr.Destination, val)
	}
	fltrRule, _ = utils.NewRSRField("~tenant:s/(.+)/itsyscom.com/")
	if _, err := cdre.cdrFieldValue(cdr, fltrRule, &utils.RSRField{Id: "destination"}, ""); err == nil {
		t.Error("Failed to use filter")
	}
}
Esempio n. 5
0
func TestCdreGetCombimedCdrFieldVal(t *testing.T) {
	logDb, _ := engine.NewMapStorage()
	cfg, _ := config.NewDefaultCGRConfig()
	cdrs := []*utils.StoredCdr{
		&utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
			ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, MediationRunId: "RUN_RTL", Cost: 1.01},
		&utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf2", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
			ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, MediationRunId: "CUSTOMER1", Cost: 2.01},
		&utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
			ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, MediationRunId: "CUSTOMER1", Cost: 3.01},
		&utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
			ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 4.01},
		&utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
			ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1000", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, MediationRunId: "RETAIL1", Cost: 5.01},
	}

	cdre, err := NewCdrExporter(cdrs, logDb, cfg.CdreDefaultInstance, cfg.CdreDefaultInstance.CdrFormat, cfg.CdreDefaultInstance.FieldSeparator,
		"firstexport", 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify)
	if err != nil {
		t.Error("Unexpected error received: ", err)
	}
	fltrRule, _ := utils.NewRSRField("~mediation_runid:s/default/RUN_RTL/")
	if costVal, err := cdre.getCombimedCdrFieldVal(cdrs[3], fltrRule, &utils.RSRField{Id: "cost"}); err != nil {
		t.Error(err)
	} else if costVal != "1.01" {
		t.Error("Expecting: 1.01, received: ", costVal)
	}
	fltrRule, _ = utils.NewRSRField("~mediation_runid:s/default/RETAIL1/")
	if acntVal, err := cdre.getCombimedCdrFieldVal(cdrs[3], fltrRule, &utils.RSRField{Id: "account"}); err != nil {
		t.Error(err)
	} else if acntVal != "1000" {
		t.Error("Expecting: 1000, received: ", acntVal)
	}
}
Esempio n. 6
0
func (self *CmdParse) LocalExecute() string {
	if self.rpcParams.Expression == "" {
		return "Empty expression error"
	}
	if self.rpcParams.Value == "" {
		return "Empty value error"
	}
	if rsrField, err := utils.NewRSRField(self.rpcParams.Expression); err == nil {
		return rsrField.ParseValue(self.rpcParams.Value)
	} else {
		return err.Error()
	}
}
Esempio n. 7
0
// Converts a list of field identifiers into proper CDR field content
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.setDefaultFieldProperties(withFixedWith); err != nil { // Set default fixed width properties to be used later if needed
				return nil, err

			}
			cdrFields[idx] = cdrFld
		}
	}
	return cdrFields, nil
}
Esempio n. 8
0
func TestPassesFieldFilter(t *testing.T) {
	cdr := &StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
		CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
		Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
		AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
		Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
	}
	if pass, _ := cdr.PassesFieldFilter(nil); !pass {
		t.Error("Not passing filter")
	}
	acntPrefxFltr, _ := utils.NewRSRField(`~Account:s/(.+)/1001/`)
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); !pass {
		t.Error("Not passing filter")
	}
	acntPrefxFltr, _ = utils.NewRSRField(`~Account:s/^(10)\d\d$/10/`)
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); !pass {
		t.Error("Not passing valid filter")
	}
	acntPrefxFltr, _ = utils.NewRSRField(`~Account:s/^\d(10)\d$/10/`)
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Passing filter")
	}
	acntPrefxFltr, _ = utils.NewRSRField(`~Account:s/^(10)\d\d$/010/`)
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Passing filter")
	}
	acntPrefxFltr, _ = utils.NewRSRField(`~Account:s/^1010$/1010/`)
	if pass, _ := cdr.PassesFieldFilter(acntPrefxFltr); pass {
		t.Error("Passing filter")
	}
	torFltr, _ := utils.NewRSRField(`^TOR::*voice/`)
	if pass, _ := cdr.PassesFieldFilter(torFltr); !pass {
		t.Error("Not passing filter")
	}
	torFltr, _ = utils.NewRSRField(`^TOR/*data/`)
	if pass, _ := cdr.PassesFieldFilter(torFltr); pass {
		t.Error("Passing filter")
	}
	inexistentFieldFltr, _ := utils.NewRSRField(`^fakefield/fakevalue/`)
	if pass, _ := cdr.PassesFieldFilter(inexistentFieldFltr); pass {
		t.Error("Passing filter")
	}
}
Esempio n. 9
0
func TestXmlCdreCfgPopulateCdreRSRFIeld(t *testing.T) {
	cdreField := CgrXmlCfgCdrField{Name: "TEST1", Type: "cdrfield", Value: `~effective_caller_id_number:s/(\d+)/+$1/`}
	if err := cdreField.populateRSRField(); err != nil {
		t.Error("Unexpected error: ", err.Error())
	} else if cdreField.valueAsRsrField == nil {
		t.Error("Failed loading the RSRField")
	}
	valRSRField, _ := utils.NewRSRField(`~effective_caller_id_number:s/(\d+)/+$1/`)
	if recv := cdreField.ValueAsRSRField(); !reflect.DeepEqual(valRSRField, recv) {
		t.Errorf("Expecting %v, received %v", valRSRField, recv)
	}
	/*cdreField = CgrXmlCfgCdrField{Name: "TEST1", Type: "constant", Value: `someval`}
	if err := cdreField.populateRSRField(); err != nil {
		t.Error("Unexpected error: ", err.Error())
	} else if cdreField.valueAsRsrField != nil {
		t.Error("Should not load the RSRField")
	}*/
}
Esempio n. 10
0
func TestCdreExtraFields(t *testing.T) {
	eFieldsCfg := []byte(`[cdre]
cdr_format = csv
export_template = cgrid,mediation_runid,accid
`)
	expectedFlds := []*CdreCdrField{
		&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"},
			Mandatory: true},
		&CdreCdrField{Name: "accid", Type: utils.CDRFIELD, Value: "accid", valueAsRsrField: &utils.RSRField{Id: "accid"},
			Mandatory: true},
	}
	expCdreCfg := &CdreConfig{CdrFormat: utils.CSV, FieldSeparator: utils.CSV_SEP, CostRoundingDecimals: -1, ExportDir: "/var/log/cgrates/cdre", ContentFields: expectedFlds}
	if cfg, err := NewCGRConfigFromBytes(eFieldsCfg); err != nil {
		t.Error("Could not parse the config", err.Error())
	} else if !reflect.DeepEqual(cfg.CdreDefaultInstance, expCdreCfg) {
		t.Errorf("Expecting: %v, received: %v", expCdreCfg, cfg.CdreDefaultInstance)
	}
	eFieldsCfg = []byte(`[cdre]
cdr_format = csv
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"}, 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())
	} else if !reflect.DeepEqual(cfg.CdreDefaultInstance, expCdreCfg) {
		t.Errorf("Expecting: %v, received: %v", expCdreCfg, cfg.CdreDefaultInstance)
	}
	eFieldsCfg = []byte(`[cdre]
cdr_format = csv
export_template = cgrid,~accid:s/(\d)/$1,runid
`)
	if _, err := NewCGRConfigFromBytes(eFieldsCfg); err == nil {
		t.Error("Failed to detect failed RSRParsing")
	}
}
Esempio n. 11
0
func TestGetDateTimeFieldVal(t *testing.T) {
	cdreTst := new(CdrExporter)
	cdrTst := &utils.StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
		ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
		Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
		Usage: time.Duration(10) * time.Second, MediationRunId: utils.DEFAULT_RUNID, Cost: 1.01,
		ExtraFields: map[string]string{"stop_time": "2014-06-11 19:19:00 +0000 UTC", "fieldextr2": "valextr2"}}
	if cdrVal, err := cdreTst.getDateTimeFieldVal(cdrTst, nil, &utils.RSRField{Id: "stop_time"}, "2006-01-02 15:04:05"); err != nil {
		t.Error(err)
	} else if cdrVal != "2014-06-11 19:19:00" {
		t.Error("Expecting: 2014-06-11 19:19:00, got: ", cdrVal)
	}
	// Test filter
	fltrRule, _ := utils.NewRSRField("~tenant:s/(.+)/itsyscom.com/")
	if _, err := cdreTst.getDateTimeFieldVal(cdrTst, fltrRule, &utils.RSRField{Id: "stop_time"}, "2006-01-02 15:04:05"); err == nil {
		t.Error(err)
	}
	// Test time parse error
	if _, err := cdreTst.getDateTimeFieldVal(cdrTst, nil, &utils.RSRField{Id: "fieldextr2"}, "2006-01-02 15:04:05"); err == nil {
		t.Error("Should give error here, got none.")
	}
}
Esempio n. 12
0
func TestStoredCdrForkCdrStaticVals(t *testing.T) {
	storCdr := StoredCdr{CgrId: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, TOR: utils.VOICE, AccId: "dsafdsaf",
		CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_RATED, Direction: "*out",
		Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
		SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: utils.DEFAULT_RUNID,
		Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
	}
	rsrStPostpaid, _ := utils.NewRSRField("^" + utils.META_POSTPAID)
	rsrStIn, _ := utils.NewRSRField("^*in")
	rsrStCgr, _ := utils.NewRSRField("^cgrates.com")
	rsrStPC, _ := utils.NewRSRField("^premium_call")
	rsrStFA, _ := utils.NewRSRField("^first_account")
	rsrStFS, _ := utils.NewRSRField("^first_subject")
	rsrStST, _ := utils.NewRSRField("^2013-12-07T08:42:24Z")
	rsrStAT, _ := utils.NewRSRField("^2013-12-07T08:42:26Z")
	rsrStDur, _ := utils.NewRSRField("^12s")
	rsrStSuppl, _ := utils.NewRSRField("^supplier1")
	rsrStDCause, _ := utils.NewRSRField("^HANGUP_COMPLETE")
	rsrPdd, _ := utils.NewRSRField("^3")
	rsrStRated, _ := utils.NewRSRField("^true")
	rsrStCost, _ := utils.NewRSRField("^1.2")
	rtCdrOut2, err := storCdr.ForkCdr("wholesale_run", rsrStPostpaid, rsrStIn, rsrStCgr, rsrStPC, rsrStFA, rsrStFS, &utils.RSRField{Id: utils.DESTINATION},
		rsrStST, rsrPdd, rsrStAT, rsrStDur, rsrStSuppl, rsrStDCause, rsrStRated, rsrStCost, []*utils.RSRField{}, true, "")
	if err != nil {
		t.Error("Unexpected error received", err)
	}
	expctRatedCdr2 := &StoredCdr{CgrId: storCdr.CgrId, TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: utils.UNIT_TEST, ReqType: utils.META_POSTPAID,
		Direction: "*in", Tenant: "cgrates.com", Category: "premium_call", Account: "first_account", Subject: "first_subject", Destination: "1002",
		SetupTime:  time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC),
		AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(12) * time.Second, Pdd: time.Duration(3) * time.Second,
		Supplier: "supplier1", DisconnectCause: "HANGUP_COMPLETE", Rated: true, Cost: 1.2,
		ExtraFields: map[string]string{}, MediationRunId: "wholesale_run"}
	if !reflect.DeepEqual(rtCdrOut2, expctRatedCdr2) {
		t.Errorf("Received: %v, expected: %v", rtCdrOut2, expctRatedCdr2)
	}
	_, err = storCdr.ForkCdr("wholesale_run", &utils.RSRField{Id: "dummy_header"}, &utils.RSRField{Id: utils.DIRECTION}, &utils.RSRField{Id: utils.TENANT},
		&utils.RSRField{Id: utils.TOR}, &utils.RSRField{Id: utils.ACCOUNT}, &utils.RSRField{Id: utils.SUBJECT}, &utils.RSRField{Id: utils.DESTINATION},
		&utils.RSRField{Id: utils.SETUP_TIME}, &utils.RSRField{Id: utils.PDD}, &utils.RSRField{Id: utils.ANSWER_TIME}, &utils.RSRField{Id: utils.USAGE},
		&utils.RSRField{Id: utils.SUPPLIER},
		&utils.RSRField{Id: utils.DISCONNECT_CAUSE}, &utils.RSRField{Id: utils.RATED_FLD}, &utils.RSRField{Id: utils.COST}, []*utils.RSRField{}, true, "")
	if err == nil {
		t.Error("Failed to detect missing header")
	}
}
Esempio n. 13
0
func (self *Mediator) RateCdr(storedCdr *utils.StoredCdr, sendToStats bool) error {
	storedCdr.MediationRunId = utils.DEFAULT_RUNID
	cdrRuns := []*utils.StoredCdr{storedCdr} // Start with initial storCdr, will add here all to be mediated
	attrsDC := utils.AttrDerivedChargers{Tenant: storedCdr.Tenant, Category: storedCdr.Category, Direction: storedCdr.Direction,
		Account: storedCdr.Account, Subject: storedCdr.Subject}
	var dcs utils.DerivedChargers
	if err := self.connector.GetDerivedChargers(attrsDC, &dcs); err != nil {
		errText := fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", storedCdr.CgrId, err.Error())
		Logger.Err(errText)
		return errors.New(errText)
	}
	for _, dc := range dcs {
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if fltrPass, _ := storedCdr.PassesFieldFilter(dcRunFilter); !fltrPass {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
			continue
		}
		dcReqTypeFld, _ := utils.NewRSRField(dc.ReqTypeField)
		dcDirFld, _ := utils.NewRSRField(dc.DirectionField)
		dcTenantFld, _ := utils.NewRSRField(dc.TenantField)
		dcCategoryFld, _ := utils.NewRSRField(dc.CategoryField)
		dcAcntFld, _ := utils.NewRSRField(dc.AccountField)
		dcSubjFld, _ := utils.NewRSRField(dc.SubjectField)
		dcDstFld, _ := utils.NewRSRField(dc.DestinationField)
		dcSTimeFld, _ := utils.NewRSRField(dc.SetupTimeField)
		dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField)
		dcDurFld, _ := utils.NewRSRField(dc.UsageField)
		forkedCdr, err := storedCdr.ForkCdr(dc.RunId, dcReqTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld, dcSTimeFld, dcATimeFld, dcDurFld,
			[]*utils.RSRField{}, true)
		if err != nil { // Errors on fork, cannot calculate further, write that into db for later analysis
			self.cdrDb.SetRatedCdr(&utils.StoredCdr{CgrId: storedCdr.CgrId, CdrSource: utils.FORKED_CDR, MediationRunId: dc.RunId, Cost: -1},
				err.Error()) // Cannot fork CDR, important just runid and error
			continue
		}
		cdrRuns = append(cdrRuns, forkedCdr)
	}
	for _, cdr := range cdrRuns {
		extraInfo := ""
		if err := self.rateCDR(cdr); err != nil {
			extraInfo = err.Error()
		}
		if !self.cgrCfg.MediatorStoreDisable {
			if err := self.cdrDb.SetRatedCdr(cdr, extraInfo); err != nil {
				Logger.Err(fmt.Sprintf("<Mediator> Could not record cost for cgrid: <%s>, ERROR: <%s>, cost: %f, extraInfo: %s",
					cdr.CgrId, err.Error(), cdr.Cost, extraInfo))
			}
		}
		if sendToStats && self.stats != nil { // We send to stats only after saving to db since there are chances we cannot store and then no way to reproduce stats offline
			go func(cdr *utils.StoredCdr) { // Pass it by value since the variable will be overwritten by for
				if err := self.stats.AppendCDR(cdr, nil); err != nil {
					Logger.Err(fmt.Sprintf("Could not append cdr to stats (mediator): %s", err.Error()))
				}
			}(cdr)
		}
	}
	return nil
}
Esempio n. 14
0
// Used in mediation, primaryMandatory marks whether missing field out of request represents error or can be ignored
func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, pddFld,
	answerTimeFld, durationFld, supplierFld, disconnectCauseFld *utils.RSRField,
	extraFlds []*utils.RSRField, primaryMandatory bool, timezone string) (*StoredCdr, error) {
	if reqTypeFld == nil {
		reqTypeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if reqTypeFld.Id == utils.META_DEFAULT {
		reqTypeFld.Id = utils.REQTYPE
	}
	if directionFld == nil {
		directionFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if directionFld.Id == utils.META_DEFAULT {
		directionFld.Id = utils.DIRECTION
	}
	if tenantFld == nil {
		tenantFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if tenantFld.Id == utils.META_DEFAULT {
		tenantFld.Id = utils.TENANT
	}
	if categFld == nil {
		categFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if categFld.Id == utils.META_DEFAULT {
		categFld.Id = utils.CATEGORY
	}
	if accountFld == nil {
		accountFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if accountFld.Id == utils.META_DEFAULT {
		accountFld.Id = utils.ACCOUNT
	}
	if subjectFld == nil {
		subjectFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if subjectFld.Id == utils.META_DEFAULT {
		subjectFld.Id = utils.SUBJECT
	}
	if destFld == nil {
		destFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if destFld.Id == utils.META_DEFAULT {
		destFld.Id = utils.DESTINATION
	}
	if setupTimeFld == nil {
		setupTimeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if setupTimeFld.Id == utils.META_DEFAULT {
		setupTimeFld.Id = utils.SETUP_TIME
	}
	if answerTimeFld == nil {
		answerTimeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if answerTimeFld.Id == utils.META_DEFAULT {
		answerTimeFld.Id = utils.ANSWER_TIME
	}
	if durationFld == nil {
		durationFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if durationFld.Id == utils.META_DEFAULT {
		durationFld.Id = utils.USAGE
	}
	if pddFld == nil {
		pddFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if pddFld.Id == utils.META_DEFAULT {
		pddFld.Id = utils.PDD
	}
	if supplierFld == nil {
		supplierFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if supplierFld.Id == utils.META_DEFAULT {
		supplierFld.Id = utils.SUPPLIER
	}
	if disconnectCauseFld == nil {
		disconnectCauseFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if disconnectCauseFld.Id == utils.META_DEFAULT {
		disconnectCauseFld.Id = utils.DISCONNECT_CAUSE
	}
	var err error
	frkStorCdr := new(StoredCdr)
	frkStorCdr.CgrId = storedCdr.CgrId
	frkStorCdr.TOR = storedCdr.TOR
	frkStorCdr.MediationRunId = runId
	frkStorCdr.Cost = -1.0 // Default for non-rated CDR
	frkStorCdr.AccId = storedCdr.AccId
	frkStorCdr.CdrHost = storedCdr.CdrHost
	frkStorCdr.CdrSource = storedCdr.CdrSource
	frkStorCdr.ReqType = storedCdr.FieldAsString(reqTypeFld)
	if primaryMandatory && len(frkStorCdr.ReqType) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.REQTYPE, reqTypeFld.Id)
	}
	frkStorCdr.Direction = storedCdr.FieldAsString(directionFld)
	if primaryMandatory && len(frkStorCdr.Direction) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.DIRECTION, directionFld.Id)
	}
	frkStorCdr.Tenant = storedCdr.FieldAsString(tenantFld)
	if primaryMandatory && len(frkStorCdr.Tenant) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.TENANT, tenantFld.Id)
	}
	frkStorCdr.Category = storedCdr.FieldAsString(categFld)
	if primaryMandatory && len(frkStorCdr.Category) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.CATEGORY, categFld.Id)
	}
	frkStorCdr.Account = storedCdr.FieldAsString(accountFld)
	if primaryMandatory && len(frkStorCdr.Account) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.ACCOUNT, accountFld.Id)
	}
	frkStorCdr.Subject = storedCdr.FieldAsString(subjectFld)
	if primaryMandatory && len(frkStorCdr.Subject) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.SUBJECT, subjectFld.Id)
	}
	frkStorCdr.Destination = storedCdr.FieldAsString(destFld)
	if primaryMandatory && len(frkStorCdr.Destination) == 0 && frkStorCdr.TOR == utils.VOICE {
		return nil, utils.NewErrMandatoryIeMissing(utils.DESTINATION, destFld.Id)
	}
	sTimeStr := storedCdr.FieldAsString(setupTimeFld)
	if primaryMandatory && len(sTimeStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.SETUP_TIME, setupTimeFld.Id)
	} else if frkStorCdr.SetupTime, err = utils.ParseTimeDetectLayout(sTimeStr, timezone); err != nil {
		return nil, err
	}
	aTimeStr := storedCdr.FieldAsString(answerTimeFld)
	if primaryMandatory && len(aTimeStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.ANSWER_TIME, answerTimeFld.Id)
	} else if frkStorCdr.AnswerTime, err = utils.ParseTimeDetectLayout(aTimeStr, timezone); err != nil {
		return nil, err
	}
	durStr := storedCdr.FieldAsString(durationFld)
	if primaryMandatory && len(durStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.USAGE, durationFld.Id)
	} else if frkStorCdr.Usage, err = utils.ParseDurationWithSecs(durStr); err != nil {
		return nil, err
	}
	pddStr := storedCdr.FieldAsString(pddFld)
	if primaryMandatory && len(pddStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.PDD, pddFld.Id)
	} else if frkStorCdr.Pdd, err = utils.ParseDurationWithSecs(pddStr); err != nil {
		return nil, err
	}
	frkStorCdr.Supplier = storedCdr.FieldAsString(supplierFld)
	frkStorCdr.DisconnectCause = storedCdr.FieldAsString(disconnectCauseFld)
	frkStorCdr.ExtraFields = make(map[string]string, len(extraFlds))
	for _, fld := range extraFlds {
		frkStorCdr.ExtraFields[fld.Id] = storedCdr.FieldAsString(fld)
	}
	return frkStorCdr, nil
}
Esempio n. 15
0
func (self *CdrServer) deriveCdrs(cdr *CDR) ([]*CDR, error) {
	dfltCDRRun := cdr.Clone()
	cdrRuns := []*CDR{dfltCDRRun}
	if cdr.RunID != utils.MetaRaw { // Only derive *raw CDRs
		return cdrRuns, nil
	}
	dfltCDRRun.RunID = utils.META_DEFAULT // Rewrite *raw with *default since we have it as first run
	if err := LoadUserProfile(cdr, utils.EXTRA_FIELDS); err != nil {
		return nil, err
	}
	if err := LoadAlias(&AttrMatchingAlias{
		Destination: cdr.Destination,
		Direction:   cdr.Direction,
		Tenant:      cdr.Tenant,
		Category:    cdr.Category,
		Account:     cdr.Account,
		Subject:     cdr.Subject,
		Context:     utils.ALIAS_CONTEXT_RATING,
	}, cdr, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound {
		return nil, err
	}
	attrsDC := &utils.AttrDerivedChargers{Tenant: cdr.Tenant, Category: cdr.Category, Direction: cdr.Direction,
		Account: cdr.Account, Subject: cdr.Subject, Destination: cdr.Destination}
	var dcs utils.DerivedChargers
	if err := self.rals.Call("Responder.GetDerivedChargers", attrsDC, &dcs); err != nil {
		utils.Logger.Err(fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", cdr.CGRID, err.Error()))
		return nil, err
	}
	for _, dc := range dcs.Chargers {
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if !dcRunFilter.FilterPasses(cdr.FieldAsString(dcRunFilter)) {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
			continue
		}
		dcRequestTypeFld, _ := utils.NewRSRField(dc.RequestTypeField)
		dcDirFld, _ := utils.NewRSRField(dc.DirectionField)
		dcTenantFld, _ := utils.NewRSRField(dc.TenantField)
		dcCategoryFld, _ := utils.NewRSRField(dc.CategoryField)
		dcAcntFld, _ := utils.NewRSRField(dc.AccountField)
		dcSubjFld, _ := utils.NewRSRField(dc.SubjectField)
		dcDstFld, _ := utils.NewRSRField(dc.DestinationField)
		dcSTimeFld, _ := utils.NewRSRField(dc.SetupTimeField)
		dcPddFld, _ := utils.NewRSRField(dc.PDDField)
		dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField)
		dcDurFld, _ := utils.NewRSRField(dc.UsageField)
		dcSupplFld, _ := utils.NewRSRField(dc.SupplierField)
		dcDCauseFld, _ := utils.NewRSRField(dc.DisconnectCauseField)
		dcRatedFld, _ := utils.NewRSRField(dc.RatedField)
		dcCostFld, _ := utils.NewRSRField(dc.CostField)
		forkedCdr, err := cdr.ForkCdr(dc.RunID, dcRequestTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld,
			dcSTimeFld, dcPddFld, dcATimeFld, dcDurFld, dcSupplFld, dcDCauseFld, dcRatedFld, dcCostFld, []*utils.RSRField{}, true, self.cgrCfg.DefaultTimezone)
		if err != nil {
			utils.Logger.Err(fmt.Sprintf("Could not fork CGR with cgrid %s, run: %s, error: %s", cdr.CGRID, dc.RunID, err.Error()))
			continue // do not add it to the forked CDR list
		}
		if !forkedCdr.Rated {
			forkedCdr.Cost = -1.0 // Make sure that un-rated CDRs start with Cost -1
		}
		cdrRuns = append(cdrRuns, forkedCdr)
	}
	return cdrRuns, nil
}
Esempio n. 16
0
func TestXmlCdreCfgAsCdreConfig(t *testing.T) {
	cfgXmlStr := `<?xml version="1.0" encoding="UTF-8"?>
<document type="cgrates/xml">
  <configuration section="cdre" type="fixed_width" id="CDRE-FW2">
    <cdr_format>fwv</cdr_format>
    <field_separator>;</field_separator>
    <data_usage_multiply_factor>1024.0</data_usage_multiply_factor>
    <cost_multiply_factor>1.19</cost_multiply_factor>
    <cost_rounding_decimals>-1</cost_rounding_decimals>
    <cost_shift_digits>-3</cost_shift_digits>
    <mask_destination_id>MASKED_DESTINATIONS</mask_destination_id>
    <mask_length>1</mask_length>
    <export_dir>/var/log/cgrates/cdre</export_dir>
    <export_template>
      <header>
        <fields>
          <field name="TypeOfRecord" type="constant" value="10" width="2" />
          <field name="LastCdr" type="metatag" value="last_cdr_time" layout="020106150400" width="12" />
        </fields>
      </header>
      <content>
        <fields>
          <field name="OperatorCode" type="cdrfield" value="operator" width="2" />
          <field name="ProductId" type="cdrfield" value="productid" width="5" />
          <field name="NetworkId" type="constant" value="3" width="1" />
          <field name="FromHttpPost1" type="http_post" value="https://localhost:8000" width="10" strip="xright" padding="left" />
          <field name="CombiMed1" type="combimed" value="cost" width="10" strip="xright" padding="left" filter="~mediation_runid:s/DEFAULT/SECOND_RUN/"/>
        </fields>
      </content>
      <trailer>
        <fields>
          <field name="DistributorCode" type="constant" value="VOI" width="3" />
          <field name="FileSeqNr" type="metatag" value="export_id" padding="zeroleft" width="5" />
        </fields>
      </trailer>
    </export_template>
  </configuration>
</document>`
	var err error
	reader := strings.NewReader(cfgXmlStr)
	if cfgDoc, err = ParseCgrXmlConfig(reader); err != nil {
		t.Error(err.Error())
	} else if cfgDoc == nil {
		t.Fatal("Could not parse xml configuration document")
	}
	xmlCdreCfgs := cfgDoc.GetCdreCfgs("CDRE-FW2")
	if xmlCdreCfgs == nil {
		t.Error("Could not parse XmlCdre instance")
	}
	eCdreCfg := &CdreConfig{
		CdrFormat:               "fwv",
		FieldSeparator:          ';',
		DataUsageMultiplyFactor: 1024.0,
		CostMultiplyFactor:      1.19,
		CostRoundingDecimals:    -1,
		CostShiftDigits:         -3,
		MaskDestId:              "MASKED_DESTINATIONS",
		MaskLength:              1,
		ExportDir:               "/var/log/cgrates/cdre",
	}
	fltrCombiMed, _ := utils.NewRSRField("~mediation_runid:s/DEFAULT/SECOND_RUN/")
	eCdreCfg.HeaderFields = []*CdreCdrField{
		&CdreCdrField{
			Name:            "TypeOfRecord",
			Type:            "constant",
			Value:           "10",
			Width:           2,
			valueAsRsrField: &utils.RSRField{Id: "10"}},
		&CdreCdrField{
			Name:            "LastCdr",
			Type:            "metatag",
			Value:           "last_cdr_time",
			Layout:          "020106150400",
			Width:           12,
			valueAsRsrField: &utils.RSRField{Id: "last_cdr_time"}},
	}
	eCdreCfg.ContentFields = []*CdreCdrField{
		&CdreCdrField{
			Name:            "OperatorCode",
			Type:            "cdrfield",
			Value:           "operator",
			Width:           2,
			valueAsRsrField: &utils.RSRField{Id: "operator"},
		},
		&CdreCdrField{
			Name:            "ProductId",
			Type:            "cdrfield",
			Value:           "productid",
			Width:           5,
			valueAsRsrField: &utils.RSRField{Id: "productid"},
		},
		&CdreCdrField{
			Name:            "NetworkId",
			Type:            "constant",
			Value:           "3",
			Width:           1,
			valueAsRsrField: &utils.RSRField{Id: "3"},
		},
		&CdreCdrField{
			Name:            "FromHttpPost1",
			Type:            "http_post",
			Value:           "https://localhost:8000",
			Width:           10,
			Strip:           "xright",
			Padding:         "left",
			valueAsRsrField: &utils.RSRField{Id: "https://localhost:8000"},
		},
		&CdreCdrField{
			Name:            "CombiMed1",
			Type:            "combimed",
			Value:           "cost",
			Width:           10,
			Strip:           "xright",
			Padding:         "left",
			Filter:          fltrCombiMed,
			valueAsRsrField: &utils.RSRField{Id: "cost"},
		},
	}
	eCdreCfg.TrailerFields = []*CdreCdrField{
		&CdreCdrField{
			Name:            "DistributorCode",
			Type:            "constant",
			Value:           "VOI",
			Width:           3,
			valueAsRsrField: &utils.RSRField{Id: "VOI"},
		},
		&CdreCdrField{
			Name:            "FileSeqNr",
			Type:            "metatag",
			Value:           "export_id",
			Width:           5,
			Padding:         "zeroleft",
			valueAsRsrField: &utils.RSRField{Id: "export_id"},
		},
	}
	if rcvCdreCfg := xmlCdreCfgs["CDRE-FW2"].AsCdreConfig(); !reflect.DeepEqual(rcvCdreCfg, eCdreCfg) {
		for _, fld := range rcvCdreCfg.ContentFields {
			fmt.Printf("Fld: %+v\n", fld)
		}
		t.Errorf("Expecting: %v, received: %v", eCdreCfg, rcvCdreCfg)
	}
}
Esempio n. 17
0
func (self *CdrServer) deriveCdrs(storedCdr *StoredCdr) ([]*StoredCdr, error) {
	if len(storedCdr.MediationRunId) == 0 {
		storedCdr.MediationRunId = utils.META_DEFAULT
	}
	cdrRuns := []*StoredCdr{storedCdr}
	if storedCdr.Rated { // Do not derive already rated CDRs since they should be already derived
		return cdrRuns, nil
	}
	attrsDC := &utils.AttrDerivedChargers{Tenant: storedCdr.Tenant, Category: storedCdr.Category, Direction: storedCdr.Direction,
		Account: storedCdr.Account, Subject: storedCdr.Subject, Destination: storedCdr.Destination}
	var dcs utils.DerivedChargers
	if err := self.rater.GetDerivedChargers(attrsDC, &dcs); err != nil {
		utils.Logger.Err(fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", storedCdr.CgrId, err.Error()))
		return nil, err
	}
	for _, dc := range dcs.Chargers {
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if fltrPass, _ := storedCdr.PassesFieldFilter(dcRunFilter); !fltrPass {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched

			continue
		}
		dcReqTypeFld, _ := utils.NewRSRField(dc.ReqTypeField)
		dcDirFld, _ := utils.NewRSRField(dc.DirectionField)
		dcTenantFld, _ := utils.NewRSRField(dc.TenantField)
		dcCategoryFld, _ := utils.NewRSRField(dc.CategoryField)
		dcAcntFld, _ := utils.NewRSRField(dc.AccountField)
		dcSubjFld, _ := utils.NewRSRField(dc.SubjectField)
		dcDstFld, _ := utils.NewRSRField(dc.DestinationField)
		dcSTimeFld, _ := utils.NewRSRField(dc.SetupTimeField)
		dcPddFld, _ := utils.NewRSRField(dc.PddField)
		dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField)
		dcDurFld, _ := utils.NewRSRField(dc.UsageField)
		dcSupplFld, _ := utils.NewRSRField(dc.SupplierField)
		dcDCauseFld, _ := utils.NewRSRField(dc.DisconnectCauseField)
		dcRatedFld, _ := utils.NewRSRField(dc.RatedField)
		dcCostFld, _ := utils.NewRSRField(dc.CostField)
		forkedCdr, err := storedCdr.ForkCdr(dc.RunId, dcReqTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld,
			dcSTimeFld, dcPddFld, dcATimeFld, dcDurFld, dcSupplFld, dcDCauseFld, dcRatedFld, dcCostFld, []*utils.RSRField{}, true, self.cgrCfg.DefaultTimezone)
		if err != nil {
			utils.Logger.Err(fmt.Sprintf("Could not fork CGR with cgrid %s, run: %s, error: %s", storedCdr.CgrId, dc.RunId, err.Error()))
			continue // do not add it to the forked CDR list
		}
		if !forkedCdr.Rated {
			forkedCdr.Cost = -1.0 // Make sure that un-rated CDRs start with Cost -1
		}
		cdrRuns = append(cdrRuns, forkedCdr)
	}
	return cdrRuns, nil
}
Esempio n. 18
0
File: cdr.go Progetto: rinor/cgrates
// Used in mediation, primaryMandatory marks whether missing field out of request represents error or can be ignored
func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, PDDFld,
	answerTimeFld, durationFld, supplierFld, disconnectCauseFld, ratedFld, costFld *utils.RSRField,
	extraFlds []*utils.RSRField, primaryMandatory bool, timezone string) (*CDR, error) {
	if RequestTypeFld == nil {
		RequestTypeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if RequestTypeFld.Id == utils.META_DEFAULT {
		RequestTypeFld.Id = utils.REQTYPE
	}
	if directionFld == nil {
		directionFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if directionFld.Id == utils.META_DEFAULT {
		directionFld.Id = utils.DIRECTION
	}
	if tenantFld == nil {
		tenantFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if tenantFld.Id == utils.META_DEFAULT {
		tenantFld.Id = utils.TENANT
	}
	if categFld == nil {
		categFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if categFld.Id == utils.META_DEFAULT {
		categFld.Id = utils.CATEGORY
	}
	if accountFld == nil {
		accountFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if accountFld.Id == utils.META_DEFAULT {
		accountFld.Id = utils.ACCOUNT
	}
	if subjectFld == nil {
		subjectFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if subjectFld.Id == utils.META_DEFAULT {
		subjectFld.Id = utils.SUBJECT
	}
	if destFld == nil {
		destFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if destFld.Id == utils.META_DEFAULT {
		destFld.Id = utils.DESTINATION
	}
	if setupTimeFld == nil {
		setupTimeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if setupTimeFld.Id == utils.META_DEFAULT {
		setupTimeFld.Id = utils.SETUP_TIME
	}
	if answerTimeFld == nil {
		answerTimeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if answerTimeFld.Id == utils.META_DEFAULT {
		answerTimeFld.Id = utils.ANSWER_TIME
	}
	if durationFld == nil {
		durationFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if durationFld.Id == utils.META_DEFAULT {
		durationFld.Id = utils.USAGE
	}
	if PDDFld == nil {
		PDDFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if PDDFld.Id == utils.META_DEFAULT {
		PDDFld.Id = utils.PDD
	}
	if supplierFld == nil {
		supplierFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if supplierFld.Id == utils.META_DEFAULT {
		supplierFld.Id = utils.SUPPLIER
	}
	if disconnectCauseFld == nil {
		disconnectCauseFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if disconnectCauseFld.Id == utils.META_DEFAULT {
		disconnectCauseFld.Id = utils.DISCONNECT_CAUSE
	}
	if ratedFld == nil {
		ratedFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if ratedFld.Id == utils.META_DEFAULT {
		ratedFld.Id = utils.RATED_FLD
	}
	if costFld == nil {
		costFld, _ = utils.NewRSRField(utils.META_DEFAULT)
	}
	if costFld.Id == utils.META_DEFAULT {
		costFld.Id = utils.COST
	}
	var err error
	frkStorCdr := new(CDR)
	frkStorCdr.CGRID = cdr.CGRID
	frkStorCdr.ToR = cdr.ToR
	frkStorCdr.RunID = runId
	frkStorCdr.Cost = -1.0 // Default for non-rated CDR
	frkStorCdr.OriginID = cdr.OriginID
	frkStorCdr.OriginHost = cdr.OriginHost
	frkStorCdr.Source = cdr.Source
	frkStorCdr.RequestType = cdr.FieldAsString(RequestTypeFld)
	if primaryMandatory && len(frkStorCdr.RequestType) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.REQTYPE, RequestTypeFld.Id)
	}
	frkStorCdr.Direction = cdr.FieldAsString(directionFld)
	if primaryMandatory && len(frkStorCdr.Direction) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.DIRECTION, directionFld.Id)
	}
	frkStorCdr.Tenant = cdr.FieldAsString(tenantFld)
	if primaryMandatory && len(frkStorCdr.Tenant) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.TENANT, tenantFld.Id)
	}
	frkStorCdr.Category = cdr.FieldAsString(categFld)
	if primaryMandatory && len(frkStorCdr.Category) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.CATEGORY, categFld.Id)
	}
	frkStorCdr.Account = cdr.FieldAsString(accountFld)
	if primaryMandatory && len(frkStorCdr.Account) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.ACCOUNT, accountFld.Id)
	}
	frkStorCdr.Subject = cdr.FieldAsString(subjectFld)
	if primaryMandatory && len(frkStorCdr.Subject) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.SUBJECT, subjectFld.Id)
	}
	frkStorCdr.Destination = cdr.FieldAsString(destFld)
	if primaryMandatory && len(frkStorCdr.Destination) == 0 && frkStorCdr.ToR == utils.VOICE {
		return nil, utils.NewErrMandatoryIeMissing(utils.DESTINATION, destFld.Id)
	}
	sTimeStr := cdr.FieldAsString(setupTimeFld)
	if primaryMandatory && len(sTimeStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.SETUP_TIME, setupTimeFld.Id)
	} else if frkStorCdr.SetupTime, err = utils.ParseTimeDetectLayout(sTimeStr, timezone); err != nil {
		return nil, err
	}
	aTimeStr := cdr.FieldAsString(answerTimeFld)
	if primaryMandatory && len(aTimeStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.ANSWER_TIME, answerTimeFld.Id)
	} else if frkStorCdr.AnswerTime, err = utils.ParseTimeDetectLayout(aTimeStr, timezone); err != nil {
		return nil, err
	}
	durStr := cdr.FieldAsString(durationFld)
	if primaryMandatory && len(durStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.USAGE, durationFld.Id)
	} else if frkStorCdr.Usage, err = utils.ParseDurationWithSecs(durStr); err != nil {
		return nil, err
	}
	PDDStr := cdr.FieldAsString(PDDFld)
	if primaryMandatory && len(PDDStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.PDD, PDDFld.Id)
	} else if frkStorCdr.PDD, err = utils.ParseDurationWithSecs(PDDStr); err != nil {
		return nil, err
	}
	frkStorCdr.Supplier = cdr.FieldAsString(supplierFld)
	frkStorCdr.DisconnectCause = cdr.FieldAsString(disconnectCauseFld)
	ratedStr := cdr.FieldAsString(ratedFld)
	if primaryMandatory && len(ratedStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.RATED_FLD, ratedFld.Id)
	} else if frkStorCdr.Rated, err = strconv.ParseBool(ratedStr); err != nil {
		return nil, err
	}
	costStr := cdr.FieldAsString(costFld)
	if primaryMandatory && len(costStr) == 0 {
		return nil, utils.NewErrMandatoryIeMissing(utils.COST, costFld.Id)
	} else if frkStorCdr.Cost, err = strconv.ParseFloat(costStr, 64); err != nil {
		return nil, err
	}
	frkStorCdr.ExtraFields = make(map[string]string, len(extraFlds))
	for _, fld := range extraFlds {
		frkStorCdr.ExtraFields[fld.Id] = cdr.FieldAsString(fld)
	}
	return frkStorCdr, nil
}