From f5ac9e1725aa19b7920432920aafbc50543e8763 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Sat, 25 Feb 2012 14:10:26 +0200 Subject: [PATCH] user budget reset --- timespans/tariff_plans.go | 11 +++++++---- timespans/userbudget.go | 36 +++++++++++++++++++++++++++++------- timespans/userbudget_test.go | 23 +++++++++++++++++++++++ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/timespans/tariff_plans.go b/timespans/tariff_plans.go index ffa6d4544..af9c5bbc7 100644 --- a/timespans/tariff_plans.go +++ b/timespans/tariff_plans.go @@ -11,7 +11,8 @@ these numbers to the user budget every month. */ type TariffPlan struct { Id string - SmsCredit int + SmsCredit float64 + Traffic float64 MinuteBuckets []*MinuteBucket } @@ -19,7 +20,8 @@ type TariffPlan struct { Serializes the tariff plan for the storage. Used for key-value storages. */ func (tp *TariffPlan) store() (result string) { - result += strconv.Itoa(tp.SmsCredit) + ";" + result += strconv.FormatFloat(tp.SmsCredit, 'f', -1, 64) + ";" + result += strconv.FormatFloat(tp.Traffic, 'f', -1, 64) + ";" for _, mb := range tp.MinuteBuckets { var mbs string mbs += strconv.Itoa(int(mb.Seconds)) + "|" @@ -36,8 +38,9 @@ De-serializes the tariff plan for the storage. Used for key-value storages. */ func (tp *TariffPlan) restore(input string) { elements := strings.Split(input, ";") - tp.SmsCredit, _ = strconv.Atoi(elements[0]) - for _, mbs := range elements[1 : len(elements)-1] { + tp.SmsCredit, _ = strconv.ParseFloat(elements[0], 64) + tp.Traffic, _ = strconv.ParseFloat(elements[1], 64) + for _, mbs := range elements[2 : len(elements)-1] { mb := &MinuteBucket{} mbse := strings.Split(mbs, "|") mb.Seconds, _ = strconv.ParseFloat(mbse[0], 64) diff --git a/timespans/userbudget.go b/timespans/userbudget.go index 00254aa12..e5698caf6 100644 --- a/timespans/userbudget.go +++ b/timespans/userbudget.go @@ -15,6 +15,7 @@ type UserBudget struct { Id string Credit float64 SmsCredit float64 + Traffic float64 VolumeDiscountSeconds float64 ResetDayOfTheMonth int TariffPlanId string @@ -57,6 +58,7 @@ Serializes the user budget for the storage. Used for key-value storages. func (ub *UserBudget) store() (result string) { result += strconv.FormatFloat(ub.Credit, 'f', -1, 64) + ";" result += strconv.FormatFloat(ub.SmsCredit, 'f', -1, 64) + ";" + result += strconv.FormatFloat(ub.Traffic, 'f', -1, 64) + ";" result += strconv.FormatFloat(ub.VolumeDiscountSeconds, 'f', -1, 64) + ";" result += strconv.Itoa(ub.ResetDayOfTheMonth) + ";" result += ub.TariffPlanId + ";" @@ -78,10 +80,11 @@ func (ub *UserBudget) restore(input string) { elements := strings.Split(input, ";") ub.Credit, _ = strconv.ParseFloat(elements[0], 64) ub.SmsCredit, _ = strconv.ParseFloat(elements[1], 64) - ub.VolumeDiscountSeconds, _ = strconv.ParseFloat(elements[2], 64) - ub.ResetDayOfTheMonth, _ = strconv.Atoi(elements[3]) - ub.TariffPlanId = elements[4] - for _, mbs := range elements[5 : len(elements)-1] { + ub.Traffic, _ = strconv.ParseFloat(elements[2], 64) + ub.VolumeDiscountSeconds, _ = strconv.ParseFloat(elements[3], 64) + ub.ResetDayOfTheMonth, _ = strconv.Atoi(elements[4]) + ub.TariffPlanId = elements[5] + for _, mbs := range elements[6 : len(elements)-1] { mb := &MinuteBucket{} mbse := strings.Split(mbs, "|") mb.Seconds, _ = strconv.ParseFloat(mbse[0], 64) @@ -96,11 +99,11 @@ func (ub *UserBudget) restore(input string) { /* Returns the tariff plan loading it from the storage if necessary. */ -func (ub *UserBudget) getTariffPlan(storage StorageGetter) (tp *TariffPlan) { +func (ub *UserBudget) getTariffPlan(storage StorageGetter) (tp *TariffPlan, err error) { if ub.tariffPlan == nil { - ub.tariffPlan, _ = storage.GetTariffPlan(ub.TariffPlanId) + ub.tariffPlan, err = storage.GetTariffPlan(ub.TariffPlanId) } - return ub.tariffPlan + return ub.tariffPlan, err } /* @@ -204,6 +207,25 @@ func (ub *UserBudget) setVolumeDiscountSeconds(sg StorageGetter, amount float64) return sg.SetUserBudget(ub) } +func (ub *UserBudget) resetUserBudget(sg StorageGetter) (err error) { + ub.mux.Lock() + defer ub.mux.Unlock() + if tp, err := ub.getTariffPlan(sg); err == nil { + ub.SmsCredit = tp.SmsCredit + ub.Traffic = tp.Traffic + ub.MinuteBuckets = make([]*MinuteBucket, 0) + for _, bucket := range tp.MinuteBuckets { + mb := &MinuteBucket{Seconds: bucket.Seconds, + Priority: bucket.Priority, + Price: bucket.Price, + DestinationId: bucket.DestinationId} + ub.MinuteBuckets = append(ub.MinuteBuckets, mb) + } + err = sg.SetUserBudget(ub) + } + return +} + /* Debits some amount of user's SMS budget. Returns the remaining SMS in user's budget. If the amount is bigger than the budget than nothing wil be debited and an error will be returned diff --git a/timespans/userbudget_test.go b/timespans/userbudget_test.go index 6349c6416..556feb221 100644 --- a/timespans/userbudget_test.go +++ b/timespans/userbudget_test.go @@ -252,6 +252,29 @@ func TestDebitMoreSMSBudget(t *testing.T) { } } +func TestResetUserBudget(t *testing.T) { + getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10) + defer getter.Close() + b1 := &MinuteBucket{Seconds: 10, Priority: 10, Price: 0.01, DestinationId: "nationale"} + b2 := &MinuteBucket{Seconds: 100, Priority: 20, Price: 0.0, DestinationId: "retea"} + seara := &TariffPlan{Id: "seara", SmsCredit: 100, MinuteBuckets: []*MinuteBucket{b1, b2}} + rifsBudget := &UserBudget{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, Credit: 21, tariffPlan: seara, ResetDayOfTheMonth: 10} + rifsBudget.MinuteBuckets[0].Seconds, rifsBudget.MinuteBuckets[1].Seconds = 0.0, 0.0 + err := rifsBudget.resetUserBudget(getter) + if err != nil || + rifsBudget.MinuteBuckets[0] == b1 || + rifsBudget.MinuteBuckets[0].Seconds != seara.MinuteBuckets[0].Seconds || + rifsBudget.MinuteBuckets[1].Seconds != seara.MinuteBuckets[1].Seconds || + rifsBudget.SmsCredit != seara.SmsCredit { + t.Log(rifsBudget.MinuteBuckets[0]) + t.Log(rifsBudget.MinuteBuckets[1]) + t.Log(rifsBudget.SmsCredit) + t.Log(rifsBudget.Traffic) + t.Errorf("Expected %v was %v", seara, rifsBudget) + } + +} + /*********************************** Benchmarks *******************************/ func BenchmarkGetSecondForPrefix(b *testing.B) {