From a78fea2f0a2a38735c06608ea8746e83eb7e48a4 Mon Sep 17 00:00:00 2001 From: Regis Date: Tue, 29 Nov 2016 17:46:17 +0100 Subject: [PATCH] connect fee in first increment --- engine/account.go | 43 ++++++++++++++++++++++++++--- engine/balances.go | 61 +++++++++++++++++++++++++++++++++++++++-- engine/callcost.go | 6 ++-- engine/calldesc.go | 3 ++ engine/calldesc_test.go | 1 + engine/timespans.go | 10 ++++++- 6 files changed, 114 insertions(+), 10 deletions(-) diff --git a/engine/account.go b/engine/account.go index 499db1318..db6df337c 100644 --- a/engine/account.go +++ b/engine/account.go @@ -416,6 +416,7 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo if debitErr != nil { return nil, debitErr } + //utils.Logger.Info(fmt.Sprintf("CD AFTER UNIT: %+v", cd)) if partCC != nil { //log.Printf("partCC: %+v", partCC.Timespans[0]) @@ -511,9 +512,13 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo if leftCC.Cost > 0 && goNegative { initialLength := len(cc.Timespans) cc.Timespans = append(cc.Timespans, leftCC.Timespans...) + + var debitedConnectFeeBalance Balance + var ok bool + if initialLength == 0 { // this is the first add, debit the connect fee - ub.DebitConnectionFee(cc, usefulMoneyBalances, count, true) + ok, debitedConnectFeeBalance = ub.DebitConnectionFee(cc, usefulMoneyBalances, count, true) } //log.Printf("Left CC: %+v ", leftCC) // get the default money balanance @@ -526,7 +531,33 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo if ts.Increments == nil { ts.createIncrementsSlice() } - for _, increment := range ts.Increments { + + if ts.RateInterval.Rating.ConnectFee > 0 && ok { + + inc := &Increment{ + Duration: 0, + Cost: ts.RateInterval.Rating.ConnectFee, + BalanceInfo: &DebitInfo{ + Monetary: &MonetaryInfo{ + UUID: debitedConnectFeeBalance.Uuid, + ID: debitedConnectFeeBalance.ID, + Value: debitedConnectFeeBalance.Value, + }, + AccountID: ub.ID, + }, + } + + incs := []*Increment{inc} + ts.Increments = append(incs, ts.Increments...) + } + + for incIndex, increment := range ts.Increments { + + if incIndex == 0 && ts.RateInterval.Rating.ConnectFee > 0 && ok { + // go to nextincrement + continue + } + cost := increment.Cost defaultBalance := ub.GetDefaultMoneyBalance() defaultBalance.SubstractValue(cost) @@ -824,6 +855,8 @@ func (acc *Account) Clone() *Account { } func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balances, count bool, block bool) (bool, Balance) { + var debitedBalance Balance + if cc.deductConnectFee { connectFee := cc.GetConnectFee() //log.Print("CONNECT FEE: %f", connectFee) @@ -836,10 +869,11 @@ func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balance acc.countUnits(connectFee, utils.MONETARY, cc, b) } connectFeePaid = true + debitedBalance = *b break } if b.Blocker && block { // stop here - return false + return false, debitedBalance } } // debit connect fee @@ -848,13 +882,14 @@ func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balance // there are no money for the connect fee; go negative b := acc.GetDefaultMoneyBalance() b.SubstractValue(connectFee) + debitedBalance = *b // the conect fee is not refundable! if count { acc.countUnits(connectFee, utils.MONETARY, cc, b) } } } - return true + return true, debitedBalance } func (acc *Account) matchActionFilter(condition string) (bool, error) { diff --git a/engine/balances.go b/engine/balances.go index b96be9b56..b3d046aab 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -385,13 +385,15 @@ func (b *Balance) debitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala } else { // get the cost from balance //log.Printf("::::::: %+v", cd) + var debitedConnectFeeBalance Balance + var ok bool cc, err = b.GetCost(cd, true) if err != nil { return nil, err } if debitConnectFee { // this is the first add, debit the connect fee - if ub.DebitConnectionFee(cc, moneyBalances, count, true) == false { + if ok, debitedConnectFeeBalance = ub.DebitConnectionFee(cc, moneyBalances, count, true); !ok { // found blocker balance return nil, nil } @@ -408,8 +410,34 @@ func (b *Balance) debitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala utils.Logger.Err(fmt.Sprintf("Nil RateInterval ERROR on TS: %+v, CC: %+v, from CD: %+v", ts, cc, cd)) return nil, errors.New("timespan with no rate interval assigned") } + + if ts.RateInterval.Rating.ConnectFee > 0 && debitConnectFee { + + inc := &Increment{ + Duration: 0, + Cost: ts.RateInterval.Rating.ConnectFee, + BalanceInfo: &DebitInfo{ + Monetary: &MonetaryInfo{ + UUID: debitedConnectFeeBalance.Uuid, + ID: debitedConnectFeeBalance.ID, + Value: debitedConnectFeeBalance.Value, + }, + AccountID: ub.ID, + }, + } + + incs := []*Increment{inc} + ts.Increments = append(incs, ts.Increments...) + } + maxCost, strategy := ts.RateInterval.GetMaxCost() for incIndex, inc := range ts.Increments { + + if incIndex == 0 && ts.RateInterval.Rating.ConnectFee > 0 && debitConnectFee { + // go to nextincrement + continue + } + // debit minutes and money amount := inc.Duration.Seconds() if b.Factor != nil { @@ -513,10 +541,13 @@ func (b *Balance) debitMoney(cd *CallDescriptor, ub *Account, moneyBalances Bala if err != nil { return nil, err } + + var debitedConnectFeeBalance Balance + var ok bool //log.Print("cc: " + utils.ToJSON(cc)) if debitConnectFee { // this is the first add, debit the connect fee - if ub.DebitConnectionFee(cc, moneyBalances, count, true) == false { + if ok, debitedConnectFeeBalance = ub.DebitConnectionFee(cc, moneyBalances, count, true); !ok { // balance is blocker return nil, nil } @@ -536,12 +567,38 @@ func (b *Balance) debitMoney(cd *CallDescriptor, ub *Account, moneyBalances Bala utils.Logger.Err(fmt.Sprintf("Nil RateInterval ERROR on TS: %+v, CC: %+v, from CD: %+v", ts, cc, cd)) return nil, errors.New("timespan with no rate interval assigned") } + + if ts.RateInterval.Rating.ConnectFee > 0 && debitConnectFee { + + inc := &Increment{ + Duration: 0, + Cost: ts.RateInterval.Rating.ConnectFee, + BalanceInfo: &DebitInfo{ + Monetary: &MonetaryInfo{ + UUID: debitedConnectFeeBalance.Uuid, + ID: debitedConnectFeeBalance.ID, + Value: debitedConnectFeeBalance.Value, + }, + AccountID: ub.ID, + }, + } + + incs := []*Increment{inc} + ts.Increments = append(incs, ts.Increments...) + } + maxCost, strategy := ts.RateInterval.GetMaxCost() //log.Printf("Timing: %+v", ts.RateInterval.Timing) //log.Printf("Rate: %+v", ts.RateInterval.Rating) for incIndex, inc := range ts.Increments { // check standard subject tags //log.Printf("INC: %+v", inc) + + if incIndex == 0 && ts.RateInterval.Rating.ConnectFee > 0 && ok { + // go to nextincrement + continue + } + amount := inc.Cost inc.paid = false if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { diff --git a/engine/callcost.go b/engine/callcost.go index 5e4ee8c75..b0899d32b 100644 --- a/engine/callcost.go +++ b/engine/callcost.go @@ -169,9 +169,9 @@ func (cc *CallCost) UpdateCost() { func (cc *CallCost) updateCost() { cost := 0.0 - if cc.deductConnectFee { // add back the connectFee - cost += cc.GetConnectFee() - } + //if cc.deductConnectFee { // add back the connectFee + // cost += cc.GetConnectFee() + //} for _, ts := range cc.Timespans { ts.Cost = ts.CalculateCost() cost += ts.Cost diff --git a/engine/calldesc.go b/engine/calldesc.go index 9df42331d..66ea9d1f0 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -370,6 +370,7 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { } //log.Printf("After SplitByRatingPlan: %+v", utils.ToJSON(timespans)) // split on days + for i := 0; i < len(timespans); i++ { rp := timespans[i].ratingInfo newTs := timespans[i].SplitByDay() @@ -386,6 +387,7 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { } //log.Printf("After SplitByDay: %+v", utils.ToJSON(timespans)) // split on rate intervals + for i := 0; i < len(timespans); i++ { //log.Printf("==============%v==================", i) //log.Printf("TS: %+v", timespans[i]) @@ -501,6 +503,7 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) { } func (cd *CallDescriptor) getCost() (*CallCost, error) { + // check for 0 duration if cd.GetDuration() == 0 { cc := cd.CreateCallCost() diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index 777134d9d..9326306d9 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -1425,6 +1425,7 @@ func TestMaxDebitZeroDefinedRate(t *testing.T) { if cc.GetDuration() != 49*time.Second { t.Error("Error obtaining max debit duration: ", cc.GetDuration()) } + if cc.Cost != 0.91 { t.Error("Error in max debit cost: ", cc.Cost) } diff --git a/engine/timespans.go b/engine/timespans.go index 4d18af209..6e65ca21a 100644 --- a/engine/timespans.go +++ b/engine/timespans.go @@ -696,7 +696,15 @@ func (nts *TimeSpan) copyRatingInfo(ts *TimeSpan) { // returns a time for the specified second in the time span func (ts *TimeSpan) GetTimeStartForIncrement(index int) time.Time { - return ts.TimeStart.Add(time.Duration(int64(index) * ts.Increments[0].Duration.Nanoseconds())) + + start := ts.TimeStart + for incIndex, inc := range ts.Increments { + if incIndex < index { + start = start.Add(time.Duration(inc.Duration.Nanoseconds())) + } + } + return start + //return ts.TimeStart.Add(time.Duration(int64(index) * ts.Increments[0].Duration.Nanoseconds())) } func (ts *TimeSpan) RoundToDuration(duration time.Duration) {