commands compilable again, worked on debit action

This commit is contained in:
Radu Ioan Fericean
2012-07-03 18:14:59 +03:00
parent d8b86cb270
commit 846fce4b27
19 changed files with 202 additions and 106 deletions

View File

@@ -45,7 +45,7 @@ The function that gets the information from the raters using balancer.
*/
func GetCallCost(key *timespans.CallDescriptor, method string) (reply *timespans.CallCost) {
balancerRWMutex.RLock()
defer balancerRWMutex
defer balancerRWMutex.RUnlock()
err := errors.New("") //not nil value
for err != nil {
client := bal.Balance()
@@ -67,6 +67,8 @@ func GetCallCost(key *timespans.CallDescriptor, method string) (reply *timespans
The function that gets the information from the raters using balancer.
*/
func CallMethod(key *timespans.CallDescriptor, method string) (reply float64) {
balancerRWMutex.Lock()
defer balancerRWMutex.Unlock()
err := errors.New("") //not nil value
for err != nil {
client := bal.Balance()

View File

@@ -30,30 +30,30 @@ type IncorrectParameters struct {
}
/*
curl "http://127.0.0.1:8000/getcost?cstmid=vdf&subj=rif&dest=0257"
curl "http://127.0.0.1:8000/getcost?tenant=vdf&subj=rif&dest=0257"
*/
func getCostHandler(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
if !ok1 || !ok2 || !ok3 {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0]}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0]}
callCost := GetCallCost(arg, "Responder.GetCost")
enc.Encode(callCost)
}
/*
curl "http://127.0.0.1:8000/debitbalance?cstmid=vdf&subj=rif&dest=0257@amount=100"
curl "http://127.0.0.1:8000/debitbalance?tenant=vdf&subj=rif&dest=0257@amount=100"
*/
func debitBalanceHandler(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
@@ -62,18 +62,18 @@ func debitBalanceHandler(w http.ResponseWriter, r *http.Request) {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount}
result := CallMethod(arg, "Responder.DebitCents")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/debitsms?cstmid=vdf&subj=rif&dest=0257@amount=100"
curl "http://127.0.0.1:8000/debitsms?tenant=vdf&subj=rif&dest=0257@amount=100"
*/
func debitSMSHandler(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
@@ -82,18 +82,18 @@ func debitSMSHandler(w http.ResponseWriter, r *http.Request) {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount}
result := CallMethod(arg, "Responder.DebitSMS")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/debitseconds?cstmid=vdf&subj=rif&dest=0257@amount=100"
curl "http://127.0.0.1:8000/debitseconds?tenant=vdf&subj=rif&dest=0257@amount=100"
*/
func debitSecondsHandler(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
@@ -102,18 +102,18 @@ func debitSecondsHandler(w http.ResponseWriter, r *http.Request) {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount}
result := CallMethod(arg, "Responder.DebitSeconds")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/getmaxsessiontime?cstmid=vdf&subj=rif&dest=0257@amount=100"
curl "http://127.0.0.1:8000/getmaxsessiontime?tenant=vdf&subj=rif&dest=0257@amount=100"
*/
func getMaxSessionTimeHandler(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
@@ -122,18 +122,18 @@ func getMaxSessionTimeHandler(w http.ResponseWriter, r *http.Request) {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount}
result := CallMethod(arg, "Responder.GetMaxSessionTime")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/addvolumediscountseconds?cstmid=vdf&subj=rif&dest=0257@amount=100"
curl "http://127.0.0.1:8000/addvolumediscountseconds?tenant=vdf&subj=rif&dest=0257@amount=100"
*/
func addVolumeDiscountSeconds(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
@@ -142,36 +142,36 @@ func addVolumeDiscountSeconds(w http.ResponseWriter, r *http.Request) {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount}
result := CallMethod(arg, "Responder.AddVolumeDiscountSeconds")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/resetvolumediscountseconds?cstmid=vdf&subj=rif&dest=0257"
curl "http://127.0.0.1:8000/resetvolumediscountseconds?tenant=vdf&subj=rif&dest=0257"
*/
func resetVolumeDiscountSeconds(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
if !ok1 || !ok2 || !ok3 {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0]}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0]}
result := CallMethod(arg, "Responder.ResetVolumeDiscountSeconds")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/addrecievedcallseconds?cstmid=vdf&subj=rif&dest=0257@amount=100"
curl "http://127.0.0.1:8000/addrecievedcallseconds?tenant=vdf&subj=rif&dest=0257@amount=100"
*/
func addRecievedCallSeconds(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
@@ -180,25 +180,25 @@ func addRecievedCallSeconds(w http.ResponseWriter, r *http.Request) {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount}
result := CallMethod(arg, "Responder.AddRecievedCallSeconds")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/resetuserbudget?cstmid=vdf&subj=rif&dest=0257"
curl "http://127.0.0.1:8000/resetuserbudget?tenant=vdf&subj=rif&dest=0257"
*/
func resetUserBudget(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
tenant, ok1 := r.Form["tenant"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
if !ok1 || !ok2 || !ok3 {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0]}
arg := &timespans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0]}
result := CallMethod(arg, "Responder.ResetUserBudget")
enc.Encode(result)
}

View File

@@ -29,14 +29,15 @@ import (
)
var (
server = flag.String("server", "127.0.0.1:2001", "server address host:port")
tor = flag.String("tor", "0", "Type of record")
cstmid = flag.String("cstmid", "vdf", "Customer identificator")
subject = flag.String("subject", "rif", "The client who made the call")
dest = flag.String("dest", "0256", "Destination prefix")
ts = flag.String("ts", "2012-02-09T00:00:00Z", "Time start")
te = flag.String("te", "2012-02-09T00:10:00Z", "Time end")
amount = flag.Float64("amount", 100, "Amount for different operations")
server = flag.String("server", "127.0.0.1:2001", "server address host:port")
tor = flag.String("tor", "0", "Type of record")
direction = flag.String("direction", "OUT", "Call direction")
tenant = flag.String("tenant", "vdf", "Tenant identificator")
subject = flag.String("subject", "rif", "The client who made the call")
dest = flag.String("dest", "0256", "Call destination")
ts = flag.String("ts", "2012-02-09T00:00:00Z", "Time start")
te = flag.String("te", "2012-02-09T00:10:00Z", "Time end")
amount = flag.Float64("amount", 100, "Amount for different operations")
)
func main() {
@@ -56,13 +57,15 @@ func main() {
log.Fatal("Time end format is invalid: ", err)
}
cd := &timespans.CallDescriptor{TOR: *tor,
CstmId: *cstmid,
Subject: *subject,
DestinationPrefix: *dest,
TimeStart: timestart,
TimeEnd: timeend,
Amount: *amount,
cd := &timespans.CallDescriptor{
Direction: *direction,
TOR: *tor,
Tenant: *tenant,
Subject: *subject,
Destination: *dest,
TimeStart: timestart,
TimeEnd: timeend,
Amount: *amount,
}
switch flag.Arg(0) {

View File

@@ -75,17 +75,23 @@ func loadActions() {
if record[5] == timespans.ABSOLUTE {
price = value
}
weight, err := strconv.ParseFloat(record[7], 64)
minutesWeight, err := strconv.ParseFloat(record[7], 64)
if err != nil {
log.Printf("Could not parse action units: %v", err)
log.Printf("Could not parse action minutes weight: %v", err)
continue
}
weight, err := strconv.ParseFloat(record[8], 64)
if err != nil {
log.Printf("Could not parse action weight: %v", err)
continue
}
a = &timespans.Action{
ActionType: record[1],
BalanceId: record[2],
Weight: weight,
MinuteBucket: &timespans.MinuteBucket{
Seconds: units,
Weight: weight,
Weight: minutesWeight,
Price: price,
Percent: percent,
DestinationId: record[4],
@@ -120,9 +126,15 @@ func loadActionTimings() {
log.Printf("Could not load the timing for tag: %v", record[2])
continue
}
weight, err := strconv.ParseFloat(record[3], 64)
if err != nil {
log.Printf("Could not parse action timing weight: %v", err)
continue
}
for _, t := range ts {
at := &timespans.ActionTiming{
Tag: record[2],
Tag: record[2],
Weight: weight,
Timing: &timespans.Interval{
Months: t.Months,
MonthDays: t.MonthDays,
@@ -160,11 +172,17 @@ func loadActionTriggers() {
log.Printf("Could not parse action trigger value: %v", err)
continue
}
weight, err := strconv.ParseFloat(record[5], 64)
if err != nil {
log.Printf("Could not parse action trigger weight: %v", err)
continue
}
at := &timespans.ActionTrigger{
BalanceId: record[1],
ThresholdValue: value,
DestinationId: record[3],
ActionsId: record[4],
Weight: weight,
}
actionsTriggers[tag] = append(actionsTriggers[tag], at)
}

View File

@@ -37,7 +37,7 @@ func main() {
flag.Parse()
t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC)
cd := timespans.CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2}
cd := timespans.CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2}
result := timespans.CallCost{}
client, err := jsonrpc.Dial("tcp", *balancer)
if err != nil {

View File

@@ -43,7 +43,7 @@ class JSONClient(object):
rpc =JSONClient(("127.0.0.1", 2001))
cd = {"Tor":0, "CstmId": "vdf", "Subject": "rif", "DestinationPrefix": "0256", "TimeStart": "2012-02-02T17:30:00Z", "TimeEnd": "2012-02-02T18:30:00Z"}
cd = {"Direction":"OUT", "TOR":"0", "Tenant": "vdf", "Subject": "rif", "DestinationPrefix": "0256", "TimeStart": "2012-02-02T17:30:00Z", "TimeEnd": "2012-02-02T18:30:00Z"}
# alternative to the above
s = socket.create_connection(("127.0.0.1", 2001))

View File

@@ -34,7 +34,7 @@ func main() {
flag.Parse()
t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC)
cd := timespans.CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2}
cd := timespans.CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2}
result := timespans.CallCost{}
client, _ := jsonrpc.Dial("tcp", "localhost:5090")
i := 0

View File

@@ -47,13 +47,12 @@ func main() {
t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC)
cd := timespans.CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2}
cd := timespans.CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2}
//getter, _ := timespans.NewRedisStorage("", 10)
getter, err := timespans.NewKyotoStorage("storage.kch")
getter, err := timespans.NewRedisStorage("", 10)
defer getter.Close()
cd.SetStorageGetter(getter)
timespans.SetStorageGetter(getter)
log.Printf("Runnning %d cycles...", *runs)
var result *timespans.CallCost

View File

@@ -31,6 +31,6 @@ type Event interface {
GetDestination() string
GetTOR() string
GetUUID() string
GetCstmId() string
GetTenant() string
GetStartTime() (time.Time, error)
}

View File

@@ -94,7 +94,7 @@ func (fsev *FSEvent) GetTOR() string {
func (fsev *FSEvent) GetUUID() string {
return fsev.Fields[UUID]
}
func (fsev *FSEvent) GetCstmId() string {
func (fsev *FSEvent) GetTenant() string {
return fsev.Fields[CSTMID]
}
func (fsev *FSEvent) GetStartTime() (t time.Time, err error) {

View File

@@ -51,9 +51,9 @@ func (psl *PostgresLogger) Log(uuid string, cc *timespans.CallCost) {
_, err = psl.db.Exec(fmt.Sprintf("INSERT INTO callcosts VALUES ('%s', '%s', '%s', '%s', '%s', %v, %v, '%s')",
uuid,
cc.TOR,
cc.CstmId,
cc.Tenant,
cc.Subject,
cc.DestinationPrefix,
cc.Destination,
cc.Cost,
cc.ConnectFee,
tss))

View File

@@ -46,11 +46,13 @@ func NewSession(ev Event, sm SessionManager) (s *Session) {
log.Print("Error parsing answer event start time, using time.Now!")
startTime = time.Now()
}
cd := &timespans.CallDescriptor{TOR: ev.GetTOR(),
CstmId: ev.GetCstmId(),
Subject: ev.GetSubject(),
DestinationPrefix: ev.GetDestination(),
TimeStart: startTime}
cd := &timespans.CallDescriptor{
Direction: ev.GetDirection(),
TOR: ev.GetTOR(),
Tenant: ev.GetTenant(),
Subject: ev.GetSubject(),
Destination: ev.GetDestination(),
TimeStart: startTime}
s = &Session{uuid: ev.GetUUID(),
callDescriptor: cd,
stopDebit: make(chan byte, 2)} //buffer it for multiple close signals
@@ -106,7 +108,7 @@ func (s *Session) Disconnect() {
// Nice print for session
func (s *Session) String() string {
return fmt.Sprintf("%v: %s -> %s", s.callDescriptor.TimeStart, s.callDescriptor.Subject, s.callDescriptor.DestinationPrefix)
return fmt.Sprintf("%v: %s -> %s", s.callDescriptor.TimeStart, s.callDescriptor.Subject, s.callDescriptor.Destination)
}
//

View File

@@ -50,6 +50,7 @@ type DirectSessionDelegate struct {
}
func NewDirectSessionDelegate(storageGetter timespans.StorageGetter) *DirectSessionDelegate {
timespans.SetStorageGetter(storageGetter)
return &DirectSessionDelegate{storageGetter}
}
@@ -98,23 +99,24 @@ func (dsd *DirectSessionDelegate) OnChannelHangupComplete(ev Event, s *Session)
}
}
if cost > 0 {
cd := &timespans.CallDescriptor{TOR: lastCC.TOR,
CstmId: lastCC.CstmId,
Subject: lastCC.CstmId,
DestinationPrefix: lastCC.DestinationPrefix,
Amount: -cost,
cd := &timespans.CallDescriptor{
TOR: lastCC.TOR,
Tenant: lastCC.Tenant,
Subject: lastCC.Subject,
Destination: lastCC.Destination,
Amount: -cost,
}
cd.SetStorageGetter(dsd.storageGetter)
cd.DebitCents()
}
if seconds > 0 {
cd := &timespans.CallDescriptor{TOR: lastCC.TOR,
CstmId: lastCC.CstmId,
Subject: lastCC.CstmId,
DestinationPrefix: lastCC.DestinationPrefix,
Amount: -seconds,
cd := &timespans.CallDescriptor{
TOR: lastCC.TOR,
Tenant: lastCC.Tenant,
Subject: lastCC.Subject,
Destination: lastCC.Destination,
Amount: -seconds,
}
cd.SetStorageGetter(dsd.storageGetter)
cd.DebitSeconds()
}
lastCC.Cost -= cost
@@ -122,7 +124,7 @@ func (dsd *DirectSessionDelegate) OnChannelHangupComplete(ev Event, s *Session)
}
func (dsd *DirectSessionDelegate) LoopAction(s *Session, cd *timespans.CallDescriptor) {
cd.SetStorageGetter(dsd.storageGetter)
timespans.SetStorageGetter(dsd.storageGetter)
cc, err := cd.Debit()
if err != nil {
log.Printf("Could not complete debit opperation: %v", err)
@@ -218,11 +220,12 @@ func (rsd *RPCSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) {
}
}
if cost > 0 {
cd := &timespans.CallDescriptor{TOR: lastCC.TOR,
CstmId: lastCC.CstmId,
Subject: lastCC.CstmId,
DestinationPrefix: lastCC.DestinationPrefix,
Amount: -cost,
cd := &timespans.CallDescriptor{
TOR: lastCC.TOR,
Tenant: lastCC.Tenant,
Subject: lastCC.Subject,
Destination: lastCC.Destination,
Amount: -cost,
}
var response float64
err := client.Call("Responder.DebitCents", cd, &response)
@@ -231,11 +234,12 @@ func (rsd *RPCSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) {
}
}
if seconds > 0 {
cd := &timespans.CallDescriptor{TOR: lastCC.TOR,
CstmId: lastCC.CstmId,
Subject: lastCC.CstmId,
DestinationPrefix: lastCC.DestinationPrefix,
Amount: -seconds,
cd := &timespans.CallDescriptor{
TOR: lastCC.TOR,
Tenant: lastCC.Tenant,
Subject: lastCC.Subject,
Destination: lastCC.Destination,
Amount: -seconds,
}
var response float64
err := client.Call("Responder.DebitSeconds", cd, &response)

View File

@@ -67,8 +67,8 @@ func setPostpaidAction(ub *UserBalance, a *Action) (err error) {
}
func resetPostpaidAction(ub *UserBalance, a *Action) (err error) {
ub.Type = UB_TYPE_POSTPAID
return
genericReset(ub)
return setPostpaidAction(ub, a)
}
func setPrepaidAction(ub *UserBalance, a *Action) (err error) {
@@ -77,8 +77,8 @@ func setPrepaidAction(ub *UserBalance, a *Action) (err error) {
}
func resetPrepaidAction(ub *UserBalance, a *Action) (err error) {
ub.Type = UB_TYPE_PREPAID
return
genericReset(ub)
return setPrepaidAction(ub, a)
}
func topupResetAction(ub *UserBalance, a *Action) (err error) {
@@ -99,14 +99,35 @@ func topupAction(ub *UserBalance, a *Action) (err error) {
}
func debitAction(ub *UserBalance, a *Action) (err error) {
switch a.ActionType {
case CREDIT:
ub.debitMoneyBalance(a.Units)
case SMS:
ub.debitSMSBalance(a.Units)
case MINUTES:
ub.debitMinuteBucket(a.MinuteBucket)
case TRAFFIC:
ub.debitTrafficBalance(a.Units)
case TRAFFIC_TIME:
ub.debitTrafficTimeBalance(a.Units)
}
return
}
func resetCountersAction(ub *UserBalance, a *Action) (err error) {
//ub.UnitsCounters
ub.UnitCounters = make([]*UnitsCounter, 0)
return
}
func genericReset(ub *UserBalance) {
for k, _ := range ub.BalanceMap {
ub.BalanceMap[k] = 0
}
ub.MinuteBuckets = make([]*MinuteBucket, 0)
ub.UnitCounters = make([]*UnitsCounter, 0)
ub.resetActionTriggers()
}
// Structure to store actions according to weight
type ActionPriotityList []*Action

View File

@@ -342,6 +342,7 @@ func (cd *CallDescriptor) Debit() (cc *CallCost, err error) {
log.Printf("error getting cost %v", err)
}
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
defer storageGetter.SetUserBalance(userBalance)
if cc.Cost != 0 || cc.ConnectFee != 0 {
userBalance.debitMoneyBalance(cc.Cost + cc.ConnectFee)
}
@@ -362,6 +363,7 @@ func (cd *CallDescriptor) DebitCents() (left float64, err error) {
userBalancesRWMutex.Lock()
defer userBalancesRWMutex.Unlock()
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
defer storageGetter.SetUserBalance(userBalance)
return userBalance.debitMoneyBalance(cd.Amount), nil
}
return 0.0, err
@@ -375,7 +377,8 @@ func (cd *CallDescriptor) DebitSMS() (left float64, err error) {
userBalancesRWMutex.Lock()
defer userBalancesRWMutex.Unlock()
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
return userBalance.debitSMSBuget(cd.Amount)
defer storageGetter.SetUserBalance(userBalance)
return userBalance.debitSMSBalance(cd.Amount)
}
return 0, err
}
@@ -388,6 +391,7 @@ func (cd *CallDescriptor) DebitSeconds() (err error) {
userBalancesRWMutex.Lock()
defer userBalancesRWMutex.Unlock()
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
defer storageGetter.SetUserBalance(userBalance)
return userBalance.debitMinutesBalance(cd.Amount, cd.Destination)
}
return err

View File

@@ -42,6 +42,14 @@ func (mb *MinuteBucket) GetSecondsForCredit(credit float64) (seconds float64) {
return
}
//
func (mb *MinuteBucket) Equal(o *MinuteBucket) bool {
return mb.DestinationId == o.DestinationId &&
mb.Weight == o.Weight &&
mb.Price == o.Price &&
mb.Percent == o.Percent
}
/*
Structure to store minute buckets according to weight, precision or price.
*/

View File

@@ -54,3 +54,12 @@ func TestMinutBucketSortPrice(t *testing.T) {
t.Error("Buckets not sorted by price!")
}
}
func TestMinutBucketEqual(t *testing.T) {
mb1 := &MinuteBucket{Weight: 1, precision: 1, Price: 1, Percent: 1, DestinationId: ""}
mb2 := &MinuteBucket{Weight: 1, precision: 1, Price: 1, Percent: 1, DestinationId: ""}
mb3 := &MinuteBucket{Weight: 1, precision: 1, Price: 2, Percent: 1, DestinationId: ""}
if !mb1.Equal(mb2) || mb2.Equal(mb3) {
t.Error("Equal failure!", mb1, mb2, mb3)
}
}

View File

@@ -53,7 +53,7 @@ type UserBalance struct {
Type string // prepaid-postpaid
BalanceMap map[string]float64
MinuteBuckets []*MinuteBucket
UnitsCounters []*UnitsCounter
UnitCounters []*UnitsCounter
ActionTriggers ActionTriggerPriotityList
}
@@ -102,10 +102,20 @@ Debits some amount of user's money credit. Returns the remaining credit in user'
*/
func (ub *UserBalance) debitMoneyBalance(amount float64) float64 {
ub.BalanceMap[CREDIT] -= amount
storageGetter.SetUserBalance(ub)
return ub.BalanceMap[CREDIT]
}
// Debit seconds from specified minute bucket
func (ub *UserBalance) debitMinuteBucket(newMb *MinuteBucket) error {
for _, mb := range ub.MinuteBuckets {
if mb.Equal(newMb) {
mb.Seconds -= newMb.Seconds
}
}
return nil
}
/*
Debits the received amount of seconds from user's minute buckets.
All the appropriate buckets will be debited until all amount of minutes is consumed.
@@ -150,7 +160,6 @@ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string) error
break
}
}
storageGetter.SetUserBalance(ub)
return nil
}
@@ -158,13 +167,30 @@ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string) error
Debits some amount of user's SMS balance. Returns the remaining SMS in user's balance.
If the amount is bigger than the balance than nothing wil be debited and an error will be returned
*/
func (ub *UserBalance) debitSMSBuget(amount float64) (float64, error) {
func (ub *UserBalance) debitSMSBalance(amount float64) (float64, error) {
if ub.BalanceMap[SMS] < amount {
return ub.BalanceMap[SMS], new(AmountTooBig)
}
ub.BalanceMap[SMS] -= amount
return ub.BalanceMap[SMS], nil
}
func (ub *UserBalance) debitTrafficBalance(amount float64) (float64, error) {
if ub.BalanceMap[SMS] < amount {
return ub.BalanceMap[SMS], new(AmountTooBig)
}
ub.BalanceMap[SMS] -= amount
return ub.BalanceMap[SMS], nil
}
func (ub *UserBalance) debitTrafficTimeBalance(amount float64) (float64, error) {
if ub.BalanceMap[SMS] < amount {
return ub.BalanceMap[SMS], new(AmountTooBig)
}
ub.BalanceMap[SMS] -= amount
storageGetter.SetUserBalance(ub)
return ub.BalanceMap[SMS], nil
}
@@ -193,7 +219,7 @@ func (ub *UserBalance) executeActionTriggers() {
// the next reset (see RESET_TRIGGERS action type)
continue
}
for _, uc := range ub.UnitsCounters {
for _, uc := range ub.UnitCounters {
if uc.BalanceId == at.BalanceId {
if at.BalanceId == MINUTES && at.DestinationId != "" { // last check adds safty
for _, mb := range uc.MinuteBuckets {
@@ -241,7 +267,7 @@ Adds the specified amount of seconds.
// }
// }
// }
// return storageGetter.SetUserBalance(ub)
// return
// }
/*
@@ -260,7 +286,7 @@ Resets the user balance items to their tariff plan values.
DestinationId: bucket.DestinationId}
ub.MinuteBuckets = append(ub.MinuteBuckets, mb)
}
err = storageGetter.SetUserBalance(ub)
err =
}
return
}

View File

@@ -162,7 +162,7 @@ func TestDebitMoreMinuteBalance(t *testing.T) {
}
}
func TestDebitPriceMinuteBalance(t *testing.T) {
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]float64{CREDIT: 21}}
@@ -219,7 +219,7 @@ 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]float64{CREDIT: 21, SMS: 100}}
result, err := rifsBalance.debitSMSBuget(12)
result, err := rifsBalance.debitSMSBalance(12)
if rifsBalance.BalanceMap[SMS] != 88 || result != rifsBalance.BalanceMap[SMS] || err != nil {
t.Errorf("Expected %v was %v", 88, rifsBalance.BalanceMap[SMS])
}
@@ -229,7 +229,7 @@ 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]float64{CREDIT: 21, SMS: 100}}
result, err := rifsBalance.debitSMSBuget(100)
result, err := rifsBalance.debitSMSBalance(100)
if rifsBalance.BalanceMap[SMS] != 0 || result != rifsBalance.BalanceMap[SMS] || err != nil {
t.Errorf("Expected %v was %v", 0, rifsBalance.BalanceMap[SMS])
}
@@ -239,7 +239,7 @@ 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]float64{CREDIT: 21, SMS: 100}}
result, err := rifsBalance.debitSMSBuget(110)
result, err := rifsBalance.debitSMSBalance(110)
if rifsBalance.BalanceMap[SMS] != 100 || result != rifsBalance.BalanceMap[SMS] || err == nil {
t.Errorf("Expected %v was %v", 100, rifsBalance.BalanceMap[SMS])
}
@@ -249,7 +249,7 @@ 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]float64{CREDIT: 21, SMS: 100}}
result, err := rifsBalance.debitSMSBuget(-15)
result, err := rifsBalance.debitSMSBalance(-15)
if rifsBalance.BalanceMap[SMS] != 115 || result != rifsBalance.BalanceMap[SMS] || err != nil {
t.Errorf("Expected %v was %v", 115, rifsBalance.BalanceMap[SMS])
}