This commit is contained in:
DanB
2015-06-18 17:15:41 +02:00
8 changed files with 77 additions and 154 deletions

View File

@@ -134,17 +134,14 @@ func (self *ApierV1) RemAccountActionTriggers(attrs AttrRemAcntActionTriggers, r
if err != nil {
return 0, err
}
for idx, actr := range ub.ActionTriggers {
nactrs := make(engine.ActionTriggerPriotityList, 0)
for _, actr := range ub.ActionTriggers {
match, _ := regexp.MatchString(attrs.ActionTriggersId, actr.Id)
if len(attrs.ActionTriggersId) != 0 && !match {
continue
}
if len(ub.ActionTriggers) != 1 { // Remove by index
ub.ActionTriggers[idx], ub.ActionTriggers = ub.ActionTriggers[len(ub.ActionTriggers)-1], ub.ActionTriggers[:len(ub.ActionTriggers)-1]
} else { // For last item, simply reinit the slice
ub.ActionTriggers = make(engine.ActionTriggerPriotityList, 0)
nactrs = append(nactrs, actr)
}
}
ub.ActionTriggers = nactrs
if err := self.AccountDb.SetAccount(ub); err != nil {
return 0, err
}

View File

@@ -150,7 +150,7 @@ func (ub *Account) debitBalanceAction(a *Action, reset bool) error {
func (ub *Account) getBalancesForPrefix(prefix, category string, balances BalanceChain, sharedGroup string) BalanceChain {
var usefulBalances BalanceChain
for _, b := range balances {
if b.IsExpired() || (ub.AllowNegative == false && b.SharedGroup == "" && b.Value <= 0) {
if b.IsExpired() || (b.SharedGroup == "" && b.Value <= 0) {
continue
}
if sharedGroup != "" && b.SharedGroup != sharedGroup {
@@ -320,18 +320,23 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo
if err != nil {
Logger.Err(fmt.Sprintf("Error getting new cost for balance subject: %v", err))
}
initialLength = len(cc.Timespans)
cc.Timespans = append(cc.Timespans, leftCC.Timespans...)
if initialLength == 0 {
// this is the first add, debit the connect fee
ub.DebitConnectionFee(cc, usefulMoneyBalances, count)
if leftCC.Cost == 0 && len(leftCC.Timespans) > 0 {
cc.Timespans = append(cc.Timespans, leftCC.Timespans...)
}
if leftCC.Cost == 0 || goNegative {
//log.Printf("Left CC: %+v", leftCC)
//log.Printf("HERE: %+v %d", leftCC)
if leftCC.Cost > 0 && goNegative {
initialLength = len(cc.Timespans)
cc.Timespans = append(cc.Timespans, leftCC.Timespans...)
if initialLength == 0 {
// this is the first add, debit the connect fee
ub.DebitConnectionFee(cc, usefulMoneyBalances, count)
}
//log.Printf("Left CC: %+v ", leftCC)
// get the default money balanance
// and go negative on it with the amount still unpaid
if len(leftCC.Timespans) > 0 && leftCC.Cost > 0 && !ub.AllowNegative {
err = errors.New("not enough credit")
if len(leftCC.Timespans) > 0 && leftCC.Cost > 0 && !ub.AllowNegative && !dryRun {
Logger.Err(fmt.Sprintf("<Rater> Going negative on account %s with AllowNegative: false", cd.GetAccountKey()))
}
for _, ts := range leftCC.Timespans {
if ts.Increments == nil {

View File

@@ -803,134 +803,6 @@ func TestDebitCreditSubjectMoney(t *testing.T) {
}
}*/
func TestDebitCreditSubjectMixedMoreTS(t *testing.T) {
b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: "NAT", RatingSubject: "minu"}
cc := &CallCost{
Tenant: "vdf",
Category: "0",
Direction: OUTBOUND,
Destination: "0723045326",
Timespans: []*TimeSpan{
&TimeSpan{
TimeStart: time.Date(2013, 9, 24, 10, 48, 0, 0, time.UTC),
TimeEnd: time.Date(2013, 9, 24, 10, 48, 10, 0, time.UTC),
DurationIndex: 0,
RateInterval: &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 100, RateIncrement: 10 * time.Second, RateUnit: time.Second}}}},
},
&TimeSpan{
TimeStart: time.Date(2013, 9, 24, 10, 48, 10, 0, time.UTC),
TimeEnd: time.Date(2013, 9, 24, 10, 49, 20, 0, time.UTC),
DurationIndex: 10 * time.Second,
RateInterval: &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 1, RateIncrement: 10 * time.Second, RateUnit: time.Second}}}},
},
},
TOR: utils.VOICE,
deductConnectFee: true,
}
cd := &CallDescriptor{
Tenant: cc.Tenant,
Category: cc.Category,
TimeStart: cc.Timespans[0].TimeStart,
TimeEnd: cc.Timespans[1].TimeEnd,
Direction: cc.Direction,
Destination: cc.Destination,
TOR: cc.TOR,
DurationIndex: cc.GetDuration(),
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
utils.VOICE + OUTBOUND: BalanceChain{b1},
utils.MONETARY + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 50, RatingSubject: "minu"}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
if err == nil {
t.Error("Error showing debiting balance error: ", err)
}
//t.Logf("%+v %+v", cc.Timespans[0], cc.Timespans[1])
/*if cc.Timespans[0].Increments[0].BalanceInfo.UnitBalanceUuid != "testb" ||
cc.Timespans[0].Increments[0].Duration != time.Second {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
if rifsBalance.BalanceMap[utils.VOICE+OUTBOUND][0].Value != 20 ||
rifsBalance.BalanceMap[utils.MONETARY+OUTBOUND][0].Value != 0 ||
rifsBalance.BalanceMap[utils.MONETARY+OUTBOUND][1].Value != -31 {
t.Errorf("Error extracting minutes from balance: %+v, %+v, %+v",
rifsBalance.BalanceMap[utils.VOICE+OUTBOUND][0].Value, rifsBalance.BalanceMap[utils.MONETARY+OUTBOUND][0].Value,
rifsBalance.BalanceMap[utils.MONETARY+OUTBOUND][1].Value)
}
if len(cc.Timespans) != 2 || cc.Timespans[0].GetDuration() != 50*time.Second || cc.Timespans[1].GetDuration() != 30*time.Second {
for _, ts := range cc.Timespans {
t.Log(ts.GetDuration())
}
t.Error("Error truncating extra timespans: ", len(cc.Timespans))
}*/
}
func TestDebitCreditSubjectMixedPartPay(t *testing.T) {
b1 := &Balance{Uuid: "testb", Value: 70, Weight: 10, DestinationIds: "NAT", RatingSubject: "minu"}
cc := &CallCost{
Tenant: "vdf",
Category: "0",
Direction: OUTBOUND,
Destination: "0723045326",
Timespans: []*TimeSpan{
&TimeSpan{
TimeStart: time.Date(2013, 9, 24, 10, 48, 0, 0, time.UTC),
TimeEnd: time.Date(2013, 9, 24, 10, 48, 10, 0, time.UTC),
DurationIndex: 0,
RateInterval: &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 100, RateIncrement: 10 * time.Second, RateUnit: time.Second}}}},
},
&TimeSpan{
TimeStart: time.Date(2013, 9, 24, 10, 48, 10, 0, time.UTC),
TimeEnd: time.Date(2013, 9, 24, 10, 49, 20, 0, time.UTC),
DurationIndex: 10 * time.Second,
RateInterval: &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 1, RateIncrement: 10 * time.Second, RateUnit: time.Second}}}},
},
},
TOR: utils.VOICE,
deductConnectFee: true,
}
cd := &CallDescriptor{
Tenant: cc.Tenant,
Category: cc.Category,
TimeStart: cc.Timespans[0].TimeStart,
TimeEnd: cc.Timespans[1].TimeEnd,
Direction: cc.Direction,
Destination: cc.Destination,
TOR: cc.TOR,
DurationIndex: cc.GetDuration(),
testCallcost: cc,
}
rifsBalance := &Account{Id: "other", BalanceMap: map[string]BalanceChain{
utils.VOICE + OUTBOUND: BalanceChain{b1},
utils.MONETARY + OUTBOUND: BalanceChain{&Balance{Uuid: "moneya", Value: 75, RatingSubject: "minu"}},
}}
var err error
cc, err = rifsBalance.debitCreditBalance(cd, false, false, true)
if err == nil {
t.Error("Error showing debiting balance error: ", err)
}
//t.Logf("%+v %+v", cc.Timespans[0], cc.Timespans[1])
/*if cc.Timespans[0].Increments[0].BalanceInfo.UnitBalanceUuid != "testb" ||
cc.Timespans[0].Increments[0].Duration != time.Second {
t.Error("Error setting balance id to increment: ", cc.Timespans[0].Increments[0])
}
if rifsBalance.BalanceMap[utils.VOICE+OUTBOUND][0].Value != 0 ||
rifsBalance.BalanceMap[utils.MONETARY+OUTBOUND][0].Value != 0 ||
rifsBalance.BalanceMap[utils.MONETARY+OUTBOUND][1].Value != -11 {
t.Errorf("Error extracting minutes from balance: %+v, %+v %+v",
rifsBalance.BalanceMap[utils.VOICE+OUTBOUND][0].Value, rifsBalance.BalanceMap[utils.MONETARY+OUTBOUND][0].Value,
rifsBalance.BalanceMap[utils.MONETARY+OUTBOUND][1].Value)
}
if len(cc.Timespans) != 3 || cc.Timespans[0].GetDuration() != 70*time.Second || cc.Timespans[1].GetDuration() != 5*time.Second || cc.Timespans[2].GetDuration() != 5*time.Second {
for _, ts := range cc.Timespans {
t.Log(ts.GetDuration())
}
t.Error("Error truncating extra timespans: ", len(cc.Timespans))
}*/
}
func TestAccountdebitBalance(t *testing.T) {
ub := &Account{
Id: "rif",

View File

@@ -314,6 +314,12 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala
},
}
prefix, destid := b.getMatchingPrefixAndDestId(cd.Destination)
if prefix == "" {
prefix = cd.Destination
}
if destid == "" {
destid = utils.ANY
}
ts.setRatingInfo(&RatingInfo{
MatchedSubject: b.Uuid,
MatchedPrefix: prefix,

View File

@@ -525,6 +525,9 @@ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Dura
return utils.MinDuration(initialDuration, totalDuration), nil
}
}
if ts.Increments == nil {
ts.createIncrementsSlice()
}
for _, incr := range ts.Increments {
totalCost += incr.Cost
if defaultBalance.Value < 0 && incr.BalanceInfo.MoneyBalanceUuid == defaultBalance.Uuid {

View File

@@ -828,7 +828,7 @@ func TestMaxSesionTimeEmptyBalance(t *testing.T) {
acc, _ := accountingStorage.GetAccount("*out:vdf:luna")
allowedTime, err := cd.getMaxSessionDuration(acc)
if err != nil || allowedTime != 0 {
t.Error("Error get max session for 0 acount")
t.Error("Error get max session for 0 acount", err)
}
}
@@ -846,7 +846,7 @@ func TestMaxSesionTimeEmptyBalanceAndNoCost(t *testing.T) {
acc, _ := accountingStorage.GetAccount("*out:vdf:luna")
allowedTime, err := cd.getMaxSessionDuration(acc)
if err != nil || allowedTime == 0 {
t.Error("Error get max session for 0 acount")
t.Error("Error get max session for 0 acount", err)
}
}
@@ -906,6 +906,43 @@ func TestDebitFromEmptyShare(t *testing.T) {
}
}
func TestDebitNegatve(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("POST_AT")
for _, at := range ap {
at.Execute()
}
cd := &CallDescriptor{
TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC),
TimeEnd: time.Date(2013, 10, 21, 18, 34, 5, 0, time.UTC),
Direction: "*out",
Category: "0",
Tenant: "vdf",
Subject: "rif",
Account: "post",
Destination: "0723",
}
cc, err := cd.MaxDebit()
//utils.PrintFull(cc)
if err != nil || cc.Cost != 2.5 {
t.Errorf("Debit from empty share error: %+v, %v", cc, err)
}
acc, _ := cd.getAccount()
//utils.PrintFull(acc)
balanceMap := acc.BalanceMap[utils.MONETARY+OUTBOUND]
if len(balanceMap) != 1 || balanceMap[0].Value != -2.5 {
t.Errorf("Error debiting from empty share: %+v", balanceMap[0].Value)
}
cc, err = cd.MaxDebit()
//utils.PrintFull(cc)
if err != nil || cc.Cost != 2.5 {
t.Errorf("Debit from empty share error: %+v, %v", cc, err)
}
if len(balanceMap) != 1 || balanceMap[0].Value != -5 {
t.Errorf("Error debiting from empty share: %+v", balanceMap[0].Value)
}
}
func TestMaxDebitZeroDefinedRate(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT")
for _, at := range ap {

View File

@@ -160,6 +160,7 @@ SE10,*topup,,,*monetary,*out,,,,,*unlimited,,10,10,10
EE0,*topup_reset,,,*monetary,*out,,,,SG3,*unlimited,,0,10,10
EE0,*allow_negative,,,*monetary,*out,,,,,*unlimited,,0,10,10
DEFEE,*cdrlog,"{""Category"":""^ddi"",""MediationRunId"":""^did_run""}",,,,,,,,,,,,10
NEG,*allow_negative,,,*monetary,*out,,,,,*unlimited,,0,10,10
`
actionTimings = `
MORE_MINUTES,MINI,ONE_TIME_RUN,10
@@ -169,6 +170,7 @@ TOPUP10_AT,TOPUP10_AC1,*asap,10
TOPUP_SHARED0_AT,SE0,*asap,10
TOPUP_SHARED10_AT,SE10,*asap,10
TOPUP_EMPTY_AT,EE0,*asap,10
POST_AT,NEG,*asap,10
`
actionTriggers = `
@@ -190,6 +192,7 @@ vdf,empty0,*out,TOPUP_SHARED0_AT,
vdf,empty10,*out,TOPUP_SHARED10_AT,
vdf,emptyX,*out,TOPUP_EMPTY_AT,
vdf,emptyY,*out,TOPUP_EMPTY_AT,
vdf,post,*out,POST_AT,
`
derivedCharges = `
@@ -765,8 +768,8 @@ func TestLoadRatingProfiles(t *testing.T) {
}
func TestLoadActions(t *testing.T) {
if len(csvr.actions) != 8 {
t.Error("Failed to load actions: ", csvr.actions)
if len(csvr.actions) != 9 {
t.Error("Failed to load actions: ", len(csvr.actions))
}
as1 := csvr.actions["MINI"]
expected := []*Action{
@@ -928,8 +931,8 @@ func TestLoadLCRs(t *testing.T) {
}
func TestLoadActionTimings(t *testing.T) {
if len(csvr.actionsTimings) != 5 {
t.Error("Failed to load action timings: ", csvr.actionsTimings)
if len(csvr.actionsTimings) != 6 {
t.Error("Failed to load action timings: ", len(csvr.actionsTimings))
}
atm := csvr.actionsTimings["MORE_MINUTES"][0]
expected := &ActionPlan{
@@ -990,8 +993,8 @@ func TestLoadActionTriggers(t *testing.T) {
}
func TestLoadAccountActions(t *testing.T) {
if len(csvr.accountActions) != 6 {
t.Error("Failed to load account actions: ", csvr.accountActions)
if len(csvr.accountActions) != 7 {
t.Error("Failed to load account actions: ", len(csvr.accountActions))
}
aa := csvr.accountActions["*out:vdf:minitsboy"]
expected := &Account{

View File

@@ -135,7 +135,7 @@ func (s *Stats) ResetQueues(ids []string, out *int) error {
return nil
}
// change the xisting ones
// change the existing ones
// add new ones
// delete the ones missing from the new list
func (s *Stats) UpdateQueues(css []*CdrStats, out *int) error {