mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-22 07:38:45 +05:00
Update Suppliers stategy
This commit is contained in:
committed by
Dan Christian Bogos
parent
55bcc28169
commit
909358a124
@@ -58,6 +58,7 @@ var sTestsSupplierSV1 = []func(t *testing.T){
|
||||
testV1SplSGetQOSSuppliers,
|
||||
testV1SplSGetQOSSuppliers2,
|
||||
testV1SplSGetQOSSuppliers3,
|
||||
testV1SplSGetQOSSuppliersFiltred,
|
||||
testV1SplSGetSupplierWithoutFilter,
|
||||
testV1SplSSetSupplierProfiles,
|
||||
testV1SplSUpdateSupplierProfiles,
|
||||
@@ -673,6 +674,53 @@ func testV1SplSGetQOSSuppliers3(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplSGetQOSSuppliersFiltred(t *testing.T) {
|
||||
ev := &engine.ArgsGetSuppliers{
|
||||
CGREvent: utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "testV1SplSGetQOSSuppliers",
|
||||
Event: map[string]interface{}{
|
||||
"DistincMatch": "*qos_filtred",
|
||||
},
|
||||
},
|
||||
}
|
||||
eSpls := engine.SortedSuppliers{
|
||||
ProfileID: "SPL_QOS_FILTRED",
|
||||
Sorting: utils.MetaQOS,
|
||||
SortedSuppliers: []*engine.SortedSupplier{
|
||||
&engine.SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
"*acd:Stat_1": 11.0,
|
||||
"*acd:Stat_1_1": 11.0,
|
||||
"*asr:Stat_1": 100.0,
|
||||
"*pdd:Stat_1_1": 12.0,
|
||||
"*tcd:Stat_1": 22.0,
|
||||
"*tcd:Stat_1_1": 11.0,
|
||||
utils.Weight: 10.0,
|
||||
},
|
||||
},
|
||||
&engine.SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
"*acd:Stat_3": 11.0,
|
||||
"*asr:Stat_3": 100.0,
|
||||
"*tcd:Stat_3": 11.0,
|
||||
utils.Weight: 35.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var suplsReply engine.SortedSuppliers
|
||||
if err := splSv1Rpc.Call(utils.SupplierSv1GetSuppliers,
|
||||
ev, &suplsReply); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eSpls, suplsReply) {
|
||||
t.Errorf("Expecting: %s, received: %s",
|
||||
utils.ToJSON(eSpls), utils.ToJSON(suplsReply))
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplSGetSupplierWithoutFilter(t *testing.T) {
|
||||
ev := &engine.ArgsGetSuppliers{
|
||||
CGREvent: utils.CGREvent{
|
||||
|
||||
@@ -6,6 +6,7 @@ cgrates.org,FLTR_1,*prefix,Destination,10;20,
|
||||
cgrates.org,FLTR_1,*rsr,,Subject(~^1.*1$);Destination(1002),
|
||||
cgrates.org,FLTR_ACNT_1007,*string,Account,1007,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_ACNT_dan,*string,Account,dan,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_SPP_ACNT_dan,*string,*req.Account,dan,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_SPP_2,*string,Account,1003;1002,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_SPP_2,*prefix,Destination,10;20,
|
||||
cgrates.org,FLTR_SPP_2,*rsr,,Subject(~^1.*1$);Destination(1002),
|
||||
@@ -16,4 +17,8 @@ cgrates.org,FLTR_STAT_2,*string,Account,1002,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_STAT_3,*string,Account,1003,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_SPP_4,*string,DistincMatch,*qos2,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_SPP_5,*string,DistincMatch,*qos3,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_STAT_1_1,*string,Stat,Stat1_1,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_STAT_1_1,*string,Stat,Stat1_1,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_SPP_6,*string,DistincMatch,*qos_filtred,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_QOS_SP1,*gte,*gs.*acd,10.0,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_QOS_SP2,*gte,*gs.*acd,10.0,2014-07-29T15:00:00Z
|
||||
cgrates.org,FLTR_QOS_SP2,*gte,*gs.*tcd,11.0,
|
||||
|
@@ -4,7 +4,7 @@ cgrates.org,SPL_ACNT_1001,,,,,supplier2,,,,,,10,,,
|
||||
cgrates.org,SPL_WEIGHT_2,,2017-11-27T00:00:00Z,*weight,,supplier1,,,,,,10,,,5
|
||||
cgrates.org,SPL_WEIGHT_1,FLTR_DST_DE;FLTR_ACNT_1007,2017-11-27T00:00:00Z,*weight,,supplier1,,,,,,10,,,10
|
||||
cgrates.org,SPL_WEIGHT_1,FLTR_DST_DE,,,,supplier2,,,,,,20,,,
|
||||
cgrates.org,SPL_WEIGHT_1,FLTR_ACNT_1007,,,,supplier3,FLTR_ACNT_dan,,,,,15,,,
|
||||
cgrates.org,SPL_WEIGHT_1,FLTR_ACNT_1007,,,,supplier3,FLTR_SPP_ACNT_dan,,,,,15,,,
|
||||
cgrates.org,SPL_LEASTCOST_1,FLTR_1,2017-11-27T00:00:00Z,*least_cost,,supplier1,,,RP_SPECIAL_1002,,,10,false,,10
|
||||
cgrates.org,SPL_LEASTCOST_1,,,,,supplier2,,,RP_RETAIL1,,,20,,,
|
||||
cgrates.org,SPL_LEASTCOST_1,,,,,supplier3,,,RP_SPECIAL_1002,,,15,,,
|
||||
@@ -20,3 +20,6 @@ cgrates.org,SPL_QOS_2,,,,,supplier3,,,,,Stat_3,35,,,
|
||||
cgrates.org,SPL_QOS_3,FLTR_SPP_5,2017-11-27T00:00:00Z,*qos,*pdd,supplier1,,,,,Stat_1;Stat_1_1,10,false,,10
|
||||
cgrates.org,SPL_QOS_3,,,,,supplier2,,,,,Stat_2,20,,,
|
||||
cgrates.org,SPL_QOS_3,,,,,supplier3,,,,,Stat_3,35,,,
|
||||
cgrates.org,SPL_QOS_FILTRED,FLTR_SPP_6,2017-11-27T00:00:00Z,*qos,*pdd,supplier1,FLTR_QOS_SP1,,,,Stat_1;Stat_1_1,10,false,,10
|
||||
cgrates.org,SPL_QOS_FILTRED,,,,,supplier2,FLTR_QOS_SP2,,,,Stat_2,20,,,
|
||||
cgrates.org,SPL_QOS_FILTRED,,,,,supplier3,,,,,Stat_3,35,,,
|
||||
|
||||
|
@@ -31,7 +31,7 @@ type SortedSupplier struct {
|
||||
SupplierID string
|
||||
SupplierParameters string
|
||||
SortingData map[string]interface{} // store here extra info like cost or stats
|
||||
worstStats map[string]float64
|
||||
globalStats map[string]float64
|
||||
}
|
||||
|
||||
// SuppliersReply is returned as part of GetSuppliers call
|
||||
@@ -97,21 +97,21 @@ func (sSpls *SortedSuppliers) SortQOS(params []string) {
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
for _, param := range params {
|
||||
// skip to next param
|
||||
if sSpls.SortedSuppliers[i].worstStats[param] == sSpls.SortedSuppliers[j].worstStats[param] {
|
||||
if sSpls.SortedSuppliers[i].globalStats[param] == sSpls.SortedSuppliers[j].globalStats[param] {
|
||||
continue
|
||||
}
|
||||
if (param != utils.MetaPDD && sSpls.SortedSuppliers[i].worstStats[param] == -1) ||
|
||||
(param == utils.MetaPDD && sSpls.SortedSuppliers[i].worstStats[param] == 1000000) {
|
||||
if (param != utils.MetaPDD && sSpls.SortedSuppliers[i].globalStats[param] == -1) ||
|
||||
(param == utils.MetaPDD && sSpls.SortedSuppliers[i].globalStats[param] == 1000000) {
|
||||
return false
|
||||
}
|
||||
switch param {
|
||||
default:
|
||||
return sSpls.SortedSuppliers[i].worstStats[param] > sSpls.SortedSuppliers[j].worstStats[param]
|
||||
return sSpls.SortedSuppliers[i].globalStats[param] > sSpls.SortedSuppliers[j].globalStats[param]
|
||||
case utils.MetaPDD:
|
||||
return sSpls.SortedSuppliers[i].worstStats[param] < sSpls.SortedSuppliers[j].worstStats[param]
|
||||
return sSpls.SortedSuppliers[i].globalStats[param] < sSpls.SortedSuppliers[j].globalStats[param]
|
||||
}
|
||||
}
|
||||
return sSpls.SortedSuppliers[i].worstStats[utils.Weight] > sSpls.SortedSuppliers[j].worstStats[utils.Weight]
|
||||
return sSpls.SortedSuppliers[i].globalStats[utils.Weight] > sSpls.SortedSuppliers[j].globalStats[utils.Weight]
|
||||
})
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ type SuppliersSorter interface {
|
||||
// NewSupplierSortDispatcher constructs SupplierSortDispatcher
|
||||
func NewSupplierSortDispatcher(lcrS *SupplierService) (ssd SupplierSortDispatcher, err error) {
|
||||
ssd = make(map[string]SuppliersSorter)
|
||||
ssd[utils.MetaWeight] = NewWeightSorter()
|
||||
ssd[utils.MetaWeight] = NewWeightSorter(lcrS)
|
||||
ssd[utils.MetaLeastCost] = NewLeastCostSorter(lcrS)
|
||||
ssd[utils.MetaHighestCost] = NewHighestCostSorter(lcrS)
|
||||
ssd[utils.MetaQOS] = NewQOSSupplierSorter(lcrS)
|
||||
@@ -153,27 +153,3 @@ func (ssd SupplierSortDispatcher) SortSuppliers(prflID, strategy string,
|
||||
}
|
||||
return sd.SortSuppliers(prflID, suppls, suplEv, extraOpts)
|
||||
}
|
||||
|
||||
func NewWeightSorter() *WeightSorter {
|
||||
return &WeightSorter{sorting: utils.MetaWeight}
|
||||
}
|
||||
|
||||
// WeightSorter orders suppliers based on their weight, no cost involved
|
||||
type WeightSorter struct {
|
||||
sorting string
|
||||
}
|
||||
|
||||
func (ws *WeightSorter) SortSuppliers(prflID string,
|
||||
suppls []*Supplier, suplEv *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
sortedSuppls = &SortedSuppliers{ProfileID: prflID,
|
||||
Sorting: ws.sorting,
|
||||
SortedSuppliers: make([]*SortedSupplier, len(suppls))}
|
||||
for i, s := range suppls {
|
||||
sortedSuppls.SortedSuppliers[i] = &SortedSupplier{
|
||||
SupplierID: s.ID,
|
||||
SortingData: map[string]interface{}{utils.Weight: s.Weight},
|
||||
SupplierParameters: s.SupplierParameters}
|
||||
}
|
||||
sortedSuppls.SortWeight()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -89,64 +89,60 @@ func TestLibSuppliersSortCost(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLibSuppliersSortWeight(t *testing.T) {
|
||||
spl := []*Supplier{
|
||||
&Supplier{
|
||||
ID: "supplier1",
|
||||
FilterIDs: []string{},
|
||||
AccountIDs: []string{},
|
||||
RatingPlanIDs: []string{},
|
||||
ResourceIDs: []string{},
|
||||
StatIDs: []string{},
|
||||
Weight: 10.0,
|
||||
SupplierParameters: "param1",
|
||||
},
|
||||
&Supplier{
|
||||
ID: "supplier2",
|
||||
FilterIDs: []string{},
|
||||
AccountIDs: []string{},
|
||||
RatingPlanIDs: []string{},
|
||||
ResourceIDs: []string{},
|
||||
StatIDs: []string{},
|
||||
Weight: 20.0,
|
||||
SupplierParameters: "param2",
|
||||
},
|
||||
}
|
||||
eSpls := SortedSuppliers{
|
||||
ProfileID: "SPL_WEIGHT_1",
|
||||
Sorting: utils.MetaWeight,
|
||||
sSpls := &SortedSuppliers{
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 10.0,
|
||||
},
|
||||
SupplierParameters: "param1",
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
"Weight": 20.0,
|
||||
utils.Weight: 20.0,
|
||||
},
|
||||
SupplierParameters: "param2",
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 10.5,
|
||||
},
|
||||
SupplierParameters: "param3",
|
||||
},
|
||||
},
|
||||
}
|
||||
sSpls.SortWeight()
|
||||
eOrderedSpls := &SortedSuppliers{
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 20.0,
|
||||
},
|
||||
SupplierParameters: "param2",
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: 10.5,
|
||||
},
|
||||
SupplierParameters: "param3",
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
SortingData: map[string]interface{}{
|
||||
"Weight": 10.0,
|
||||
utils.Weight: 10.0,
|
||||
},
|
||||
SupplierParameters: "param1",
|
||||
},
|
||||
},
|
||||
}
|
||||
se := &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "supplierevent1",
|
||||
Event: make(map[string]interface{}),
|
||||
}
|
||||
ws := NewWeightSorter()
|
||||
result, err := ws.SortSuppliers("SPL_WEIGHT_1", spl, se, nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !reflect.DeepEqual(eSpls.ProfileID, result.ProfileID) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eSpls.ProfileID, result.ProfileID)
|
||||
} else if !reflect.DeepEqual(eSpls.SortedSuppliers, result.SortedSuppliers) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eSpls.SortedSuppliers, result.SortedSuppliers)
|
||||
} else if !reflect.DeepEqual(eSpls.Sorting, result.Sorting) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eSpls.Sorting, result.Sorting)
|
||||
if !reflect.DeepEqual(eOrderedSpls, sSpls) {
|
||||
t.Errorf("Expecting: %s, received: %s",
|
||||
utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +284,7 @@ func TestLibSuppliersSortQOS(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 15.0,
|
||||
},
|
||||
@@ -296,7 +292,7 @@ func TestLibSuppliersSortQOS(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
},
|
||||
@@ -304,7 +300,7 @@ func TestLibSuppliersSortQOS(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.05,
|
||||
utils.MetaTCD: 10.0,
|
||||
},
|
||||
@@ -317,7 +313,7 @@ func TestLibSuppliersSortQOS(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
},
|
||||
@@ -325,7 +321,7 @@ func TestLibSuppliersSortQOS(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 15.0,
|
||||
},
|
||||
@@ -333,7 +329,7 @@ func TestLibSuppliersSortQOS(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.05,
|
||||
utils.MetaTCD: 10.0,
|
||||
},
|
||||
@@ -352,7 +348,7 @@ func TestLibSuppliersSortQOS2(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 15.0,
|
||||
},
|
||||
@@ -360,7 +356,7 @@ func TestLibSuppliersSortQOS2(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
},
|
||||
@@ -368,7 +364,7 @@ func TestLibSuppliersSortQOS2(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 10.0,
|
||||
},
|
||||
@@ -381,7 +377,7 @@ func TestLibSuppliersSortQOS2(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
},
|
||||
@@ -389,7 +385,7 @@ func TestLibSuppliersSortQOS2(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 15.0,
|
||||
},
|
||||
@@ -397,7 +393,7 @@ func TestLibSuppliersSortQOS2(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 10.0,
|
||||
},
|
||||
@@ -416,7 +412,7 @@ func TestLibSuppliersSortQOS3(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 15.0,
|
||||
utils.MetaASR: 1.2,
|
||||
@@ -425,7 +421,7 @@ func TestLibSuppliersSortQOS3(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
utils.MetaASR: -1.0,
|
||||
@@ -434,7 +430,7 @@ func TestLibSuppliersSortQOS3(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 10.0,
|
||||
utils.MetaASR: 1.2,
|
||||
@@ -448,7 +444,7 @@ func TestLibSuppliersSortQOS3(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 15.0,
|
||||
utils.MetaASR: 1.2,
|
||||
@@ -457,7 +453,7 @@ func TestLibSuppliersSortQOS3(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 10.0,
|
||||
utils.MetaASR: 1.2,
|
||||
@@ -466,7 +462,7 @@ func TestLibSuppliersSortQOS3(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
utils.MetaASR: -1.0,
|
||||
@@ -486,7 +482,7 @@ func TestLibSuppliersSortQOS4(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 15.0,
|
||||
utils.MetaASR: -1.0,
|
||||
@@ -496,7 +492,7 @@ func TestLibSuppliersSortQOS4(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
utils.MetaASR: 1.2,
|
||||
@@ -506,7 +502,7 @@ func TestLibSuppliersSortQOS4(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 10.0,
|
||||
utils.MetaASR: 1.2,
|
||||
@@ -521,7 +517,7 @@ func TestLibSuppliersSortQOS4(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 20.0,
|
||||
utils.MetaASR: 1.2,
|
||||
@@ -531,7 +527,7 @@ func TestLibSuppliersSortQOS4(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaTCD: 10.0,
|
||||
utils.MetaASR: 1.2,
|
||||
@@ -541,7 +537,7 @@ func TestLibSuppliersSortQOS4(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaTCD: 15.0,
|
||||
utils.MetaASR: -1.0,
|
||||
@@ -562,7 +558,7 @@ func TestLibSuppliersSortQOS5(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaPDD: 0.5,
|
||||
},
|
||||
@@ -570,7 +566,7 @@ func TestLibSuppliersSortQOS5(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaPDD: 0.6,
|
||||
},
|
||||
@@ -578,7 +574,7 @@ func TestLibSuppliersSortQOS5(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaPDD: 0.2,
|
||||
},
|
||||
@@ -591,7 +587,7 @@ func TestLibSuppliersSortQOS5(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.MetaPDD: 0.2,
|
||||
},
|
||||
@@ -599,7 +595,7 @@ func TestLibSuppliersSortQOS5(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaPDD: 0.5,
|
||||
},
|
||||
@@ -607,7 +603,7 @@ func TestLibSuppliersSortQOS5(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.MetaPDD: 0.6,
|
||||
},
|
||||
@@ -626,7 +622,7 @@ func TestLibSuppliersSortQOS6(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.Weight: 15.0,
|
||||
},
|
||||
@@ -634,7 +630,7 @@ func TestLibSuppliersSortQOS6(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.Weight: 25.0,
|
||||
},
|
||||
@@ -642,7 +638,7 @@ func TestLibSuppliersSortQOS6(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.Weight: 20.0,
|
||||
},
|
||||
@@ -655,7 +651,7 @@ func TestLibSuppliersSortQOS6(t *testing.T) {
|
||||
SortedSuppliers: []*SortedSupplier{
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier2",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.Weight: 25.0,
|
||||
},
|
||||
@@ -663,7 +659,7 @@ func TestLibSuppliersSortQOS6(t *testing.T) {
|
||||
},
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier1",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.2,
|
||||
utils.Weight: 15.0,
|
||||
},
|
||||
@@ -672,7 +668,7 @@ func TestLibSuppliersSortQOS6(t *testing.T) {
|
||||
|
||||
&SortedSupplier{
|
||||
SupplierID: "supplier3",
|
||||
worstStats: map[string]float64{
|
||||
globalStats: map[string]float64{
|
||||
utils.MetaACD: 0.1,
|
||||
utils.Weight: 20.0,
|
||||
},
|
||||
|
||||
@@ -19,8 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -35,42 +33,17 @@ type HightCostSorter struct {
|
||||
spS *SupplierService
|
||||
}
|
||||
|
||||
func (lcs *HightCostSorter) SortSuppliers(prflID string, suppls []*Supplier,
|
||||
func (hcs *HightCostSorter) SortSuppliers(prflID string, suppls []*Supplier,
|
||||
ev *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
sortedSuppls = &SortedSuppliers{ProfileID: prflID,
|
||||
Sorting: lcs.sorting,
|
||||
Sorting: hcs.sorting,
|
||||
SortedSuppliers: make([]*SortedSupplier, 0)}
|
||||
for _, s := range suppls {
|
||||
costData, err := lcs.spS.costForEvent(ev, s.AccountIDs, s.RatingPlanIDs)
|
||||
if err != nil {
|
||||
if extraOpts.ignoreErrors {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> profile: %s ignoring supplier with ID: %s, err: %s",
|
||||
utils.SupplierS, prflID, s.ID, err.Error()))
|
||||
continue
|
||||
}
|
||||
if srtSpl, pass, err := hcs.spS.populateSortingData(ev, s, extraOpts); err != nil {
|
||||
return nil, err
|
||||
} else if len(costData) == 0 {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> profile: %s ignoring supplier with ID: %s, missing cost information",
|
||||
utils.SupplierS, prflID, s.ID))
|
||||
continue
|
||||
} else if pass && srtSpl != nil {
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl)
|
||||
}
|
||||
if extraOpts.maxCost != 0 &&
|
||||
costData[utils.Cost].(float64) > extraOpts.maxCost {
|
||||
continue
|
||||
}
|
||||
srtData := map[string]interface{}{
|
||||
utils.Weight: s.Weight,
|
||||
}
|
||||
for k, v := range costData {
|
||||
srtData[k] = v
|
||||
}
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers,
|
||||
&SortedSupplier{
|
||||
SupplierID: s.ID,
|
||||
SortingData: srtData,
|
||||
SupplierParameters: s.SupplierParameters})
|
||||
}
|
||||
if len(sortedSuppls.SortedSuppliers) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
|
||||
@@ -19,8 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -41,36 +39,11 @@ func (lcs *LeastCostSorter) SortSuppliers(prflID string, suppls []*Supplier,
|
||||
Sorting: lcs.sorting,
|
||||
SortedSuppliers: make([]*SortedSupplier, 0)}
|
||||
for _, s := range suppls {
|
||||
costData, err := lcs.spS.costForEvent(ev, s.AccountIDs, s.RatingPlanIDs)
|
||||
if err != nil {
|
||||
if extraOpts.ignoreErrors {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> profile: %s ignoring supplier with ID: %s, err: %s",
|
||||
utils.SupplierS, prflID, s.ID, err.Error()))
|
||||
continue
|
||||
}
|
||||
if srtSpl, pass, err := lcs.spS.populateSortingData(ev, s, extraOpts); err != nil {
|
||||
return nil, err
|
||||
} else if len(costData) == 0 {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> profile: %s ignoring supplier with ID: %s, missing cost information",
|
||||
utils.SupplierS, prflID, s.ID))
|
||||
continue
|
||||
} else if pass && srtSpl != nil {
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl)
|
||||
}
|
||||
if extraOpts.maxCost != 0 &&
|
||||
costData[utils.Cost].(float64) > extraOpts.maxCost {
|
||||
continue
|
||||
}
|
||||
srtData := map[string]interface{}{
|
||||
utils.Weight: s.Weight,
|
||||
}
|
||||
for k, v := range costData {
|
||||
srtData[k] = v
|
||||
}
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers,
|
||||
&SortedSupplier{
|
||||
SupplierID: s.ID,
|
||||
SortingData: srtData,
|
||||
SupplierParameters: s.SupplierParameters})
|
||||
}
|
||||
if len(sortedSuppls.SortedSuppliers) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
|
||||
@@ -19,9 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -36,62 +33,17 @@ type QOSSupplierSorter struct {
|
||||
spS *SupplierService
|
||||
}
|
||||
|
||||
func (lcs *QOSSupplierSorter) SortSuppliers(prflID string, suppls []*Supplier,
|
||||
func (qos *QOSSupplierSorter) SortSuppliers(prflID string, suppls []*Supplier,
|
||||
ev *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
sortedSuppls = &SortedSuppliers{ProfileID: prflID,
|
||||
Sorting: lcs.sorting,
|
||||
Sorting: qos.sorting,
|
||||
SortedSuppliers: make([]*SortedSupplier, 0)}
|
||||
for _, s := range suppls {
|
||||
metricSupp, err := lcs.spS.statMetrics(s.StatIDs, ev.Tenant) //create metric map for suppier s
|
||||
if err != nil {
|
||||
if extraOpts.ignoreErrors {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> profile: %s ignoring supplier with ID: %s, err: %s",
|
||||
utils.SupplierS, prflID, s.ID, err.Error()))
|
||||
continue
|
||||
}
|
||||
if srtSpl, pass, err := qos.spS.populateSortingData(ev, s, extraOpts); err != nil {
|
||||
return nil, err
|
||||
} else if pass && srtSpl != nil {
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl)
|
||||
}
|
||||
|
||||
srtData := map[string]float64{
|
||||
utils.Weight: s.Weight,
|
||||
}
|
||||
for _, metric := range extraOpts.sortingParameters {
|
||||
hasMetric := false //check if metricSupp have sortingParameter
|
||||
for keyWithID, value := range metricSupp { //transfer data from metric into srtData
|
||||
if metric == strings.Split(keyWithID, utils.InInFieldSep)[0] {
|
||||
if val, hasKey := srtData[metric]; !hasKey ||
|
||||
(metric == utils.MetaPDD && val < value) || //worst values
|
||||
(metric != utils.MetaPDD && val > value) {
|
||||
srtData[metric] = value
|
||||
hasMetric = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasMetric { //if not have populate with default value
|
||||
switch metric {
|
||||
default:
|
||||
srtData[metric] = -1
|
||||
case utils.MetaPDD:
|
||||
srtData[metric] = 1000000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortingData := map[string]interface{}{
|
||||
utils.Weight: s.Weight,
|
||||
}
|
||||
for k, v := range metricSupp {
|
||||
sortingData[k] = v
|
||||
}
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers,
|
||||
&SortedSupplier{
|
||||
SupplierID: s.ID,
|
||||
SortingData: sortingData,
|
||||
SupplierParameters: s.SupplierParameters,
|
||||
worstStats: srtData,
|
||||
},
|
||||
)
|
||||
}
|
||||
if len(sortedSuppls.SortedSuppliers) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
|
||||
50
engine/spls_weight.go
Executable file
50
engine/spls_weight.go
Executable file
@@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func NewWeightSorter(spS *SupplierService) *WeightSorter {
|
||||
return &WeightSorter{spS: spS,
|
||||
sorting: utils.MetaWeight}
|
||||
}
|
||||
|
||||
// WeightSorter orders suppliers based on their weight, no cost involved
|
||||
type WeightSorter struct {
|
||||
sorting string
|
||||
spS *SupplierService
|
||||
}
|
||||
|
||||
func (ws *WeightSorter) SortSuppliers(prflID string,
|
||||
suppls []*Supplier, suplEv *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
sortedSuppls = &SortedSuppliers{ProfileID: prflID,
|
||||
Sorting: ws.sorting,
|
||||
SortedSuppliers: make([]*SortedSupplier, 0)}
|
||||
for _, s := range suppls {
|
||||
if srtSpl, pass, err := ws.spS.populateSortingData(suplEv, s, extraOpts); err != nil {
|
||||
return nil, err
|
||||
} else if pass && srtSpl != nil {
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl)
|
||||
}
|
||||
}
|
||||
sortedSuppls.SortWeight()
|
||||
return
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
@@ -284,6 +285,100 @@ func (spS *SupplierService) resourceUsage(resIDs []string) (tUsage float64, err
|
||||
return
|
||||
}
|
||||
|
||||
func (spS *SupplierService) populateSortingData(ev *utils.CGREvent, spl *Supplier, extraOpts *optsGetSuppliers) (srtSpl *SortedSupplier, pass bool, err error) {
|
||||
globalStats := map[string]float64{ //used for QOS strategy
|
||||
utils.Weight: spl.Weight,
|
||||
}
|
||||
sortedSpl := &SortedSupplier{
|
||||
SupplierID: spl.ID,
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Weight: spl.Weight,
|
||||
},
|
||||
SupplierParameters: spl.SupplierParameters,
|
||||
}
|
||||
//calculate costData if we have fields
|
||||
if len(spl.AccountIDs) != 0 || len(spl.RatingPlanIDs) != 0 {
|
||||
costData, err := spS.costForEvent(ev, spl.AccountIDs, spl.RatingPlanIDs)
|
||||
if err != nil {
|
||||
if extraOpts.ignoreErrors {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> ignoring supplier with ID: %s, err: %s",
|
||||
utils.SupplierS, spl.ID, err.Error()))
|
||||
} else {
|
||||
return nil, false, err
|
||||
}
|
||||
} else if len(costData) == 0 {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> profile: %s ignoring supplier with ID: %s, missing cost information",
|
||||
utils.SupplierS, spl.ID))
|
||||
} else {
|
||||
if extraOpts.maxCost != 0 &&
|
||||
costData[utils.Cost].(float64) > extraOpts.maxCost {
|
||||
return nil, false, nil
|
||||
}
|
||||
for k, v := range costData {
|
||||
sortedSpl.SortingData[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
metricForFilter := map[string]interface{}{
|
||||
utils.Weight: spl.Weight,
|
||||
}
|
||||
//calculate metrics
|
||||
if len(spl.StatIDs) != 0 {
|
||||
metricSupp, err := spS.statMetrics(spl.StatIDs, ev.Tenant) //create metric map for suppier
|
||||
if err != nil {
|
||||
if extraOpts.ignoreErrors {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> ignoring supplier with ID: %s, err: %s",
|
||||
utils.SupplierS, spl.ID, err.Error()))
|
||||
} else {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
for _, metric := range extraOpts.sortingParameters {
|
||||
hasMetric := false //check if metricSupp have sortingParameter
|
||||
for keyWithID, value := range metricSupp { //transfer data from metric into globalStats
|
||||
if metric == strings.Split(keyWithID, utils.InInFieldSep)[0] {
|
||||
if val, hasKey := globalStats[metric]; !hasKey ||
|
||||
(metric == utils.MetaPDD && val < value) || //worst values
|
||||
(metric != utils.MetaPDD && val > value) {
|
||||
globalStats[metric] = value
|
||||
hasMetric = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasMetric { //if not have populate with default value
|
||||
switch metric {
|
||||
default:
|
||||
globalStats[metric] = -1
|
||||
case utils.MetaPDD:
|
||||
globalStats[metric] = 1000000
|
||||
}
|
||||
}
|
||||
}
|
||||
for k, v := range metricSupp {
|
||||
sortedSpl.SortingData[k] = v
|
||||
metricForFilter[strings.Split(k, utils.InInFieldSep)[0]] = v
|
||||
}
|
||||
sortedSpl.globalStats = globalStats
|
||||
}
|
||||
//filter the supplier
|
||||
if len(spl.FilterIDs) != 0 {
|
||||
nM := NewNavigableMap(nil)
|
||||
nM.Set([]string{"*req"}, ev.Event, false)
|
||||
nM.Set([]string{"*sd"}, sortedSpl.SortingData, false)
|
||||
nM.Set([]string{"*gs"}, metricForFilter, false)
|
||||
if pass, err = spS.filterS.Pass(ev.Tenant, spl.FilterIDs,
|
||||
nM); err != nil {
|
||||
return nil, false, err
|
||||
} else if !pass {
|
||||
return nil, false, nil
|
||||
}
|
||||
}
|
||||
return sortedSpl, true, nil
|
||||
}
|
||||
|
||||
// supliersForEvent will return the list of valid supplier IDs
|
||||
// for event based on filters and sorting algorithms
|
||||
func (spS *SupplierService) sortedSuppliersForEvent(args *ArgsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
@@ -296,40 +391,36 @@ func (spS *SupplierService) sortedSuppliersForEvent(args *ArgsGetSuppliers) (sor
|
||||
} else if len(suppPrfls) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
splPrfl := suppPrfls[0] // pick up the first lcr profile as winner
|
||||
var spls []*Supplier
|
||||
for _, s := range splPrfl.Suppliers {
|
||||
if len(s.FilterIDs) != 0 { // filters should be applied, check them here
|
||||
if pass, err := spS.filterS.Pass(args.Tenant, s.FilterIDs,
|
||||
NewNavigableMap(args.Event)); err != nil {
|
||||
return nil, err
|
||||
} else if !pass {
|
||||
continue
|
||||
}
|
||||
}
|
||||
spls = append(spls, s)
|
||||
}
|
||||
splPrfl := suppPrfls[0] // pick up the first lcr profile as winner
|
||||
extraOpts, err := args.asOptsGetSuppliers() // convert suppliers arguments into internal options used to limit data
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extraOpts.sortingParameters = splPrfl.SortingParameters // populate sortingParameters in extraOpts
|
||||
sortedSuppliers, err := spS.sorter.SortSuppliers(splPrfl.ID, splPrfl.Sorting,
|
||||
spls, &args.CGREvent, extraOpts)
|
||||
splPrfl.Suppliers, &args.CGREvent, extraOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
srtTmp := &SortedSuppliers{
|
||||
ProfileID: sortedSuppliers.ProfileID,
|
||||
Sorting: sortedSuppliers.Sorting,
|
||||
}
|
||||
for _, s := range sortedSuppliers.SortedSuppliers {
|
||||
|
||||
srtTmp.SortedSuppliers = append(srtTmp.SortedSuppliers, s)
|
||||
}
|
||||
if args.Paginator.Offset != nil {
|
||||
if *args.Paginator.Offset <= len(sortedSuppliers.SortedSuppliers) {
|
||||
sortedSuppliers.SortedSuppliers = sortedSuppliers.SortedSuppliers[*args.Paginator.Offset:]
|
||||
if *args.Paginator.Offset <= len(srtTmp.SortedSuppliers) {
|
||||
srtTmp.SortedSuppliers = srtTmp.SortedSuppliers[*args.Paginator.Offset:]
|
||||
}
|
||||
}
|
||||
if args.Paginator.Limit != nil {
|
||||
if *args.Paginator.Limit <= len(sortedSuppliers.SortedSuppliers) {
|
||||
sortedSuppliers.SortedSuppliers = sortedSuppliers.SortedSuppliers[:*args.Paginator.Limit]
|
||||
if *args.Paginator.Limit <= len(srtTmp.SortedSuppliers) {
|
||||
srtTmp.SortedSuppliers = srtTmp.SortedSuppliers[:*args.Paginator.Limit]
|
||||
}
|
||||
}
|
||||
return sortedSuppliers, nil
|
||||
return srtTmp, nil
|
||||
}
|
||||
|
||||
type ArgsGetSuppliers struct {
|
||||
|
||||
@@ -45,7 +45,7 @@ var (
|
||||
Suppliers: []*Supplier{
|
||||
&Supplier{
|
||||
ID: "supplier1",
|
||||
FilterIDs: []string{"FLTR_SUPP_1"},
|
||||
FilterIDs: []string{},
|
||||
AccountIDs: []string{},
|
||||
RatingPlanIDs: []string{},
|
||||
ResourceIDs: []string{},
|
||||
@@ -70,7 +70,7 @@ var (
|
||||
Suppliers: []*Supplier{
|
||||
&Supplier{
|
||||
ID: "supplier2",
|
||||
FilterIDs: []string{"FLTR_SUPP_2"},
|
||||
FilterIDs: []string{},
|
||||
AccountIDs: []string{},
|
||||
RatingPlanIDs: []string{},
|
||||
ResourceIDs: []string{},
|
||||
@@ -80,7 +80,7 @@ var (
|
||||
},
|
||||
&Supplier{
|
||||
ID: "supplier3",
|
||||
FilterIDs: []string{"FLTR_SUPP_2"},
|
||||
FilterIDs: []string{},
|
||||
AccountIDs: []string{},
|
||||
RatingPlanIDs: []string{},
|
||||
ResourceIDs: []string{},
|
||||
@@ -90,7 +90,7 @@ var (
|
||||
},
|
||||
&Supplier{
|
||||
ID: "supplier1",
|
||||
FilterIDs: []string{"FLTR_SUPP_2"},
|
||||
FilterIDs: []string{},
|
||||
AccountIDs: []string{},
|
||||
RatingPlanIDs: []string{},
|
||||
ResourceIDs: []string{},
|
||||
@@ -115,7 +115,7 @@ var (
|
||||
Suppliers: []*Supplier{
|
||||
&Supplier{
|
||||
ID: "supplier1",
|
||||
FilterIDs: []string{"FLTR_SUPP_3"},
|
||||
FilterIDs: []string{},
|
||||
AccountIDs: []string{},
|
||||
RatingPlanIDs: []string{},
|
||||
ResourceIDs: []string{},
|
||||
@@ -430,6 +430,7 @@ func TestSuppliersSortedForEvent(t *testing.T) {
|
||||
if !reflect.DeepEqual(eFirstSupplierProfile, sprf) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eFirstSupplierProfile, sprf)
|
||||
}
|
||||
|
||||
eFirstSupplierProfile = &SortedSuppliers{
|
||||
ProfileID: "SupplierProfile2",
|
||||
Sorting: utils.MetaWeight,
|
||||
|
||||
@@ -1386,6 +1386,7 @@ type TPFilter struct {
|
||||
|
||||
type TPSupplier struct {
|
||||
ID string // SupplierID
|
||||
SortingFilter []string
|
||||
FilterIDs []string
|
||||
AccountIDs []string
|
||||
RatingPlanIDs []string // used when computing price
|
||||
|
||||
@@ -486,6 +486,7 @@ const (
|
||||
MetaLeastCost = "*least_cost"
|
||||
MetaHighestCost = "*highest_cost"
|
||||
MetaQOS = "*qos"
|
||||
MetaStatFiltered = "*stat_filtered"
|
||||
Weight = "Weight"
|
||||
Cost = "Cost"
|
||||
RatingPlanID = "RatingPlanID"
|
||||
|
||||
Reference in New Issue
Block a user