mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-24 08:38:45 +05:00
converted minutebucket to balance, compiled but test fail
This commit is contained in:
@@ -28,17 +28,16 @@ import (
|
||||
Structure to be filled for each tariff plan with the bonus value for received calls minutes.
|
||||
*/
|
||||
type Action struct {
|
||||
Id string
|
||||
ActionType string
|
||||
BalanceId string
|
||||
Direction string
|
||||
ExpirationString string
|
||||
ExpirationDate time.Time
|
||||
Units float64
|
||||
Weight float64
|
||||
MinuteBucket *MinuteBucket
|
||||
DestinationTag, RateType string // From here for import/load purposes only
|
||||
RateValue, MinutesWeight float64
|
||||
Id string
|
||||
ActionType string
|
||||
BalanceId string
|
||||
Direction string
|
||||
ExpirationString string
|
||||
Weight float64
|
||||
Balance *Balance
|
||||
DestinationTag, RateType string // From here for import/load purposes only
|
||||
ExpirationDate time.Time
|
||||
Units, RateValue, MinutesWeight float64
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -86,7 +85,7 @@ func getActionFunc(typ string) (actionTypeFunc, bool) {
|
||||
}
|
||||
|
||||
func logAction(ub *UserBalance, a *Action) (err error) {
|
||||
Logger.Info(fmt.Sprintf("%v %v %v", a.BalanceId, a.Units, a.MinuteBucket))
|
||||
Logger.Info(fmt.Sprintf("%v %v %v", a.BalanceId, a.Balance))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -116,11 +115,7 @@ func resetPrepaidAction(ub *UserBalance, a *Action) (err error) {
|
||||
}
|
||||
|
||||
func topupResetAction(ub *UserBalance, a *Action) (err error) {
|
||||
if a.BalanceId == MINUTES {
|
||||
ub.MinuteBuckets = make([]*MinuteBucket, 0)
|
||||
} else {
|
||||
ub.BalanceMap[a.BalanceId+a.Direction] = BalanceChain{&Balance{Value: 0}} // ToDo: can ub be empty here?
|
||||
}
|
||||
ub.BalanceMap[a.BalanceId+a.Direction] = BalanceChain{&Balance{Value: 0}} // ToDo: can ub be empty here?
|
||||
genericMakeNegative(a)
|
||||
genericDebit(ub, a)
|
||||
return
|
||||
@@ -157,11 +152,8 @@ func resetCountersAction(ub *UserBalance, a *Action) (err error) {
|
||||
}
|
||||
|
||||
func genericMakeNegative(a *Action) {
|
||||
if a.Units > 0 { // only apply if not allready negative
|
||||
a.Units = -a.Units
|
||||
}
|
||||
if a.MinuteBucket != nil && a.MinuteBucket.Seconds > 0 {
|
||||
a.MinuteBucket.Seconds = -a.MinuteBucket.Seconds
|
||||
if a.Balance != nil && a.Balance.Value > 0 { // only apply if not allready negative
|
||||
a.Balance.Value = -a.Balance.Value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +162,7 @@ func genericDebit(ub *UserBalance, a *Action) (err error) {
|
||||
ub.BalanceMap = make(map[string]BalanceChain)
|
||||
}
|
||||
if a.BalanceId == MINUTES {
|
||||
ub.debitMinuteBucket(a.MinuteBucket)
|
||||
ub.debitMinuteBalance(a.Balance)
|
||||
} else {
|
||||
ub.debitBalanceAction(a)
|
||||
}
|
||||
@@ -181,7 +173,6 @@ func genericReset(ub *UserBalance) {
|
||||
for k, _ := range ub.BalanceMap {
|
||||
ub.BalanceMap[k] = BalanceChain{&Balance{Value: 0}}
|
||||
}
|
||||
ub.MinuteBuckets = make([]*MinuteBucket, 0)
|
||||
ub.UnitCounters = make([]*UnitsCounter, 0)
|
||||
ub.resetActionTriggers(nil)
|
||||
}
|
||||
|
||||
@@ -219,10 +219,7 @@ func (at *ActionTiming) Execute() (err error) {
|
||||
return
|
||||
}
|
||||
for _, a := range aac {
|
||||
a.ExpirationDate, _ = utils.ParseDate(a.ExpirationString)
|
||||
if a.MinuteBucket != nil {
|
||||
a.MinuteBucket.ExpirationDate = a.ExpirationDate
|
||||
}
|
||||
a.Balance.ExpirationDate, _ = utils.ParseDate(a.ExpirationString)
|
||||
actionFunction, exists := getActionFunc(a.ActionType)
|
||||
if !exists {
|
||||
Logger.Crit(fmt.Sprintf("Function type %v not available, aborting execution!", a.ActionType))
|
||||
|
||||
@@ -46,10 +46,10 @@ func (at *ActionTrigger) Execute(ub *UserBalance) (err error) {
|
||||
return
|
||||
}
|
||||
for _, a := range aac {
|
||||
a.ExpirationDate, _ = utils.ParseDate(a.ExpirationString)
|
||||
if a.MinuteBucket != nil {
|
||||
a.MinuteBucket.ExpirationDate = a.ExpirationDate
|
||||
if a.Balance == nil {
|
||||
a.Balance = &Balance{}
|
||||
}
|
||||
a.Balance.ExpirationDate, _ = utils.ParseDate(a.ExpirationString)
|
||||
actionFunction, exists := getActionFunc(a.ActionType)
|
||||
if !exists {
|
||||
Logger.Warning(fmt.Sprintf("Function type %v not available, aborting execution!", a.ActionType))
|
||||
@@ -73,9 +73,9 @@ func (at *ActionTrigger) Match(a *Action) bool {
|
||||
id := a.BalanceId == "" || at.BalanceId == a.BalanceId
|
||||
direction := a.Direction == "" || at.Direction == a.Direction
|
||||
thresholdType, thresholdValue := true, true
|
||||
if a.MinuteBucket != nil {
|
||||
thresholdType = a.MinuteBucket.PriceType == "" || at.ThresholdType == a.MinuteBucket.PriceType
|
||||
thresholdValue = a.MinuteBucket.Price == 0 || at.ThresholdValue == a.MinuteBucket.Price
|
||||
if a.Balance != nil {
|
||||
thresholdType = a.Balance.SpecialPriceType == "" || at.ThresholdType == a.Balance.SpecialPriceType
|
||||
thresholdValue = a.Balance.SpecialPrice == 0 || at.ThresholdValue == a.Balance.SpecialPrice
|
||||
}
|
||||
return id && direction && thresholdType && thresholdValue
|
||||
}
|
||||
|
||||
@@ -338,10 +338,9 @@ func TestActionTimingOneTimeRun(t *testing.T) {
|
||||
|
||||
func TestActionTimingLogFunction(t *testing.T) {
|
||||
a := &Action{
|
||||
ActionType: "*log",
|
||||
BalanceId: "test",
|
||||
Units: 1.1,
|
||||
MinuteBucket: &MinuteBucket{},
|
||||
ActionType: "*log",
|
||||
BalanceId: "test",
|
||||
Balance: &Balance{Value: 1.1},
|
||||
}
|
||||
at := &ActionTiming{
|
||||
actions: []*Action{a},
|
||||
@@ -446,7 +445,7 @@ func TestActionTriggerMatchMinuteBucketFull(t *testing.T) {
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{MinuteBucket: &MinuteBucket{PriceType: TRIGGER_MAX_BALANCE, Price: 2}}
|
||||
a := &Action{Balance: &Balance{SpecialPriceType: TRIGGER_MAX_BALANCE, SpecialPrice: 2}}
|
||||
if !at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -459,7 +458,7 @@ func TestActionTriggerMatchAllFull(t *testing.T) {
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: OUTBOUND, BalanceId: CREDIT, MinuteBucket: &MinuteBucket{PriceType: TRIGGER_MAX_BALANCE, Price: 2}}
|
||||
a := &Action{Direction: OUTBOUND, BalanceId: CREDIT, Balance: &Balance{SpecialPriceType: TRIGGER_MAX_BALANCE, SpecialPrice: 2}}
|
||||
if !at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -472,20 +471,20 @@ func TestActionTriggerMatchSomeFalse(t *testing.T) {
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: INBOUND, BalanceId: CREDIT, MinuteBucket: &MinuteBucket{PriceType: TRIGGER_MAX_BALANCE, Price: 2}}
|
||||
a := &Action{Direction: INBOUND, BalanceId: CREDIT, Balance: &Balance{SpecialPriceType: TRIGGER_MAX_BALANCE, SpecialPrice: 2}}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionTriggerMatcMinuteBucketFalse(t *testing.T) {
|
||||
func TestActionTriggerMatcBalanceFalse(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: CREDIT,
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: OUTBOUND, BalanceId: CREDIT, MinuteBucket: &MinuteBucket{PriceType: TRIGGER_MAX_BALANCE, Price: 3}}
|
||||
a := &Action{Direction: OUTBOUND, BalanceId: CREDIT, Balance: &Balance{SpecialPriceType: TRIGGER_MAX_BALANCE, SpecialPrice: 3}}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -498,7 +497,7 @@ func TestActionTriggerMatcAllFalse(t *testing.T) {
|
||||
ThresholdType: TRIGGER_MAX_BALANCE,
|
||||
ThresholdValue: 2,
|
||||
}
|
||||
a := &Action{Direction: INBOUND, BalanceId: MINUTES, MinuteBucket: &MinuteBucket{PriceType: TRIGGER_MAX_COUNTER, Price: 3}}
|
||||
a := &Action{Direction: INBOUND, BalanceId: MINUTES, Balance: &Balance{SpecialPriceType: TRIGGER_MAX_COUNTER, SpecialPrice: 3}}
|
||||
if at.Match(a) {
|
||||
t.Errorf("Action trigger [%v] does not match action [%v]", at, a)
|
||||
}
|
||||
@@ -522,7 +521,7 @@ func TestActionTriggerPriotityList(t *testing.T) {
|
||||
BalanceId: "BALANCE",
|
||||
Units: 10,
|
||||
Weight: 11,
|
||||
MinuteBucket: &MinuteBucket{},
|
||||
Balance: &Balance{},
|
||||
}
|
||||
logAction(nil, a)
|
||||
}*/
|
||||
@@ -530,9 +529,8 @@ func TestActionTriggerPriotityList(t *testing.T) {
|
||||
func TestActionResetTriggres(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 10}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 10}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetTriggersAction(ub, nil)
|
||||
@@ -557,9 +555,8 @@ func TestActionResetTriggresExecutesThem(t *testing.T) {
|
||||
func TestActionResetTriggresActionFilter(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 10}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 10}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetTriggersAction(ub, &Action{BalanceId: SMS})
|
||||
@@ -572,9 +569,8 @@ func TestActionSetPostpaid(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
setPostpaidAction(ub, nil)
|
||||
@@ -587,9 +583,8 @@ func TestActionSetPrepaid(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
setPrepaidAction(ub, nil)
|
||||
@@ -602,16 +597,15 @@ func TestActionResetPrepaid(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetPrepaidAction(ub, nil)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 0 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
len(ub.MinuteBuckets) != 0 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 0 ||
|
||||
ub.ActionTriggers[0].Executed == true || ub.ActionTriggers[1].Executed == true {
|
||||
t.Error("Reset prepaid action failed!")
|
||||
}
|
||||
@@ -621,16 +615,15 @@ func TestActionResetPostpaid(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: SMS, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetPostpaidAction(ub, nil)
|
||||
if ub.Type != UB_TYPE_POSTPAID ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 0 ||
|
||||
len(ub.UnitCounters) != 0 ||
|
||||
len(ub.MinuteBuckets) != 0 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 0 ||
|
||||
ub.ActionTriggers[0].Executed == true || ub.ActionTriggers[1].Executed == true {
|
||||
t.Error("Reset postpaid action failed!")
|
||||
}
|
||||
@@ -640,9 +633,8 @@ func TestActionTopupResetCredit(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: CREDIT, Direction: OUTBOUND, Units: 10}
|
||||
@@ -650,7 +642,7 @@ func TestActionTopupResetCredit(t *testing.T) {
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue() != 10 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.MinuteBuckets) != 2 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Errorf("Topup reset action failed: %#v", ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue())
|
||||
}
|
||||
@@ -660,20 +652,19 @@ func TestActionTopupResetMinutes(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: MINUTES, Direction: OUTBOUND, MinuteBucket: &MinuteBucket{Seconds: 5, Weight: 20, Price: 1, DestinationId: "NAT"}}
|
||||
a := &Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: &Balance{Value: 5, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}}
|
||||
topupResetAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
ub.MinuteBuckets[0].Seconds != 5 ||
|
||||
ub.BalanceMap[MINUTES][0].Value != 5 ||
|
||||
ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.MinuteBuckets) != 1 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 1 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Topup reset minutes action failed!", ub.MinuteBuckets[0])
|
||||
t.Error("Topup reset minutes action failed!", ub.BalanceMap[MINUTES][0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -681,9 +672,8 @@ func TestActionTopupCredit(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: CREDIT, Direction: OUTBOUND, Units: 10}
|
||||
@@ -691,7 +681,7 @@ func TestActionTopupCredit(t *testing.T) {
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue() != 110 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.MinuteBuckets) != 2 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Topup action failed!", ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue())
|
||||
}
|
||||
@@ -701,20 +691,19 @@ func TestActionTopupMinutes(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: MINUTES, MinuteBucket: &MinuteBucket{Seconds: 5, Weight: 20, Price: 1, DestinationId: "NAT"}}
|
||||
a := &Action{BalanceId: MINUTES, Balance: &Balance{Value: 5, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}}
|
||||
topupAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
ub.MinuteBuckets[0].Seconds != 15 ||
|
||||
ub.BalanceMap[MINUTES][0].Value != 15 ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.MinuteBuckets) != 2 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Topup minutes action failed!", ub.MinuteBuckets[0])
|
||||
t.Error("Topup minutes action failed!", ub.BalanceMap[MINUTES][0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,9 +711,8 @@ func TestActionDebitCredit(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: CREDIT, Direction: OUTBOUND, Units: 10}
|
||||
@@ -732,7 +720,7 @@ func TestActionDebitCredit(t *testing.T) {
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue() != 90 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.MinuteBuckets) != 2 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Debit action failed!", ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue())
|
||||
}
|
||||
@@ -742,20 +730,19 @@ func TestActionDebitMinutes(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}, &ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: MINUTES, MinuteBucket: &MinuteBucket{Seconds: 5, Weight: 20, Price: 1, DestinationId: "NAT"}}
|
||||
a := &Action{BalanceId: MINUTES, Balance: &Balance{Value: 5, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}}
|
||||
debitAction(ub, a)
|
||||
if ub.Type != UB_TYPE_PREPAID ||
|
||||
ub.MinuteBuckets[0].Seconds != 5 ||
|
||||
ub.BalanceMap[MINUTES][0].Value != 5 ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.MinuteBuckets) != 2 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true || ub.ActionTriggers[1].Executed != true {
|
||||
t.Error("Debit minutes action failed!", ub.MinuteBuckets[0])
|
||||
t.Error("Debit minutes action failed!", ub.BalanceMap[MINUTES][0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,25 +750,24 @@ func TestActionResetAllCounters(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
resetCountersAction(ub, nil)
|
||||
if ub.Type != UB_TYPE_POSTPAID ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 1 ||
|
||||
len(ub.UnitCounters[0].MinuteBuckets) != 1 ||
|
||||
len(ub.MinuteBuckets) != 2 ||
|
||||
len(ub.UnitCounters[0].MinuteBalances) != 1 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true {
|
||||
t.Error("Reset counters action failed!")
|
||||
}
|
||||
if len(ub.UnitCounters) < 1 {
|
||||
t.FailNow()
|
||||
}
|
||||
mb := ub.UnitCounters[0].MinuteBuckets[0]
|
||||
if mb.Weight != 20 || mb.Price != 1 || mb.Seconds != 10 || mb.DestinationId != "NAT" {
|
||||
mb := ub.UnitCounters[0].MinuteBalances[0]
|
||||
if mb.Weight != 20 || mb.SpecialPrice != 1 || mb.Value != 10 || mb.DestinationId != "NAT" {
|
||||
t.Errorf("Minute bucked cloned incorrectly: %v!", mb)
|
||||
}
|
||||
}
|
||||
@@ -790,9 +776,8 @@ func TestActionResetCounterMinutes(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: MINUTES}
|
||||
@@ -800,16 +785,16 @@ func TestActionResetCounterMinutes(t *testing.T) {
|
||||
if ub.Type != UB_TYPE_POSTPAID ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 2 ||
|
||||
len(ub.UnitCounters[1].MinuteBuckets) != 1 ||
|
||||
len(ub.MinuteBuckets) != 2 ||
|
||||
len(ub.UnitCounters[1].MinuteBalances) != 1 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true {
|
||||
t.Error("Reset counters action failed!", ub.UnitCounters[1].MinuteBuckets)
|
||||
t.Error("Reset counters action failed!", ub.UnitCounters[1].MinuteBalances)
|
||||
}
|
||||
if len(ub.UnitCounters) < 2 || len(ub.UnitCounters[1].MinuteBuckets) < 1 {
|
||||
if len(ub.UnitCounters) < 2 || len(ub.UnitCounters[1].MinuteBalances) < 1 {
|
||||
t.FailNow()
|
||||
}
|
||||
mb := ub.UnitCounters[1].MinuteBuckets[0]
|
||||
if mb.Weight != 20 || mb.Price != 1 || mb.Seconds != 10 || mb.DestinationId != "NAT" {
|
||||
mb := ub.UnitCounters[1].MinuteBalances[0]
|
||||
if mb.Weight != 20 || mb.SpecialPrice != 1 || mb.Value != 10 || mb.DestinationId != "NAT" {
|
||||
t.Errorf("Minute bucked cloned incorrectly: %v!", mb)
|
||||
}
|
||||
}
|
||||
@@ -818,9 +803,8 @@ func TestActionResetCounterCREDIT(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1}, &UnitsCounter{BalanceId: SMS, Direction: OUTBOUND, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
|
||||
}
|
||||
a := &Action{BalanceId: CREDIT, Direction: OUTBOUND}
|
||||
@@ -828,7 +812,7 @@ func TestActionResetCounterCREDIT(t *testing.T) {
|
||||
if ub.Type != UB_TYPE_POSTPAID ||
|
||||
ub.BalanceMap[CREDIT].GetTotalValue() != 100 ||
|
||||
len(ub.UnitCounters) != 2 ||
|
||||
len(ub.MinuteBuckets) != 2 ||
|
||||
len(ub.BalanceMap[MINUTES]) != 2 ||
|
||||
ub.ActionTriggers[0].Executed != true {
|
||||
t.Error("Reset counters action failed!", ub.UnitCounters)
|
||||
}
|
||||
|
||||
@@ -26,14 +26,15 @@ import (
|
||||
|
||||
// Can hold different units as seconds or monetary
|
||||
type Balance struct {
|
||||
Id string
|
||||
Value float64
|
||||
ExpirationDate time.Time
|
||||
Weight float64
|
||||
GroupIds []string
|
||||
SpecialPrice float64 // absolute for minutes and percent for monetary (can be positive or negative)
|
||||
DestinationId string
|
||||
precision int
|
||||
Id string
|
||||
Value float64
|
||||
ExpirationDate time.Time
|
||||
Weight float64
|
||||
GroupIds []string
|
||||
SpecialPriceType string
|
||||
SpecialPrice float64 // absolute for minutes and percent for monetary (can be positive or negative)
|
||||
DestinationId string
|
||||
precision int
|
||||
}
|
||||
|
||||
func (b *Balance) Equal(o *Balance) bool {
|
||||
|
||||
@@ -197,13 +197,13 @@ func (cd *CallDescriptor) splitInTimeSpans(firstSpan *TimeSpan) (timespans []*Ti
|
||||
timespans = append(timespans, firstSpan)
|
||||
// split on (free) minute buckets
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
_, _, bucketList := userBalance.getSecondsForPrefix(cd.Destination)
|
||||
for _, mb := range bucketList {
|
||||
_, _, minuteBalances := userBalance.getSecondsForPrefix(cd.Destination)
|
||||
for _, b := range minuteBalances {
|
||||
for i := 0; i < len(timespans); i++ {
|
||||
if timespans[i].MinuteInfo != nil {
|
||||
continue
|
||||
}
|
||||
newTs := timespans[i].SplitByMinuteBucket(mb)
|
||||
newTs := timespans[i].SplitByMinuteBalance(b)
|
||||
if newTs != nil {
|
||||
timespans = append(timespans, newTs)
|
||||
firstSpan = newTs // we move the firstspan to the newly created one for further spliting
|
||||
@@ -443,8 +443,8 @@ The amount filed has to be filled in call descriptor.
|
||||
func (cd *CallDescriptor) AddRecievedCallSeconds() (err error) {
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
a := &Action{
|
||||
Direction: INBOUND,
|
||||
MinuteBucket: &MinuteBucket{Seconds: cd.Amount, DestinationId: cd.Destination},
|
||||
Direction: INBOUND,
|
||||
Balance: &Balance{Value: cd.Amount, DestinationId: cd.Destination},
|
||||
}
|
||||
userBalance.countUnits(a)
|
||||
return nil
|
||||
|
||||
@@ -36,21 +36,20 @@ func init() {
|
||||
|
||||
func populateDB() {
|
||||
minu := &UserBalance{
|
||||
Id: "*out:vdf:minu",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 0}}},
|
||||
MinuteBuckets: []*MinuteBucket{
|
||||
&MinuteBucket{Seconds: 200, DestinationId: "NAT", Weight: 10},
|
||||
&MinuteBucket{Seconds: 100, DestinationId: "RET", Weight: 20},
|
||||
},
|
||||
Id: "*out:vdf:minu",
|
||||
Type: UB_TYPE_PREPAID,
|
||||
BalanceMap: map[string]BalanceChain{CREDIT: BalanceChain{&Balance{Value: 0}}, MINUTES: BalanceChain{
|
||||
&Balance{Value: 200, DestinationId: "NAT", Weight: 10},
|
||||
&Balance{Value: 100, DestinationId: "RET", Weight: 20},
|
||||
}},
|
||||
}
|
||||
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},
|
||||
},
|
||||
BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{
|
||||
&Balance{Value: 20, DestinationId: "NAT", Weight: 10, SpecialPrice: 1},
|
||||
&Balance{Value: 100, DestinationId: "RET", Weight: 20},
|
||||
}},
|
||||
}
|
||||
if storageGetter != nil {
|
||||
storageGetter.(Storage).Flush()
|
||||
|
||||
@@ -348,50 +348,35 @@ func (csvr *CSVReader) LoadActions() (err error) {
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse action units: %v", err))
|
||||
}
|
||||
var a *Action
|
||||
if record[2] != MINUTES {
|
||||
a = &Action{
|
||||
ActionType: record[1],
|
||||
BalanceId: record[2],
|
||||
Direction: record[3],
|
||||
Units: units,
|
||||
ExpirationString: record[5],
|
||||
}
|
||||
if _, err := utils.ParseDate(a.ExpirationString); err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse expiration time: %v", err))
|
||||
}
|
||||
} else {
|
||||
value, err := strconv.ParseFloat(record[8], 64)
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse action price: %v", err))
|
||||
}
|
||||
minutesWeight, err := strconv.ParseFloat(record[9], 64)
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse action minutes weight: %v", err))
|
||||
}
|
||||
weight, err := strconv.ParseFloat(record[9], 64)
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse action weight: %v", err))
|
||||
}
|
||||
a = &Action{
|
||||
Id: utils.GenUUID(),
|
||||
ActionType: record[1],
|
||||
BalanceId: record[2],
|
||||
Direction: record[3],
|
||||
Weight: weight,
|
||||
ExpirationString: record[5],
|
||||
MinuteBucket: &MinuteBucket{
|
||||
Seconds: units,
|
||||
Weight: minutesWeight,
|
||||
Price: value,
|
||||
PriceType: record[7],
|
||||
DestinationId: record[6],
|
||||
},
|
||||
}
|
||||
if _, err := utils.ParseDate(a.ExpirationString); err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse expiration time: %v", err))
|
||||
}
|
||||
|
||||
value, err := strconv.ParseFloat(record[8], 64)
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse action price: %v", err))
|
||||
}
|
||||
minutesWeight, err := strconv.ParseFloat(record[9], 64)
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse action minutes weight: %v", err))
|
||||
}
|
||||
weight, err := strconv.ParseFloat(record[9], 64)
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse action weight: %v", err))
|
||||
}
|
||||
a := &Action{
|
||||
Id: utils.GenUUID(),
|
||||
ActionType: record[1],
|
||||
BalanceId: record[2],
|
||||
Direction: record[3],
|
||||
Weight: weight,
|
||||
ExpirationString: record[5],
|
||||
Balance: &Balance{
|
||||
Value: units,
|
||||
Weight: minutesWeight,
|
||||
SpecialPrice: value,
|
||||
SpecialPriceType: record[7],
|
||||
DestinationId: record[6],
|
||||
},
|
||||
}
|
||||
if _, err := utils.ParseDate(a.ExpirationString); err != nil {
|
||||
return errors.New(fmt.Sprintf("Could not parse expiration time: %v", err))
|
||||
}
|
||||
csvr.actions[tag] = append(csvr.actions[tag], a)
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
Rating system designed to be used in VoIP Carriers World
|
||||
Copyright (C) 2013 ITsysCOM
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MinuteBucket struct {
|
||||
Seconds float64
|
||||
Weight float64
|
||||
Price float64 // percentage from standard price or absolute value depending on Type
|
||||
PriceType string
|
||||
DestinationId string
|
||||
ExpirationDate time.Time
|
||||
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 {
|
||||
seconds = math.Min(credit/mb.Price, mb.Seconds)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Creates a similar minute
|
||||
func (mb *MinuteBucket) Clone() *MinuteBucket {
|
||||
return &MinuteBucket{
|
||||
Seconds: mb.Seconds,
|
||||
Weight: mb.Weight,
|
||||
Price: mb.Price,
|
||||
PriceType: mb.PriceType,
|
||||
DestinationId: mb.DestinationId,
|
||||
}
|
||||
}
|
||||
|
||||
// Equal method
|
||||
func (mb *MinuteBucket) Equal(o *MinuteBucket) bool {
|
||||
return mb.DestinationId == o.DestinationId &&
|
||||
mb.Weight == o.Weight &&
|
||||
mb.Price == o.Price &&
|
||||
mb.ExpirationDate.Equal(o.ExpirationDate)
|
||||
}
|
||||
|
||||
func (mb *MinuteBucket) IsExpired() bool {
|
||||
return !mb.ExpirationDate.IsZero() && mb.ExpirationDate.Before(time.Now())
|
||||
}
|
||||
|
||||
/*
|
||||
Structure to store minute buckets according to weight, precision or price.
|
||||
*/
|
||||
type bucketsorter []*MinuteBucket
|
||||
|
||||
func (bs bucketsorter) Len() int {
|
||||
return len(bs)
|
||||
}
|
||||
|
||||
func (bs bucketsorter) Swap(i, j int) {
|
||||
bs[i], bs[j] = bs[j], bs[i]
|
||||
}
|
||||
|
||||
func (bs bucketsorter) Less(j, i int) bool {
|
||||
return bs[i].Weight < bs[j].Weight ||
|
||||
bs[i].precision < bs[j].precision ||
|
||||
bs[i].Price > bs[j].Price
|
||||
}
|
||||
|
||||
func (bs bucketsorter) Sort() {
|
||||
sort.Sort(bs)
|
||||
}
|
||||
@@ -24,9 +24,9 @@ import (
|
||||
)
|
||||
|
||||
func TestMinutBucketSortWeight(t *testing.T) {
|
||||
mb1 := &MinuteBucket{Weight: 1, precision: 2, Price: 2}
|
||||
mb2 := &MinuteBucket{Weight: 2, precision: 1, Price: 1}
|
||||
var bs bucketsorter
|
||||
mb1 := &Balance{Weight: 1, precision: 2, SpecialPrice: 2}
|
||||
mb2 := &Balance{Weight: 2, precision: 1, SpecialPrice: 1}
|
||||
var bs BalanceChain
|
||||
bs = append(bs, mb2, mb1)
|
||||
bs.Sort()
|
||||
if bs[0] != mb1 || bs[1] != mb2 {
|
||||
@@ -35,9 +35,9 @@ func TestMinutBucketSortWeight(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMinutBucketSortPrecision(t *testing.T) {
|
||||
mb1 := &MinuteBucket{Weight: 1, precision: 2, Price: 2}
|
||||
mb2 := &MinuteBucket{Weight: 1, precision: 1, Price: 1}
|
||||
var bs bucketsorter
|
||||
mb1 := &Balance{Weight: 1, precision: 2, SpecialPrice: 2}
|
||||
mb2 := &Balance{Weight: 1, precision: 1, SpecialPrice: 1}
|
||||
var bs BalanceChain
|
||||
bs = append(bs, mb2, mb1)
|
||||
bs.Sort()
|
||||
if bs[0] != mb1 || bs[1] != mb2 {
|
||||
@@ -45,10 +45,10 @@ func TestMinutBucketSortPrecision(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinutBucketSortPrice(t *testing.T) {
|
||||
mb1 := &MinuteBucket{Weight: 1, precision: 1, Price: 1}
|
||||
mb2 := &MinuteBucket{Weight: 1, precision: 1, Price: 2}
|
||||
var bs bucketsorter
|
||||
func TestMinutBucketSortSpecialPrice(t *testing.T) {
|
||||
mb1 := &Balance{Weight: 1, precision: 1, SpecialPrice: 1}
|
||||
mb2 := &Balance{Weight: 1, precision: 1, SpecialPrice: 2}
|
||||
var bs BalanceChain
|
||||
bs = append(bs, mb2, mb1)
|
||||
bs.Sort()
|
||||
if bs[0] != mb1 || bs[1] != mb2 {
|
||||
@@ -57,16 +57,16 @@ func TestMinutBucketSortPrice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMinutBucketEqual(t *testing.T) {
|
||||
mb1 := &MinuteBucket{Weight: 1, precision: 1, Price: 1, PriceType: PRICE_ABSOLUTE, DestinationId: ""}
|
||||
mb2 := &MinuteBucket{Weight: 1, precision: 1, Price: 1, PriceType: PRICE_ABSOLUTE, DestinationId: ""}
|
||||
mb3 := &MinuteBucket{Weight: 1, precision: 1, Price: 2, PriceType: PRICE_ABSOLUTE, DestinationId: ""}
|
||||
mb1 := &Balance{Weight: 1, precision: 1, SpecialPrice: 1, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: ""}
|
||||
mb2 := &Balance{Weight: 1, precision: 1, SpecialPrice: 1, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: ""}
|
||||
mb3 := &Balance{Weight: 1, precision: 1, SpecialPrice: 2, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: ""}
|
||||
if !mb1.Equal(mb2) || mb2.Equal(mb3) {
|
||||
t.Error("Equal failure!", mb1, mb2, mb3)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinutBucketClone(t *testing.T) {
|
||||
mb1 := &MinuteBucket{Seconds: 1, Weight: 2, Price: 3, PriceType: PRICE_ABSOLUTE, DestinationId: "5"}
|
||||
mb1 := &Balance{Value: 1, Weight: 2, SpecialPrice: 3, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "5"}
|
||||
mb2 := mb1.Clone()
|
||||
if mb1 == mb2 || !reflect.DeepEqual(mb1, mb2) {
|
||||
t.Error("Cloning failure: ", mb1, mb2)
|
||||
|
||||
@@ -540,7 +540,7 @@ func (self *SQLStorage) SetTPActions(tpid string, acts map[string][]*Action) err
|
||||
qry += ","
|
||||
}
|
||||
qry += fmt.Sprintf("('%s','%s','%s','%s','%s',%f,'%s','%s','%s',%f,%f,%f)",
|
||||
tpid, actId, act.ActionType, act.BalanceId, act.Direction, act.Units, act.ExpirationString,
|
||||
tpid, actId, act.ActionType, act.BalanceId, act.Direction, act.Balance.Value, act.ExpirationString,
|
||||
act.DestinationTag, act.RateType, act.RateValue, act.MinutesWeight, act.Weight)
|
||||
i++
|
||||
}
|
||||
@@ -1083,32 +1083,21 @@ func (self *SQLStorage) GetTpActions(tpid, tag string) (map[string][]*Action, er
|
||||
if err := rows.Scan(&id, &tpid, &tag, &action, &balance_type, &direction, &units, &expirationDate, &destinations_tag, &rate_type, &rate, &minutes_weight, &weight); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var a *Action
|
||||
if balance_type != MINUTES {
|
||||
a = &Action{
|
||||
ActionType: action,
|
||||
BalanceId: balance_type,
|
||||
Direction: direction,
|
||||
Units: units,
|
||||
ExpirationString: expirationDate,
|
||||
}
|
||||
} else {
|
||||
var price float64
|
||||
a = &Action{
|
||||
Id: utils.GenUUID(),
|
||||
ActionType: action,
|
||||
BalanceId: balance_type,
|
||||
Direction: direction,
|
||||
Weight: weight,
|
||||
ExpirationString: expirationDate,
|
||||
MinuteBucket: &MinuteBucket{
|
||||
Seconds: units,
|
||||
Weight: minutes_weight,
|
||||
Price: price,
|
||||
PriceType: rate_type,
|
||||
DestinationId: destinations_tag,
|
||||
},
|
||||
}
|
||||
var price float64
|
||||
a := &Action{
|
||||
Id: utils.GenUUID(),
|
||||
ActionType: action,
|
||||
BalanceId: balance_type,
|
||||
Direction: direction,
|
||||
Weight: weight,
|
||||
ExpirationString: expirationDate,
|
||||
Balance: &Balance{
|
||||
Value: units,
|
||||
Weight: minutes_weight,
|
||||
SpecialPrice: price,
|
||||
SpecialPriceType: rate_type,
|
||||
DestinationId: destinations_tag,
|
||||
},
|
||||
}
|
||||
as[tag] = append(as[tag], a)
|
||||
}
|
||||
|
||||
@@ -75,10 +75,10 @@ func TestMsgpackTime(t *testing.T) {
|
||||
|
||||
func GetUB() *UserBalance {
|
||||
uc := &UnitsCounter{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Units: 100,
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Units: 100,
|
||||
MinuteBalances: BalanceChain{&Balance{Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
}
|
||||
at := &ActionTrigger{
|
||||
Id: "some_uuid",
|
||||
@@ -94,8 +94,7 @@ func GetUB() *UserBalance {
|
||||
ub := &UserBalance{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}, MINUTES: BalanceChain{&Balance{Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{uc, uc},
|
||||
ActionTriggers: ActionTriggerPriotityList{at, at, at},
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ func (ts *TimeSpan) SplitByActivationPeriod(ap *ActivationPeriod) (newTs *TimeSp
|
||||
/*
|
||||
Splits the given timespan on minute bucket's duration.
|
||||
*/
|
||||
func (ts *TimeSpan) SplitByMinuteBucket(mb *MinuteBucket) (newTs *TimeSpan) {
|
||||
func (ts *TimeSpan) SplitByMinuteBalance(mb *Balance) (newTs *TimeSpan) {
|
||||
// if mb expired skip it
|
||||
if !mb.ExpirationDate.IsZero() && (ts.TimeStart.Equal(mb.ExpirationDate) || ts.TimeStart.After(mb.ExpirationDate)) {
|
||||
return nil
|
||||
@@ -197,20 +197,20 @@ func (ts *TimeSpan) SplitByMinuteBucket(mb *MinuteBucket) (newTs *TimeSpan) {
|
||||
}
|
||||
|
||||
s := ts.GetDuration().Seconds()
|
||||
ts.MinuteInfo = &MinuteInfo{mb.DestinationId, s, mb.Price}
|
||||
if s <= mb.Seconds {
|
||||
mb.Seconds -= s
|
||||
ts.MinuteInfo = &MinuteInfo{mb.DestinationId, s, mb.SpecialPrice}
|
||||
if s <= mb.Value {
|
||||
mb.Value -= s
|
||||
return newTs
|
||||
}
|
||||
secDuration, _ := time.ParseDuration(fmt.Sprintf("%vs", mb.Seconds))
|
||||
secDuration, _ := time.ParseDuration(fmt.Sprintf("%vs", mb.Value))
|
||||
|
||||
newTimeEnd := ts.TimeStart.Add(secDuration)
|
||||
newTs = &TimeSpan{TimeStart: newTimeEnd, TimeEnd: ts.TimeEnd}
|
||||
ts.TimeEnd = newTimeEnd
|
||||
newTs.CallDuration = ts.CallDuration
|
||||
ts.MinuteInfo.Quantity = mb.Seconds
|
||||
ts.MinuteInfo.Quantity = mb.Value
|
||||
ts.SetNewCallDuration(newTs)
|
||||
mb.Seconds = 0
|
||||
mb.Value = 0
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -220,9 +220,9 @@ func TestSetInterval(t *testing.T) {
|
||||
func TestTimespanSplitByMinuteBucketPlenty(t *testing.T) {
|
||||
t1 := time.Date(2013, time.July, 15, 10, 40, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)
|
||||
mb := &MinuteBucket{Seconds: 180}
|
||||
mb := &Balance{Value: 180}
|
||||
ts := TimeSpan{TimeStart: t1, TimeEnd: t2}
|
||||
newTs := ts.SplitByMinuteBucket(mb)
|
||||
newTs := ts.SplitByMinuteBalance(mb)
|
||||
if ts.MinuteInfo == nil || ts.MinuteInfo.Quantity != 120 {
|
||||
t.Error("Not enough minutes on minute bucket split")
|
||||
}
|
||||
@@ -231,12 +231,12 @@ func TestTimespanSplitByMinuteBucketPlenty(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimespanSplitByMinuteBucketScarce(t *testing.T) {
|
||||
func TestTimespanSplitByMinuteBalanceScarce(t *testing.T) {
|
||||
t1 := time.Date(2013, time.July, 15, 10, 40, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)
|
||||
mb := &MinuteBucket{Seconds: 60}
|
||||
mb := &Balance{Value: 60}
|
||||
ts := TimeSpan{TimeStart: t1, TimeEnd: t2}
|
||||
newTs := ts.SplitByMinuteBucket(mb)
|
||||
newTs := ts.SplitByMinuteBalance(mb)
|
||||
if ts.MinuteInfo == nil || ts.MinuteInfo.Quantity != 60 {
|
||||
t.Error("Not enough minutes on minute bucket split")
|
||||
}
|
||||
@@ -245,12 +245,12 @@ func TestTimespanSplitByMinuteBucketScarce(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimespanSplitByMinuteBucketPlentyExpired(t *testing.T) {
|
||||
func TestTimespanSplitByMinuteBalancePlentyExpired(t *testing.T) {
|
||||
t1 := time.Date(2013, time.July, 15, 10, 40, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)
|
||||
mb := &MinuteBucket{Seconds: 180, ExpirationDate: time.Date(2013, time.July, 15, 10, 39, 0, 0, time.UTC)}
|
||||
mb := &Balance{Value: 180, ExpirationDate: time.Date(2013, time.July, 15, 10, 39, 0, 0, time.UTC)}
|
||||
ts := TimeSpan{TimeStart: t1, TimeEnd: t2}
|
||||
newTs := ts.SplitByMinuteBucket(mb)
|
||||
newTs := ts.SplitByMinuteBalance(mb)
|
||||
if ts.MinuteInfo != nil {
|
||||
t.Error("Not enough minutes on minute bucket split")
|
||||
}
|
||||
@@ -259,12 +259,12 @@ func TestTimespanSplitByMinuteBucketPlentyExpired(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimespanSplitByMinuteBucketPlentyExpiring(t *testing.T) {
|
||||
func TestTimespanSplitByMinuteBalancePlentyExpiring(t *testing.T) {
|
||||
t1 := time.Date(2013, time.July, 15, 10, 40, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)
|
||||
mb := &MinuteBucket{Seconds: 180, ExpirationDate: time.Date(2013, time.July, 15, 10, 41, 0, 0, time.UTC)}
|
||||
mb := &Balance{Value: 180, ExpirationDate: time.Date(2013, time.July, 15, 10, 41, 0, 0, time.UTC)}
|
||||
ts := TimeSpan{TimeStart: t1, TimeEnd: t2}
|
||||
newTs := ts.SplitByMinuteBucket(mb)
|
||||
newTs := ts.SplitByMinuteBalance(mb)
|
||||
if ts.MinuteInfo == nil || ts.MinuteInfo.Quantity != 60 {
|
||||
t.Error("Not enough minutes on minute bucket split")
|
||||
}
|
||||
@@ -273,12 +273,12 @@ func TestTimespanSplitByMinuteBucketPlentyExpiring(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimespanSplitByMinuteBucketPlentyExpiringEnd(t *testing.T) {
|
||||
func TestTimespanSplitByMinuteBalancePlentyExpiringEnd(t *testing.T) {
|
||||
t1 := time.Date(2013, time.July, 15, 10, 40, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)
|
||||
mb := &MinuteBucket{Seconds: 180, ExpirationDate: time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)}
|
||||
mb := &Balance{Value: 180, ExpirationDate: time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)}
|
||||
ts := TimeSpan{TimeStart: t1, TimeEnd: t2}
|
||||
newTs := ts.SplitByMinuteBucket(mb)
|
||||
newTs := ts.SplitByMinuteBalance(mb)
|
||||
if ts.MinuteInfo == nil || ts.MinuteInfo.Quantity != 120 {
|
||||
t.Error("Not enough minutes on minute bucket split")
|
||||
}
|
||||
@@ -287,12 +287,12 @@ func TestTimespanSplitByMinuteBucketPlentyExpiringEnd(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimespanSplitByMinuteBucketScarceExpiringSame(t *testing.T) {
|
||||
func TestTimespanSplitByMinuteBalanceScarceExpiringSame(t *testing.T) {
|
||||
t1 := time.Date(2013, time.July, 15, 10, 40, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)
|
||||
mb := &MinuteBucket{Seconds: 120, ExpirationDate: time.Date(2013, time.July, 15, 10, 41, 0, 0, time.UTC)}
|
||||
mb := &Balance{Value: 120, ExpirationDate: time.Date(2013, time.July, 15, 10, 41, 0, 0, time.UTC)}
|
||||
ts := TimeSpan{TimeStart: t1, TimeEnd: t2}
|
||||
newTs := ts.SplitByMinuteBucket(mb)
|
||||
newTs := ts.SplitByMinuteBalance(mb)
|
||||
if ts.MinuteInfo == nil || ts.MinuteInfo.Quantity != 60 {
|
||||
t.Error("Not enough minutes on minute bucket split")
|
||||
}
|
||||
@@ -301,12 +301,12 @@ func TestTimespanSplitByMinuteBucketScarceExpiringSame(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimespanSplitByMinuteBucketScarceExpiringDifferentExpFirst(t *testing.T) {
|
||||
func TestTimespanSplitByMinuteBalanceScarceExpiringDifferentExpFirst(t *testing.T) {
|
||||
t1 := time.Date(2013, time.July, 15, 10, 40, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)
|
||||
mb := &MinuteBucket{Seconds: 140, ExpirationDate: time.Date(2013, time.July, 15, 10, 41, 1, 0, time.UTC)}
|
||||
mb := &Balance{Value: 140, ExpirationDate: time.Date(2013, time.July, 15, 10, 41, 1, 0, time.UTC)}
|
||||
ts := TimeSpan{TimeStart: t1, TimeEnd: t2}
|
||||
newTs := ts.SplitByMinuteBucket(mb)
|
||||
newTs := ts.SplitByMinuteBalance(mb)
|
||||
if ts.MinuteInfo == nil || ts.MinuteInfo.Quantity != 61 {
|
||||
t.Error("Not enough minutes on minute bucket split: ", ts.MinuteInfo.Quantity)
|
||||
}
|
||||
@@ -315,12 +315,12 @@ func TestTimespanSplitByMinuteBucketScarceExpiringDifferentExpFirst(t *testing.T
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimespanSplitByMinuteBucketScarceExpiringDifferentScarceFirst(t *testing.T) {
|
||||
func TestTimespanSplitByMinuteBalanceScarceExpiringDifferentScarceFirst(t *testing.T) {
|
||||
t1 := time.Date(2013, time.July, 15, 10, 40, 0, 0, time.UTC)
|
||||
t2 := time.Date(2013, time.July, 15, 10, 42, 0, 0, time.UTC)
|
||||
mb := &MinuteBucket{Seconds: 61, ExpirationDate: time.Date(2013, time.July, 15, 10, 41, 30, 0, time.UTC)}
|
||||
mb := &Balance{Value: 61, ExpirationDate: time.Date(2013, time.July, 15, 10, 41, 30, 0, time.UTC)}
|
||||
ts := TimeSpan{TimeStart: t1, TimeEnd: t2}
|
||||
newTs := ts.SplitByMinuteBucket(mb)
|
||||
newTs := ts.SplitByMinuteBalance(mb)
|
||||
if ts.MinuteInfo == nil || ts.MinuteInfo.Quantity != 61 {
|
||||
t.Error("Not enough minutes on minute bucket split")
|
||||
}
|
||||
|
||||
@@ -24,39 +24,39 @@ import (
|
||||
|
||||
// Amount of a trafic of a certain type
|
||||
type UnitsCounter struct {
|
||||
Direction string
|
||||
BalanceId string
|
||||
Units float64
|
||||
MinuteBuckets bucketsorter
|
||||
Direction string
|
||||
BalanceId string
|
||||
Units float64
|
||||
MinuteBalances BalanceChain
|
||||
}
|
||||
|
||||
func (uc *UnitsCounter) initMinuteBuckets(ats []*ActionTrigger) {
|
||||
uc.MinuteBuckets = make(bucketsorter, 0)
|
||||
uc.MinuteBalances = make(BalanceChain, 0)
|
||||
for _, at := range ats {
|
||||
acs, err := storageGetter.GetActions(at.ActionsId)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, a := range acs {
|
||||
if a.MinuteBucket != nil {
|
||||
uc.MinuteBuckets = append(uc.MinuteBuckets, a.MinuteBucket.Clone())
|
||||
if a.Balance != nil {
|
||||
uc.MinuteBalances = append(uc.MinuteBalances, a.Balance.Clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
uc.MinuteBuckets.Sort()
|
||||
uc.MinuteBalances.Sort()
|
||||
}
|
||||
|
||||
// Adds the minutes from the received minute bucket to an existing bucket if the destination
|
||||
// is the same or ads the minutye bucket to the list if none matches.
|
||||
// Adds the minutes from the received minute balance to an existing bucket if the destination
|
||||
// is the same or ads the minute balance to the list if none matches.
|
||||
func (uc *UnitsCounter) addMinutes(amount float64, prefix string) {
|
||||
for _, mb := range uc.MinuteBuckets {
|
||||
for _, mb := range uc.MinuteBalances {
|
||||
d, err := GetDestination(mb.DestinationId)
|
||||
if err != nil {
|
||||
Logger.Err(fmt.Sprintf("Minutes counter: unknown destination: %s", mb.DestinationId))
|
||||
continue
|
||||
}
|
||||
if _, ok := d.containsPrefix(prefix); ok {
|
||||
mb.Seconds += amount
|
||||
mb.Value += amount
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,28 +22,28 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnitsCounterAddMinuteBucket(t *testing.T) {
|
||||
func TestUnitsCounterAddBalance(t *testing.T) {
|
||||
uc := &UnitsCounter{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Units: 100,
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Units: 100,
|
||||
MinuteBalances: []*Balance{&Balance{Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
}
|
||||
uc.addMinutes(20, "test")
|
||||
if len(uc.MinuteBuckets) != 2 {
|
||||
if len(uc.MinuteBalances) != 2 {
|
||||
t.Error("Error adding minute bucket!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnitsCounterAddMinuteBucketExists(t *testing.T) {
|
||||
func TestUnitsCounterAddBalanceExists(t *testing.T) {
|
||||
uc := &UnitsCounter{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Units: 100,
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Units: 100,
|
||||
MinuteBalances: []*Balance{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
}
|
||||
uc.addMinutes(5, "0723")
|
||||
if len(uc.MinuteBuckets) != 2 || uc.MinuteBuckets[0].Seconds != 15 {
|
||||
if len(uc.MinuteBalances) != 2 || uc.MinuteBalances[0].Value != 15 {
|
||||
t.Error("Error adding minute bucket!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ Structure containing information about user's credit (minutes, cents, sms...).'
|
||||
This can represent a user or a shared group.
|
||||
*/
|
||||
type UserBalance struct {
|
||||
Id string
|
||||
Type string // prepaid-postpaid
|
||||
BalanceMap map[string]BalanceChain
|
||||
MinuteBuckets []*MinuteBucket
|
||||
Id string
|
||||
Type string // prepaid-postpaid
|
||||
BalanceMap map[string]BalanceChain
|
||||
//MinuteBuckets []*MinuteBucket
|
||||
UnitCounters []*UnitsCounter
|
||||
ActionTriggers ActionTriggerPriotityList
|
||||
|
||||
@@ -70,57 +70,60 @@ type UserBalance struct {
|
||||
/*
|
||||
Returns user's available minutes for the specified destination
|
||||
*/
|
||||
func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds, credit float64, bucketList bucketsorter) {
|
||||
func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds, credit float64, balances BalanceChain) {
|
||||
credit = ub.BalanceMap[CREDIT+OUTBOUND].GetTotalValue()
|
||||
if len(ub.MinuteBuckets) == 0 {
|
||||
if len(ub.BalanceMap[MINUTES]) == 0 {
|
||||
// Logger.Debug("There are no minute buckets to check for user: ", ub.Id)
|
||||
return
|
||||
}
|
||||
for _, mb := range ub.MinuteBuckets {
|
||||
if mb.IsExpired() {
|
||||
for _, b := range ub.BalanceMap[MINUTES] {
|
||||
if b.IsExpired() {
|
||||
continue
|
||||
}
|
||||
d, err := GetDestination(mb.DestinationId)
|
||||
d, err := GetDestination(b.DestinationId)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if precision, ok := d.containsPrefix(prefix); ok {
|
||||
mb.precision = precision
|
||||
if mb.Seconds > 0 {
|
||||
bucketList = append(bucketList, mb)
|
||||
b.precision = precision
|
||||
if b.Value > 0 {
|
||||
balances = append(balances, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
bucketList.Sort() // sorts the buckets according to priority, precision or price
|
||||
for _, mb := range bucketList {
|
||||
s := mb.GetSecondsForCredit(credit)
|
||||
credit -= s * mb.Price
|
||||
balances.Sort() // sorts the buckets according to priority, precision or price
|
||||
for _, b := range balances {
|
||||
s := b.GetSecondsForCredit(credit)
|
||||
credit -= s * b.SpecialPrice
|
||||
seconds += s
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Debit seconds from specified minute bucket
|
||||
func (ub *UserBalance) debitMinuteBucket(newMb *MinuteBucket) error {
|
||||
func (ub *UserBalance) debitMinuteBalance(newMb *Balance) error {
|
||||
if newMb == nil {
|
||||
return errors.New("Nil minute bucket!")
|
||||
}
|
||||
if ub.BalanceMap == nil {
|
||||
ub.BalanceMap = make(map[string]BalanceChain, 0)
|
||||
}
|
||||
found := false
|
||||
for _, mb := range ub.MinuteBuckets {
|
||||
for _, mb := range ub.BalanceMap[MINUTES] {
|
||||
if mb.IsExpired() {
|
||||
continue
|
||||
}
|
||||
if mb.Equal(newMb) {
|
||||
mb.Seconds -= newMb.Seconds
|
||||
mb.Value -= newMb.Value
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// if it is not found and the Seconds are negative (topup)
|
||||
// then we add it to the list
|
||||
if !found && newMb.Seconds <= 0 {
|
||||
newMb.Seconds = -newMb.Seconds
|
||||
ub.MinuteBuckets = append(ub.MinuteBuckets, newMb)
|
||||
if !found && newMb.Value <= 0 {
|
||||
newMb.Value = -newMb.Value
|
||||
ub.BalanceMap[MINUTES] = append(ub.BalanceMap[MINUTES], newMb)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -133,7 +136,7 @@ debited and an error will be returned.
|
||||
*/
|
||||
func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string, count bool) error {
|
||||
if count {
|
||||
ub.countUnits(&Action{BalanceId: MINUTES, Direction: OUTBOUND, MinuteBucket: &MinuteBucket{Seconds: amount, DestinationId: prefix}})
|
||||
ub.countUnits(&Action{BalanceId: MINUTES, Direction: OUTBOUND, Balance: &Balance{Value: amount, DestinationId: prefix}})
|
||||
}
|
||||
avaliableNbSeconds, _, bucketList := ub.getSecondsForPrefix(prefix)
|
||||
if avaliableNbSeconds < amount {
|
||||
@@ -144,13 +147,13 @@ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string, count
|
||||
credit = bc.Clone()
|
||||
}
|
||||
for _, mb := range bucketList {
|
||||
if mb.Seconds < amount {
|
||||
if mb.Price > 0 { // debit the money if the bucket has price
|
||||
credit.Debit(mb.Seconds * mb.Price)
|
||||
if mb.Value < amount {
|
||||
if mb.SpecialPrice > 0 { // debit the money if the bucket has price
|
||||
credit.Debit(mb.Value * mb.SpecialPrice)
|
||||
}
|
||||
} else {
|
||||
if mb.Price > 0 { // debit the money if the bucket has price
|
||||
credit.Debit(amount * mb.Price)
|
||||
if mb.SpecialPrice > 0 { // debit the money if the bucket has price
|
||||
credit.Debit(amount * mb.SpecialPrice)
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -165,11 +168,11 @@ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string, count
|
||||
ub.BalanceMap[CREDIT+OUTBOUND] = credit // credit is > 0
|
||||
|
||||
for _, mb := range bucketList {
|
||||
if mb.Seconds < amount {
|
||||
amount -= mb.Seconds
|
||||
mb.Seconds = 0
|
||||
if mb.Value < amount {
|
||||
amount -= mb.Value
|
||||
mb.Value = 0
|
||||
} else {
|
||||
mb.Seconds -= amount
|
||||
mb.Value -= amount
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -183,8 +186,8 @@ func (ub *UserBalance) debitBalanceAction(a *Action) float64 {
|
||||
Id: utils.GenUUID(),
|
||||
ExpirationDate: a.ExpirationDate,
|
||||
}
|
||||
if a.MinuteBucket != nil {
|
||||
newBalance.Weight = a.MinuteBucket.Weight
|
||||
if a.Balance != nil {
|
||||
newBalance.Weight = a.Balance.Weight
|
||||
}
|
||||
found := false
|
||||
id := a.BalanceId + a.Direction
|
||||
@@ -228,14 +231,14 @@ func (ub *UserBalance) executeActionTriggers(a *Action) {
|
||||
for _, uc := range ub.UnitCounters {
|
||||
if uc.BalanceId == at.BalanceId {
|
||||
if at.BalanceId == MINUTES {
|
||||
for _, mb := range uc.MinuteBuckets {
|
||||
for _, mb := range uc.MinuteBalances {
|
||||
if strings.Contains(at.ThresholdType, "*max") {
|
||||
if mb.DestinationId == at.DestinationId && mb.Seconds >= at.ThresholdValue {
|
||||
if mb.DestinationId == at.DestinationId && mb.Value >= at.ThresholdValue {
|
||||
// run the actions
|
||||
at.Execute(ub)
|
||||
}
|
||||
} else { //MIN
|
||||
if mb.DestinationId == at.DestinationId && mb.Seconds <= at.ThresholdValue {
|
||||
if mb.DestinationId == at.DestinationId && mb.Value <= at.ThresholdValue {
|
||||
// run the actions
|
||||
at.Execute(ub)
|
||||
}
|
||||
@@ -259,14 +262,14 @@ func (ub *UserBalance) executeActionTriggers(a *Action) {
|
||||
} else { // BALANCE
|
||||
for _, b := range ub.BalanceMap[at.BalanceId] {
|
||||
if at.BalanceId == MINUTES && at.DestinationId != "" { // last check adds safety
|
||||
for _, mb := range ub.MinuteBuckets {
|
||||
for _, mb := range ub.BalanceMap[MINUTES] {
|
||||
if strings.Contains(at.ThresholdType, "*max") {
|
||||
if mb.DestinationId == at.DestinationId && mb.Seconds >= at.ThresholdValue {
|
||||
if mb.DestinationId == at.DestinationId && mb.Value >= at.ThresholdValue {
|
||||
// run the actions
|
||||
at.Execute(ub)
|
||||
}
|
||||
} else { //MIN
|
||||
if mb.DestinationId == at.DestinationId && mb.Seconds <= at.ThresholdValue {
|
||||
if mb.DestinationId == at.DestinationId && mb.Value <= at.ThresholdValue {
|
||||
// run the actions
|
||||
at.Execute(ub)
|
||||
}
|
||||
@@ -329,8 +332,8 @@ func (ub *UserBalance) countUnits(a *Action) {
|
||||
unitsCounter = &UnitsCounter{BalanceId: a.BalanceId, Direction: direction}
|
||||
ub.UnitCounters = append(ub.UnitCounters, unitsCounter)
|
||||
}
|
||||
if a.BalanceId == MINUTES && a.MinuteBucket != nil {
|
||||
unitsCounter.addMinutes(a.MinuteBucket.Seconds, a.MinuteBucket.DestinationId)
|
||||
if a.BalanceId == MINUTES && a.Balance != nil {
|
||||
unitsCounter.addMinutes(a.Balance.Value, a.Balance.DestinationId)
|
||||
} else {
|
||||
unitsCounter.Units += a.Units
|
||||
}
|
||||
@@ -346,7 +349,7 @@ func (ub *UserBalance) initMinuteCounters() {
|
||||
continue
|
||||
}
|
||||
for _, a := range acs {
|
||||
if a.MinuteBucket != nil {
|
||||
if a.Balance != nil {
|
||||
direction := at.Direction
|
||||
if direction == "" {
|
||||
direction = OUTBOUND
|
||||
@@ -355,11 +358,11 @@ func (ub *UserBalance) initMinuteCounters() {
|
||||
if !exists {
|
||||
uc = &UnitsCounter{BalanceId: MINUTES, Direction: direction}
|
||||
ucTempMap[direction] = uc
|
||||
uc.MinuteBuckets = bucketsorter{}
|
||||
uc.MinuteBalances = BalanceChain{}
|
||||
ub.UnitCounters = append(ub.UnitCounters, uc)
|
||||
}
|
||||
uc.MinuteBuckets = append(uc.MinuteBuckets, a.MinuteBucket.Clone())
|
||||
uc.MinuteBuckets.Sort()
|
||||
uc.MinuteBalances = append(uc.MinuteBalances, a.Balance.Clone())
|
||||
uc.MinuteBalances.Sort()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,9 +379,9 @@ func (ub *UserBalance) CleanExpiredBalancesAndBuckets() {
|
||||
}
|
||||
ub.BalanceMap[key] = bm
|
||||
}
|
||||
for i := 0; i < len(ub.MinuteBuckets); i++ {
|
||||
if ub.MinuteBuckets[i].IsExpired() {
|
||||
ub.MinuteBuckets = append(ub.MinuteBuckets[:i], ub.MinuteBuckets[i+1:]...)
|
||||
for i := 0; i < len(ub.BalanceMap[MINUTES]); i++ {
|
||||
if ub.BalanceMap[MINUTES][i].IsExpired() {
|
||||
ub.BalanceMap[MINUTES] = append(ub.BalanceMap[MINUTES][:i], ub.BalanceMap[MINUTES][i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func init() {
|
||||
func populateTestActionsForTriggers() {
|
||||
ats := []*Action{
|
||||
&Action{ActionType: "*topup", BalanceId: CREDIT, Direction: OUTBOUND, Units: 10},
|
||||
&Action{ActionType: "*topup", BalanceId: MINUTES, Direction: OUTBOUND, MinuteBucket: &MinuteBucket{Weight: 20, Price: 1, Seconds: 10, DestinationId: "NAT"}},
|
||||
&Action{ActionType: "*topup", BalanceId: MINUTES, Direction: OUTBOUND, Balance: &Balance{Weight: 20, SpecialPrice: 1, Value: 10, DestinationId: "NAT"}},
|
||||
}
|
||||
storageGetter.SetActions("TEST_ACTIONS", ats)
|
||||
ats1 := []*Action{
|
||||
@@ -96,9 +96,9 @@ func TestBalanceChainStoreRestore(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUserBalanceStorageStoreRestore(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.01, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.01, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
storageGetter.SetUserBalance(rifsBalance)
|
||||
ub1, err := storageGetter.GetUserBalance("other")
|
||||
if err != nil || !ub1.BalanceMap[CREDIT+OUTBOUND].Equal(rifsBalance.BalanceMap[CREDIT+OUTBOUND]) {
|
||||
@@ -108,9 +108,9 @@ func TestUserBalanceStorageStoreRestore(t *testing.T) {
|
||||
}
|
||||
|
||||
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]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 200}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 200}}}}
|
||||
seconds, credit, bucketList := ub1.getSecondsForPrefix("0723")
|
||||
expected := 110.0
|
||||
if credit != 200 || seconds != expected || bucketList[0].Weight < bucketList[1].Weight {
|
||||
@@ -118,11 +118,11 @@ func TestGetSecondsForPrefix(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPricedSeconds(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Price: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Price: 1, Weight: 20, DestinationId: "RET"}
|
||||
func TestGetSpecialPricedSeconds(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, SpecialPrice: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, SpecialPrice: 1, Weight: 20, DestinationId: "RET"}
|
||||
|
||||
ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
seconds, credit, bucketList := ub1.getSecondsForPrefix("0723")
|
||||
expected := 21.0
|
||||
if credit != 0 || seconds != expected || len(bucketList) < 2 || bucketList[0].Weight < bucketList[1].Weight {
|
||||
@@ -131,24 +131,24 @@ func TestGetPricedSeconds(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUserBalanceStorageStore(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.01, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.01, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
storageGetter.SetUserBalance(rifsBalance)
|
||||
result, err := storageGetter.GetUserBalance(rifsBalance.Id)
|
||||
if err != nil || rifsBalance.Id != result.Id ||
|
||||
len(rifsBalance.MinuteBuckets) < 2 || len(result.MinuteBuckets) < 2 ||
|
||||
!(rifsBalance.MinuteBuckets[0].Equal(result.MinuteBuckets[0])) ||
|
||||
!(rifsBalance.MinuteBuckets[1].Equal(result.MinuteBuckets[1])) ||
|
||||
len(rifsBalance.BalanceMap[MINUTES]) < 2 || len(result.BalanceMap[MINUTES]) < 2 ||
|
||||
!(rifsBalance.BalanceMap[MINUTES][0].Equal(result.BalanceMap[MINUTES][0])) ||
|
||||
!(rifsBalance.BalanceMap[MINUTES][1].Equal(result.BalanceMap[MINUTES][1])) ||
|
||||
!rifsBalance.BalanceMap[CREDIT+OUTBOUND].Equal(result.BalanceMap[CREDIT+OUTBOUND]) {
|
||||
t.Errorf("Expected %v was %v", rifsBalance, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitMoneyBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.01, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.01, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
result := rifsBalance.debitBalance(CREDIT, 6, false)
|
||||
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 15 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 15, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
@@ -156,9 +156,9 @@ func TestDebitMoneyBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDebitAllMoneyBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.01, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.01, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
rifsBalance.debitBalance(CREDIT, 21, false)
|
||||
result := rifsBalance.debitBalance(CREDIT, 0, false)
|
||||
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 0 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
|
||||
@@ -167,9 +167,9 @@ func TestDebitAllMoneyBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDebitMoreMoneyBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
result := rifsBalance.debitBalance(CREDIT, 22, false)
|
||||
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != -1 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", -1, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
@@ -177,9 +177,9 @@ func TestDebitMoreMoneyBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDebitNegativeMoneyBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
result := rifsBalance.debitBalance(CREDIT, -15, false)
|
||||
if rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 36 || result != rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 36, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
@@ -187,120 +187,120 @@ func TestDebitNegativeMoneyBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDebitMinuteBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(6, "0723", false)
|
||||
if b2.Seconds != 94 || err != nil {
|
||||
if b2.Value != 94 || err != nil {
|
||||
t.Log(err)
|
||||
t.Errorf("Expected %v was %v", 94, b2.Seconds)
|
||||
t.Errorf("Expected %v was %v", 94, b2.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitMultipleBucketsMinuteBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(105, "0723", false)
|
||||
if b2.Seconds != 0 || b1.Seconds != 5 || err != nil {
|
||||
if b2.Value != 0 || b1.Value != 5 || err != nil {
|
||||
t.Log(err)
|
||||
t.Errorf("Expected %v was %v", 0, b2.Seconds)
|
||||
t.Errorf("Expected %v was %v", 0, b2.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitAllMinuteBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(110, "0723", false)
|
||||
if b2.Seconds != 0 || b1.Seconds != 0 || err != nil {
|
||||
t.Errorf("Expected %v was %v", 0, b2.Seconds)
|
||||
if b2.Value != 0 || b1.Value != 0 || err != nil {
|
||||
t.Errorf("Expected %v was %v", 0, b2.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitMoreMinuteBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(115, "0723", false)
|
||||
if b2.Seconds != 100 || b1.Seconds != 10 || err == nil {
|
||||
t.Errorf("Expected %v was %v", 1000, b2.Seconds)
|
||||
if b2.Value != 100 || b1.Value != 10 || err == nil {
|
||||
t.Errorf("Expected %v was %v", 1000, b2.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitPriceMinuteBalance0(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
func TestDebitSpecialPriceMinuteBalance0(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(5, "0723", false)
|
||||
if b2.Seconds != 95 || b1.Seconds != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 16 {
|
||||
if b2.Value != 95 || b1.Value != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 16 {
|
||||
t.Errorf("Expected %v was %v", 16, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitPriceAllMinuteBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
func TestDebitSpecialPriceAllMinuteBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(21, "0723", false)
|
||||
if b2.Seconds != 79 || b1.Seconds != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 0 {
|
||||
if b2.Value != 79 || b1.Value != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 0 {
|
||||
t.Errorf("Expected %v was %v", 0, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitPriceMoreMinuteBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
func TestDebitSpecialPriceMoreMinuteBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(25, "0723", false)
|
||||
if b2.Seconds != 75 || b1.Seconds != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != -4 {
|
||||
t.Log(b2.Seconds)
|
||||
t.Log(b1.Seconds)
|
||||
if b2.Value != 75 || b1.Value != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != -4 {
|
||||
t.Log(b2.Value)
|
||||
t.Log(b1.Value)
|
||||
t.Log(err)
|
||||
t.Errorf("Expected %v was %v", -4, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitPriceMoreMinuteBalancePrepay(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", Type: UB_TYPE_PREPAID, MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
func TestDebitSpecialPriceMoreMinuteBalancePrepay(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", Type: UB_TYPE_PREPAID, BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(25, "0723", false)
|
||||
expected := 21.0
|
||||
if b2.Seconds != 100 || b1.Seconds != 10 || err != AMOUNT_TOO_BIG || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != expected {
|
||||
t.Log(b2.Seconds)
|
||||
t.Log(b1.Seconds)
|
||||
if b2.Value != 100 || b1.Value != 10 || err != AMOUNT_TOO_BIG || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != expected {
|
||||
t.Log(b2.Value)
|
||||
t.Log(b1.Value)
|
||||
t.Log(err)
|
||||
t.Errorf("Expected %v was %v", expected, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitPriceNegativeMinuteBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
func TestDebitSpecialPriceNegativeMinuteBalance(t *testing.T) {
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 1.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(-15, "0723", false)
|
||||
if b2.Seconds != 115 || b1.Seconds != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 36 {
|
||||
if b2.Value != 115 || b1.Value != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 36 {
|
||||
t.Log(b1, b2, err)
|
||||
t.Errorf("Expected %v was %v", 36, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitNegativeMinuteBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
err := rifsBalance.debitMinutesBalance(-15, "0723", false)
|
||||
if b2.Seconds != 115 || b1.Seconds != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 21 {
|
||||
if b2.Value != 115 || b1.Value != 10 || err != nil || rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value != 21 {
|
||||
t.Log(b1, b2, err)
|
||||
t.Errorf("Expected %v was %v", 21, rifsBalance.BalanceMap[CREDIT+OUTBOUND][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDebitSMSBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
result := rifsBalance.debitBalance(SMS, 12, false)
|
||||
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 88 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 88, rifsBalance.BalanceMap[SMS+OUTBOUND])
|
||||
@@ -308,9 +308,9 @@ func TestDebitSMSBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDebitAllSMSBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
result := rifsBalance.debitBalance(SMS, 100, false)
|
||||
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 0 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 0, rifsBalance.BalanceMap[SMS+OUTBOUND])
|
||||
@@ -318,9 +318,9 @@ func TestDebitAllSMSBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDebitMoreSMSBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
result := rifsBalance.debitBalance(SMS, 110, false)
|
||||
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != -10 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", -10, rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value)
|
||||
@@ -328,112 +328,107 @@ func TestDebitMoreSMSBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDebitNegativeSMSBalance(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.0, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}, SMS + OUTBOUND: BalanceChain{&Balance{Value: 100}}}}
|
||||
result := rifsBalance.debitBalance(SMS, -15, false)
|
||||
if rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value != 115 || result != rifsBalance.BalanceMap[SMS+OUTBOUND][0].Value {
|
||||
t.Errorf("Expected %v was %v", 115, rifsBalance.BalanceMap[SMS+OUTBOUND])
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalancedebitMinuteBucket(t *testing.T) {
|
||||
func TestUserBalancedebitBalance(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS: BalanceChain{&Balance{Value: 14}}, TRAFFIC: BalanceChain{&Balance{Value: 1204}}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS: BalanceChain{&Balance{Value: 14}}, TRAFFIC: BalanceChain{&Balance{Value: 1204}}, MINUTES: BalanceChain{&Balance{Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
}
|
||||
newMb := &MinuteBucket{Weight: 20, Price: 1, DestinationId: "NEW"}
|
||||
ub.debitMinuteBucket(newMb)
|
||||
if len(ub.MinuteBuckets) != 3 || ub.MinuteBuckets[2] != newMb {
|
||||
t.Error("Error adding minute bucket!", len(ub.MinuteBuckets), ub.MinuteBuckets)
|
||||
newMb := &Balance{Weight: 20, SpecialPrice: 1, DestinationId: "NEW"}
|
||||
ub.debitMinuteBalance(newMb)
|
||||
if len(ub.BalanceMap[MINUTES]) != 3 || ub.BalanceMap[MINUTES][2] != newMb {
|
||||
t.Error("Error adding minute bucket!", len(ub.BalanceMap[MINUTES]), ub.BalanceMap[MINUTES])
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalancedebitMinuteBucketExists(t *testing.T) {
|
||||
func TestUserBalancedebitBalanceExists(t *testing.T) {
|
||||
|
||||
ub := &UserBalance{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 15, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES: BalanceChain{&Balance{Value: 15, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
}
|
||||
newMb := &MinuteBucket{Seconds: -10, Weight: 20, Price: 1, DestinationId: "NAT"}
|
||||
ub.debitMinuteBucket(newMb)
|
||||
if len(ub.MinuteBuckets) != 2 || ub.MinuteBuckets[0].Seconds != 25 {
|
||||
newMb := &Balance{Value: -10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}
|
||||
ub.debitMinuteBalance(newMb)
|
||||
if len(ub.BalanceMap[MINUTES]) != 2 || ub.BalanceMap[MINUTES][0].Value != 25 {
|
||||
t.Error("Error adding minute bucket!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceAddMinuteNil(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024}}, MINUTES: BalanceChain{&Balance{Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
}
|
||||
ub.debitMinuteBucket(nil)
|
||||
if len(ub.MinuteBuckets) != 2 {
|
||||
ub.debitMinuteBalance(nil)
|
||||
if len(ub.BalanceMap[MINUTES]) != 2 {
|
||||
t.Error("Error adding minute bucket!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceAddMinutBucketEmpty(t *testing.T) {
|
||||
mb1 := &MinuteBucket{Seconds: -10, DestinationId: "NAT"}
|
||||
mb2 := &MinuteBucket{Seconds: -10, DestinationId: "NAT"}
|
||||
mb3 := &MinuteBucket{Seconds: -10, DestinationId: "OTHER"}
|
||||
mb1 := &Balance{Value: -10, DestinationId: "NAT"}
|
||||
mb2 := &Balance{Value: -10, DestinationId: "NAT"}
|
||||
mb3 := &Balance{Value: -10, DestinationId: "OTHER"}
|
||||
ub := &UserBalance{}
|
||||
ub.debitMinuteBucket(mb1)
|
||||
if len(ub.MinuteBuckets) != 1 {
|
||||
t.Error("Error adding minute bucket: ", ub.MinuteBuckets)
|
||||
ub.debitMinuteBalance(mb1)
|
||||
if len(ub.BalanceMap[MINUTES]) != 1 {
|
||||
t.Error("Error adding minute bucket: ", ub.BalanceMap[MINUTES])
|
||||
}
|
||||
ub.debitMinuteBucket(mb2)
|
||||
if len(ub.MinuteBuckets) != 1 || ub.MinuteBuckets[0].Seconds != 20 {
|
||||
t.Error("Error adding minute bucket: ", ub.MinuteBuckets)
|
||||
ub.debitMinuteBalance(mb2)
|
||||
if len(ub.BalanceMap[MINUTES]) != 1 || ub.BalanceMap[MINUTES][0].Value != 20 {
|
||||
t.Error("Error adding minute bucket: ", ub.BalanceMap[MINUTES])
|
||||
}
|
||||
ub.debitMinuteBucket(mb3)
|
||||
if len(ub.MinuteBuckets) != 2 {
|
||||
t.Error("Error adding minute bucket: ", ub.MinuteBuckets)
|
||||
ub.debitMinuteBalance(mb3)
|
||||
if len(ub.BalanceMap[MINUTES]) != 2 {
|
||||
t.Error("Error adding minute bucket: ", ub.BalanceMap[MINUTES])
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceExecuteTriggeredActions(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 2, ThresholdType: TRIGGER_MAX_COUNTER, ActionsId: "TEST_ACTIONS"}},
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Units: 1})
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.MinuteBuckets[0].Seconds != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.MinuteBuckets[0].Seconds)
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.BalanceMap[MINUTES][0].Value != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES][0].Value)
|
||||
}
|
||||
// are set to executed
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1})
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.MinuteBuckets[0].Seconds != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.MinuteBuckets[0].Seconds)
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.BalanceMap[MINUTES][0].Value != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES][0].Value)
|
||||
}
|
||||
// we can reset them
|
||||
ub.resetActionTriggers(nil)
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1})
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 120 || ub.MinuteBuckets[0].Seconds != 30 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.MinuteBuckets[0].Seconds)
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 120 || ub.BalanceMap[MINUTES][0].Value != 30 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceExecuteTriggeredActionsBalance(t *testing.T) {
|
||||
ub := &UserBalance{
|
||||
Id: "TEST_UB",
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}},
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 100}}, MINUTES: BalanceChain{&Balance{Value: 10, Weight: 20, SpecialPrice: 1, DestinationId: "NAT"}, &Balance{Weight: 10, SpecialPrice: 10, SpecialPriceType: PRICE_ABSOLUTE, DestinationId: "RET"}}},
|
||||
UnitCounters: []*UnitsCounter{&UnitsCounter{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1}},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: PRICE_ABSOLUTE, DestinationId: "RET"}},
|
||||
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, Direction: OUTBOUND, ThresholdValue: 100, ThresholdType: TRIGGER_MIN_COUNTER, ActionsId: "TEST_ACTIONS"}},
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Units: 1})
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.MinuteBuckets[0].Seconds != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.MinuteBuckets[0].Seconds)
|
||||
if ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 110 || ub.BalanceMap[MINUTES][0].Value != 20 {
|
||||
t.Error("Error executing triggered actions", ub.BalanceMap[CREDIT+OUTBOUND][0].Value, ub.BalanceMap[MINUTES][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,8 +441,6 @@ func TestUserBalanceExecuteTriggeredActionsOrder(t *testing.T) {
|
||||
}
|
||||
ub.countUnits(&Action{BalanceId: CREDIT, Direction: OUTBOUND, Units: 1})
|
||||
if len(ub.BalanceMap[CREDIT+OUTBOUND]) != 1 || ub.BalanceMap[CREDIT+OUTBOUND][0].Value != 10 {
|
||||
t.Log(ub.BalanceMap[CREDIT+OUTBOUND][0])
|
||||
t.Log(ub.BalanceMap[CREDIT+OUTBOUND][1])
|
||||
t.Error("Error executing triggered actions in order", ub.BalanceMap[CREDIT+OUTBOUND])
|
||||
}
|
||||
}
|
||||
@@ -458,17 +451,16 @@ func TestCleanExpired(t *testing.T) {
|
||||
BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{
|
||||
&Balance{ExpirationDate: time.Now().Add(10 * time.Second)},
|
||||
&Balance{ExpirationDate: time.Date(2013, 7, 18, 14, 33, 0, 0, time.UTC)},
|
||||
&Balance{ExpirationDate: time.Now().Add(10 * time.Second)}}},
|
||||
MinuteBuckets: []*MinuteBucket{
|
||||
&MinuteBucket{ExpirationDate: time.Date(2013, 7, 18, 14, 33, 0, 0, time.UTC)},
|
||||
&MinuteBucket{ExpirationDate: time.Now().Add(10 * time.Second)},
|
||||
},
|
||||
&Balance{ExpirationDate: time.Now().Add(10 * time.Second)}}, MINUTES: BalanceChain{
|
||||
&Balance{ExpirationDate: time.Date(2013, 7, 18, 14, 33, 0, 0, time.UTC)},
|
||||
&Balance{ExpirationDate: time.Now().Add(10 * time.Second)},
|
||||
}},
|
||||
}
|
||||
ub.CleanExpiredBalancesAndBuckets()
|
||||
if len(ub.BalanceMap[CREDIT+OUTBOUND]) != 2 {
|
||||
t.Error("Error cleaning expired balances!")
|
||||
}
|
||||
if len(ub.MinuteBuckets) != 1 {
|
||||
if len(ub.BalanceMap[MINUTES]) != 1 {
|
||||
t.Error("Error cleaning expired minute buckets!")
|
||||
}
|
||||
}
|
||||
@@ -521,10 +513,10 @@ func TestUserBalanceUnitCountingOutboundInbound(t *testing.T) {
|
||||
|
||||
func BenchmarkGetSecondForPrefix(b *testing.B) {
|
||||
b.StopTimer()
|
||||
b1 := &MinuteBucket{Seconds: 10, Price: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Price: 1, Weight: 20, DestinationId: "RET"}
|
||||
b1 := &Balance{Value: 10, SpecialPrice: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, SpecialPrice: 1, Weight: 20, DestinationId: "RET"}
|
||||
|
||||
ub1 := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
ub1 := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
ub1.getSecondsForPrefix("0723")
|
||||
@@ -532,9 +524,9 @@ func BenchmarkGetSecondForPrefix(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkUserBalanceStorageStoreRestore(b *testing.B) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.01, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, SpecialPrice: 0.01, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, SpecialPrice: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
for i := 0; i < b.N; i++ {
|
||||
storageGetter.SetUserBalance(rifsBalance)
|
||||
storageGetter.GetUserBalance(rifsBalance.Id)
|
||||
@@ -542,9 +534,9 @@ func BenchmarkUserBalanceStorageStoreRestore(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkGetSecondsForPrefix(b *testing.B) {
|
||||
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]BalanceChain{CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
b1 := &Balance{Value: 10, Weight: 10, DestinationId: "NAT"}
|
||||
b2 := &Balance{Value: 100, Weight: 20, DestinationId: "RET"}
|
||||
ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", BalanceMap: map[string]BalanceChain{MINUTES: BalanceChain{b1, b2}, CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 21}}}}
|
||||
for i := 0; i < b.N; i++ {
|
||||
ub1.getSecondsForPrefix("0723")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user