func (self *ApierV1) RemDerivedChargers(attrs AttrRemDerivedChargers, reply *string) error { if len(attrs.Direction) == 0 { attrs.Direction = utils.OUT } if len(attrs.Tenant) == 0 { attrs.Tenant = utils.ANY } if len(attrs.Category) == 0 { attrs.Category = utils.ANY } if len(attrs.Account) == 0 { attrs.Account = utils.ANY } if len(attrs.Subject) == 0 { attrs.Subject = utils.ANY } if err := self.RatingDb.SetDerivedChargers(utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject), nil, utils.NonTransactional); err != nil { return utils.NewErrServerError(err) } if err := self.RatingDb.CacheDataFromDB(utils.DERIVEDCHARGERS_PREFIX, []string{utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject)}, true); err != nil { return utils.NewErrServerError(err) } *reply = "OK" return nil }
// Transparently handles merging between storage data and configuration, useful as local handler func HandleGetDerivedChargers(acntStorage AccountingStorage, cfg *config.CGRConfig, attrs utils.AttrDerivedChargers) (utils.DerivedChargers, error) { var dcs utils.DerivedChargers var err error strictKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject) anySubjKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, utils.ANY) for _, dcKey := range []string{strictKey, anySubjKey} { if dcsDb, err := acntStorage.GetDerivedChargers(dcKey, false); err != nil && err.Error() != utils.ERR_NOT_FOUND { return nil, err } else if dcsDb != nil { dcs = dcsDb break } } if dcs == nil { dcs = cfg.DerivedChargers return dcs, nil } if cfg.CombinedDerivedChargers { for _, cfgDc := range cfg.DerivedChargers { if dcs, err = dcs.Append(cfgDc); err != nil { return nil, err } } } return dcs, nil }
func (self *ApierV1) RemDerivedChargers(attrs AttrRemDerivedChargers, reply *string) error { if len(attrs.Direction) == 0 { attrs.Direction = utils.OUT } if len(attrs.Tenant) == 0 { attrs.Tenant = utils.ANY } if len(attrs.Category) == 0 { attrs.Category = utils.ANY } if len(attrs.Account) == 0 { attrs.Account = utils.ANY } if len(attrs.Subject) == 0 { attrs.Subject = utils.ANY } if err := self.RatingDb.SetDerivedChargers(utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject), nil); err != nil { return utils.NewErrServerError(err) } else { *reply = "OK" } if err := self.RatingDb.CacheRatingPrefixes(utils.DERIVEDCHARGERS_PREFIX); err != nil { return utils.NewErrServerError(err) } return nil }
// Receive composed derived chargers func TestHandleGetStoredDC(t *testing.T) { keyCharger1 := utils.DerivedChargersKey("*out", "cgrates.org", "call", "rif", "rif") charger1 := utils.DerivedChargers{ &utils.DerivedCharger{RunId: "extra1", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"}, &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"}, } if err := acntDb.SetDerivedChargers(keyCharger1, charger1); err != nil { t.Error("Error on setDerivedChargers", err.Error()) } // Expected Charger should have default configured values added expCharger1 := append(charger1, &utils.DerivedCharger{RunId: "responder1", ReqTypeField: "test", DirectionField: "test", TenantField: "test", CategoryField: "test", AccountField: "test", SubjectField: "test", DestinationField: "test", SetupTimeField: "test", AnswerTimeField: "test", UsageField: "test"}) acntDb.CacheAccounting(nil, nil, nil, nil) attrs := utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "rif", Subject: "rif"} if dcs, err := HandleGetDerivedChargers(acntDb, cfgDcT, attrs); err != nil { t.Error("Unexpected error", err.Error()) } else if !reflect.DeepEqual(dcs, expCharger1) { t.Error("Returned DerivedChargers not matching the configured ones") } cfgDcT.CombinedDerivedChargers = false if dcs, err := HandleGetDerivedChargers(acntDb, cfgDcT, attrs); err != nil { t.Error("Unexpected error", err.Error()) } else if !reflect.DeepEqual(dcs, charger1) { t.Error("Returned DerivedChargers not matching the configured ones") } }
// Handles retrieving of DerivedChargers profile based on longest match from AccountingDb func HandleGetDerivedChargers(ratingStorage RatingStorage, attrs *utils.AttrDerivedChargers) (*utils.DerivedChargers, error) { dcs := &utils.DerivedChargers{} strictKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject) anySubjKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, utils.ANY) anyAcntKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, utils.ANY, utils.ANY) anyCategKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, utils.ANY, utils.ANY, utils.ANY) anyTenantKey := utils.DerivedChargersKey(attrs.Direction, utils.ANY, utils.ANY, utils.ANY, utils.ANY) for _, dcKey := range []string{strictKey, anySubjKey, anyAcntKey, anyCategKey, anyTenantKey} { if dcsDb, err := ratingStorage.GetDerivedChargers(dcKey, false); err != nil && err != utils.ErrNotFound { return nil, err } else if dcsDb != nil && DerivedChargersMatchesDest(dcsDb, attrs.Destination) { dcs = dcsDb break } } return dcs, nil }
func (csvr *CSVReader) LoadDerivedChargers() (err error) { csvReader, fp, err := csvr.readerFunc(csvr.derivedChargersFn, csvr.sep, utils.DERIVED_CHARGERS_NRCOLS) if err != nil { log.Print("Could not load derivedChargers file: ", err) // allow writing of the other values return nil } if fp != nil { defer fp.Close() } for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() { if _, err = utils.ParseRSRFields(record[6], utils.INFIELD_SEP); err != nil { // Make sure rules are OK before loading in db return err } tag := utils.DerivedChargersKey(record[0], record[1], record[2], record[3], record[4]) if _, found := csvr.derivedChargers[tag]; found { if csvr.derivedChargers[tag], err = csvr.derivedChargers[tag].Append(&utils.DerivedCharger{ RunId: ValueOrDefault(record[5], "*default"), RunFilters: record[6], ReqTypeField: ValueOrDefault(record[7], "*default"), DirectionField: ValueOrDefault(record[8], "*default"), TenantField: ValueOrDefault(record[9], "*default"), CategoryField: ValueOrDefault(record[10], "*default"), AccountField: ValueOrDefault(record[11], "*default"), SubjectField: ValueOrDefault(record[12], "*default"), DestinationField: ValueOrDefault(record[13], "*default"), SetupTimeField: ValueOrDefault(record[14], "*default"), AnswerTimeField: ValueOrDefault(record[15], "*default"), UsageField: ValueOrDefault(record[16], "*default"), }); err != nil { return err } } else { if record[5] == utils.DEFAULT_RUNID { return errors.New("Reserved RunId") } csvr.derivedChargers[tag] = utils.DerivedChargers{&utils.DerivedCharger{ RunId: ValueOrDefault(record[5], "*default"), RunFilters: record[6], ReqTypeField: ValueOrDefault(record[7], "*default"), DirectionField: ValueOrDefault(record[8], "*default"), TenantField: ValueOrDefault(record[9], "*default"), CategoryField: ValueOrDefault(record[10], "*default"), AccountField: ValueOrDefault(record[11], "*default"), SubjectField: ValueOrDefault(record[12], "*default"), DestinationField: ValueOrDefault(record[13], "*default"), SetupTimeField: ValueOrDefault(record[14], "*default"), AnswerTimeField: ValueOrDefault(record[15], "*default"), UsageField: ValueOrDefault(record[16], "*default"), }} } } return }
func (self *ApierV1) RemDerivedChargers(attrs AttrRemDerivedChargers, reply *string) error { if missing := utils.MissingStructFields(&attrs, []string{"Direction", "Tenant", "Category", "Account", "Subject"}); len(missing) != 0 { //Params missing return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) } if err := self.AccountDb.SetDerivedChargers(utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject), nil); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) } else { *reply = "OK" } if err := self.AccountDb.CacheAccounting([]string{}, []string{}, []string{}, nil); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) } return nil }
func TestLoadDerivedChargers(t *testing.T) { if len(csvr.derivedChargers) != 2 { t.Error("Failed to load derivedChargers: ", csvr.derivedChargers) } expCharger1 := utils.DerivedChargers{ &utils.DerivedCharger{RunId: "extra1", RunFilters: "^filteredHeader1/filterValue1/", ReqTypeField: "^prepaid", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "rif", SubjectField: "rif", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"}, &utils.DerivedCharger{RunId: "extra2", ReqTypeField: "*default", DirectionField: "*default", TenantField: "*default", CategoryField: "*default", AccountField: "ivo", SubjectField: "ivo", DestinationField: "*default", SetupTimeField: "*default", AnswerTimeField: "*default", UsageField: "*default"}, } keyCharger1 := utils.DerivedChargersKey("*out", "cgrates.org", "call", "dan", "dan") if !reflect.DeepEqual(csvr.derivedChargers[keyCharger1], expCharger1) { t.Error("Unexpected charger", csvr.derivedChargers[keyCharger1]) } }
// Test internal abilites of GetDerivedChargers func TestResponderGetDerivedChargers(t *testing.T) { cfgedDC := &utils.DerivedChargers{DestinationIDs: utils.StringMap{}, Chargers: []*utils.DerivedCharger{&utils.DerivedCharger{RunID: "responder1", RequestTypeField: utils.META_DEFAULT, DirectionField: "test", TenantField: "test", CategoryField: "test", AccountField: "test", SubjectField: "test", DestinationField: "test", SetupTimeField: "test", AnswerTimeField: "test", UsageField: "test"}}} rsponder = &Responder{} attrs := &utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "responder_test", Subject: "responder_test"} if err := ratingStorage.SetDerivedChargers(utils.DerivedChargersKey(utils.OUT, utils.ANY, utils.ANY, utils.ANY, utils.ANY), cfgedDC, utils.NonTransactional); err != nil { t.Error(err) } dcs := &utils.DerivedChargers{} if err := rsponder.GetDerivedChargers(attrs, dcs); err != nil { t.Error("Unexpected error", err.Error()) } else if !reflect.DeepEqual(dcs, cfgedDC) { t.Errorf("Expecting: %v, received: %v ", cfgedDC, dcs) } }
func (self *ApierV1) SetDerivedChargers(attrs AttrSetDerivedChargers, reply *string) (err error) { if len(attrs.DerivedChargers) == 0 { return utils.NewErrMandatoryIeMissing("DerivedChargers") } if len(attrs.Direction) == 0 { attrs.Direction = utils.OUT } if len(attrs.Tenant) == 0 { attrs.Tenant = utils.ANY } if len(attrs.Category) == 0 { attrs.Category = utils.ANY } if len(attrs.Account) == 0 { attrs.Account = utils.ANY } if len(attrs.Subject) == 0 { attrs.Subject = utils.ANY } for _, dc := range attrs.DerivedChargers { if _, err = utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP); err != nil { // Make sure rules are OK before loading in db return fmt.Errorf("%s:%s", utils.ErrParserError.Error(), err.Error()) } } dcKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject) if !attrs.Overwrite { if exists, err := self.RatingDb.HasData(utils.DERIVEDCHARGERS_PREFIX, dcKey); err != nil { return utils.NewErrServerError(err) } else if exists { return utils.ErrExists } } dstIds := strings.Split(attrs.DestinationIds, utils.INFIELD_SEP) dcs := &utils.DerivedChargers{DestinationIDs: utils.NewStringMap(dstIds...), Chargers: attrs.DerivedChargers} if err := self.RatingDb.SetDerivedChargers(dcKey, dcs); err != nil { return utils.NewErrServerError(err) } if err := self.RatingDb.CacheRatingPrefixValues(map[string][]string{ utils.DERIVEDCHARGERS_PREFIX: []string{utils.DERIVEDCHARGERS_PREFIX + dcKey}, }); err != nil { return utils.NewErrServerError(err) } *reply = utils.OK return nil }
// Test internal abilites of GetDerivedChargers func TestResponderGetDerivedChargers(t *testing.T) { cfgedDC := utils.DerivedChargers{&utils.DerivedCharger{RunId: "responder1", ReqTypeField: utils.META_DEFAULT, DirectionField: "test", TenantField: "test", CategoryField: "test", AccountField: "test", SubjectField: "test", DestinationField: "test", SetupTimeField: "test", AnswerTimeField: "test", UsageField: "test"}} rsponder = &Responder{} attrs := &utils.AttrDerivedChargers{Tenant: "cgrates.org", Category: "call", Direction: "*out", Account: "responder_test", Subject: "responder_test"} if err := ratingStorage.SetDerivedChargers(utils.DerivedChargersKey(utils.OUT, utils.ANY, utils.ANY, utils.ANY, utils.ANY), cfgedDC); err != nil { t.Error(err) } if err := ratingStorage.CacheRatingPrefixes(utils.DERIVEDCHARGERS_PREFIX); err != nil { t.Error(err) } var dcs utils.DerivedChargers if err := rsponder.GetDerivedChargers(attrs, &dcs); err != nil { t.Error("Unexpected error", err.Error()) } else if !reflect.DeepEqual(dcs, cfgedDC) { t.Errorf("Expecting: %v, received: %v ", cfgedDC, dcs) } }
func (self *ApierV1) SetDerivedChargers(attrs AttrSetDerivedChargers, reply *string) (err error) { if missing := utils.MissingStructFields(&attrs, []string{"Tenant", "Category", "Direction", "Account", "Subject", "DerivedChargers"}); len(missing) != 0 { return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing) } for _, dc := range attrs.DerivedChargers { if _, err = utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP); err != nil { // Make sure rules are OK before loading in db return fmt.Errorf("%s:%s", utils.ERR_PARSER_ERROR, err.Error()) } } dcKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject) if err := self.AccountDb.SetDerivedChargers(dcKey, attrs.DerivedChargers); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) } if err := self.AccountDb.CacheAccounting([]string{}, []string{}, []string{}, []string{engine.DERIVEDCHARGERS_PREFIX + dcKey}); err != nil { return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) } *reply = utils.OK return nil }
func TestLoadDerivedChargers(t *testing.T) { if len(csvr.derivedChargers) != 2 { t.Error("Failed to load derivedChargers: ", csvr.derivedChargers) } expCharger1 := utils.DerivedChargers{ &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}, &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}, } keyCharger1 := utils.DerivedChargersKey("*out", "cgrates.org", "call", "dan", "dan") if !csvr.derivedChargers[keyCharger1].Equal(expCharger1) { t.Errorf("Expecting: %+v, received: %+v", expCharger1[0], csvr.derivedChargers[keyCharger1][0]) } }