mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 10:06:24 +05:00
Rated and Cost fields inside derived charging
This commit is contained in:
@@ -296,6 +296,8 @@ CREATE TABLE tp_derived_chargers (
|
||||
`usage_field` varchar(24) NOT NULL,
|
||||
`supplier_field` varchar(24) NOT NULL,
|
||||
`disconnect_cause_field` varchar(24) NOT NULL,
|
||||
`rated_field` varchar(24) NOT NULL,
|
||||
`cost_field` varchar(24) NOT NULL,
|
||||
`created_at` TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `tpid` (`tpid`)
|
||||
|
||||
@@ -291,6 +291,8 @@ CREATE TABLE tp_derived_chargers (
|
||||
usage_field VARCHAR(24) NOT NULL,
|
||||
supplier_field VARCHAR(24) NOT NULL,
|
||||
disconnect_cause_field VARCHAR(24) NOT NULL,
|
||||
rated_field VARCHAR(24) NOT NULL,
|
||||
cost_field VARCHAR(24) NOT NULL,
|
||||
created_at TIMESTAMP
|
||||
);
|
||||
CREATE INDEX tpderivedchargers_tpid_idx ON tp_derived_chargers (tpid);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],RunId[5],RunFilter[6],ReqTypeField[7],DirectionField[8],TenantField[9],CategoryField[10],AccountField[11],SubjectField[12],DestinationField[13],SetupTimeField[14],PddField[15],AnswerTimeField[16],UsageField[17],SupplierField[18],DisconnectCause[19]
|
||||
*out,cgrates.org,call,dan,dan,extra1,,^prepaid,,,,^rif,^rif,,,,,^1s,*default,*default
|
||||
*out,cgrates.org,call,dan,dan,extra2,,,,,,^ivo,^ivo,,,,,,*default,*default
|
||||
*out,cgrates.org,call,dan,dan,extra3,~filterhdr1:s/(.+)/special_run3/,,,,,^runusr3,^runusr3,,,,,,*default,*default
|
||||
*out,cgrates.org,call,dan,*any,extra1,,,,,,^rif2,^rif2,,,,,,*default,*default
|
||||
#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],RunId[5],RunFilter[6],ReqTypeField[7],DirectionField[8],TenantField[9],CategoryField[10],AccountField[11],SubjectField[12],DestinationField[13],SetupTimeField[14],PddField[15],AnswerTimeField[16],UsageField[17],SupplierField[18],DisconnectCause[19],RatedField[20],CostField[21]
|
||||
*out,cgrates.org,call,dan,dan,extra1,,^prepaid,,,,^rif,^rif,,,,,^1s,*default,*default,*default,*default
|
||||
*out,cgrates.org,call,dan,dan,extra2,,,,,,^ivo,^ivo,,,,,,*default,*default,*default,*default
|
||||
*out,cgrates.org,call,dan,dan,extra3,~filterhdr1:s/(.+)/special_run3/,,,,,^runusr3,^runusr3,,,,,,*default,*default,*default,*default
|
||||
*out,cgrates.org,call,dan,*any,extra1,,,,,,^rif2,^rif2,,,,,,*default,*default,*default,*default
|
||||
|
||||
|
@@ -1,2 +1,2 @@
|
||||
#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],RunId[5],RunFilter[6],ReqTypeField[7],DirectionField[8],TenantField[9],CategoryField[10],AccountField[11],SubjectField[12],DestinationField[13],SetupTimeField[14],PddField[15],AnswerTimeField[16],UsageField[17],SupplierField[18],DisconnectCause[19]
|
||||
*out,cgrates.org,call,1001,1001,derived_run1,,^*rated,*default,*default,*default,*default,^1002,*default,*default,*default,*default,*default,*default,*default
|
||||
#Direction[0],Tenant[1],Category[2],Account[3],Subject[4],RunId[5],RunFilter[6],ReqTypeField[7],DirectionField[8],TenantField[9],CategoryField[10],AccountField[11],SubjectField[12],DestinationField[13],SetupTimeField[14],PddField[15],AnswerTimeField[16],UsageField[17],SupplierField[18],DisconnectCause[19],RatedField[20],CostField[21]
|
||||
*out,cgrates.org,call,1001,1001,derived_run1,,^*rated,*default,*default,*default,*default,^1002,*default,*default,*default,*default,*default,*default,*default,*default,*default
|
||||
|
||||
|
@@ -274,13 +274,18 @@ func (self *CdrServer) deriveCdrs(storedCdr *StoredCdr) ([]*StoredCdr, error) {
|
||||
dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField)
|
||||
dcDurFld, _ := utils.NewRSRField(dc.UsageField)
|
||||
dcSupplFld, _ := utils.NewRSRField(dc.SupplierField)
|
||||
dcDCausseld, _ := utils.NewRSRField(dc.DisconnectCauseField)
|
||||
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, dcDCausseld, []*utils.RSRField{}, true, self.cgrCfg.DefaultTimezone)
|
||||
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
|
||||
@@ -365,7 +370,6 @@ func (self *CdrServer) replicateCdr(cdr *StoredCdr) error {
|
||||
case utils.META_HTTP_POST:
|
||||
errChan := make(chan error)
|
||||
go func(cdr *StoredCdr, rplCfg *config.CdrReplicationCfg, errChan chan error) {
|
||||
utils.Logger.Debug(fmt.Sprintf("Replicating CDR: %+v, attempts: %d", cdr, rplCfg.Attempts))
|
||||
fallbackPath := path.Join(self.cgrCfg.HttpFailedDir, fmt.Sprintf("cdr_%s_%s_%s.form", rplCfg.Transport, rplCfg.Server, utils.GenUUID()))
|
||||
if _, err := utils.HttpPoster(rplCfg.Server, self.cgrCfg.HttpSkipTlsVerify, cdr.AsHttpForm(), utils.CONTENT_FORM, rplCfg.Attempts, fallbackPath); err != nil {
|
||||
utils.Logger.Err(fmt.Sprintf("<CDRReplicator> Replicating CDR: %+v, got error: %s", cdr, err.Error()))
|
||||
|
||||
@@ -203,10 +203,10 @@ cgrates.org,alodis,*out,TOPUP_EMPTY_AT,,true,true
|
||||
`
|
||||
|
||||
derivedCharges = `
|
||||
#Direction,Tenant,Category,Account,Subject,RunId,RunFilter,ReqTypeField,DirectionField,TenantField,TorField,AccountField,SubjectField,DestinationField,SetupTimeField,PddField,AnswerTimeField,UsageField
|
||||
*out,cgrates.org,call,dan,dan,extra1,^filteredHeader1/filterValue1/,^prepaid,,,,rif,rif,,,,,,,
|
||||
*out,cgrates.org,call,dan,dan,extra2,,,,,,ivo,ivo,,,,,,,
|
||||
*out,cgrates.org,call,dan,*any,extra1,,,,,,rif2,rif2,,,,,,,
|
||||
#Direction,Tenant,Category,Account,Subject,RunId,RunFilter,ReqTypeField,DirectionField,TenantField,TorField,AccountField,SubjectField,DestinationField,SetupTimeField,PddField,AnswerTimeField,UsageField,SupplierField,DisconnectCauseField,CostField,RatedField
|
||||
*out,cgrates.org,call,dan,dan,extra1,^filteredHeader1/filterValue1/,^prepaid,,,,rif,rif,,,,,,,,,
|
||||
*out,cgrates.org,call,dan,dan,extra2,,,,,,ivo,ivo,,,,,,,,,
|
||||
*out,cgrates.org,call,dan,*any,extra1,,,,,,rif2,rif2,,,,,,,,,
|
||||
`
|
||||
cdrStats = `
|
||||
#Id[0],QueueLength[1],TimeWindow[2],SaveInterval[3],Metric[4],SetupInterval[5],TOR[6],CdrHost[7],CdrSource[8],ReqType[9],Direction[10],Tenant[11],Category[12],Account[13],Subject[14],DestinationPrefix[15],PddInterval[16],UsageInterval[17],Supplier[18],DisconnectCause[19],MediationRunIds[20],RatedAccount[21],RatedSubject[22],CostInterval[23],Triggers[24]
|
||||
@@ -1058,11 +1058,11 @@ func TestLoadDerivedChargers(t *testing.T) {
|
||||
&utils.DerivedCharger{RunId: "extra1", RunFilters: "^filteredHeader1/filterValue1/", ReqTypeField: "^prepaid", DirectionField: utils.META_DEFAULT,
|
||||
TenantField: utils.META_DEFAULT, CategoryField: utils.META_DEFAULT, AccountField: "rif", SubjectField: "rif", DestinationField: utils.META_DEFAULT,
|
||||
SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
|
||||
SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT},
|
||||
SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT},
|
||||
&utils.DerivedCharger{RunId: "extra2", ReqTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
|
||||
CategoryField: utils.META_DEFAULT, AccountField: "ivo", SubjectField: "ivo", DestinationField: utils.META_DEFAULT,
|
||||
SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT,
|
||||
SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT},
|
||||
SupplierField: utils.META_DEFAULT, DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT},
|
||||
}
|
||||
keyCharger1 := utils.DerivedChargersKey("*out", "cgrates.org", "call", "dan", "dan")
|
||||
|
||||
|
||||
@@ -302,6 +302,8 @@ func APItoModelDerivedCharger(dcs *utils.TPDerivedChargers) (result []TpDerivedC
|
||||
UsageField: dc.UsageField,
|
||||
SupplierField: dc.SupplierField,
|
||||
DisconnectCauseField: dc.DisconnectCauseField,
|
||||
CostField: dc.CostField,
|
||||
RatedField: dc.RatedField,
|
||||
})
|
||||
}
|
||||
if len(dcs.DerivedChargers) == 0 {
|
||||
|
||||
@@ -494,6 +494,8 @@ func (tps TpDerivedChargers) GetDerivedChargers() (map[string]*utils.TPDerivedCh
|
||||
UsageField: ValueOrDefault(tpDcMdl.UsageField, utils.META_DEFAULT),
|
||||
SupplierField: ValueOrDefault(tpDcMdl.SupplierField, utils.META_DEFAULT),
|
||||
DisconnectCauseField: ValueOrDefault(tpDcMdl.DisconnectCauseField, utils.META_DEFAULT),
|
||||
CostField: ValueOrDefault(tpDcMdl.CostField, utils.META_DEFAULT),
|
||||
RatedField: ValueOrDefault(tpDcMdl.RatedField, utils.META_DEFAULT),
|
||||
}
|
||||
dcs[tag].DerivedChargers = append(dcs[tag].DerivedChargers, nDc)
|
||||
}
|
||||
|
||||
@@ -468,6 +468,8 @@ func TestTPDerivedChargersAsExportSlice(t *testing.T) {
|
||||
UsageField: utils.META_DEFAULT,
|
||||
SupplierField: utils.META_DEFAULT,
|
||||
DisconnectCauseField: utils.META_DEFAULT,
|
||||
CostField: utils.META_DEFAULT,
|
||||
RatedField: utils.META_DEFAULT,
|
||||
},
|
||||
&utils.TPDerivedCharger{
|
||||
RunId: "derived_run2",
|
||||
@@ -485,14 +487,16 @@ func TestTPDerivedChargersAsExportSlice(t *testing.T) {
|
||||
UsageField: utils.META_DEFAULT,
|
||||
SupplierField: utils.META_DEFAULT,
|
||||
DisconnectCauseField: utils.META_DEFAULT,
|
||||
RatedField: utils.META_DEFAULT,
|
||||
CostField: utils.META_DEFAULT,
|
||||
},
|
||||
},
|
||||
}
|
||||
expectedSlc := [][]string{
|
||||
[]string{"*out", "cgrates.org", "call", "1001", "1001",
|
||||
"derived_run1", "", "^rated", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, "^1002", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT},
|
||||
"derived_run1", "", "^rated", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, "^1002", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT},
|
||||
[]string{"*out", "cgrates.org", "call", "1001", "1001",
|
||||
"derived_run2", "", "^rated", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, "^1002", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT},
|
||||
"derived_run2", "", "^rated", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, "^1002", utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT, utils.META_DEFAULT},
|
||||
}
|
||||
ms := APItoModelDerivedCharger(dcs)
|
||||
var slc [][]string
|
||||
|
||||
@@ -272,6 +272,8 @@ type TpDerivedCharger struct {
|
||||
UsageField string `index:"17" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
|
||||
SupplierField string `index:"18" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
|
||||
DisconnectCauseField string `index:"19" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
|
||||
RatedField string `index:"20" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
|
||||
CostField string `index:"21" re:"\*default\s*|[~^]*[0-9A-Za-z_/:().+]+\s*"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ func TestGetSessionRuns(t *testing.T) {
|
||||
dfDC := &utils.DerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
|
||||
CategoryField: utils.META_DEFAULT, AccountField: utils.META_DEFAULT, SubjectField: utils.META_DEFAULT, DestinationField: utils.META_DEFAULT,
|
||||
SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT,
|
||||
DisconnectCauseField: utils.META_DEFAULT}
|
||||
DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT}
|
||||
extra1DC := &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^" + utils.META_PREPAID, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
|
||||
CategoryField: "^0", AccountField: "^minitsboy", SubjectField: "^rif", DestinationField: "^0256",
|
||||
SetupTimeField: utils.META_DEFAULT, PddField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT}
|
||||
|
||||
@@ -183,6 +183,8 @@ func (storedCdr *StoredCdr) FieldAsString(rsrFld *utils.RSRField) string {
|
||||
return rsrFld.ParseValue(storedCdr.RatedAccount)
|
||||
case utils.RATED_SUBJECT:
|
||||
return rsrFld.ParseValue(storedCdr.RatedSubject)
|
||||
case utils.RATED_FLD:
|
||||
return rsrFld.ParseValue(strconv.FormatBool(storedCdr.Rated))
|
||||
case utils.COST:
|
||||
return rsrFld.ParseValue(strconv.FormatFloat(storedCdr.Cost, 'f', -1, 64)) // Recommended to use FormatCost
|
||||
case utils.COST_DETAILS:
|
||||
@@ -270,7 +272,7 @@ func (storedCdr *StoredCdr) AsHttpForm() url.Values {
|
||||
|
||||
// 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,
|
||||
answerTimeFld, durationFld, supplierFld, disconnectCauseFld, ratedFld, costFld *utils.RSRField,
|
||||
extraFlds []*utils.RSRField, primaryMandatory bool, timezone string) (*StoredCdr, error) {
|
||||
if reqTypeFld == nil {
|
||||
reqTypeFld, _ = utils.NewRSRField(utils.META_DEFAULT)
|
||||
@@ -350,6 +352,18 @@ func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tena
|
||||
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(StoredCdr)
|
||||
frkStorCdr.CgrId = storedCdr.CgrId
|
||||
@@ -413,6 +427,18 @@ func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tena
|
||||
}
|
||||
frkStorCdr.Supplier = storedCdr.FieldAsString(supplierFld)
|
||||
frkStorCdr.DisconnectCause = storedCdr.FieldAsString(disconnectCauseFld)
|
||||
ratedStr := storedCdr.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 := storedCdr.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] = storedCdr.FieldAsString(fld)
|
||||
|
||||
@@ -370,7 +370,7 @@ func TestStoredCdrForkCdr(t *testing.T) {
|
||||
rtSampleCdrOut, err := storCdr.ForkCdr("sample_run1", &utils.RSRField{Id: utils.REQTYPE}, &utils.RSRField{Id: utils.DIRECTION}, &utils.RSRField{Id: utils.TENANT},
|
||||
&utils.RSRField{Id: utils.CATEGORY}, &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.SUPPLIER}, &utils.RSRField{Id: utils.DISCONNECT_CAUSE}, &utils.RSRField{Id: utils.RATED_FLD}, &utils.RSRField{Id: utils.COST},
|
||||
[]*utils.RSRField{&utils.RSRField{Id: "field_extr1"}, &utils.RSRField{Id: "field_extr2"}}, true, "")
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received", err)
|
||||
@@ -379,7 +379,7 @@ func TestStoredCdrForkCdr(t *testing.T) {
|
||||
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), Pdd: time.Duration(200) * time.Millisecond, AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
|
||||
Usage: time.Duration(10) * time.Second, Supplier: "suppl1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"},
|
||||
MediationRunId: "sample_run1", Cost: -1}
|
||||
MediationRunId: "sample_run1", Rated: false, Cost: 1.01}
|
||||
if !reflect.DeepEqual(expctSplRatedCdr, rtSampleCdrOut) {
|
||||
t.Errorf("Expected: %v, received: %v", expctSplRatedCdr, rtSampleCdrOut)
|
||||
}
|
||||
@@ -404,8 +404,10 @@ func TestStoredCdrForkCdrStaticVals(t *testing.T) {
|
||||
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, []*utils.RSRField{}, true, "")
|
||||
rsrStST, rsrPdd, rsrStAT, rsrStDur, rsrStSuppl, rsrStDCause, rsrStRated, rsrStCost, []*utils.RSRField{}, true, "")
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received", err)
|
||||
}
|
||||
@@ -413,8 +415,8 @@ func TestStoredCdrForkCdrStaticVals(t *testing.T) {
|
||||
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",
|
||||
ExtraFields: map[string]string{}, MediationRunId: "wholesale_run", Cost: -1}
|
||||
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)
|
||||
}
|
||||
@@ -422,7 +424,7 @@ func TestStoredCdrForkCdrStaticVals(t *testing.T) {
|
||||
&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{}, true, "")
|
||||
&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")
|
||||
}
|
||||
@@ -433,17 +435,18 @@ func TestStoredCdrForkCdrFromMetaDefaults(t *testing.T) {
|
||||
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, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL3", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
Usage: time.Duration(10) * time.Second, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL3",
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
expctCdr := &StoredCdr{CgrId: storCdr.CgrId, 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),
|
||||
Usage: time.Duration(10) * time.Second, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL3",
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: "wholesale_run", Cost: -1}
|
||||
Usage: time.Duration(10) * time.Second, Pdd: time.Duration(4) * time.Second, Supplier: "SUPPL3", Cost: 1.01,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: "wholesale_run"}
|
||||
cdrOut, err := storCdr.ForkCdr("wholesale_run", &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT},
|
||||
&utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT},
|
||||
&utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT},
|
||||
&utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT},
|
||||
&utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT}, &utils.RSRField{Id: utils.META_DEFAULT},
|
||||
[]*utils.RSRField{&utils.RSRField{Id: "field_extr1"}, &utils.RSRField{Id: "fieldextr2"}}, true, "")
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error received", err)
|
||||
@@ -453,7 +456,7 @@ func TestStoredCdrForkCdrFromMetaDefaults(t *testing.T) {
|
||||
t.Errorf("Expected: %v, received: %v", expctCdr, cdrOut)
|
||||
}
|
||||
// Should also accept nil as defaults
|
||||
if cdrOut, err := storCdr.ForkCdr("wholesale_run", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
if cdrOut, err := storCdr.ForkCdr("wholesale_run", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
[]*utils.RSRField{&utils.RSRField{Id: "field_extr1"}, &utils.RSRField{Id: "fieldextr2"}}, true, ""); err != nil {
|
||||
t.Fatal("Unexpected error received", err)
|
||||
} else if !reflect.DeepEqual(expctCdr, cdrOut) {
|
||||
|
||||
@@ -895,7 +895,7 @@ func (tpr *TpReader) LoadDerivedChargersFiltered(filter *TpDerivedCharger, save
|
||||
for _, tpDc := range tpDcs.DerivedChargers {
|
||||
dc, err := utils.NewDerivedCharger(tpDc.RunId, tpDc.RunFilters, tpDc.ReqTypeField, tpDc.DirectionField, tpDc.TenantField, tpDc.CategoryField,
|
||||
tpDc.AccountField, tpDc.SubjectField, tpDc.DestinationField, tpDc.SetupTimeField, tpDc.PddField, tpDc.AnswerTimeField, tpDc.UsageField, tpDc.SupplierField,
|
||||
tpDc.DisconnectCauseField)
|
||||
tpDc.DisconnectCauseField, tpDc.RatedField, tpDc.CostField)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -446,6 +446,8 @@ type TPDerivedCharger struct {
|
||||
UsageField string
|
||||
SupplierField string
|
||||
DisconnectCauseField string
|
||||
CostField string
|
||||
RatedField string
|
||||
}
|
||||
|
||||
type TPActionPlan struct {
|
||||
|
||||
@@ -24,7 +24,8 @@ import (
|
||||
)
|
||||
|
||||
// Wraps regexp compiling in case of rsr fields
|
||||
func NewDerivedCharger(runId, runFilters, reqTypeFld, dirFld, tenantFld, catFld, acntFld, subjFld, dstFld, sTimeFld, pddFld, aTimeFld, durFld, supplFld, dCauseFld string) (dc *DerivedCharger, err error) {
|
||||
func NewDerivedCharger(runId, runFilters, reqTypeFld, dirFld, tenantFld, catFld, acntFld, subjFld, dstFld, sTimeFld, pddFld, aTimeFld, durFld,
|
||||
supplFld, dCauseFld, ratedFld, costFld string) (dc *DerivedCharger, err error) {
|
||||
if len(runId) == 0 {
|
||||
return nil, errors.New("Empty run id field")
|
||||
}
|
||||
@@ -113,6 +114,18 @@ func NewDerivedCharger(runId, runFilters, reqTypeFld, dirFld, tenantFld, catFld,
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
dc.RatedField = ratedFld
|
||||
if strings.HasPrefix(dc.RatedField, REGEXP_PREFIX) || strings.HasPrefix(dc.RatedField, STATIC_VALUE_PREFIX) {
|
||||
if dc.rsrRatedField, err = NewRSRField(dc.RatedField); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
dc.CostField = costFld
|
||||
if strings.HasPrefix(dc.CostField, REGEXP_PREFIX) || strings.HasPrefix(dc.CostField, STATIC_VALUE_PREFIX) {
|
||||
if dc.rsrCostField, err = NewRSRField(dc.CostField); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
@@ -132,6 +145,8 @@ type DerivedCharger struct {
|
||||
UsageField string // Field containing usage information
|
||||
SupplierField string // Field containing supplier information
|
||||
DisconnectCauseField string // Field containing disconnect cause information
|
||||
CostField string // Field containing cost information
|
||||
RatedField string // Field marking rated request in CDR
|
||||
rsrRunFilters []*RSRField // Storage for compiled Regexp in case of RSRFields
|
||||
rsrReqTypeField *RSRField
|
||||
rsrDirectionField *RSRField
|
||||
@@ -146,6 +161,8 @@ type DerivedCharger struct {
|
||||
rsrUsageField *RSRField
|
||||
rsrSupplierField *RSRField
|
||||
rsrDisconnectCauseField *RSRField
|
||||
rsrCostField *RSRField
|
||||
rsrRatedField *RSRField
|
||||
}
|
||||
|
||||
func DerivedChargersKey(direction, tenant, category, account, subject string) string {
|
||||
@@ -169,7 +186,7 @@ func (dcs DerivedChargers) Append(dc *DerivedCharger) (DerivedChargers, error) {
|
||||
|
||||
func (dcs DerivedChargers) AppendDefaultRun() (DerivedChargers, error) {
|
||||
dcDf, _ := NewDerivedCharger(DEFAULT_RUNID, "", META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT,
|
||||
META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT)
|
||||
META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT)
|
||||
return append(dcs, dcDf), nil
|
||||
}
|
||||
|
||||
@@ -197,5 +214,7 @@ func (dc *DerivedCharger) Equal(other *DerivedCharger) bool {
|
||||
dc.AnswerTimeField == other.AnswerTimeField &&
|
||||
dc.UsageField == other.UsageField &&
|
||||
dc.SupplierField == other.SupplierField &&
|
||||
dc.DisconnectCauseField == other.DisconnectCauseField
|
||||
dc.DisconnectCauseField == other.DisconnectCauseField &&
|
||||
dc.CostField == other.CostField &&
|
||||
dc.RatedField == other.RatedField
|
||||
}
|
||||
|
||||
@@ -61,9 +61,11 @@ func TestNewDerivedCharger(t *testing.T) {
|
||||
UsageField: "duration1",
|
||||
SupplierField: "supplier1",
|
||||
DisconnectCauseField: "NORMAL_CLEARING",
|
||||
RatedField: "rated1",
|
||||
CostField: "cost1",
|
||||
}
|
||||
if dc1, err := NewDerivedCharger("test1", "", "reqtype1", "direction1", "tenant1", "tor1", "account1", "subject1", "destination1",
|
||||
"setuptime1", "pdd1", "answertime1", "duration1", "supplier1", "NORMAL_CLEARING"); err != nil {
|
||||
"setuptime1", "pdd1", "answertime1", "duration1", "supplier1", "NORMAL_CLEARING", "rated1", "cost1"); err != nil {
|
||||
t.Error("Unexpected error", err.Error)
|
||||
} else if !reflect.DeepEqual(edc1, dc1) {
|
||||
t.Errorf("Expecting: %v, received: %v", edc1, dc1)
|
||||
@@ -84,6 +86,8 @@ func TestNewDerivedCharger(t *testing.T) {
|
||||
UsageField: "~duration2:s/sip:(.+)/$1/",
|
||||
SupplierField: "~supplier2:s/(.+)/$1/",
|
||||
DisconnectCauseField: "~cgr_disconnect:s/(.+)/$1/",
|
||||
CostField: "~cgr_cost:s/(.+)/$1/",
|
||||
RatedField: "~cgr_rated:s/(.+)/$1/",
|
||||
}
|
||||
edc2.rsrRunFilters, _ = ParseRSRFields("^cdr_source/tdm_cdrs/", INFIELD_SEP)
|
||||
edc2.rsrReqTypeField, _ = NewRSRField("~reqtype2:s/sip:(.+)/$1/")
|
||||
@@ -99,6 +103,8 @@ func TestNewDerivedCharger(t *testing.T) {
|
||||
edc2.rsrUsageField, _ = NewRSRField("~duration2:s/sip:(.+)/$1/")
|
||||
edc2.rsrSupplierField, _ = NewRSRField("~supplier2:s/(.+)/$1/")
|
||||
edc2.rsrDisconnectCauseField, _ = NewRSRField("~cgr_disconnect:s/(.+)/$1/")
|
||||
edc2.rsrCostField, _ = NewRSRField("~cgr_cost:s/(.+)/$1/")
|
||||
edc2.rsrRatedField, _ = NewRSRField("~cgr_rated:s/(.+)/$1/")
|
||||
if dc2, err := NewDerivedCharger("test2",
|
||||
"^cdr_source/tdm_cdrs/",
|
||||
"~reqtype2:s/sip:(.+)/$1/",
|
||||
@@ -113,7 +119,9 @@ func TestNewDerivedCharger(t *testing.T) {
|
||||
"~answertime2:s/sip:(.+)/$1/",
|
||||
"~duration2:s/sip:(.+)/$1/",
|
||||
"~supplier2:s/(.+)/$1/",
|
||||
"~cgr_disconnect:s/(.+)/$1/"); err != nil {
|
||||
"~cgr_disconnect:s/(.+)/$1/",
|
||||
"~cgr_rated:s/(.+)/$1/",
|
||||
"~cgr_cost:s/(.+)/$1/"); err != nil {
|
||||
t.Error("Unexpected error", err)
|
||||
} else if !reflect.DeepEqual(edc2, dc2) {
|
||||
t.Errorf("Expecting: %v, received: %v", edc2, dc2)
|
||||
@@ -131,7 +139,7 @@ func TestAppendDefaultRun(t *testing.T) {
|
||||
dcDf := &DerivedCharger{RunId: DEFAULT_RUNID, RunFilters: "", ReqTypeField: META_DEFAULT, DirectionField: META_DEFAULT,
|
||||
TenantField: META_DEFAULT, CategoryField: META_DEFAULT, AccountField: META_DEFAULT, SubjectField: META_DEFAULT,
|
||||
DestinationField: META_DEFAULT, SetupTimeField: META_DEFAULT, PddField: META_DEFAULT, AnswerTimeField: META_DEFAULT, UsageField: META_DEFAULT, SupplierField: META_DEFAULT,
|
||||
DisconnectCauseField: META_DEFAULT}
|
||||
DisconnectCauseField: META_DEFAULT, CostField: META_DEFAULT, RatedField: META_DEFAULT}
|
||||
eDc1 := DerivedChargers{dcDf}
|
||||
if dc1, _ = dc1.AppendDefaultRun(); !reflect.DeepEqual(dc1, eDc1) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eDc1[0], dc1[0])
|
||||
|
||||
Reference in New Issue
Block a user