diff --git a/apier/v1/accounts.go b/apier/v1/accounts.go index c5a5e1e16..72e31c52a 100644 --- a/apier/v1/accounts.go +++ b/apier/v1/accounts.go @@ -21,6 +21,7 @@ package v1 import ( "errors" "fmt" + "regexp" "time" "github.com/cgrates/cgrates/engine" @@ -120,7 +121,7 @@ type AttrRemAcntActionTriggers struct { Tenant string // Tenant he account belongs to Account string // Account name Direction string // Traffic direction - ActionTriggerId string // Id filtering only specific id to remove + ActionTriggerId string // Id filtering only specific id to remove (can be regexp pattern) } // Returns a list of ActionTriggers on an account @@ -135,7 +136,8 @@ func (self *ApierV1) RemAccountActionTriggers(attrs AttrRemAcntActionTriggers, r return 0, err } for idx, actr := range ub.ActionTriggers { - if len(attrs.ActionTriggerId) != 0 && actr.Id != attrs.ActionTriggerId { // Empty actionTriggerId will match always + match, _ := regexp.MatchString(attrs.ActionTriggerId, actr.Id) + if len(attrs.ActionTriggerId) != 0 && !match { continue } if len(ub.ActionTriggers) != 1 { // Remove by index diff --git a/apier/v1/apier.go b/apier/v1/apier.go index e88744241..289340386 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -435,7 +435,7 @@ func (self *ApierV1) SetActions(attrs AttrSetActions, reply *string) error { // Retrieves actions attached to specific ActionsId within cache func (self *ApierV1) GetActions(actsId string, reply *[]*utils.TPAction) error { if len(actsId) == 0 { - return fmt.Errorf("%s:ActionsId", utils.ERR_MANDATORY_IE_MISSING, actsId) + return fmt.Errorf("%s ActionsId: %s", utils.ERR_MANDATORY_IE_MISSING, actsId) } acts := make([]*utils.TPAction, 0) engActs, err := self.AccountDb.GetActions(actsId, false) @@ -534,6 +534,7 @@ func (self *ApierV1) SetActionPlan(attrs AttrSetActionPlan, reply *string) error } type AttrAddActionTrigger struct { + Id string Tenant string Account string ThresholdType string @@ -559,7 +560,7 @@ func (self *ApierV1) AddTriggeredAction(attr AttrAddActionTrigger, reply *string return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error()) } at := &engine.ActionTrigger{ - Id: utils.GenUUID(), + Id: attr.Id, ThresholdType: attr.ThresholdType, ThresholdValue: attr.ThresholdValue, BalanceId: attr.BalanceId, @@ -596,6 +597,7 @@ func (self *ApierV1) AddTriggeredAction(attr AttrAddActionTrigger, reply *string } type AttrResetTriggeredAction struct { + Id string Tenant string Account string Direction string @@ -609,35 +611,41 @@ type AttrResetTriggeredAction struct { } func (self *ApierV1) ResetTriggeredActions(attr AttrResetTriggeredAction, reply *string) error { - if attr.Direction == "" { - attr.Direction = engine.OUTBOUND - } - extraParameters, err := json.Marshal(struct { - ThresholdType string - ThresholdValue float64 - DestinationId string - BalanceWeight float64 - BalanceRatingSubject string - BalanceSharedGroup string - }{ - attr.ThresholdType, - attr.ThresholdValue, - attr.DestinationId, - attr.BalanceWeight, - attr.BalanceRatingSubject, - attr.BalanceSharedGroup, - }) - if err != nil { - *reply = err.Error() - return err - } - a := &engine.Action{ - BalanceType: attr.BalanceType, - Direction: attr.Direction, - ExtraParameters: string(extraParameters), + var a *engine.Action + if attr.Id != "" { + // we can identify the trigge by the id + a = &engine.Action{Id: attr.Id} + } else { + if attr.Direction == "" { + attr.Direction = engine.OUTBOUND + } + extraParameters, err := json.Marshal(struct { + ThresholdType string + ThresholdValue float64 + DestinationId string + BalanceWeight float64 + BalanceRatingSubject string + BalanceSharedGroup string + }{ + attr.ThresholdType, + attr.ThresholdValue, + attr.DestinationId, + attr.BalanceWeight, + attr.BalanceRatingSubject, + attr.BalanceSharedGroup, + }) + if err != nil { + *reply = err.Error() + return err + } + a = &engine.Action{ + BalanceType: attr.BalanceType, + Direction: attr.Direction, + ExtraParameters: string(extraParameters), + } } accID := utils.AccountKey(attr.Tenant, attr.Account, attr.Direction) - _, err = engine.AccLock.Guard(accID, func() (float64, error) { + _, err := engine.AccLock.Guard(accID, func() (float64, error) { acc, err := self.AccountDb.GetAccount(accID) if err != nil { return 0, err diff --git a/apier/v1/apier_local_test.go b/apier/v1/apier_local_test.go index ebb03a692..b63798d6c 100644 --- a/apier/v1/apier_local_test.go +++ b/apier/v1/apier_local_test.go @@ -217,7 +217,7 @@ func TestApierTPTiming(t *testing.T) { // Test getIds var rplyTmIds []string expectedTmIds := []string{"ALWAYS", "ASAP"} - if err := rater.Call("ApierV1.GetTPTimingIds", AttrGetTPTimingIds{tmAlways.TPid, utils.Paginator{0, 0, ""}}, &rplyTmIds); err != nil { + if err := rater.Call("ApierV1.GetTPTimingIds", AttrGetTPTimingIds{tmAlways.TPid, utils.Paginator{Page: 0, ItemsPerPage: 0, SearchTerm: ""}}, &rplyTmIds); err != nil { t.Error("Calling ApierV1.GetTPTimingIds, got error: ", err.Error()) } else if !reflect.DeepEqual(expectedTmIds, rplyTmIds) { t.Errorf("Calling ApierV1.GetTPTimingIds expected: %v, received: %v", expectedTmIds, rplyTmIds) @@ -325,7 +325,7 @@ func TestApierTPRate(t *testing.T) { // Test getIds var rplyRtIds []string expectedRtIds := []string{"RT_FS_USERS"} - if err := rater.Call("ApierV1.GetTPRateIds", AttrGetTPRateIds{rt.TPid, utils.Paginator{0, 0, ""}}, &rplyRtIds); err != nil { + if err := rater.Call("ApierV1.GetTPRateIds", AttrGetTPRateIds{rt.TPid, utils.Paginator{Page: 0, ItemsPerPage: 0, SearchTerm: ""}}, &rplyRtIds); err != nil { t.Error("Calling ApierV1.GetTPRateIds, got error: ", err.Error()) } else if !reflect.DeepEqual(expectedRtIds, rplyRtIds) { t.Errorf("Calling ApierV1.GetTPDestinationIds expected: %v, received: %v", expectedRtIds, rplyRtIds) @@ -382,7 +382,7 @@ func TestApierTPDestinationRate(t *testing.T) { // Test getIds var rplyDrIds []string expectedDrIds := []string{"DR_FREESWITCH_USERS"} - if err := rater.Call("ApierV1.GetTPDestinationRateIds", AttrTPDestinationRateIds{dr.TPid, utils.Paginator{0, 0, ""}}, &rplyDrIds); err != nil { + if err := rater.Call("ApierV1.GetTPDestinationRateIds", AttrTPDestinationRateIds{dr.TPid, utils.Paginator{Page: 0, ItemsPerPage: 0, SearchTerm: ""}}, &rplyDrIds); err != nil { t.Error("Calling ApierV1.GetTPDestinationRateIds, got error: ", err.Error()) } else if !reflect.DeepEqual(expectedDrIds, rplyDrIds) { t.Errorf("Calling ApierV1.GetTPDestinationRateIds expected: %v, received: %v", expectedDrIds, rplyDrIds) @@ -436,7 +436,7 @@ func TestApierTPRatingPlan(t *testing.T) { // Test getIds var rplyRpIds []string expectedRpIds := []string{"RETAIL1"} - if err := rater.Call("ApierV1.GetTPRatingPlanIds", AttrGetTPRatingPlanIds{rp.TPid, utils.Paginator{0, 0, ""}}, &rplyRpIds); err != nil { + if err := rater.Call("ApierV1.GetTPRatingPlanIds", AttrGetTPRatingPlanIds{rp.TPid, utils.Paginator{Page: 0, ItemsPerPage: 0, SearchTerm: ""}}, &rplyRpIds); err != nil { t.Error("Calling ApierV1.GetTPRatingPlanIds, got error: ", err.Error()) } else if !reflect.DeepEqual(expectedRpIds, rplyRpIds) { t.Errorf("Calling ApierV1.GetTPRatingPlanIds expected: %v, received: %v", expectedRpIds, rplyRpIds) diff --git a/apier/v1/tp.go b/apier/v1/tp.go index 2ed639c84..9339d66cb 100644 --- a/apier/v1/tp.go +++ b/apier/v1/tp.go @@ -77,7 +77,14 @@ func (self *ApierV1) ImportTPZipFile(attrs AttrImportTPZipFile, reply *string) e *reply = "ERROR: missing TPid!" return err } - csvImporter := engine.TPCSVImporter{attrs.TPid, self.StorDb, path, ',', false, ""} + csvImporter := engine.TPCSVImporter{ + TPid: attrs.TPid, + StorDb: self.StorDb, + DirPath: path, + Sep: ',', + Verbose: false, + ImportId: "", + } if errImport := csvImporter.Run(); errImport != nil { return errImport } diff --git a/apier/v1/tpactiontimings.go b/apier/v1/tpactiontimings.go index fdbd9e570..aeff26e5d 100644 --- a/apier/v1/tpactiontimings.go +++ b/apier/v1/tpactiontimings.go @@ -58,7 +58,11 @@ func (self *ApierV1) GetTPActionPlan(attrs AttrGetTPActionPlan, reply *utils.TPA } else if len(ats) == 0 { return errors.New(utils.ERR_NOT_FOUND) } else { // Got the data we need, convert it - atRply := &utils.TPActionPlan{attrs.TPid, attrs.Id, ats[attrs.Id]} + atRply := &utils.TPActionPlan{ + TPid: attrs.TPid, + Id: attrs.Id, + ActionPlan: ats[attrs.Id], + } *reply = *atRply } return nil diff --git a/apier/v1/tpactiontriggers.go b/apier/v1/tpactiontriggers.go index c3eedbf8e..9fb328518 100644 --- a/apier/v1/tpactiontriggers.go +++ b/apier/v1/tpactiontriggers.go @@ -56,7 +56,11 @@ func (self *ApierV1) GetTPActionTriggers(attrs AttrGetTPActionTriggers, reply *u } else if len(atsMap) == 0 { return errors.New(utils.ERR_NOT_FOUND) } else { - atRply := &utils.TPActionTriggers{attrs.TPid, attrs.ActionTriggersId, atsMap[attrs.ActionTriggersId]} + atRply := &utils.TPActionTriggers{ + TPid: attrs.TPid, + ActionTriggersId: attrs.ActionTriggersId, + ActionTriggers: atsMap[attrs.ActionTriggersId], + } *reply = *atRply } return nil diff --git a/cdre/cdrexporter.go b/cdre/cdrexporter.go index 974179604..82ea89608 100644 --- a/cdre/cdrexporter.go +++ b/cdre/cdrexporter.go @@ -22,13 +22,14 @@ import ( "encoding/csv" "encoding/json" "fmt" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" "io" "os" "strconv" "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" ) const ( @@ -239,7 +240,6 @@ func (cdre *CdrExporter) metaHandler(tag, arg string) (string, error) { default: return "", fmt.Errorf("Unsupported METATAG: %s", tag) } - return "", nil } // Compose and cache the header diff --git a/cmd/cgr-console/cgr-console.go b/cmd/cgr-console/cgr-console.go index ef1cd202d..7092d3c6f 100644 --- a/cmd/cgr-console/cgr-console.go +++ b/cmd/cgr-console/cgr-console.go @@ -121,7 +121,7 @@ func main() { } fmt.Println("Welcome to CGRateS console!") - fmt.Println("Type `help` for a list of commands\n") + fmt.Print("Type `help` for a list of commands\n\n") line := liner.NewLiner() defer line.Close() diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index b474aba5e..245d76f89 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -424,7 +424,7 @@ func main() { cdrStats.AddQueue(engine.NewCdrStatsFromCdrStatsCfg(cfg.CDRStatConfig), nil) } server.RpcRegister(cdrStats) - server.RpcRegister(&v1.CDRStatsV1{cdrStats}) // Public APIs + server.RpcRegister(&v1.CDRStatsV1{CdrStats: cdrStats}) // Public APIs } responder := &engine.Responder{ExitChan: exitChan} diff --git a/cmd/cgr-loader/cgr-loader.go b/cmd/cgr-loader/cgr-loader.go index ae34ade41..ccb5e3f0f 100644 --- a/cmd/cgr-loader/cgr-loader.go +++ b/cmd/cgr-loader/cgr-loader.go @@ -116,7 +116,14 @@ func main() { if *tpid == "" { log.Fatal("TPid required, please define it via *-tpid* command argument.") } - csvImporter := engine.TPCSVImporter{*tpid, storDb, *dataPath, ',', *verbose, *runId} + csvImporter := engine.TPCSVImporter{ + TPid: *tpid, + StorDb: storDb, + DirPath: *dataPath, + Sep: ',', + Verbose: *verbose, + ImportId: *runId, + } if errImport := csvImporter.Run(); errImport != nil { log.Fatal(errImport) } @@ -218,7 +225,17 @@ func main() { if *flush { dstIds, rplIds, rpfIds, rpAliases, lcrIds = nil, nil, nil, nil, nil // Should reload all these on flush } - if err = rater.Call("ApierV1.ReloadCache", utils.ApiReloadCache{dstIds, rplIds, rpfIds, actIds, shgIds, rpAliases, accAliases, lcrIds, dcs}, &reply); err != nil { + if err = rater.Call("ApierV1.ReloadCache", utils.ApiReloadCache{ + DestinationIds: dstIds, + RatingPlanIds: rplIds, + RatingProfileIds: rpfIds, + ActionIds: actIds, + SharedGroupIds: shgIds, + RpAliases: rpAliases, + AccAliases: accAliases, + LCRIds: lcrIds, + DerivedChargers: dcs, + }, &reply); err != nil { log.Printf("WARNING: Got error on cache reload: %s\n", err.Error()) } actTmgIds, _ := loader.GetLoadedIds(engine.ACTION_TIMING_PREFIX) diff --git a/cmd/cgr-tester/cgr-tester.go b/cmd/cgr-tester/cgr-tester.go index e990b3efb..2fddfefd0 100644 --- a/cmd/cgr-tester/cgr-tester.go +++ b/cmd/cgr-tester/cgr-tester.go @@ -109,7 +109,7 @@ func durRemoteRater(cd *engine.CallDescriptor) (time.Duration, error) { result := engine.CallCost{} client, err := rpc.Dial("tcp", *raterAddress) if err != nil { - return nilDuration, fmt.Errorf("Could not connect to engine: ", err.Error()) + return nilDuration, fmt.Errorf("Could not connect to engine: %s", err.Error()) } defer client.Close() start := time.Now() diff --git a/engine/action_trigger.go b/engine/action_trigger.go index 8b2b67729..60c48116a 100644 --- a/engine/action_trigger.go +++ b/engine/action_trigger.go @@ -21,6 +21,7 @@ package engine import ( "encoding/json" "fmt" + "regexp" "sort" "time" @@ -28,7 +29,7 @@ import ( ) type ActionTrigger struct { - Id string // uniquely identify the trigger + Id string // for visual identification ThresholdType string //*min_counter, *max_counter, *min_balance, *max_balance // stats: *min_asr, *max_asr, *min_acd, *max_acd, *min_acc, *max_acc ThresholdValue float64 @@ -102,6 +103,11 @@ func (at *ActionTrigger) Match(a *Action) bool { if a == nil { return true } + // if we have Id than we can draw an early conclusion + if a.Id != "" { + match, _ := regexp.MatchString(a.Id, at.Id) + return match + } id := a.BalanceType == "" || at.BalanceType == a.BalanceType direction := a.Direction == "" || at.BalanceDirection == a.Direction thresholdType, thresholdValue, destinationId, weight, ratingSubject, category, sharedGroup := true, true, true, true, true, true, true diff --git a/engine/balances_test.go b/engine/balances_test.go index 9f3551b7c..5cff27d56 100644 --- a/engine/balances_test.go +++ b/engine/balances_test.go @@ -91,7 +91,7 @@ func TestBalanceMatchFilter(t *testing.T) { mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationId: ""} mb2 := &Balance{Weight: 1, precision: 1, RatingSubject: "", DestinationId: ""} if !mb1.MatchFilter(mb2) { - t.Error("Match filter failure: %+v == %+v", mb1, mb2) + t.Errorf("Match filter failure: %+v == %+v", mb1, mb2) } } @@ -99,7 +99,7 @@ func TestBalanceMatchFilterEmpty(t *testing.T) { mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationId: ""} mb2 := &Balance{} if !mb1.MatchFilter(mb2) { - t.Error("Match filter failure: %+v == %+v", mb1, mb2) + t.Errorf("Match filter failure: %+v == %+v", mb1, mb2) } } @@ -107,7 +107,7 @@ func TestBalanceMatchFilterId(t *testing.T) { mb1 := &Balance{Id: "T1", Weight: 2, precision: 2, RatingSubject: "2", DestinationId: "NAT"} mb2 := &Balance{Id: "T1", Weight: 1, precision: 1, RatingSubject: "1", DestinationId: ""} if !mb1.MatchFilter(mb2) { - t.Error("Match filter failure: %+v == %+v", mb1, mb2) + t.Errorf("Match filter failure: %+v == %+v", mb1, mb2) } } @@ -115,7 +115,7 @@ func TestBalanceMatchFilterDiffId(t *testing.T) { mb1 := &Balance{Id: "T1", Weight: 1, precision: 1, RatingSubject: "1", DestinationId: ""} mb2 := &Balance{Id: "T2", Weight: 1, precision: 1, RatingSubject: "1", DestinationId: ""} if mb1.MatchFilter(mb2) { - t.Error("Match filter failure: %+v != %+v", mb1, mb2) + t.Errorf("Match filter failure: %+v != %+v", mb1, mb2) } } @@ -235,6 +235,6 @@ func TestBalanceMatchActionTriggerSharedGroup(t *testing.T) { func TestBalanceIsDefault(t *testing.T) { b := &Balance{Weight: 0} if !b.IsDefault() { - t.Errorf("Balance should be default: +v", b) + t.Errorf("Balance should be default: %+v", b) } } diff --git a/engine/calldesc.go b/engine/calldesc.go index 22bc1eec2..bfa8332a6 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -457,6 +457,7 @@ If the user has postpayed plan it returns -1. */ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Duration, error) { // clone the account for discarding chenges on debit dry run + //log.Printf("ORIG CD: %+v", origCD) account := origAcc.Clone() if account.AllowNegative { return -1, nil @@ -538,6 +539,7 @@ func (cd *CallDescriptor) debit(account *Account, dryRun bool) (cc *CallCost, er if cd.TOR == "" { cd.TOR = MINUTES } + //log.Printf("Debit CD: %+v", cd) cc, err = account.debitCreditBalance(cd, !dryRun, dryRun) //log.Print("HERE: ", cc, err) if err != nil { diff --git a/engine/loader_csv.go b/engine/loader_csv.go index 54313a002..d75edd56a 100644 --- a/engine/loader_csv.go +++ b/engine/loader_csv.go @@ -679,7 +679,7 @@ func (csvr *CSVReader) LoadActions() (err error) { return fmt.Errorf("Could not parse action weight: %v", err) } a := &Action{ - Id: utils.GenUUID(), + Id: tag, ActionType: record[ACTSCSVIDX_ACTION], BalanceType: record[ACTSCSVIDX_BALANCE_TYPE], Direction: record[ACTSCSVIDX_DIRECTION], @@ -719,6 +719,12 @@ func (csvr *CSVReader) LoadActions() (err error) { if _, err := utils.ParseDate(a.ExpirationString); err != nil { return fmt.Errorf("Could not parse expiration time: %v", err) } + // update Id + idx := 0 + if previous, ok := csvr.actions[tag]; ok { + idx = len(previous) + } + a.Id = a.Id + strconv.Itoa(idx) csvr.actions[tag] = append(csvr.actions[tag], a) } return @@ -815,7 +821,7 @@ func (csvr *CSVReader) LoadActionTriggers() (err error) { } at := &ActionTrigger{ - Id: utils.GenUUID(), + Id: tag, ThresholdType: record[ATRIGCSVIDX_THRESHOLD_TYPE], ThresholdValue: value, Recurrent: recurrent, @@ -834,6 +840,12 @@ func (csvr *CSVReader) LoadActionTriggers() (err error) { ActionsId: record[ATRIGCSVIDX_ACTIONS_TAG], Weight: weight, } + // update Id + idx := 0 + if previous, ok := csvr.actionsTriggers[tag]; ok { + idx = len(previous) + } + at.Id = at.Id + strconv.Itoa(idx) csvr.actionsTriggers[tag] = append(csvr.actionsTriggers[tag], at) } return diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index e7b781daa..9dfaffb78 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -696,7 +696,7 @@ func TestLoadActions(t *testing.T) { as1 := csvr.actions["MINI"] expected := []*Action{ &Action{ - Id: as1[0].Id, + Id: "MINI0", ActionType: TOPUP_RESET, BalanceType: CREDIT, Direction: OUTBOUND, @@ -710,7 +710,7 @@ func TestLoadActions(t *testing.T) { }, }, &Action{ - Id: as1[1].Id, + Id: "MINI1", ActionType: TOPUP, BalanceType: MINUTES, Direction: OUTBOUND, @@ -732,7 +732,7 @@ func TestLoadActions(t *testing.T) { as2 := csvr.actions["SHARED"] expected = []*Action{ &Action{ - Id: as2[0].Id, + Id: "SHARED0", ActionType: TOPUP, BalanceType: CREDIT, Direction: OUTBOUND, @@ -867,7 +867,7 @@ func TestLoadActionTriggers(t *testing.T) { } atr := csvr.actionsTriggers["STANDARD_TRIGGER"][0] expected := &ActionTrigger{ - Id: atr.Id, + Id: "STANDARD_TRIGGER0", BalanceType: MINUTES, BalanceDirection: OUTBOUND, ThresholdType: TRIGGER_MIN_COUNTER, @@ -882,7 +882,7 @@ func TestLoadActionTriggers(t *testing.T) { } atr = csvr.actionsTriggers["STANDARD_TRIGGER"][1] expected = &ActionTrigger{ - Id: atr.Id, + Id: "STANDARD_TRIGGER1", BalanceType: MINUTES, BalanceDirection: OUTBOUND, ThresholdType: TRIGGER_MAX_BALANCE, diff --git a/engine/loader_db.go b/engine/loader_db.go index 8b12209eb..8b9dd4336 100644 --- a/engine/loader_db.go +++ b/engine/loader_db.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "log" + "strconv" "strings" "github.com/cgrates/cgrates/utils" @@ -561,7 +562,7 @@ func (dbr *DbReader) LoadActions() (err error) { acts := make([]*Action, len(tpacts)) for idx, tpact := range tpacts { acts[idx] = &Action{ - Id: utils.GenUUID(), + Id: tag + strconv.Itoa(idx), ActionType: tpact.Identifier, BalanceType: tpact.BalanceType, Direction: tpact.Direction, @@ -650,7 +651,7 @@ func (dbr *DbReader) LoadActionTriggers() (err error) { for idx, apiAtr := range atrsLst { balance_expiration_date, _ := utils.ParseTimeDetectLayout(apiAtr.BalanceExpirationDate) atrs[idx] = &ActionTrigger{ - Id: utils.GenUUID(), + Id: key + strconv.Itoa(idx), ThresholdType: apiAtr.ThresholdType, ThresholdValue: apiAtr.ThresholdValue, Recurrent: apiAtr.Recurrent, @@ -841,7 +842,7 @@ func (dbr *DbReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions) enacts := make([]*Action, len(tpacts)) for idx, tpact := range tpacts { enacts[idx] = &Action{ - Id: utils.GenUUID(), + Id: tag + strconv.Itoa(idx), ActionType: tpact.Identifier, BalanceType: tpact.BalanceType, Direction: tpact.Direction, diff --git a/engine/stats_test.go b/engine/stats_test.go index adb36c6e7..4868d4823 100644 --- a/engine/stats_test.go +++ b/engine/stats_test.go @@ -76,7 +76,7 @@ func TestStatsSimplifyCDR(t *testing.T) { cdr.AnswerTime != qcdr.AnswerTime || cdr.Usage != qcdr.Usage || cdr.Cost != qcdr.Cost { - t.Error("Failed to simplify cdr: %+v", qcdr) + t.Errorf("Failed to simplify cdr: %+v", qcdr) } } @@ -101,83 +101,83 @@ func TestAcceptCdr(t *testing.T) { } sq.conf = &CdrStats{} if sq.conf.AcceptCdr(cdr) != true { - t.Error("Should have accepted thif CDR: %+v", cdr) + t.Errorf("Should have accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{TOR: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{CdrHost: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{CdrSource: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{Direction: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{Tenant: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{Category: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{Account: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{Subject: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{RatedAccount: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{RatedSubject: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{DestinationPrefix: []string{"test"}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{DestinationPrefix: []string{"test", "123"}} if sq.conf.AcceptCdr(cdr) != true { - t.Error("Should have accepted thif CDR: %+v", cdr) + t.Errorf("Should have accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC), time.Date(2014, 7, 3, 13, 43, 0, 0, time.UTC)}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC)}} if sq.conf.AcceptCdr(cdr) != true { - t.Error("Should have accepted thif CDR: %+v", cdr) + t.Errorf("Should have accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{SetupInterval: []time.Time{time.Date(2014, 7, 3, 13, 42, 0, 0, time.UTC), time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)}} if sq.conf.AcceptCdr(cdr) != true { - t.Error("Should have accepted thif CDR: %+v", cdr) + t.Errorf("Should have accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{UsageInterval: []time.Duration{11 * time.Second}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{UsageInterval: []time.Duration{1 * time.Second, 10 * time.Second}} if sq.conf.AcceptCdr(cdr) == true { - t.Error("Should have NOT accepted thif CDR: %+v", cdr) + t.Errorf("Should have NOT accepted thif CDR: %+v", cdr) } sq.conf = &CdrStats{UsageInterval: []time.Duration{10 * time.Second, 11 * time.Second}} if sq.conf.AcceptCdr(cdr) != true { - t.Error("Should have accepted thif CDR: %+v", cdr) + t.Errorf("Should have accepted thif CDR: %+v", cdr) } } @@ -185,12 +185,12 @@ func TestStatsQueueIds(t *testing.T) { cdrStats := NewStats(dataStorage) ids := []string{} if err := cdrStats.GetQueueIds(0, &ids); err != nil { - t.Error("Error getting queue ids: ", err) + t.Error("Errorf getting queue ids: ", err) } result := len(ids) expected := 2 if result != expected { - t.Errorf("Error loading stats queues. Expected %v was %v", expected, result) + t.Errorf("Errorf loading stats queues. Expected %v was %v", expected, result) } } diff --git a/engine/storage_mysql_local_test.go b/engine/storage_mysql_local_test.go index 02a5283ce..35e9c3735 100644 --- a/engine/storage_mysql_local_test.go +++ b/engine/storage_mysql_local_test.go @@ -77,7 +77,7 @@ func TestMySQLSetGetTPTiming(t *testing.T) { if tmgs, err := mysqlDb.GetTpTimings(TEST_SQL, tm.TimingId); err != nil { t.Error(err.Error()) } else if !reflect.DeepEqual(tm, tmgs[tm.TimingId]) { - t.Errorf("Expecting: %+v, received: %+v", tmgs[tm.TimingId]) + t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[tm.TimingId]) } } diff --git a/engine/storage_psql_local_test.go b/engine/storage_psql_local_test.go index fd91f70d6..196947836 100644 --- a/engine/storage_psql_local_test.go +++ b/engine/storage_psql_local_test.go @@ -67,7 +67,7 @@ func TestPSQLSetGetTPTiming(t *testing.T) { if tmgs, err := psqlDb.GetTpTimings(TEST_SQL, tm.TimingId); err != nil { t.Error(err.Error()) } else if !reflect.DeepEqual(tm, tmgs[tm.TimingId]) { - t.Errorf("Expecting: %+v, received: %+v", tmgs[tm.TimingId]) + t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[tm.TimingId]) } // Update tm.Time = "00:00:01" @@ -77,7 +77,7 @@ func TestPSQLSetGetTPTiming(t *testing.T) { if tmgs, err := psqlDb.GetTpTimings(TEST_SQL, tm.TimingId); err != nil { t.Error(err.Error()) } else if !reflect.DeepEqual(tm, tmgs[tm.TimingId]) { - t.Errorf("Expecting: %+v, received: %+v", tmgs[tm.TimingId]) + t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[tm.TimingId]) } } diff --git a/engine/storage_redis.go b/engine/storage_redis.go index 2c7941bf6..1cbcda558 100644 --- a/engine/storage_redis.go +++ b/engine/storage_redis.go @@ -87,7 +87,7 @@ func (rs *RedisStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []s } for _, key := range dKeys { if len(key) <= len(DESTINATION_PREFIX) { - Logger.Warning(fmt.Sprintf("Got malformed destination id: ", key)) + Logger.Warning(fmt.Sprintf("Got malformed destination id: %s", key)) continue } if _, err = rs.GetDestination(key[len(DESTINATION_PREFIX):]); err != nil { diff --git a/engine/storage_sql.go b/engine/storage_sql.go index c32a6f113..5ef08fcf0 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -478,7 +478,7 @@ func (self *SQLStorage) SetTPLCRs(tpid string, lcrs map[string]*LCR) error { if i != 0 { //Consecutive values after the first will be prefixed with "," as separator buffer.WriteRune(',') } - buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s','%s','%s','%s','%v','%v')", + buffer.WriteString(fmt.Sprintf("('%s','%s','%s','%s','%s','%s','%s','%v','%v', '%v')", tpid, lcr.Direction, lcr.Tenant, lcr.Customer, entry.DestinationId, entry.Category, entry.Strategy, entry.Suppliers, act.ActivationTime, entry.Weight)) i++ } @@ -608,10 +608,10 @@ func (self *SQLStorage) SetTPActionTriggers(tpid string, ats map[string][]*utils tx.Rollback() return err } - for _, at := range aTriggers { + for idx, at := range aTriggers { saved := tx.Save(TpActionTrigger{ Tpid: tpid, - Tag: atId, + Tag: atId + strconv.Itoa(idx), ThresholdType: at.ThresholdType, ThresholdValue: at.ThresholdValue, Recurrent: at.Recurrent, diff --git a/general_tests/ddazmbl1_test.go b/general_tests/ddazmbl1_test.go index 29faae1d2..1cea02a77 100644 --- a/general_tests/ddazmbl1_test.go +++ b/general_tests/ddazmbl1_test.go @@ -133,7 +133,7 @@ func TestExecuteActions(t *testing.T) { } else if len(acnt.BalanceMap) != 2 { t.Error("Account does not have enough balances: ", acnt.BalanceMap) } else if acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value != 40 { - t.Errorf("Account does not have enough minutes in balance", acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value) + t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value) } else if acnt.BalanceMap[engine.CREDIT+engine.OUTBOUND][0].Value != 10 { t.Error("Account does not have enough monetary balance", acnt.BalanceMap[engine.CREDIT+engine.OUTBOUND][0].Value) } diff --git a/general_tests/ddazmbl2_test.go b/general_tests/ddazmbl2_test.go index 641618288..571cfa8cf 100644 --- a/general_tests/ddazmbl2_test.go +++ b/general_tests/ddazmbl2_test.go @@ -131,7 +131,7 @@ func TestExecuteActions2(t *testing.T) { } else if len(acnt.BalanceMap) != 2 { t.Error("Account does not have enough balances: ", acnt.BalanceMap) } else if acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value != 40 { - t.Errorf("Account does not have enough minutes in balance", acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value) + t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value) } else if acnt.BalanceMap[engine.CREDIT+engine.OUTBOUND][0].Value != 0 { t.Error("Account does not have enough monetary balance", acnt.BalanceMap[engine.CREDIT+engine.OUTBOUND][0].Value) } diff --git a/general_tests/ddazmbl3_test.go b/general_tests/ddazmbl3_test.go index 9f941296d..75580a395 100644 --- a/general_tests/ddazmbl3_test.go +++ b/general_tests/ddazmbl3_test.go @@ -129,7 +129,7 @@ func TestExecuteActions3(t *testing.T) { } else if len(acnt.BalanceMap) != 1 { t.Error("Account does not have enough balances: ", acnt.BalanceMap) } else if acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value != 40 { - t.Errorf("Account does not have enough minutes in balance", acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value) + t.Error("Account does not have enough minutes in balance", acnt.BalanceMap[engine.MINUTES+engine.OUTBOUND][0].Value) } } diff --git a/sessionmanager/osipsevent.go b/sessionmanager/osipsevent.go index 2c8430d94..6c61f2f0f 100644 --- a/sessionmanager/osipsevent.go +++ b/sessionmanager/osipsevent.go @@ -19,12 +19,13 @@ along with this program. If not, see package sessionmanager import ( - "fmt" + "encoding/json" + "strings" + "time" + "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" "github.com/cgrates/osipsdagram" - "strings" - "time" ) /* @@ -62,7 +63,8 @@ func (osipsev *OsipsEvent) AsEvent(evStr string) utils.Event { } func (osipsev *OsipsEvent) String() string { - return fmt.Sprintf("%+v", osipsev) + mrsh, _ := json.Marshal(osipsev) + return string(mrsh) } func (osipsev *OsipsEvent) GetName() string { diff --git a/sessionmanager/osipssm.go b/sessionmanager/osipssm.go index fe0129d53..bfed586c0 100644 --- a/sessionmanager/osipssm.go +++ b/sessionmanager/osipssm.go @@ -22,12 +22,13 @@ import ( "bytes" "errors" "fmt" + "strings" + "time" + "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" "github.com/cgrates/osipsdagram" - "strings" - "time" ) func NewOSipsSessionManager(cfg *config.CGRConfig, rater, cdrsrv engine.Connector) (*OsipsSessionManager, error) { @@ -133,7 +134,6 @@ func (osm *OsipsSessionManager) SubscribeEvents(evStop chan struct{}) error { time.Sleep(osm.cgrCfg.OsipsEvSubscInterval) } } - return nil } func (osm *OsipsSessionManager) OnOpensipsStart(cdrDagram *osipsdagram.OsipsEvent) { diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 80d91ea04..0384fe3b3 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -514,7 +514,7 @@ type TPActionTiming struct { type TPActionTriggers struct { TPid string // Tariff plan id - ActionTriggersId string // Profile id + ActionTriggersId string // action trigger id ActionTriggers []*TPActionTrigger // Set of triggers grouped in this profile } @@ -531,6 +531,7 @@ func (self *TPActionTriggers) AsExportSlice() [][]string { } type TPActionTrigger struct { + Id string ThresholdType string // This threshold type ThresholdValue float64 // Threshold Recurrent bool // reset executed flag each run diff --git a/utils/rsrfield_test.go b/utils/rsrfield_test.go index f90fb1461..78c907608 100644 --- a/utils/rsrfield_test.go +++ b/utils/rsrfield_test.go @@ -35,7 +35,7 @@ func TestNewRSRField1(t *testing.T) { } // Separator escaped if rsrField, err := NewRSRField(`~sip_redirected_to:s\/sip:\+49(\d+)@/0$1/`); err == nil { - t.Error("Parse error, field rule does not contain correct number of separators, received: %v", rsrField) + t.Errorf("Parse error, field rule does not contain correct number of separators, received: %v", rsrField) } // One extra separator but escaped expRSRField3 := &RSRField{Id: "sip_redirected_to", diff --git a/utils/storedcdr_test.go b/utils/storedcdr_test.go index 31c37ce64..196d0463f 100644 --- a/utils/storedcdr_test.go +++ b/utils/storedcdr_test.go @@ -193,11 +193,11 @@ func TestUsageMultiply(t *testing.T) { func TestCostMultiply(t *testing.T) { cdr := StoredCdr{Cost: 1.01} if cdr.CostMultiply(1.19, 4); cdr.Cost != 1.2019 { - t.Error("Unexpected cost after multiply: %v", cdr.Cost) + t.Errorf("Unexpected cost after multiply: %v", cdr.Cost) } cdr = StoredCdr{Cost: 1.01} if cdr.CostMultiply(1000, 0); cdr.Cost != 1010 { - t.Error("Unexpected cost after multiply: %v", cdr.Cost) + t.Errorf("Unexpected cost after multiply: %v", cdr.Cost) } }