mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Allow multiple suppliers with the same ID
This commit is contained in:
committed by
Dan Christian Bogos
parent
109d3c2ea5
commit
2cc081592a
@@ -67,10 +67,11 @@ var (
|
||||
testV1SplSRemSupplierProfiles,
|
||||
testV1SplSGetSupplierForEvent,
|
||||
// reset the database and load the TP again
|
||||
// testV1SplSInitDataDb,
|
||||
// testV1SplSFromFolder,
|
||||
testV1SplSInitDataDb,
|
||||
testV1SplSFromFolder,
|
||||
// for the moment we decide to comment the tests
|
||||
// testV1SplsOneSupplierWithoutDestination,
|
||||
testV1SplMultipleSupplierSameID,
|
||||
testV1SplSupplierPing,
|
||||
testV1SplSStopEngine,
|
||||
}
|
||||
@@ -1119,6 +1120,120 @@ func testV1SplsOneSupplierWithoutDestination(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testV1SplMultipleSupplierSameID(t *testing.T) {
|
||||
var reply *engine.SupplierProfile
|
||||
if err := splSv1Rpc.Call(utils.APIerSv1GetSupplierProfile,
|
||||
&utils.TenantID{Tenant: "cgrates.org", ID: "MULTIPLE_ROUTES"}, &reply); err == nil ||
|
||||
err.Error() != utils.ErrNotFound.Error() {
|
||||
t.Error(err)
|
||||
}
|
||||
splPrf = &SupplierWithCache{
|
||||
SupplierProfile: &engine.SupplierProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "MULTIPLE_ROUTES",
|
||||
FilterIDs: []string{"*string:~*req.Account:SpecialCase2"},
|
||||
Sorting: utils.MetaLC,
|
||||
Suppliers: []*engine.Supplier{
|
||||
{
|
||||
ID: "Route1",
|
||||
RatingPlanIDs: []string{"RP_LOCAL"},
|
||||
FilterIDs: []string{"*string:~*req.Month:April"},
|
||||
Weight: 10,
|
||||
},
|
||||
{
|
||||
ID: "Route1",
|
||||
RatingPlanIDs: []string{"RP_MOBILE"},
|
||||
FilterIDs: []string{"*string:~*req.Month:May"},
|
||||
Weight: 10,
|
||||
},
|
||||
},
|
||||
Weight: 100,
|
||||
},
|
||||
}
|
||||
|
||||
var result string
|
||||
if err := splSv1Rpc.Call(utils.APIerSv1SetSupplierProfile, splPrf, &result); err != nil {
|
||||
t.Error(err)
|
||||
} else if result != utils.OK {
|
||||
t.Error("Unexpected reply returned", result)
|
||||
}
|
||||
tNow := time.Now()
|
||||
ev := &engine.ArgsGetSuppliers{
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
Time: &tNow,
|
||||
ID: "testV1RouteMultipleRouteSameID",
|
||||
Event: map[string]interface{}{
|
||||
utils.Account: "SpecialCase2",
|
||||
utils.Destination: "+135876",
|
||||
utils.SetupTime: utils.MetaNow,
|
||||
utils.Usage: "2m",
|
||||
"Month": "April",
|
||||
},
|
||||
},
|
||||
}
|
||||
eSpls := engine.SortedSuppliers{
|
||||
ProfileID: "MULTIPLE_ROUTES",
|
||||
Sorting: utils.MetaLC,
|
||||
Count: 1,
|
||||
SortedSuppliers: []*engine.SortedSupplier{
|
||||
{
|
||||
SupplierID: "Route1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Cost: 0.0396,
|
||||
"RatingPlanID": "RP_LOCAL",
|
||||
utils.Weight: 10.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))
|
||||
}
|
||||
|
||||
ev = &engine.ArgsGetSuppliers{
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
Time: &tNow,
|
||||
ID: "testV1RouteMultipleRouteSameID",
|
||||
Event: map[string]interface{}{
|
||||
utils.Account: "SpecialCase2",
|
||||
utils.Destination: "+135876",
|
||||
utils.SetupTime: utils.MetaNow,
|
||||
utils.Usage: "2m",
|
||||
"Month": "May",
|
||||
},
|
||||
},
|
||||
}
|
||||
eSpls = engine.SortedSuppliers{
|
||||
ProfileID: "MULTIPLE_ROUTES",
|
||||
Sorting: utils.MetaLC,
|
||||
Count: 1,
|
||||
SortedSuppliers: []*engine.SortedSupplier{
|
||||
{
|
||||
SupplierID: "Route1",
|
||||
SortingData: map[string]interface{}{
|
||||
utils.Cost: 0.0204,
|
||||
"RatingPlanID": "RP_MOBILE",
|
||||
utils.Weight: 10.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
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 testV1SplSStopEngine(t *testing.T) {
|
||||
if err := engine.KillEngine(100); err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -1239,24 +1239,57 @@ func TestLoadSupplierProfiles(t *testing.T) {
|
||||
Suppliers: []*utils.TPSupplier{
|
||||
&utils.TPSupplier{
|
||||
ID: "supplier1",
|
||||
FilterIDs: []string{"FLTR_ACNT_dan", "FLTR_DST_DE"},
|
||||
AccountIDs: []string{"Account1", "Account1_1", "Account2"},
|
||||
RatingPlanIDs: []string{"RPL_1", "RPL_2", "RPL_3"},
|
||||
ResourceIDs: []string{"ResGroup1", "ResGroup2", "ResGroup3", "ResGroup4"},
|
||||
StatIDs: []string{"Stat1", "Stat2", "Stat3"},
|
||||
FilterIDs: []string{"FLTR_DST_DE"},
|
||||
AccountIDs: []string{"Account2"},
|
||||
RatingPlanIDs: []string{"RPL_3"},
|
||||
ResourceIDs: []string{"ResGroup3"},
|
||||
StatIDs: []string{"Stat2"},
|
||||
Weight: 10,
|
||||
Blocker: false,
|
||||
SupplierParameters: utils.EmptyString,
|
||||
},
|
||||
&utils.TPSupplier{
|
||||
ID: "supplier1",
|
||||
FilterIDs: []string{"FLTR_ACNT_dan"},
|
||||
AccountIDs: []string{"Account1", "Account1_1"},
|
||||
RatingPlanIDs: []string{"RPL_1"},
|
||||
ResourceIDs: []string{"ResGroup1"},
|
||||
StatIDs: []string{"Stat1"},
|
||||
Weight: 10,
|
||||
Blocker: true,
|
||||
SupplierParameters: "param1",
|
||||
},
|
||||
&utils.TPSupplier{
|
||||
ID: "supplier1",
|
||||
RatingPlanIDs: []string{"RPL_2"},
|
||||
ResourceIDs: []string{"ResGroup2", "ResGroup4"},
|
||||
StatIDs: []string{"Stat3"},
|
||||
Weight: 10,
|
||||
Blocker: false,
|
||||
SupplierParameters: utils.EmptyString,
|
||||
},
|
||||
},
|
||||
Weight: 20,
|
||||
},
|
||||
}
|
||||
resKey := utils.TenantID{Tenant: "cgrates.org", ID: "SPP_1"}
|
||||
sort.Slice(eSppProfiles[resKey].Suppliers, func(i, j int) bool {
|
||||
return strings.Compare(eSppProfiles[resKey].Suppliers[i].ID+
|
||||
strings.Join(eSppProfiles[resKey].Suppliers[i].FilterIDs, utils.CONCATENATED_KEY_SEP),
|
||||
eSppProfiles[resKey].Suppliers[j].ID+strings.Join(eSppProfiles[resKey].Suppliers[j].FilterIDs, utils.CONCATENATED_KEY_SEP)) < 0
|
||||
})
|
||||
|
||||
if len(csvr.sppProfiles) != len(eSppProfiles) {
|
||||
t.Errorf("Failed to load SupplierProfiles: %s", utils.ToIJSON(csvr.sppProfiles))
|
||||
} else if !reflect.DeepEqual(eSppProfiles[resKey], csvr.sppProfiles[resKey]) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eSppProfiles[resKey], csvr.sppProfiles[resKey])
|
||||
} else {
|
||||
sort.Slice(csvr.sppProfiles[resKey].Suppliers, func(i, j int) bool {
|
||||
return strings.Compare(csvr.sppProfiles[resKey].Suppliers[i].ID+
|
||||
strings.Join(csvr.sppProfiles[resKey].Suppliers[i].FilterIDs, utils.CONCATENATED_KEY_SEP),
|
||||
csvr.sppProfiles[resKey].Suppliers[j].ID+strings.Join(csvr.sppProfiles[resKey].Suppliers[j].FilterIDs, utils.CONCATENATED_KEY_SEP)) < 0
|
||||
})
|
||||
if !reflect.DeepEqual(eSppProfiles[resKey], csvr.sppProfiles[resKey]) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eSppProfiles[resKey]), utils.ToJSON(csvr.sppProfiles[resKey]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1809,7 +1809,12 @@ func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) {
|
||||
if _, has := suppliersMap[tenID]; !has {
|
||||
suppliersMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(map[string]*utils.TPSupplier)
|
||||
}
|
||||
sup, found := suppliersMap[tenID][tp.SupplierID]
|
||||
supID := tp.SupplierID
|
||||
if tp.SupplierFilterIDs != "" {
|
||||
supID = utils.ConcatenatedKey(supID,
|
||||
utils.NewStringSet(strings.Split(tp.SupplierFilterIDs, utils.INFIELD_SEP)).Sha1())
|
||||
}
|
||||
sup, found := suppliersMap[tenID][supID]
|
||||
if !found {
|
||||
sup = &utils.TPSupplier{
|
||||
ID: tp.SupplierID,
|
||||
@@ -1840,7 +1845,7 @@ func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) {
|
||||
accSplit := strings.Split(tp.SupplierAccountIDs, utils.INFIELD_SEP)
|
||||
sup.AccountIDs = append(sup.AccountIDs, accSplit...)
|
||||
}
|
||||
suppliersMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][tp.SupplierID] = sup
|
||||
suppliersMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][supID] = sup
|
||||
}
|
||||
if tp.SortingParameters != "" {
|
||||
if _, has := sortingParameterMap[tenID]; !has {
|
||||
|
||||
@@ -770,25 +770,56 @@ func TestLoaderProcessSuppliers(t *testing.T) {
|
||||
Suppliers: []*engine.Supplier{
|
||||
&engine.Supplier{
|
||||
ID: "supplier1",
|
||||
FilterIDs: []string{"FLTR_ACNT_dan", "FLTR_DST_DE"},
|
||||
AccountIDs: []string{"Account1", "Account1_1", "Account2"},
|
||||
RatingPlanIDs: []string{"RPL_1", "RPL_2", "RPL_3"},
|
||||
ResourceIDs: []string{"ResGroup1", "ResGroup2", "ResGroup3", "ResGroup4"},
|
||||
StatIDs: []string{"Stat1", "Stat2", "Stat3"},
|
||||
FilterIDs: []string{"FLTR_DST_DE"},
|
||||
AccountIDs: []string{"Account2"},
|
||||
RatingPlanIDs: []string{"RPL_3"},
|
||||
ResourceIDs: []string{"ResGroup3"},
|
||||
StatIDs: []string{"Stat2"},
|
||||
Weight: 10,
|
||||
Blocker: false,
|
||||
SupplierParameters: utils.EmptyString,
|
||||
},
|
||||
&engine.Supplier{
|
||||
ID: "supplier1",
|
||||
FilterIDs: []string{"FLTR_ACNT_dan"},
|
||||
AccountIDs: []string{"Account1", "Account1_1"},
|
||||
RatingPlanIDs: []string{"RPL_1"},
|
||||
ResourceIDs: []string{"ResGroup1"},
|
||||
StatIDs: []string{"Stat1"},
|
||||
Weight: 10,
|
||||
Blocker: true,
|
||||
SupplierParameters: "param1",
|
||||
},
|
||||
&engine.Supplier{
|
||||
ID: "supplier1",
|
||||
RatingPlanIDs: []string{"RPL_2"},
|
||||
ResourceIDs: []string{"ResGroup2", "ResGroup4"},
|
||||
StatIDs: []string{"Stat3"},
|
||||
Weight: 10,
|
||||
Blocker: false,
|
||||
SupplierParameters: utils.EmptyString,
|
||||
},
|
||||
},
|
||||
Weight: 20,
|
||||
}
|
||||
|
||||
sort.Slice(eSp3.Suppliers, func(i, j int) bool {
|
||||
return strings.Compare(eSp3.Suppliers[i].ID+
|
||||
strings.Join(eSp3.Suppliers[i].FilterIDs, utils.CONCATENATED_KEY_SEP),
|
||||
eSp3.Suppliers[j].ID+strings.Join(eSp3.Suppliers[j].FilterIDs, utils.CONCATENATED_KEY_SEP)) < 0
|
||||
})
|
||||
if aps, err := ldr.dm.GetSupplierProfile("cgrates.org", "SPP_1",
|
||||
true, false, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eSp3, aps) {
|
||||
t.Errorf("expecting: %s, received: %s",
|
||||
utils.ToJSON(eSp3), utils.ToJSON(aps))
|
||||
} else {
|
||||
sort.Slice(aps.Suppliers, func(i, j int) bool {
|
||||
return strings.Compare(aps.Suppliers[i].ID+
|
||||
strings.Join(aps.Suppliers[i].FilterIDs, utils.CONCATENATED_KEY_SEP),
|
||||
aps.Suppliers[j].ID+strings.Join(aps.Suppliers[j].FilterIDs, utils.CONCATENATED_KEY_SEP)) < 0
|
||||
})
|
||||
if !reflect.DeepEqual(eSp3, aps) {
|
||||
t.Errorf("expecting: %s, received: %s",
|
||||
utils.ToJSON(eSp3), utils.ToJSON(aps))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ cgrates (0.10.1~dev) UNRELEASED; urgency=medium
|
||||
* [SessionS] Update subflags for *rals ( *authorize and *initiate )
|
||||
* [AgentRequest] Improved NavigableMap
|
||||
* [AgentRequest] FieldAsInterface return Data instead of NMItem
|
||||
* [SupplierS] Allow multiple suppliers with the same ID
|
||||
|
||||
-- Alexandru Tripon <alexandru.tripon@itsyscom.com> Wed, 19 Feb 2020 15:22:59 +0200
|
||||
|
||||
|
||||
14
utils/set.go
14
utils/set.go
@@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
package utils
|
||||
|
||||
import "sort"
|
||||
|
||||
// NewStringSet returns a new StringSet
|
||||
func NewStringSet(dataSlice []string) (s StringSet) {
|
||||
s = make(StringSet)
|
||||
@@ -62,6 +64,18 @@ func (s StringSet) AsSlice() []string {
|
||||
return result
|
||||
}
|
||||
|
||||
// AsOrderedSlice returns the keys as ordered string slice
|
||||
func (s StringSet) AsOrderedSlice() (ss []string) {
|
||||
ss = s.AsSlice()
|
||||
sort.Strings(ss)
|
||||
return
|
||||
}
|
||||
|
||||
// Sha1 returns the Sha1 on top of ordered slice
|
||||
func (s StringSet) Sha1() string {
|
||||
return Sha1(s.AsOrderedSlice()...)
|
||||
}
|
||||
|
||||
// Size returns the size of the set
|
||||
func (s StringSet) Size() int {
|
||||
return len(s)
|
||||
|
||||
@@ -115,6 +115,43 @@ func TestAsSlice(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAsOrderedSlice(t *testing.T) {
|
||||
s := StringSet{}
|
||||
eOut := make([]string, 0)
|
||||
if rcv := s.AsOrderedSlice(); !reflect.DeepEqual(eOut, rcv) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
|
||||
}
|
||||
s = StringSet{
|
||||
"test3": struct{}{},
|
||||
"test12": struct{}{},
|
||||
"test2": struct{}{}}
|
||||
eOut = []string{"test12", "test2", "test3"}
|
||||
rcv := s.AsOrderedSlice()
|
||||
if !reflect.DeepEqual(eOut, rcv) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSha1(t *testing.T) {
|
||||
s := StringSet{
|
||||
"test3": struct{}{},
|
||||
"test12": struct{}{},
|
||||
"test2": struct{}{}}
|
||||
eOut := "8fbb49ecf2ee4116bc492505865d2125a78f2161"
|
||||
if rcv := s.Sha1(); rcv != eOut {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
|
||||
}
|
||||
|
||||
s2 := StringSet{
|
||||
"test2": struct{}{},
|
||||
"test3": struct{}{},
|
||||
"test12": struct{}{},
|
||||
}
|
||||
if rcv := s2.Sha1(); rcv != eOut {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
s := StringSet{}
|
||||
if rcv := s.Size(); rcv != 0 {
|
||||
|
||||
Reference in New Issue
Block a user