Merge branch 'actmods' of https://github.com/cgrates/cgrates into actmods

This commit is contained in:
DanB
2015-10-28 12:56:09 +01:00
8 changed files with 55 additions and 20 deletions

View File

@@ -642,6 +642,7 @@ func (bc BalanceChain) SaveDirtyBalances(acc *Account) {
allowNegative := ""
disabled := ""
if b.account != nil { // only publish modifications for balances with account set
//utils.LogStack()
accountId = b.account.Id
allowNegative = strconv.FormatBool(b.account.AllowNegative)
disabled = strconv.FormatBool(b.account.Disabled)

View File

@@ -152,3 +152,15 @@ func (cc *CallCost) AsJSON() string {
ccJson, _ := json.Marshal(cc)
return string(ccJson)
}
func (cc *CallCost) UpdateCost() {
cost := 0.0
if cc.deductConnectFee { // add back the connectFee
cost += cc.GetConnectFee()
}
for _, ts := range cc.Timespans {
cost += ts.getCost()
cost = utils.Round(cost, globalRoundingDecimals, utils.ROUNDING_MIDDLE) // just get rid of the extra decimals
}
cc.Cost = cost
}

View File

@@ -83,7 +83,7 @@ var (
// Exported method to set the storage getter.
func SetRatingStorage(sg RatingStorage) {
ratingStorage = sg
ratingStorage = sg
}
func SetAccountingStorage(ag AccountingStorage) {
@@ -636,16 +636,7 @@ func (cd *CallDescriptor) debit(account *Account, dryRun bool, goNegative bool)
utils.Logger.Err(fmt.Sprintf("<Rater> Error getting cost for account key <%s>: %s", cd.GetAccountKey(), err.Error()))
return nil, err
}
cost := 0.0
// calculate call cost after balances
if cc.deductConnectFee { // add back the connectFee
cost += cc.GetConnectFee()
}
for _, ts := range cc.Timespans {
cost += ts.getCost()
cost = utils.Round(cost, globalRoundingDecimals, utils.ROUNDING_MIDDLE) // just get rid of the extra decimals
}
cc.Cost = cost
cc.UpdateCost()
cc.Timespans.Compress()
//log.Printf("OUT CC: ", cc)
return

View File

@@ -557,6 +557,28 @@ func TestGetCostWithMaxCost(t *testing.T) {
t.Errorf("Expected %v was %v", expected, cc.Cost)
}
}
func TestGetCostRoundingIssue(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT")
for _, at := range ap {
at.Execute()
}
cd := &CallDescriptor{
Direction: "*out",
Category: "call",
Tenant: "cgrates.org",
Subject: "dy",
Account: "dy",
Destination: "0723123113",
TimeStart: time.Date(2015, 10, 26, 13, 29, 27, 0, time.UTC),
TimeEnd: time.Date(2015, 10, 26, 13, 29, 51, 0, time.UTC),
MaxCostSoFar: 0,
}
cc, err := cd.GetCost()
expected := 0.17
if cc.Cost != expected || err != nil {
t.Errorf("Expected %v was %+v", expected, cc)
}
}
func TestMaxSessionTimeWithMaxCostFree(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT")

View File

@@ -70,6 +70,7 @@ RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s
RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s
R_URG,0,0,1,1,0
MX,0,1,1s,1s,0
DY,0.15,0.05,60s,1s,0s
`
destinationRates = `
RT_STANDARD,GERMANY,R1,*middle,4,0,
@@ -91,6 +92,7 @@ DATA_RATE,*any,LANDLINE_OFFPEAK,*middle,4,0,
RT_URG,URG,R_URG,*middle,4,0,
MX_FREE,RET,MX,*middle,4,10,*free
MX_DISC,RET,MX,*middle,4,10,*disconnect
RT_DY,RET,DY,*up,2,0,
`
ratingPlans = `
STANDARD,RT_STANDARD,WORKDAYS_00,10
@@ -115,6 +117,7 @@ RP_MX,MX_DISC,WORKDAYS_00,10
RP_MX,MX_FREE,WORKDAYS_18,10
GER_ONLY,GER,*any,10
ANY_PLAN,DATA_RATE,*any,10
DY_PLAN,RT_DY,*any,10
`
ratingProfiles = `
*out,CUSTOMER_1,0,rif:from:tm,2012-01-01T00:00:00Z,PREMIUM,danb,
@@ -141,6 +144,7 @@ ANY_PLAN,DATA_RATE,*any,10
*out,cgrates.org,call,nt,2012-02-28T00:00:00Z,GER_ONLY,,
*in,cgrates.org,LCR_STANDARD,max,2013-03-23T00:00:00Z,RP_MX,,
*out,cgrates.org,call,money,2015-02-28T00:00:00Z,EVENING,,
*out,cgrates.org,call,dy,2015-02-28T00:00:00Z,DY_PLAN,,
`
sharedGroups = `
SG1,*any,*lowest,
@@ -391,7 +395,7 @@ func TestLoadTimimgs(t *testing.T) {
}
func TestLoadRates(t *testing.T) {
if len(csvr.rates) != 13 {
if len(csvr.rates) != 14 {
t.Error("Failed to load rates: ", len(csvr.rates))
}
rate := csvr.rates["R1"].RateSlots[0]
@@ -461,7 +465,7 @@ func TestLoadRates(t *testing.T) {
}
func TestLoadDestinationRates(t *testing.T) {
if len(csvr.destinationRates) != 14 {
if len(csvr.destinationRates) != 15 {
t.Error("Failed to load destinationrates: ", len(csvr.destinationRates))
}
drs := csvr.destinationRates["RT_STANDARD"]
@@ -609,7 +613,7 @@ func TestLoadDestinationRates(t *testing.T) {
}
func TestLoadRatingPlans(t *testing.T) {
if len(csvr.ratingPlans) != 13 {
if len(csvr.ratingPlans) != 14 {
t.Error("Failed to load rating plans: ", len(csvr.ratingPlans))
}
rplan := csvr.ratingPlans["STANDARD"]
@@ -781,7 +785,7 @@ func TestLoadRatingPlans(t *testing.T) {
}
func TestLoadRatingProfiles(t *testing.T) {
if len(csvr.ratingProfiles) != 21 {
if len(csvr.ratingProfiles) != 22 {
t.Error("Failed to load rating profiles: ", len(csvr.ratingProfiles), csvr.ratingProfiles)
}
rp := csvr.ratingProfiles["*out:test:0:trp"]

View File

@@ -263,11 +263,7 @@ func (ts *TimeSpan) getCost() float64 {
ts.Cost = utils.Round(cost, ts.RateInterval.Rating.RoundingDecimals, ts.RateInterval.Rating.RoundingMethod)
return ts.Cost
} else {
cost := 0.0
// some increments may have 0 cost because of the max cost strategy
for _, inc := range ts.Increments {
cost += inc.Cost
}
cost := ts.Increments.GetTotalCost()
if ts.RateInterval != nil && ts.RateInterval.Rating != nil {
return utils.Round(cost, ts.RateInterval.Rating.RoundingDecimals, ts.RateInterval.Rating.RoundingMethod)
} else {

View File

@@ -233,6 +233,8 @@ func (s *Session) SaveOperations() {
firstCC.Merge(cc)
//utils.Logger.Debug(fmt.Sprintf("AFTER MERGE: %s", utils.ToJSON(firstCC)))
}
// make sure we have rounded timespans final cost
firstCC.UpdateCost()
var reply string
err := s.sessionManager.CdrSrv().LogCallCost(&engine.CallCostLog{

View File

@@ -22,6 +22,7 @@ import (
"fmt"
"log"
"log/syslog"
"runtime"
)
var Logger LoggerInterface
@@ -85,3 +86,9 @@ func (sl *StdLogger) Warning(m string) (err error) {
log.Print("[WARNING]" + m)
return
}
func LogStack() {
buf := make([]byte, 300)
runtime.Stack(buf, false)
Logger.Debug(string(buf))
}