diff --git a/data/RatingProfiles.csv b/data/RatingProfiles.csv index b45a7622f..1a8e6650b 100644 --- a/data/RatingProfiles.csv +++ b/data/RatingProfiles.csv @@ -4,4 +4,6 @@ CUSTOMER_1,0,OUT,rif:from:tm,danb,STANDARD,2012-02-28T00:00:00Z CUSTOMER_2,0,OUT,danb:87.139.12.167,danb,STANDARD,2012-01-01T00:00:00Z CUSTOMER_1,0,OUT,danb,,PREMIUM,2012-01-01T00:00:00Z vdf,0,OUT,rif,,EVENING,2012-01-01T00:00:00Z -vdf,0,OUT,rif,,EVENING,2012-02-28T00:00:00Z \ No newline at end of file +vdf,0,OUT,rif,,EVENING,2012-02-28T00:00:00Z +vdf,0,OUT,minu,,EVENING,2012-01-01T00:00:00Z +vdf,0,OUT,minu,,EVENING,2012-02-28T00:00:00Z \ No newline at end of file diff --git a/timespans/actions.go b/timespans/actions.go index 4dd1a54df..54bf4d01d 100644 --- a/timespans/actions.go +++ b/timespans/actions.go @@ -86,7 +86,7 @@ func logAction(ub *UserBalance, a *Action) (err error) { } func resetTriggersAction(ub *UserBalance, a *Action) (err error) { - ub.ResetActionTriggers() + ub.resetActionTriggers() return } diff --git a/timespans/calldesc.go b/timespans/calldesc.go index 52cba6968..9ec90e66f 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -178,7 +178,7 @@ func (cd *CallDescriptor) splitTimeSpan(firstSpan *TimeSpan) (timespans []*TimeS timespans = append(timespans, firstSpan) // split on (free) minute buckets if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil { - _, bucketList := userBalance.getSecondsForPrefix(cd.Destination) + _, _, bucketList := userBalance.getSecondsForPrefix(cd.Destination) for _, mb := range bucketList { for i := 0; i < len(timespans); i++ { if timespans[i].MinuteInfo != nil { @@ -296,8 +296,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) { if userBalance.Type == UB_TYPE_POSTPAID { return -1, nil } else { - availableCredit = userBalance.BalanceMap[CREDIT] - availableSeconds, _ = userBalance.getSecondsForPrefix(cd.Destination) + availableSeconds, availableCredit, _ = userBalance.getSecondsForPrefix(cd.Destination) } } else { return cd.Amount, err @@ -306,10 +305,9 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) { if availableCredit == 0 { return availableSeconds, nil } - maxSessionSeconds := cd.Amount for i := 0; i < 10; i++ { - maxDuration, _ := time.ParseDuration(fmt.Sprintf("%vs", maxSessionSeconds)) + maxDuration, _ := time.ParseDuration(fmt.Sprintf("%vs", maxSessionSeconds-availableSeconds)) ts := &TimeSpan{TimeStart: now, TimeEnd: now.Add(maxDuration)} timespans := cd.splitTimeSpan(ts) @@ -320,6 +318,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) { } cost += ts.getCost(cd) } + //log.Print(availableCredit, availableSeconds, cost) if cost < availableCredit { return maxSessionSeconds, nil } else { //decrease the period by 10% and try again diff --git a/timespans/calldesc_test.go b/timespans/calldesc_test.go index d6d72f9e5..dae54a5a1 100644 --- a/timespans/calldesc_test.go +++ b/timespans/calldesc_test.go @@ -31,18 +31,27 @@ func init() { } func populateDB() { - ub := &UserBalance{ + minu := &UserBalance{ Id: "OUT:vdf:minu", Type: UB_TYPE_PREPAID, - /*BalanceMap: map[string]float64{ + BalanceMap: map[string]float64{ CREDIT: 21, - },*/ + }, MinuteBuckets: []*MinuteBucket{ &MinuteBucket{Seconds: 200, DestinationId: "NAT", Weight: 10}, &MinuteBucket{Seconds: 100, DestinationId: "RET", Weight: 20}, }, } - storageGetter.SetUserBalance(ub) + broker := &UserBalance{ + Id: "OUT:vdf:broker", + Type: UB_TYPE_PREPAID, + MinuteBuckets: []*MinuteBucket{ + &MinuteBucket{Seconds: 20, DestinationId: "NAT", Weight: 10, Price: 1}, + &MinuteBucket{Seconds: 100, DestinationId: "RET", Weight: 20}, + }, + } + storageGetter.SetUserBalance(broker) + storageGetter.SetUserBalance(minu) } func TestSplitSpans(t *testing.T) { @@ -174,7 +183,7 @@ func TestMaxSessionTimeNoUserBalance(t *testing.T) { } func TestMaxSessionTimeWithUserBalance(t *testing.T) { - cd := &CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "minu", Destination: "0723", Amount: 5400} + cd := &CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "minu", Destination: "0723", Amount: 1000} result, err := cd.GetMaxSessionTime() expected := 300.0 if result != expected || err != nil { diff --git a/timespans/minute_buckets.go b/timespans/minute_buckets.go index 6944ec360..22402039d 100644 --- a/timespans/minute_buckets.go +++ b/timespans/minute_buckets.go @@ -33,6 +33,7 @@ type MinuteBucket struct { precision int } +// Returns the available number of seconds for a specified credit func (mb *MinuteBucket) GetSecondsForCredit(credit float64) (seconds float64) { seconds = mb.Seconds if mb.Price > 0 { @@ -63,9 +64,3 @@ func (bs bucketsorter) Less(j, i int) bool { func (bs bucketsorter) Sort() { sort.Sort(bs) } - -func (ub *UserBalance) ResetActionTriggers() { - for _, at := range ub.ActionTriggers { - at.executed = false - } -} diff --git a/timespans/userbalance.go b/timespans/userbalance.go index cac57fd0a..c58788697 100644 --- a/timespans/userbalance.go +++ b/timespans/userbalance.go @@ -19,8 +19,7 @@ along with this program. If not, see package timespans import ( - // "log" - "sort" +// "log" ) const ( @@ -68,7 +67,7 @@ func (a AmountTooBig) Error() string { /* Returns user's available minutes for the specified destination */ -func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds float64, bucketList bucketsorter) { +func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds, credit float64, bucketList bucketsorter) { if len(ub.MinuteBuckets) == 0 { // log.Print("There are no minute buckets to check for user: ", ub.Id) return @@ -86,8 +85,8 @@ func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds float64, buck } } } - sort.Sort(bucketList) // sorts the buckets according to priority, precision or price - credit := ub.BalanceMap[CREDIT] + bucketList.Sort() // sorts the buckets according to priority, precision or price + credit = ub.BalanceMap[CREDIT] for _, mb := range bucketList { s := mb.GetSecondsForCredit(credit) credit -= s * mb.Price @@ -112,7 +111,7 @@ If the amount is bigger than the sum of all seconds in the minute buckets than n debited and an error will be returned. */ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string) error { - avaliableNbSeconds, bucketList := ub.getSecondsForPrefix(prefix) + avaliableNbSeconds, _, bucketList := ub.getSecondsForPrefix(prefix) if avaliableNbSeconds < amount { return new(AmountTooBig) } @@ -139,6 +138,7 @@ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string) error return new(AmountTooBig) } ub.BalanceMap[CREDIT] = credit // credit is > 0 + for _, mb := range bucketList { if mb.Seconds < amount { amount -= mb.Seconds @@ -182,6 +182,7 @@ func (ub *UserBalance) addMinuteBucket(newMb *MinuteBucket) { } } +// Scans the action trigers and execute the actions for which trigger is met func (ub *UserBalance) executeActionTriggers() { ub.ActionTriggers.Sort() for _, at := range ub.ActionTriggers { @@ -209,6 +210,13 @@ func (ub *UserBalance) executeActionTriggers() { } } +// Mark all action trigers as ready for execution +func (ub *UserBalance) resetActionTriggers() { + for _, at := range ub.ActionTriggers { + at.executed = false + } +} + /* Adds the specified amount of seconds. */ diff --git a/timespans/userbalance_test.go b/timespans/userbalance_test.go index 68c6c3529..fcca9dc18 100644 --- a/timespans/userbalance_test.go +++ b/timespans/userbalance_test.go @@ -49,9 +49,9 @@ func TestGetSecondsForPrefix(t *testing.T) { b1 := &MinuteBucket{Seconds: 10, Weight: 10, DestinationId: "NAT"} b2 := &MinuteBucket{Seconds: 100, Weight: 20, DestinationId: "RET"} ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 200}} - seconds, bucketList := ub1.getSecondsForPrefix("0723") + seconds, credit, bucketList := ub1.getSecondsForPrefix("0723") expected := 110.0 - if seconds != expected || bucketList[0].Weight < bucketList[1].Weight { + if credit != 200 || seconds != expected || bucketList[0].Weight < bucketList[1].Weight { t.Errorf("Expected %v was %v", expected, seconds) } } @@ -61,9 +61,9 @@ func TestGetPricedSeconds(t *testing.T) { b2 := &MinuteBucket{Seconds: 100, Price: 1, Weight: 20, DestinationId: "RET"} ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21}} - seconds, bucketList := ub1.getSecondsForPrefix("0723") + seconds, credit, bucketList := ub1.getSecondsForPrefix("0723") expected := 21.0 - if seconds != expected || bucketList[0].Weight < bucketList[1].Weight { + if credit != 0 || seconds != expected || bucketList[0].Weight < bucketList[1].Weight { t.Errorf("Expected %v was %v", expected, seconds) } } @@ -168,7 +168,6 @@ func TestDebitPriceMinuteBalance(t *testing.T) { rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21}} err := rifsBalance.debitMinutesBalance(5, "0723") if b2.Seconds != 95 || b1.Seconds != 10 || err != nil || rifsBalance.BalanceMap[CREDIT] != 16 { - t.Log(rifsBalance.BalanceMap[CREDIT]) t.Errorf("Expected %v was %v", 16, rifsBalance.BalanceMap[CREDIT]) } }