Considering account bundles within *least_cost strategy

This commit is contained in:
DanB
2017-12-03 19:31:59 +01:00
parent cbe04edec2
commit 3c4fbaa10f
3 changed files with 43 additions and 10 deletions

View File

@@ -41,20 +41,24 @@ func (lcs *LeastCostSorter) SortSuppliers(prflID string,
Sorting: lcs.sorting,
SortedSuppliers: make([]*SortedSupplier, 0)}
for _, s := range suppls {
ec, err := lcs.spS.costForEvent(ev, s.AccountIDs, s.RatingPlanIDs)
costData, err := lcs.spS.costForEvent(ev, s.AccountIDs, s.RatingPlanIDs)
if err != nil {
return nil, err
} else if ec == nil {
} 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
}
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: map[string]interface{}{
utils.Weight: s.Weight,
utils.Cost: ec.GetCost()}})
SupplierID: s.ID,
SortingData: srtData})
}
sortedSuppls.SortCost()
return

View File

@@ -167,8 +167,9 @@ func (spS *SupplierService) matchingSupplierProfilesForEvent(ev *SupplierEvent)
}
// costForEvent will compute cost out of accounts and rating plans for event
// returns map[string]interface{} with cost and relevant matching information inside
func (spS *SupplierService) costForEvent(ev *SupplierEvent,
acntIDs, rpIDs []string) (ec *EventCost, err error) {
acntIDs, rpIDs []string) (costData map[string]interface{}, err error) {
if err = ev.CheckMandatoryFields([]string{utils.ACCOUNT,
utils.DESTINATION, utils.ANSWER_TIME, utils.USAGE}); err != nil {
return
@@ -194,6 +195,29 @@ func (spS *SupplierService) costForEvent(ev *SupplierEvent,
if usage, err = ev.FieldAsDuration(utils.USAGE); err != nil {
return
}
for _, anctID := range acntIDs {
cd := &CallDescriptor{
Direction: utils.OUT,
Category: utils.MetaSuppliers,
Tenant: ev.Tenant,
Subject: subj,
Account: anctID,
Destination: dst,
TimeStart: aTime,
TimeEnd: aTime.Add(usage),
DurationIndex: usage,
}
if maxDur, err := cd.GetMaxSessionDuration(); err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> ignoring cost for account: %s, err: %s",
anctID, err.Error()))
} else if maxDur >= usage {
return map[string]interface{}{
utils.Cost: 0.0,
utils.ACCOUNT: anctID,
}, nil
}
}
for _, rp := range rpIDs { // loop through RatingPlans until we find one without errors
rPrfl := &RatingProfile{
Id: utils.ConcatenatedKey(utils.OUT,
@@ -206,8 +230,8 @@ func (spS *SupplierService) costForEvent(ev *SupplierEvent,
},
}
// force cache set so it can be picked by calldescriptor for cost calculation
cache.Set(utils.RATING_PROFILE_PREFIX+rPrfl.Id, rPrfl,
true, utils.NonTransactional)
cacheKey := utils.RATING_PROFILE_PREFIX + rPrfl.Id
cache.Set(cacheKey, rPrfl, true, utils.NonTransactional)
cd := &CallDescriptor{
Direction: utils.OUT,
Category: utils.MetaSuppliers,
@@ -220,13 +244,17 @@ func (spS *SupplierService) costForEvent(ev *SupplierEvent,
DurationIndex: usage,
}
cc, err := cd.GetCost()
cache.RemKey(cacheKey, true, utils.NonTransactional) // Remove here so we don't overload memory
if err != nil {
if err != utils.ErrNotFound {
return nil, err
}
continue
}
return NewEventCostFromCallCost(cc, "", ""), nil
ec := NewEventCostFromCallCost(cc, "", "")
return map[string]interface{}{
utils.Cost: ec.GetCost(),
utils.RatingPlanID: rp}, nil
}
return
}

View File

@@ -592,6 +592,7 @@ const (
MetaLeastCost = "*least_cost"
Weight = "Weight"
Cost = "Cost"
RatingPlanID = "RatingPlanID"
)
//Meta