diff --git a/engine/calldesc.go b/engine/calldesc.go
index a5a403b97..c1c314cf0 100644
--- a/engine/calldesc.go
+++ b/engine/calldesc.go
@@ -45,6 +45,10 @@ func init() {
var err error
switch DB {
case "map":
+ if cgrCfg := config.CgrConfig(); cgrCfg == nil {
+ cgrCfg, _ = config.NewDefaultCGRConfig()
+ config.SetCgrConfig(cgrCfg)
+ }
ratingStorage, _ = NewMapStorage()
accountingStorage, _ = NewMapStorage()
case utils.MONGO:
diff --git a/engine/storage_map.go b/engine/storage_map.go
index 5a8cb3769..2ddf3f775 100644
--- a/engine/storage_map.go
+++ b/engine/storage_map.go
@@ -21,6 +21,7 @@ import (
"bytes"
"compress/zlib"
"errors"
+ "fmt"
"io/ioutil"
"strings"
"sync"
@@ -70,11 +71,13 @@ func (s storage) smembers(key string, ms Marshaler) (idMap utils.StringMap, ok b
}
func NewMapStorage() (*MapStorage, error) {
- return &MapStorage{dict: make(map[string][]byte), ms: NewCodecMsgpackMarshaler(), cacheCfg: &config.CacheConfig{RatingPlans: &config.CacheParamConfig{Precache: true}}}, nil
+ return &MapStorage{dict: make(map[string][]byte), ms: NewCodecMsgpackMarshaler(), cacheCfg: config.CgrConfig().CacheConfig}, nil
}
-func NewMapStorageJson() (*MapStorage, error) {
- return &MapStorage{dict: make(map[string][]byte), ms: new(JSONBufMarshaler), cacheCfg: &config.CacheConfig{RatingPlans: &config.CacheParamConfig{Precache: true}}}, nil
+func NewMapStorageJson() (mpStorage *MapStorage, err error) {
+ mpStorage, err = NewMapStorage()
+ mpStorage.ms = new(JSONBufMarshaler)
+ return
}
func (ms *MapStorage) Close() {}
@@ -95,7 +98,7 @@ func (ms *MapStorage) SelectDatabase(dbName string) (err error) {
}
func (ms *MapStorage) RebuildReverseForPrefix(prefix string) error {
- // FIXME: should do transaction
+ // ToDo: should do transaction
keys, err := ms.GetKeysForPrefix(prefix)
if err != nil {
return err
@@ -142,7 +145,6 @@ func (ms *MapStorage) RebuildReverseForPrefix(prefix string) error {
return nil
}
-// FixMe
func (ms *MapStorage) LoadRatingCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs []string) error {
if ms.cacheCfg == nil {
return nil
@@ -250,6 +252,119 @@ func (ms *MapStorage) PreloadCacheForPrefix(prefix string) error {
// CacheDataFromDB loads data to cache,
// prefix represents the cache prefix, IDs should be nil if all available data should be loaded
func (ms *MapStorage) CacheDataFromDB(prefix string, IDs []string, mustBeCached bool) (err error) {
+ if !utils.IsSliceMember([]string{utils.DESTINATION_PREFIX,
+ utils.REVERSE_DESTINATION_PREFIX,
+ utils.RATING_PLAN_PREFIX,
+ utils.RATING_PROFILE_PREFIX,
+ utils.ACTION_PREFIX,
+ utils.ACTION_PLAN_PREFIX,
+ utils.AccountActionPlansPrefix,
+ utils.ACTION_TRIGGER_PREFIX,
+ utils.SHARED_GROUP_PREFIX,
+ utils.DERIVEDCHARGERS_PREFIX,
+ utils.LCR_PREFIX,
+ utils.ALIASES_PREFIX,
+ utils.REVERSE_ALIASES_PREFIX,
+ utils.ResourceLimitsPrefix}, prefix) {
+ return utils.NewCGRError(utils.REDIS,
+ utils.MandatoryIEMissingCaps,
+ utils.UnsupportedCachePrefix,
+ fmt.Sprintf("prefix <%s> is not a supported cache prefix", prefix))
+ }
+ if IDs == nil {
+ keyIDs, err := ms.GetKeysForPrefix(prefix)
+ if err != nil {
+ return utils.NewCGRError(utils.REDIS,
+ utils.ServerErrorCaps,
+ err.Error(),
+ fmt.Sprintf("MapStorage error <%s> querying keys for prefix: <%s>", prefix))
+ }
+ for _, keyID := range keyIDs {
+ if mustBeCached { // Only consider loading ids which are already in cache
+ if _, hasIt := cache.Get(keyID); !hasIt {
+ continue
+ }
+ }
+ IDs = append(IDs, keyID[len(prefix):])
+ }
+ var nrItems int
+ switch prefix {
+ case utils.DESTINATION_PREFIX:
+ nrItems = ms.cacheCfg.Destinations.Limit
+ case utils.REVERSE_DESTINATION_PREFIX:
+ nrItems = ms.cacheCfg.ReverseDestinations.Limit
+ case utils.RATING_PLAN_PREFIX:
+ nrItems = ms.cacheCfg.RatingPlans.Limit
+ case utils.RATING_PROFILE_PREFIX:
+ nrItems = ms.cacheCfg.RatingProfiles.Limit
+ case utils.ACTION_PREFIX:
+ nrItems = ms.cacheCfg.Actions.Limit
+ case utils.ACTION_PLAN_PREFIX:
+ nrItems = ms.cacheCfg.ActionPlans.Limit
+ case utils.AccountActionPlansPrefix:
+ nrItems = ms.cacheCfg.AccountActionPlans.Limit
+ case utils.ACTION_TRIGGER_PREFIX:
+ nrItems = ms.cacheCfg.ActionTriggers.Limit
+ case utils.SHARED_GROUP_PREFIX:
+ nrItems = ms.cacheCfg.SharedGroups.Limit
+ case utils.DERIVEDCHARGERS_PREFIX:
+ nrItems = ms.cacheCfg.DerivedChargers.Limit
+ case utils.LCR_PREFIX:
+ nrItems = ms.cacheCfg.Lcr.Limit
+ case utils.ALIASES_PREFIX:
+ nrItems = ms.cacheCfg.Aliases.Limit
+ case utils.REVERSE_ALIASES_PREFIX:
+ nrItems = ms.cacheCfg.ReverseAliases.Limit
+ case utils.ResourceLimitsPrefix:
+ nrItems = ms.cacheCfg.ResourceLimits.Limit
+ }
+ if nrItems != 0 && nrItems < len(IDs) {
+ IDs = IDs[:nrItems]
+ }
+ }
+ for _, dataID := range IDs {
+ if mustBeCached {
+ if _, hasIt := cache.Get(prefix + dataID); !hasIt { // only cache if previously there
+ continue
+ }
+ }
+ switch prefix {
+ case utils.DESTINATION_PREFIX:
+ _, err = ms.GetDestination(dataID, true, utils.NonTransactional)
+ case utils.REVERSE_DESTINATION_PREFIX:
+ _, err = ms.GetReverseDestination(dataID, true, utils.NonTransactional)
+ case utils.RATING_PLAN_PREFIX:
+ _, err = ms.GetRatingPlan(dataID, true, utils.NonTransactional)
+ case utils.RATING_PROFILE_PREFIX:
+ _, err = ms.GetRatingProfile(dataID, true, utils.NonTransactional)
+ case utils.ACTION_PREFIX:
+ _, err = ms.GetActions(dataID, true, utils.NonTransactional)
+ case utils.ACTION_PLAN_PREFIX:
+ _, err = ms.GetActionPlan(dataID, true, utils.NonTransactional)
+ case utils.AccountActionPlansPrefix:
+ _, err = ms.GetAccountActionPlans(dataID, true, utils.NonTransactional)
+ case utils.ACTION_TRIGGER_PREFIX:
+ _, err = ms.GetActionTriggers(dataID, true, utils.NonTransactional)
+ case utils.SHARED_GROUP_PREFIX:
+ _, err = ms.GetSharedGroup(dataID, true, utils.NonTransactional)
+ case utils.DERIVEDCHARGERS_PREFIX:
+ _, err = ms.GetDerivedChargers(dataID, true, utils.NonTransactional)
+ case utils.LCR_PREFIX:
+ _, err = ms.GetLCR(dataID, true, utils.NonTransactional)
+ case utils.ALIASES_PREFIX:
+ _, err = ms.GetAlias(dataID, true, utils.NonTransactional)
+ case utils.REVERSE_ALIASES_PREFIX:
+ _, err = ms.GetReverseAlias(dataID, true, utils.NonTransactional)
+ case utils.ResourceLimitsPrefix:
+ _, err = ms.GetResourceLimit(dataID, true, utils.NonTransactional)
+ }
+ if err != nil {
+ return utils.NewCGRError(utils.REDIS,
+ utils.ServerErrorCaps,
+ err.Error(),
+ fmt.Sprintf("error <%s> querying MapStorage for category: <%s>, dataID: <%s>", prefix, dataID))
+ }
+ }
return
}
@@ -343,7 +458,9 @@ func (ms *MapStorage) GetRatingProfile(key string, skipCache bool, transactionID
cCommit := cacheCommit(transactionID)
if values, ok := ms.dict[key]; ok {
rpf = new(RatingProfile)
- err = ms.ms.Unmarshal(values, rpf)
+ if err = ms.ms.Unmarshal(values, &rpf); err != nil {
+ return nil, err
+ }
} else {
cache.Set(key, nil, cCommit, transactionID)
return nil, utils.ErrNotFound
@@ -439,14 +556,18 @@ func (ms *MapStorage) GetDestination(key string, skipCache bool, transactionID s
}
r.Close()
dest = new(Destination)
- err = ms.ms.Unmarshal(out, dest)
+ err = ms.ms.Unmarshal(out, &dest)
if err != nil {
- cache.Set(key, dest, cCommit, transactionID)
+ cache.Set(key, nil, cCommit, transactionID)
+ return nil, utils.ErrNotFound
}
- } else {
+ }
+ if dest == nil {
cache.Set(key, nil, cCommit, transactionID)
return nil, utils.ErrNotFound
}
+ cache.Set(key, dest, cCommit, transactionID)
+
return
}
@@ -508,16 +629,19 @@ func (ms *MapStorage) RemoveDestination(destID string, transactionID string) (er
if err != nil {
return
}
+
ms.mu.Lock()
delete(ms.dict, key)
ms.mu.Unlock()
cache.RemKey(key, cacheCommit(transactionID), transactionID)
+
for _, prefix := range d.Prefixes {
ms.mu.Lock()
ms.dict.srem(utils.REVERSE_DESTINATION_PREFIX+prefix, destID, ms.ms)
ms.mu.Unlock()
ms.GetReverseDestination(prefix, true, transactionID) // it will recache the destination
}
+
return
}
@@ -577,9 +701,9 @@ func (ms *MapStorage) GetActions(key string, skipCache bool, transactionID strin
ms.mu.RLock()
defer ms.mu.RUnlock()
cCommit := cacheCommit(transactionID)
- key = utils.ACTION_PREFIX + key
+ cachekey := utils.ACTION_PREFIX + key
if !skipCache {
- if x, err := cache.GetCloned(key); err != nil {
+ if x, err := cache.GetCloned(cachekey); err != nil {
if err.Error() != utils.ItemNotFound {
return nil, err
}
@@ -589,13 +713,13 @@ func (ms *MapStorage) GetActions(key string, skipCache bool, transactionID strin
return x.(Actions), nil
}
}
- if values, ok := ms.dict[key]; ok {
+ if values, ok := ms.dict[cachekey]; ok {
err = ms.ms.Unmarshal(values, &as)
} else {
- cache.Set(key, nil, cCommit, transactionID)
+ cache.Set(cachekey, nil, cCommit, transactionID)
return nil, utils.ErrNotFound
}
- cache.Set(key, as, cCommit, transactionID)
+ cache.Set(cachekey, as, cCommit, transactionID)
return
}
@@ -603,26 +727,28 @@ func (ms *MapStorage) SetActions(key string, as Actions, transactionID string) (
ms.mu.Lock()
defer ms.mu.Unlock()
cCommit := cacheCommit(transactionID)
+ cachekey := utils.ACTION_PREFIX + key
result, err := ms.ms.Marshal(&as)
- ms.dict[utils.ACTION_PREFIX+key] = result
- cache.RemKey(utils.ACTION_PREFIX+key, cCommit, transactionID)
+ ms.dict[cachekey] = result
+ cache.RemKey(cachekey, cCommit, transactionID)
return
}
func (ms *MapStorage) RemoveActions(key string, transactionID string) (err error) {
+ cachekey := utils.ACTION_PREFIX + key
ms.mu.Lock()
- defer ms.mu.Unlock()
- delete(ms.dict, utils.ACTION_PREFIX+key)
- cache.RemKey(utils.ACTION_PREFIX+key, cacheCommit(transactionID), transactionID)
+ delete(ms.dict, cachekey)
+ ms.mu.Unlock()
+ cache.RemKey(cachekey, cacheCommit(transactionID), transactionID)
return
}
func (ms *MapStorage) GetSharedGroup(key string, skipCache bool, transactionID string) (sg *SharedGroup, err error) {
ms.mu.RLock()
defer ms.mu.RUnlock()
- key = utils.SHARED_GROUP_PREFIX + key
+ cachekey := utils.SHARED_GROUP_PREFIX + key
if !skipCache {
- if x, ok := cache.Get(key); ok {
+ if x, ok := cache.Get(cachekey); ok {
if x != nil {
return x.(*SharedGroup), nil
}
@@ -630,13 +756,13 @@ func (ms *MapStorage) GetSharedGroup(key string, skipCache bool, transactionID s
}
}
cCommit := cacheCommit(transactionID)
- if values, ok := ms.dict[key]; ok {
+ if values, ok := ms.dict[cachekey]; ok {
err = ms.ms.Unmarshal(values, &sg)
if err == nil {
- cache.Set(key, sg, cCommit, transactionID)
+ cache.Set(cachekey, sg, cCommit, transactionID)
}
} else {
- cache.Set(key, nil, cCommit, transactionID)
+ cache.Set(cachekey, nil, cCommit, transactionID)
return nil, utils.ErrNotFound
}
return
@@ -654,12 +780,19 @@ func (ms *MapStorage) SetSharedGroup(sg *SharedGroup, transactionID string) (err
func (ms *MapStorage) GetAccount(key string) (ub *Account, err error) {
ms.mu.RLock()
defer ms.mu.RUnlock()
- if values, ok := ms.dict[utils.ACCOUNT_PREFIX+key]; ok {
- ub = &Account{ID: key}
- err = ms.ms.Unmarshal(values, ub)
- } else {
+ values, ok := ms.dict[utils.ACCOUNT_PREFIX+key]
+ if !ok {
return nil, utils.ErrNotFound
}
+ ub = &Account{ID: key}
+ err = ms.ms.Unmarshal(values, &ub)
+ if err != nil {
+ return nil, err
+ }
+ if len(values) == 0 {
+ return nil, utils.ErrNotFound
+ }
+
return
}
@@ -785,41 +918,40 @@ func (ms *MapStorage) RemoveUser(key string) error {
func (ms *MapStorage) GetAlias(key string, skipCache bool, transactionID string) (al *Alias, err error) {
ms.mu.RLock()
defer ms.mu.RUnlock()
- origKey := key
- key = utils.ALIASES_PREFIX + key
+ cacheKey := utils.ALIASES_PREFIX + key
+ cCommit := cacheCommit(transactionID)
if !skipCache {
- if x, ok := cache.Get(key); ok {
- if x != nil {
- al = &Alias{Values: x.(AliasValues)}
- al.SetId(origKey)
- return al, nil
+ if x, ok := cache.Get(cacheKey); ok {
+ if x == nil {
+ return nil, utils.ErrNotFound
}
- return nil, utils.ErrNotFound
+ return x.(*Alias), nil
}
}
- cCommit := cacheCommit(transactionID)
- if values, ok := ms.dict[key]; ok {
+ if values, ok := ms.dict[cacheKey]; ok {
al = &Alias{Values: make(AliasValues, 0)}
- al.SetId(key[len(utils.ALIASES_PREFIX):])
- err = ms.ms.Unmarshal(values, &al.Values)
- if err == nil {
- cache.Set(key, al.Values, cCommit, transactionID)
+ al.SetId(key)
+ if err = ms.ms.Unmarshal(values, &al.Values); err != nil {
+ return nil, err
}
} else {
- cache.Set(key, nil, cCommit, transactionID)
+ cache.Set(cacheKey, nil, cCommit, transactionID)
return nil, utils.ErrNotFound
}
- return al, nil
+ cache.Set(cacheKey, al, cCommit, transactionID)
+ return
+
}
func (ms *MapStorage) SetAlias(al *Alias, transactionID string) error {
- ms.mu.Lock()
- defer ms.mu.Unlock()
+
result, err := ms.ms.Marshal(al.Values)
if err != nil {
return err
}
key := utils.ALIASES_PREFIX + al.GetId()
+ ms.mu.Lock()
+ defer ms.mu.Unlock()
ms.dict[key] = result
cache.RemKey(key, cacheCommit(transactionID), transactionID)
return nil
@@ -837,15 +969,15 @@ func (ms *MapStorage) GetReverseAlias(reverseID string, skipCache bool, transact
return nil, utils.ErrNotFound
}
}
- var values []string
+
cCommit := cacheCommit(transactionID)
if idMap, ok := ms.dict.smembers(key, ms.ms); len(idMap) > 0 && ok {
- values = idMap.Slice()
+ ids = idMap.Slice()
} else {
cache.Set(key, nil, cCommit, transactionID)
return nil, utils.ErrNotFound
}
- cache.Set(key, values, cCommit, transactionID)
+ cache.Set(key, ids, cCommit, transactionID)
return
}
@@ -1027,6 +1159,8 @@ func (ms *MapStorage) GetAllActionPlans() (ats map[string]*ActionPlan, err error
}
func (ms *MapStorage) GetAccountActionPlans(acntID string, skipCache bool, transactionID string) (apIDs []string, err error) {
+ ms.mu.RLock()
+ defer ms.mu.RUnlock()
key := utils.AccountActionPlansPrefix + acntID
if !skipCache {
if x, ok := cache.Get(key); ok {
@@ -1036,9 +1170,7 @@ func (ms *MapStorage) GetAccountActionPlans(acntID string, skipCache bool, trans
return x.([]string), nil
}
}
- ms.mu.RLock()
values, ok := ms.dict[key]
- ms.mu.RUnlock()
if !ok {
cache.Set(key, nil, cacheCommit(transactionID), transactionID)
err = utils.ErrNotFound
@@ -1053,8 +1185,7 @@ func (ms *MapStorage) GetAccountActionPlans(acntID string, skipCache bool, trans
func (ms *MapStorage) SetAccountActionPlans(acntID string, apIDs []string, overwrite bool) (err error) {
if !overwrite {
- oldaPlIDs, err := ms.GetAccountActionPlans(acntID, true, utils.NonTransactional)
- if err != nil && err != utils.ErrNotFound {
+ if oldaPlIDs, err := ms.GetAccountActionPlans(acntID, true, utils.NonTransactional); err != nil && err != utils.ErrNotFound {
return err
} else {
for _, oldAPid := range oldaPlIDs {
@@ -1064,7 +1195,6 @@ func (ms *MapStorage) SetAccountActionPlans(acntID string, apIDs []string, overw
}
}
}
-
ms.mu.Lock()
defer ms.mu.Unlock()
result, err := ms.ms.Marshal(apIDs)
@@ -1072,12 +1202,11 @@ func (ms *MapStorage) SetAccountActionPlans(acntID string, apIDs []string, overw
return err
}
ms.dict[utils.AccountActionPlansPrefix+acntID] = result
+
return
}
func (ms *MapStorage) RemAccountActionPlans(acntID string, apIDs []string) (err error) {
- ms.mu.Lock()
- defer ms.mu.Unlock()
key := utils.AccountActionPlansPrefix + acntID
if len(apIDs) == 0 {
delete(ms.dict, key)
@@ -1094,10 +1223,17 @@ func (ms *MapStorage) RemAccountActionPlans(acntID string, apIDs []string) (err
}
i++
}
+ ms.mu.Lock()
+ defer ms.mu.Unlock()
if len(oldaPlIDs) == 0 {
delete(ms.dict, key)
return
}
+ var result []byte
+ if result, err = ms.ms.Marshal(oldaPlIDs); err != nil {
+ return err
+ }
+ ms.dict[key] = result
return
}
@@ -1277,7 +1413,8 @@ func (ms *MapStorage) SetResourceLimit(rl *ResourceLimit, transactionID string)
if err != nil {
return err
}
- ms.dict[utils.ResourceLimitsPrefix+rl.ID] = result
+ key := utils.ResourceLimitsPrefix + rl.ID
+ ms.dict[key] = result
return nil
}
@@ -1314,9 +1451,10 @@ func (ms *MapStorage) SetReqFilterIndexes(dbKey string, indexes map[string]map[s
return
}
func (ms *MapStorage) MatchReqFilterIndex(dbKey, fieldValKey string) (itemIDs utils.StringMap, err error) {
+ cacheKey := dbKey + fieldValKey
ms.mu.RLock()
defer ms.mu.RUnlock()
- if x, ok := cache.Get(dbKey + fieldValKey); ok { // Attempt to find in cache first
+ if x, ok := cache.Get(cacheKey); ok { // Attempt to find in cache first
if x != nil {
return x.(utils.StringMap), nil
}
@@ -1325,7 +1463,7 @@ func (ms *MapStorage) MatchReqFilterIndex(dbKey, fieldValKey string) (itemIDs ut
// Not found in cache, check in DB
values, ok := ms.dict[dbKey]
if !ok {
- cache.Set(dbKey+fieldValKey, nil, true, utils.NonTransactional)
+ cache.Set(cacheKey, nil, true, utils.NonTransactional)
return nil, utils.ErrNotFound
}
var indexes map[string]map[string]utils.StringMap
@@ -1336,7 +1474,12 @@ func (ms *MapStorage) MatchReqFilterIndex(dbKey, fieldValKey string) (itemIDs ut
if _, hasIt := indexes[keySplt[0]]; hasIt {
itemIDs = indexes[keySplt[0]][keySplt[1]]
}
- cache.Set(dbKey+fieldValKey, itemIDs, true, utils.NonTransactional)
+ //Verify items
+ if len(itemIDs) == 0 {
+ cache.Set(cacheKey, nil, true, utils.NonTransactional)
+ return nil, utils.ErrNotFound
+ }
+ cache.Set(cacheKey, itemIDs, true, utils.NonTransactional)
return
}
diff --git a/migrator/accounts.go b/migrator/accounts.go
index c4c6c6de1..9bcb46d19 100644
--- a/migrator/accounts.go
+++ b/migrator/accounts.go
@@ -18,6 +18,9 @@ along with this program. If not, see
package migrator
import (
+ "fmt"
+ "log"
+ "strings"
"time"
"github.com/cgrates/cgrates/engine"
@@ -53,6 +56,12 @@ type v1Balance struct {
TimingIDs string
Disabled bool
}
+type v1UnitsCounter struct {
+ Direction string
+ BalanceType string
+ // Units float64
+ Balances v1BalanceChain // first balance is the general one (no destination)
+}
func (b *v1Balance) IsDefault() bool {
return (b.DestinationIds == "" || b.DestinationIds == utils.ANY) &&
@@ -64,34 +73,149 @@ func (b *v1Balance) IsDefault() bool {
b.Disabled == false
}
-type v1UnitsCounter struct {
- Direction string
- BalanceType string
- // Units float64
- Balances v1BalanceChain // first balance is the general one (no destination)
-}
-
-type v1ActionTriggers []*v1ActionTrigger
-
-type v1ActionTrigger struct {
- Id string
- ThresholdType string
- ThresholdValue float64
- Recurrent bool
- MinSleep time.Duration
- BalanceId string
- BalanceType string
- BalanceDirection string
- BalanceDestinationIds string
- BalanceWeight float64
- BalanceExpirationDate time.Time
- BalanceTimingTags string
- BalanceRatingSubject string
- BalanceCategory string
- BalanceSharedGroup string
- BalanceDisabled bool
- Weight float64
- ActionsId string
- MinQueuedItems int
- Executed bool
+func (v1Acc v1Account) AsAccount() (ac engine.Account) {
+ // transfer data into new structure
+ ac = engine.Account{
+ ID: v1Acc.Id,
+ BalanceMap: make(map[string]engine.Balances, len(v1Acc.BalanceMap)),
+ UnitCounters: make(engine.UnitCounters, len(v1Acc.UnitCounters)),
+ ActionTriggers: make(engine.ActionTriggers, len(v1Acc.ActionTriggers)),
+ AllowNegative: v1Acc.AllowNegative,
+ Disabled: v1Acc.Disabled,
+ }
+ idElements := strings.Split(ac.ID, utils.CONCATENATED_KEY_SEP)
+ if len(idElements) != 3 {
+ log.Printf("Malformed account ID %s", v1Acc.Id)
+ }
+ ac.ID = fmt.Sprintf("%s:%s", idElements[1], idElements[2])
+ // balances
+ for oldBalKey, oldBalChain := range v1Acc.BalanceMap {
+ keyElements := strings.Split(oldBalKey, "*")
+ newBalKey := "*" + keyElements[1]
+ newBalDirection := "*" + idElements[0]
+ ac.BalanceMap[newBalKey] = make(engine.Balances, len(oldBalChain))
+ for index, oldBal := range oldBalChain {
+ // check default to set new id
+ ac.BalanceMap[newBalKey][index] = &engine.Balance{
+ Uuid: oldBal.Uuid,
+ ID: oldBal.Id,
+ Value: oldBal.Value,
+ Directions: utils.ParseStringMap(newBalDirection),
+ ExpirationDate: oldBal.ExpirationDate,
+ Weight: oldBal.Weight,
+ DestinationIDs: utils.ParseStringMap(oldBal.DestinationIds),
+ RatingSubject: oldBal.RatingSubject,
+ Categories: utils.ParseStringMap(oldBal.Category),
+ SharedGroups: utils.ParseStringMap(oldBal.SharedGroup),
+ Timings: oldBal.Timings,
+ TimingIDs: utils.ParseStringMap(oldBal.TimingIDs),
+ Disabled: oldBal.Disabled,
+ }
+ }
+ }
+ // unit counters
+ for _, oldUc := range v1Acc.UnitCounters {
+ newUc := &engine.UnitCounter{Counters: make(engine.CounterFilters, len(oldUc.Balances))}
+ for index, oldUcBal := range oldUc.Balances {
+ bf := &engine.BalanceFilter{}
+ if oldUcBal.Uuid != "" {
+ bf.Uuid = utils.StringPointer(oldUcBal.Uuid)
+ }
+ if oldUcBal.Id != "" {
+ bf.ID = utils.StringPointer(oldUcBal.Id)
+ }
+ if oldUc.BalanceType != "" {
+ bf.Type = utils.StringPointer(oldUc.BalanceType)
+ }
+ if oldUc.Direction != "" {
+ bf.Directions = utils.StringMapPointer(utils.ParseStringMap(oldUc.Direction))
+ }
+ if !oldUcBal.ExpirationDate.IsZero() {
+ bf.ExpirationDate = utils.TimePointer(oldUcBal.ExpirationDate)
+ }
+ if oldUcBal.Weight != 0 {
+ bf.Weight = utils.Float64Pointer(oldUcBal.Weight)
+ }
+ if oldUcBal.DestinationIds != "" {
+ bf.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(oldUcBal.DestinationIds))
+ }
+ if oldUcBal.RatingSubject != "" {
+ bf.RatingSubject = utils.StringPointer(oldUcBal.RatingSubject)
+ }
+ if oldUcBal.Category != "" {
+ bf.Categories = utils.StringMapPointer(utils.ParseStringMap(oldUcBal.Category))
+ }
+ if oldUcBal.SharedGroup != "" {
+ bf.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(oldUcBal.SharedGroup))
+ }
+ if oldUcBal.TimingIDs != "" {
+ bf.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(oldUcBal.TimingIDs))
+ }
+ if oldUcBal.Disabled != false {
+ bf.Disabled = utils.BoolPointer(oldUcBal.Disabled)
+ }
+ bf.Timings = oldUcBal.Timings
+ cf := &engine.CounterFilter{
+ Value: oldUcBal.Value,
+ Filter: bf,
+ }
+ newUc.Counters[index] = cf
+ }
+ ac.UnitCounters[oldUc.BalanceType] = append(ac.UnitCounters[oldUc.BalanceType], newUc)
+ }
+ //action triggers
+ for index, oldAtr := range v1Acc.ActionTriggers {
+ at := &engine.ActionTrigger{
+ UniqueID: oldAtr.Id,
+ ThresholdType: oldAtr.ThresholdType,
+ ThresholdValue: oldAtr.ThresholdValue,
+ Recurrent: oldAtr.Recurrent,
+ MinSleep: oldAtr.MinSleep,
+ Weight: oldAtr.Weight,
+ ActionsID: oldAtr.ActionsId,
+ MinQueuedItems: oldAtr.MinQueuedItems,
+ Executed: oldAtr.Executed,
+ }
+ bf := &engine.BalanceFilter{}
+ if oldAtr.BalanceId != "" {
+ bf.ID = utils.StringPointer(oldAtr.BalanceId)
+ }
+ if oldAtr.BalanceType != "" {
+ bf.Type = utils.StringPointer(oldAtr.BalanceType)
+ }
+ if oldAtr.BalanceRatingSubject != "" {
+ bf.RatingSubject = utils.StringPointer(oldAtr.BalanceRatingSubject)
+ }
+ if oldAtr.BalanceDirection != "" {
+ bf.Directions = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceDirection))
+ }
+ if oldAtr.BalanceDestinationIds != "" {
+ bf.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceDestinationIds))
+ }
+ if oldAtr.BalanceTimingTags != "" {
+ bf.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceTimingTags))
+ }
+ if oldAtr.BalanceCategory != "" {
+ bf.Categories = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceCategory))
+ }
+ if oldAtr.BalanceSharedGroup != "" {
+ bf.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(oldAtr.BalanceSharedGroup))
+ }
+ if oldAtr.BalanceWeight != 0 {
+ bf.Weight = utils.Float64Pointer(oldAtr.BalanceWeight)
+ }
+ if oldAtr.BalanceDisabled != false {
+ bf.Disabled = utils.BoolPointer(oldAtr.BalanceDisabled)
+ }
+ if !oldAtr.BalanceExpirationDate.IsZero() {
+ bf.ExpirationDate = utils.TimePointer(oldAtr.BalanceExpirationDate)
+ }
+ at.Balance = bf
+ ac.ActionTriggers[index] = at
+ if ac.ActionTriggers[index].ThresholdType == "*min_counter" ||
+ ac.ActionTriggers[index].ThresholdType == "*max_counter" {
+ ac.ActionTriggers[index].ThresholdType = strings.Replace(ac.ActionTriggers[index].ThresholdType, "_", "_event_", 1)
+ }
+ }
+ return
}
diff --git a/migrator/accounts_test.go b/migrator/accounts_test.go
new file mode 100644
index 000000000..af782d3f6
--- /dev/null
+++ b/migrator/accounts_test.go
@@ -0,0 +1,41 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+package migrator
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestV1AccountAsAccount(t *testing.T) {
+ v1b := &v1Balance{Value: 10, Weight: 10, DestinationIds: "NAT"}
+ v1Acc := &v1Account{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]v1BalanceChain{utils.VOICE: v1BalanceChain{v1b}, utils.MONETARY: v1BalanceChain{&v1Balance{Value: 21}}}}
+ v2 := &engine.Balance{Uuid: "", ID: "", Value: 10, Directions: utils.StringMap{"*OUT": true}, Weight: 10, DestinationIDs: utils.StringMap{"NAT": true}, RatingSubject: "", Categories: utils.NewStringMap(""), SharedGroups: utils.NewStringMap(""), TimingIDs: utils.NewStringMap("")}
+ m2 := &engine.Balance{Uuid: "", ID: "", Value: 21, Directions: utils.StringMap{"*OUT": true}, DestinationIDs: utils.NewStringMap(""), RatingSubject: "", Categories: utils.NewStringMap(""), SharedGroups: utils.NewStringMap(""), TimingIDs: utils.NewStringMap("")}
+ testAccount := &engine.Account{ID: "CUSTOMER_1:rif", BalanceMap: map[string]engine.Balances{utils.VOICE: engine.Balances{v2}, utils.MONETARY: engine.Balances{m2}}, UnitCounters: engine.UnitCounters{}, ActionTriggers: engine.ActionTriggers{}}
+ if def := v1b.IsDefault(); def != false {
+ t.Errorf("Expecting: false, received: true")
+ }
+ newAcc := v1Acc.AsAccount()
+ if !reflect.DeepEqual(*testAccount, newAcc) {
+ t.Errorf("Expecting: %+v, received: %+v", *testAccount, newAcc)
+ }
+}
diff --git a/migrator/action.go b/migrator/action.go
new file mode 100644
index 000000000..e73e88efd
--- /dev/null
+++ b/migrator/action.go
@@ -0,0 +1,86 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+package migrator
+
+import (
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+type v1Action struct {
+ Id string
+ ActionType string
+ BalanceType string
+ Direction string
+ ExtraParameters string
+ ExpirationString string
+ Weight float64
+ Balance *v1Balance
+}
+
+type v1Actions []*v1Action
+
+func (v1Act v1Action) AsAction() (act engine.Action) {
+ act = engine.Action{
+ Id: v1Act.Id,
+ ActionType: v1Act.ActionType,
+ ExtraParameters: v1Act.ExtraParameters,
+ ExpirationString: v1Act.ExpirationString,
+ Weight: v1Act.Weight,
+ Balance: &engine.BalanceFilter{},
+ }
+ bf := act.Balance
+ if v1Act.Balance.Uuid != "" {
+ bf.Uuid = utils.StringPointer(v1Act.Balance.Uuid)
+ }
+ if v1Act.Balance.Id != "" {
+ bf.ID = utils.StringPointer(v1Act.Balance.Id)
+ }
+ if v1Act.BalanceType != "" {
+ bf.Type = utils.StringPointer(v1Act.BalanceType)
+ }
+ if v1Act.Balance.Value != 0 {
+ bf.Value = &utils.ValueFormula{Static: v1Act.Balance.Value}
+ }
+ if v1Act.Balance.RatingSubject != "" {
+ bf.RatingSubject = utils.StringPointer(v1Act.Balance.RatingSubject)
+ }
+ if v1Act.Balance.DestinationIds != "" {
+ bf.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(v1Act.Balance.DestinationIds))
+ }
+ if v1Act.Balance.TimingIDs != "" {
+ bf.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(v1Act.Balance.TimingIDs))
+ }
+ if v1Act.Balance.Category != "" {
+ bf.Categories = utils.StringMapPointer(utils.ParseStringMap(v1Act.Balance.Category))
+ }
+ if v1Act.Balance.SharedGroup != "" {
+ bf.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(v1Act.Balance.SharedGroup))
+ }
+ if v1Act.Balance.Weight != 0 {
+ bf.Weight = utils.Float64Pointer(v1Act.Balance.Weight)
+ }
+ if v1Act.Balance.Disabled != false {
+ bf.Disabled = utils.BoolPointer(v1Act.Balance.Disabled)
+ }
+ if !v1Act.Balance.ExpirationDate.IsZero() {
+ bf.ExpirationDate = utils.TimePointer(v1Act.Balance.ExpirationDate)
+ }
+ bf.Timings = v1Act.Balance.Timings
+ return
+}
diff --git a/migrator/action_plan.go b/migrator/action_plan.go
new file mode 100644
index 000000000..0c4e56019
--- /dev/null
+++ b/migrator/action_plan.go
@@ -0,0 +1,75 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+package migrator
+
+import (
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+type v1ActionPlan struct {
+ Uuid string // uniquely identify the timing
+ Id string // informative purpose only
+ AccountIds []string
+ Timing *engine.RateInterval
+ Weight float64
+ ActionsId string
+ actions v1Actions
+ stCache time.Time // cached time of the next start
+}
+
+type v1ActionPlans []*v1ActionPlan
+
+func (at *v1ActionPlan) IsASAP() bool {
+ if at.Timing == nil {
+ return false
+ }
+ return at.Timing.Timing.StartTime == utils.ASAP
+}
+
+func (v1AP v1ActionPlan) AsActionPlan() (ap engine.ActionPlan) {
+ for idx, actionId := range v1AP.AccountIds {
+ idElements := strings.Split(actionId, utils.CONCATENATED_KEY_SEP)
+ if len(idElements) != 3 {
+ continue
+ }
+ v1AP.AccountIds[idx] = fmt.Sprintf("%s:%s", idElements[1], idElements[2])
+ }
+ ap = engine.ActionPlan{
+ Id: v1AP.Id,
+ AccountIDs: make(utils.StringMap),
+ }
+ if x := v1AP.IsASAP(); !x {
+ for _, accID := range v1AP.AccountIds {
+ if _, exists := ap.AccountIDs[accID]; !exists {
+ ap.AccountIDs[accID] = true
+ }
+ }
+ }
+ ap.ActionTimings = append(ap.ActionTimings, &engine.ActionTiming{
+ Uuid: utils.GenUUID(),
+ Timing: v1AP.Timing,
+ ActionsID: v1AP.ActionsId,
+ Weight: v1AP.Weight,
+ })
+ return
+}
diff --git a/migrator/action_plan_test.go b/migrator/action_plan_test.go
new file mode 100644
index 000000000..8b4135559
--- /dev/null
+++ b/migrator/action_plan_test.go
@@ -0,0 +1,39 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+package migrator
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestV1ActionPlanAsActionPlan(t *testing.T) {
+ v1ap := &v1ActionPlan{Id: "test", AccountIds: []string{"one"}, Timing: &engine.RateInterval{Timing: new(engine.RITiming)}}
+ ap := &engine.ActionPlan{Id: "test", AccountIDs: utils.StringMap{"one": true}, ActionTimings: []*engine.ActionTiming{&engine.ActionTiming{Timing: &engine.RateInterval{Timing: new(engine.RITiming)}}}}
+ newap := v1ap.AsActionPlan()
+ if ap.Id != newap.Id || !reflect.DeepEqual(ap.AccountIDs, newap.AccountIDs) {
+ t.Errorf("Expecting: %+v, received: %+v", *ap, newap)
+ } else if !reflect.DeepEqual(ap.ActionTimings[0].Timing, newap.ActionTimings[0].Timing) {
+ t.Errorf("Expecting: %+v, received: %+v", ap.ActionTimings[0].Timing, newap.ActionTimings[0].Timing)
+ } else if ap.ActionTimings[0].Weight != newap.ActionTimings[0].Weight || ap.ActionTimings[0].ActionsID != newap.ActionTimings[0].ActionsID {
+ t.Errorf("Expecting: %+v, received: %+v", ap.ActionTimings[0].Weight, newap.ActionTimings[0].Weight)
+ }
+}
diff --git a/migrator/action_test.go b/migrator/action_test.go
new file mode 100644
index 000000000..db29d3db6
--- /dev/null
+++ b/migrator/action_test.go
@@ -0,0 +1,34 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+package migrator
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/cgrates/cgrates/engine"
+)
+
+func TestV1ActionsAsActions(t *testing.T) {
+ v1act := &v1Action{Id: "", ActionType: "", BalanceType: "", Direction: "INBOUND", ExtraParameters: "", ExpirationString: "", Balance: &v1Balance{}}
+ act := &engine.Action{Id: "", ActionType: "", ExtraParameters: "", ExpirationString: "", Weight: 0.00, Balance: &engine.BalanceFilter{}}
+ newact := v1act.AsAction()
+ if !reflect.DeepEqual(*act, newact) {
+ t.Errorf("Expecting: %+v, received: %+v", *act, newact)
+ }
+}
diff --git a/migrator/action_trigger.go b/migrator/action_trigger.go
new file mode 100644
index 000000000..862115352
--- /dev/null
+++ b/migrator/action_trigger.go
@@ -0,0 +1,89 @@
+package migrator
+
+import (
+ "strings"
+ "time"
+
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+type v1ActionTrigger struct {
+ Id string
+ ThresholdType string
+ ThresholdValue float64
+ Recurrent bool
+ MinSleep time.Duration
+ BalanceId string
+ BalanceType string
+ BalanceDirection string
+ BalanceDestinationIds string
+ BalanceWeight float64
+ BalanceExpirationDate time.Time
+ BalanceTimingTags string
+ BalanceRatingSubject string
+ BalanceCategory string
+ BalanceSharedGroup string
+ BalanceDisabled bool
+ Weight float64
+ ActionsId string
+ MinQueuedItems int
+ Executed bool
+}
+
+type v1ActionTriggers []*v1ActionTrigger
+
+func (v1Act v1ActionTrigger) AsActionTrigger() (at engine.ActionTrigger) {
+
+ at = engine.ActionTrigger{
+ UniqueID: v1Act.Id,
+ ThresholdType: v1Act.ThresholdType,
+ ThresholdValue: v1Act.ThresholdValue,
+ Recurrent: v1Act.Recurrent,
+ MinSleep: v1Act.MinSleep,
+ Weight: v1Act.Weight,
+ ActionsID: v1Act.ActionsId,
+ MinQueuedItems: v1Act.MinQueuedItems,
+ Executed: v1Act.Executed,
+ }
+ bf := &engine.BalanceFilter{}
+ if v1Act.BalanceId != "" {
+ bf.ID = utils.StringPointer(v1Act.BalanceId)
+ }
+ if v1Act.BalanceType != "" {
+ bf.Type = utils.StringPointer(v1Act.BalanceType)
+ }
+ if v1Act.BalanceRatingSubject != "" {
+ bf.RatingSubject = utils.StringPointer(v1Act.BalanceRatingSubject)
+ }
+ if v1Act.BalanceDirection != "" {
+ bf.Directions = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceDirection))
+ }
+ if v1Act.BalanceDestinationIds != "" {
+ bf.DestinationIDs = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceDestinationIds))
+ }
+ if v1Act.BalanceTimingTags != "" {
+ bf.TimingIDs = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceTimingTags))
+ }
+ if v1Act.BalanceCategory != "" {
+ bf.Categories = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceCategory))
+ }
+ if v1Act.BalanceSharedGroup != "" {
+ bf.SharedGroups = utils.StringMapPointer(utils.ParseStringMap(v1Act.BalanceSharedGroup))
+ }
+ if v1Act.BalanceWeight != 0 {
+ bf.Weight = utils.Float64Pointer(v1Act.BalanceWeight)
+ }
+ if v1Act.BalanceDisabled != false {
+ bf.Disabled = utils.BoolPointer(v1Act.BalanceDisabled)
+ }
+ if !v1Act.BalanceExpirationDate.IsZero() {
+ bf.ExpirationDate = utils.TimePointer(v1Act.BalanceExpirationDate)
+ }
+ at.Balance = bf
+ if at.ThresholdType == "*min_counter" ||
+ at.ThresholdType == "*max_counter" {
+ at.ThresholdType = strings.Replace(at.ThresholdType, "_", "_event_", 1)
+ }
+ return
+}
diff --git a/migrator/action_trigger_test.go b/migrator/action_trigger_test.go
new file mode 100644
index 000000000..e9cc646e8
--- /dev/null
+++ b/migrator/action_trigger_test.go
@@ -0,0 +1,50 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+package migrator
+
+import (
+ "encoding/json"
+ "reflect"
+ "testing"
+
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+var v1ActionTriggers1 = `{"BalanceType": "*monetary","BalanceDirection": "*out","ThresholdType":"*max_balance", "ThresholdValue" :2, "ActionsId": "TEST_ACTIONS", "Executed": true}`
+
+func TestV1ActionTriggersAsActionTriggers(t *testing.T) {
+ atrs := &engine.ActionTrigger{
+ Balance: &engine.BalanceFilter{
+ Type: utils.StringPointer(utils.MONETARY),
+ Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
+ },
+ ThresholdType: utils.TRIGGER_MAX_BALANCE,
+ ThresholdValue: 2,
+ ActionsID: "TEST_ACTIONS",
+ Executed: true,
+ }
+ var v1actstrgrs v1ActionTrigger
+ if err := json.Unmarshal([]byte(v1ActionTriggers1), &v1actstrgrs); err != nil {
+ t.Error(err)
+ }
+ newatrs := v1actstrgrs.AsActionTrigger()
+ if !reflect.DeepEqual(*atrs, newatrs) {
+ t.Errorf("Expecting: %+v, received: %+v", *atrs, newatrs)
+ }
+}
diff --git a/migrator/costdetails.go b/migrator/costdetails.go
index 7d2755b61..67095994d 100644
--- a/migrator/costdetails.go
+++ b/migrator/costdetails.go
@@ -89,8 +89,8 @@ func (m *Migrator) migrateCostDetails() (err error) {
v1CC := &v1CallCost{Direction: ccDirection.String, Category: ccCategory.String, Tenant: ccTenant.String,
Subject: ccSubject.String, Account: ccAccount.String, Destination: ccDestination.String, TOR: ccTor.String,
Cost: ccCost.Float64, Timespans: v1tmsps}
- cc, err := v1CC.AsCallCost()
- if err != nil {
+ cc := v1CC.AsCallCost()
+ if cc == nil {
utils.Logger.Warning(
fmt.Sprintf(" Error: <%s> when converting into CallCost CDR with id: <%d>", err.Error(), id))
continue
@@ -152,7 +152,7 @@ type v1UnitInfo struct {
TOR string
}
-func (v1cc *v1CallCost) AsCallCost() (cc *engine.CallCost, err error) {
+func (v1cc *v1CallCost) AsCallCost() (cc *engine.CallCost) {
cc = new(engine.CallCost)
cc.Direction = v1cc.Direction
cc.Category = v1cc.Category
diff --git a/migrator/costdetails_test.go b/migrator/costdetails_test.go
index 84d8297de..9b101bbdf 100644
--- a/migrator/costdetails_test.go
+++ b/migrator/costdetails_test.go
@@ -31,9 +31,7 @@ func TestV1CostDetailsAsCostDetails1(t *testing.T) {
t.Error(err)
}
v1CC := &v1CallCost{Timespans: v1tmsps}
- if _, err := v1CC.AsCallCost(); err != nil {
- t.Error(err)
- }
+ _ = v1CC.AsCallCost()
// ToDo: Test here the content
}
@@ -44,7 +42,6 @@ func TestV1CostDetailsAsCostDetails2(t *testing.T) {
t.Error(err)
}
v1CC := &v1CallCost{Timespans: v1tmsps}
- if _, err := v1CC.AsCallCost(); err != nil {
- t.Error(err)
- }
+ _ = v1CC.AsCallCost()
+
}
diff --git a/migrator/sharedgroup.go b/migrator/sharedgroup.go
new file mode 100644
index 000000000..e728e46db
--- /dev/null
+++ b/migrator/sharedgroup.go
@@ -0,0 +1,41 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+package migrator
+
+import (
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+type v1SharedGroup struct {
+ Id string
+ AccountParameters map[string]*engine.SharingParameters
+ MemberIds []string
+}
+
+func (v1SG v1SharedGroup) AsSharedGroup() (sg engine.SharedGroup) {
+ sg = engine.SharedGroup{
+ Id: v1SG.Id,
+ AccountParameters: v1SG.AccountParameters,
+ MemberIds: make(utils.StringMap),
+ }
+ for _, accID := range v1SG.MemberIds {
+ sg.MemberIds[accID] = true
+ }
+ return
+}
diff --git a/migrator/sharedgroup_test.go b/migrator/sharedgroup_test.go
new file mode 100644
index 000000000..bc7085b16
--- /dev/null
+++ b/migrator/sharedgroup_test.go
@@ -0,0 +1,48 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+package migrator
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestV1SharedGroupAsSharedGroup(t *testing.T) {
+ v1sg := &v1SharedGroup{
+ Id: "Test",
+ AccountParameters: map[string]*engine.SharingParameters{
+ "test": &engine.SharingParameters{Strategy: "*highest"},
+ },
+ MemberIds: []string{"1", "2", "3"},
+ }
+ sg := &engine.SharedGroup{
+ Id: "Test",
+ AccountParameters: map[string]*engine.SharingParameters{
+ "test": &engine.SharingParameters{Strategy: "*highest"},
+ },
+ MemberIds: utils.NewStringMap("1", "2", "3"),
+ }
+ newsg := v1sg.AsSharedGroup()
+ if !reflect.DeepEqual(*sg, newsg) {
+ t.Errorf("Expecting: %+v, received: %+v", *sg, newsg)
+ }
+
+}