diff --git a/sessionmanager/sessiondelegate.go b/sessionmanager/sessiondelegate.go index 3cb6d43cd..9a65c3e62 100644 --- a/sessionmanager/sessiondelegate.go +++ b/sessionmanager/sessiondelegate.go @@ -51,7 +51,7 @@ type SessionDelegate interface { type DirectSessionDelegate byte func (dsd *DirectSessionDelegate) OnHeartBeat(ev Event) { - log.Print("direct hearbeat") + log.Print("♥") } func (dsd *DirectSessionDelegate) OnChannelAnswer(ev Event, s *Session) { @@ -63,16 +63,35 @@ func (dsd *DirectSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) // put credit back start := time.Now() end := lastCC.Timespans[len(lastCC.Timespans)-1].TimeEnd - cost := 0 - seconds := 0 - for _, ts := range lastCC.Timespans { - if ts.TimeEnd > start { - sec := ts.TimeEnd.Sub(start) - if ts.Interval.BillingUnit > 0 { - cost = (sec / ts.Interval.BillingUnit) * ts.Interval.Price - } else { - cost = sec * ts.Interval.Price + refoundDuration := end.Sub(start).Seconds() + cost := 0.0 + seconds := 0.0 + log.Printf("Refund duration: %v", refoundDuration) + for i := len(lastCC.Timespans) - 1; i >= 0; i-- { + ts := lastCC.Timespans[i] + tsDuration := ts.GetDuration().Seconds() + if refoundDuration <= tsDuration { + // find procentage + procentage := (refoundDuration * 100) / tsDuration + tmpCost := (procentage * ts.Cost) / 100 + ts.Cost -= tmpCost + cost += tmpCost + if ts.MinuteInfo != nil { + // DestinationPrefix and Price take from lastCC and above caclulus + seconds += (procentage * ts.MinuteInfo.Quantity) / 100 } + // set the end time to now + ts.TimeEnd = start + break // do not go to other timespans + } else { + cost += ts.Cost + if ts.MinuteInfo != nil { + seconds += ts.MinuteInfo.Quantity + } + // remove the timestamp entirely + lastCC.Timespans = lastCC.Timespans[:i] + // continue to the next timespan with what is left to refound + refoundDuration -= tsDuration } } if cost > 0 { @@ -82,6 +101,7 @@ func (dsd *DirectSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) DestinationPrefix: lastCC.DestinationPrefix, Amount: -cost, } + cd.SetStorageGetter(storageGetter) cd.DebitCents() } if seconds > 0 { @@ -91,9 +111,11 @@ func (dsd *DirectSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) DestinationPrefix: lastCC.DestinationPrefix, Amount: -seconds, } + cd.SetStorageGetter(storageGetter) cd.DebitSeconds() } - log.Print("Rambursed %v cents, %v seconds") + lastCC.Cost -= cost + log.Printf("Rambursed %v cents, %v seconds", cost, seconds) } func (dsd *DirectSessionDelegate) LoopAction(s *Session, cd *timespans.CallDescriptor) { diff --git a/timespans/calldesc.go b/timespans/calldesc.go index ed2db05c5..3022aa973 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -211,7 +211,7 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) { if i == 0 && ts.MinuteInfo == nil && ts.Interval != nil { connectionFee = ts.Interval.ConnectFee } - cost += ts.GetCost(cd) + cost += ts.getCost(cd) } cc := &CallCost{TOR: cd.TOR, CstmId: cd.CstmId, @@ -236,7 +236,7 @@ func (cd *CallDescriptor) getPresentSecondCost() (cost float64, err error) { timespans := cd.splitTimeSpan(ts) if len(timespans) > 0 { - cost = round(timespans[0].GetCost(cd), 3) + cost = round(timespans[0].getCost(cd), 3) } return } @@ -278,7 +278,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) { if i == 0 && ts.MinuteInfo == nil && ts.Interval != nil { cost += ts.Interval.ConnectFee } - cost += ts.GetCost(cd) + cost += ts.getCost(cd) } if cost < availableCredit { return maxSessionSeconds, nil diff --git a/timespans/timespans.go b/timespans/timespans.go index 14366533f..08fa774a0 100644 --- a/timespans/timespans.go +++ b/timespans/timespans.go @@ -29,6 +29,7 @@ A unit in which a call will be split that has a specific price related interval */ type TimeSpan struct { TimeStart, TimeEnd time.Time + Cost float64 ActivationPeriod *ActivationPeriod Interval *Interval MinuteInfo *MinuteInfo @@ -48,10 +49,10 @@ func (ts *TimeSpan) GetDuration() time.Duration { return ts.TimeEnd.Sub(ts.TimeStart) } -/* -Returns the cost of the timespan according to the relevant cost interval. -*/ -func (ts *TimeSpan) GetCost(cd *CallDescriptor) (cost float64) { +// Returns the cost of the timespan according to the relevant cost interval. +// It also sets the Cost field of this timespan (used for refound on session +// manager debit loop where the cost cannot be recalculated) +func (ts *TimeSpan) getCost(cd *CallDescriptor) (cost float64) { if ts.MinuteInfo != nil { return ts.GetDuration().Seconds() * ts.MinuteInfo.Price } @@ -70,6 +71,7 @@ func (ts *TimeSpan) GetCost(cd *CallDescriptor) (cost float64) { } userBudget.mux.RUnlock() } + ts.Cost = cost return }