Fixed the config for loaders

This commit is contained in:
Trial97
2021-11-24 19:32:27 +02:00
committed by Dan Christian Bogos
parent fd5cf12eac
commit 6a3c682f42
32 changed files with 585 additions and 784 deletions

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package utils
import (
"fmt"
"sort"
"strings"
"time"
@@ -667,11 +668,17 @@ func (ap *Account) Set(path []string, val interface{}, newBranch bool, _ string)
case ID:
ap.ID = IfaceAsString(val)
case FilterIDs:
ap.FilterIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
ap.FilterIDs = append(ap.FilterIDs, valA...)
case ThresholdIDs:
ap.ThresholdIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
ap.ThresholdIDs = append(ap.ThresholdIDs, valA...)
case Weights:
ap.Weights, err = NewDynamicWeightsFromString(IfaceAsString(val), InfieldSep, ANDSep)
case Opts:
ap.Opts, err = NewMapFromCSV(IfaceAsString(val))
}
return
default:
@@ -684,14 +691,14 @@ func (ap *Account) Set(path []string, val interface{}, newBranch bool, _ string)
return MapStorage(ap.Opts).Set(path[1:], val)
}
var id string
if strings.HasPrefix(path[0], Balances) &&
path[0][8] == '[' && path[0][len(path[0])-1] == ']' {
id = path[0][9 : len(path[0])-1]
} else if path[0] == Balances {
if path[0] == Balances {
id = path[1]
path = path[1:]
} else if strings.HasPrefix(path[0], Balances) &&
path[0][8] == '[' && path[0][len(path[0])-1] == ']' {
id = path[0][9 : len(path[0])-1]
}
if id == EmptyString {
if id != EmptyString {
if _, has := ap.Balances[id]; !has {
ap.Balances[id] = &Balance{ID: path[0], Opts: make(map[string]interface{}), Units: NewDecimal(0, 0)}
}
@@ -718,17 +725,70 @@ func (bL *Balance) Set(path []string, val interface{}, newBranch bool) (err erro
case Type:
bL.Type = IfaceAsString(val)
case FilterIDs:
bL.FilterIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
bL.FilterIDs = append(bL.FilterIDs, valA...)
case AttributeIDs:
bL.AttributeIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
bL.AttributeIDs = append(bL.AttributeIDs, valA...)
case RateProfileIDs:
bL.RateProfileIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
bL.RateProfileIDs = append(bL.RateProfileIDs, valA...)
case Units:
var valB *decimal.Big
valB, err = IfaceAsBig(val)
bL.Units = &Decimal{valB}
case Weights:
bL.Weights, err = NewDynamicWeightsFromString(IfaceAsString(val), InfieldSep, ANDSep)
case UnitFactors:
sls := strings.Split(IfaceAsString(val), InfieldSep)
if len(sls)%2 != 0 {
return fmt.Errorf("invalid key: <%s> for BalanceUnitFactors", IfaceAsString(val))
}
for j := 0; j < len(sls); j += 2 {
uf := new(UnitFactor)
if len(sls[j]) != 0 {
uf.FilterIDs = strings.Split(sls[j], ANDSep)
}
var valB *decimal.Big
if valB, err = IfaceAsBig(sls[j+1]); err != nil {
return
}
uf.Factor = &Decimal{valB}
bL.UnitFactors = append(bL.UnitFactors, uf)
}
case CostIncrements:
sls := strings.Split(IfaceAsString(val), InfieldSep)
if len(sls)%4 != 0 {
return fmt.Errorf("invalid key: <%s> for BalanceCostIncrements", IfaceAsString(val))
}
for j := 0; j < len(sls); j += 4 {
cI := new(CostIncrement)
if len(sls[j]) != 0 {
cI.FilterIDs = strings.Split(sls[j], ANDSep)
}
if len(sls[j+1]) != 0 {
if cI.Increment, err = NewDecimalFromString(sls[j+1]); err != nil {
return
}
}
if len(sls[j+2]) != 0 {
if cI.FixedFee, err = NewDecimalFromString(sls[j+2]); err != nil {
return
}
}
if len(sls[j+3]) != 0 {
if cI.RecurrentFee, err = NewDecimalFromString(sls[j+3]); err != nil {
return
}
}
bL.CostIncrements = append(bL.CostIncrements, cI)
}
case Opts:
bL.Opts, err = NewMapFromCSV(IfaceAsString(val))
}
return
case 2:
@@ -743,35 +803,47 @@ func (bL *Balance) Set(path []string, val interface{}, newBranch bool) (err erro
default:
return ErrWrongPath
case FilterIDs:
uf.FilterIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
uf.FilterIDs = append(uf.FilterIDs, valA...)
case Factor:
var valB *decimal.Big
valB, err = IfaceAsBig(val)
uf.Factor = &Decimal{valB}
if val != EmptyString {
var valB *decimal.Big
valB, err = IfaceAsBig(val)
uf.Factor = &Decimal{valB}
}
}
return
case CostIncrements:
if len(bL.CostIncrements) == 0 || newBranch {
bL.CostIncrements = append(bL.CostIncrements, new(CostIncrement))
bL.CostIncrements = append(bL.CostIncrements, &CostIncrement{FixedFee: NewDecimal(0, 0)})
}
cI := bL.CostIncrements[len(bL.CostIncrements)-1]
switch path[1] {
default:
return ErrWrongPath
case FilterIDs:
cI.FilterIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
cI.FilterIDs = append(cI.FilterIDs, valA...)
case Increment:
var valB *decimal.Big
valB, err = IfaceAsBig(val)
cI.Increment = &Decimal{valB}
if val != EmptyString {
var valB *decimal.Big
valB, err = IfaceAsBig(val)
cI.Increment = &Decimal{valB}
}
case FixedFee:
var valB *decimal.Big
valB, err = IfaceAsBig(val)
cI.FixedFee = &Decimal{valB}
if val != EmptyString {
var valB *decimal.Big
valB, err = IfaceAsBig(val)
cI.FixedFee = &Decimal{valB}
}
case RecurrentFee:
var valB *decimal.Big
valB, err = IfaceAsBig(val)
cI.RecurrentFee = &Decimal{valB}
if val != EmptyString {
var valB *decimal.Big
valB, err = IfaceAsBig(val)
cI.RecurrentFee = &Decimal{valB}
}
}
return
}

View File

@@ -1033,19 +1033,19 @@ type TPBalanceCostIncrement struct {
func (costIncr *TPBalanceCostIncrement) AsString() (s string) {
if len(costIncr.FilterIDs) != 0 {
s = s + strings.Join(costIncr.FilterIDs, ANDSep)
s += strings.Join(costIncr.FilterIDs, ANDSep)
}
s = s + InfieldSep
s += InfieldSep
if costIncr.Increment != EmptyString {
s = s + costIncr.Increment
s += costIncr.Increment
}
s = s + InfieldSep
s += InfieldSep
if costIncr.FixedFee != nil {
s = s + strconv.FormatFloat(*costIncr.FixedFee, 'f', -1, 64)
s += strconv.FormatFloat(*costIncr.FixedFee, 'f', -1, 64)
}
s = s + InfieldSep
s += InfieldSep
if costIncr.RecurrentFee != nil {
s = s + strconv.FormatFloat(*costIncr.RecurrentFee, 'f', -1, 64)
s += strconv.FormatFloat(*costIncr.RecurrentFee, 'f', -1, 64)
}
return
}
@@ -1054,9 +1054,7 @@ func NewTPBalanceUnitFactor(filtersStr, factorStr string) (unitFactor *TPBalance
unitFactor = &TPBalanceUnitFactor{
FilterIDs: strings.Split(filtersStr, ANDSep),
}
if unitFactor.Factor, err = strconv.ParseFloat(factorStr, 64); err != nil {
return
}
unitFactor.Factor, err = strconv.ParseFloat(factorStr, 64)
return
}
@@ -1065,10 +1063,6 @@ type TPBalanceUnitFactor struct {
Factor float64
}
func (unitFactor *TPBalanceUnitFactor) AsString() (s string) {
if len(unitFactor.FilterIDs) != 0 {
s = s + strings.Join(unitFactor.FilterIDs, ANDSep)
}
s = s + InfieldSep + strconv.FormatFloat(unitFactor.Factor, 'f', -1, 64)
return
func (unitFactor *TPBalanceUnitFactor) AsString() string {
return strings.Join(unitFactor.FilterIDs, ANDSep) + InfieldSep + strconv.FormatFloat(unitFactor.Factor, 'f', -1, 64)
}

View File

@@ -26,14 +26,16 @@ import (
// NewDynamicWeightsFromString creates a DynamicWeight list based on the string received from .csv/StorDB
func NewDynamicWeightsFromString(s, dWSep, fltrSep string) (dWs DynamicWeights, err error) {
nrFlds := 2
if len(s) == 0 {
return DynamicWeights{{}}, nil
}
dwStrs := strings.Split(s, dWSep)
lnDwStrs := len(dwStrs)
if lnDwStrs%nrFlds != 0 { // need to have multiples of number of fields in one DynamicWeight
if lnDwStrs%2 != 0 { // need to have multiples of number of fields in one DynamicWeight
return nil, fmt.Errorf("invalid DynamicWeight format for string <%s>", s)
}
dWs = make([]*DynamicWeight, 0, lnDwStrs/nrFlds)
for i := 0; i < lnDwStrs; i += nrFlds {
dWs = make([]*DynamicWeight, 0, lnDwStrs/2)
for i := 0; i < lnDwStrs; i += 2 {
var fltrIDs []string
if len(dwStrs[i]) != 0 {
fltrIDs = strings.Split(dwStrs[i], fltrSep)

View File

@@ -573,12 +573,12 @@ func (rp *RateProfile) Set(path []string, val interface{}, newBranch bool, _ str
return ErrWrongPath
}
var rtID string
if strings.HasPrefix(path[0], Rates) &&
path[0][5] == '[' && path[0][len(path[0])-1] == ']' {
rtID = path[0][6 : len(path[0])-1]
} else if len(path) != 1 && path[0] == Rates {
if len(path) != 1 && path[0] == Rates {
rtID = path[1]
path = path[1:]
} else if strings.HasPrefix(path[0], Rates) &&
path[0][5] == '[' && path[0][len(path[0])-1] == ']' {
rtID = path[0][6 : len(path[0])-1]
}
if rtID != EmptyString {
if _, has := rp.Rates[rtID]; !has {
@@ -599,17 +599,23 @@ func (rp *RateProfile) Set(path []string, val interface{}, newBranch bool, _ str
case ID:
rp.ID = IfaceAsString(val)
case FilterIDs:
rp.FilterIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
rp.FilterIDs = append(rp.FilterIDs, valA...)
case Weights:
rp.Weights, err = NewDynamicWeightsFromString(IfaceAsString(val), InfieldSep, ANDSep)
case MinCost:
var valB *decimal.Big
valB, err = IfaceAsBig(val)
rp.MinCost = &Decimal{valB}
if val != EmptyString {
var valB *decimal.Big
valB, err = IfaceAsBig(val)
rp.MinCost = &Decimal{valB}
}
case MaxCost:
var valB *decimal.Big
valB, err = IfaceAsBig(val)
rp.MaxCost = &Decimal{valB}
if val != EmptyString {
var valB *decimal.Big
valB, err = IfaceAsBig(val)
rp.MaxCost = &Decimal{valB}
}
case MaxCostStrategy:
rp.MaxCostStrategy = IfaceAsString(val)
}
@@ -628,7 +634,9 @@ func (rt *Rate) Set(path []string, val interface{}, newBranch bool) (err error)
case ID:
rt.ID = IfaceAsString(val)
case FilterIDs:
rt.FilterIDs, err = IfaceAsStringSlice(val)
var valA []string
valA, err = IfaceAsStringSlice(val)
rt.FilterIDs = append(rt.FilterIDs, valA...)
case Weights:
rt.Weights, err = NewDynamicWeightsFromString(IfaceAsString(val), InfieldSep, ANDSep)
case ActivationTimes:

View File

@@ -36,6 +36,21 @@ type DataStorage interface {
GetKeys(nested bool, nesteedLimit int, prefix string) []string
}
func NewMapFromCSV(str string) (MapStorage, error) {
m := make(MapStorage)
if len(str) == 0 {
return nil, nil
}
for _, opt := range InfieldSplit(str) {
keyVal := strings.SplitN(opt, ConcatenatedKeySep, 2)
if len(keyVal) != 2 {
return nil, fmt.Errorf("malformed map pair: <%q>", opt)
}
m[keyVal[0]] = keyVal[1]
}
return m, nil
}
// MapStorage is the basic dataStorage
type MapStorage map[string]interface{}

View File

@@ -73,6 +73,9 @@ func IfaceAsTime(itm interface{}, timezone string) (t time.Time, err error) {
}
func StringAsBig(itm string) (b *decimal.Big, err error) {
if len(itm) == 0 {
return decimal.New(0, 0), nil
}
if strings.HasSuffix(itm, NsSuffix) ||
strings.HasSuffix(itm, UsSuffix) ||
strings.HasSuffix(itm, µSuffix) ||
@@ -242,6 +245,9 @@ func IfaceAsBool(itm interface{}) (b bool, err error) {
case bool:
return v, nil
case string:
if len(v) == 0 {
return
}
return strconv.ParseBool(v)
case int:
return v > 0, nil
@@ -749,7 +755,9 @@ func IfaceAsStringSlice(fld interface{}) (ss []string, err error) {
ss[i] = IfaceAsString(v)
}
case string:
ss = strings.Split(value, InfieldSep)
if value != EmptyString {
ss = strings.Split(value, InfieldSep)
}
default: // Maybe we are lucky and the value converts to string
err = fmt.Errorf("cannot convert field: %+v to []string", value)
}