Esempio n. 1
0
/*
Returns the approximate max allowed session for user balance. It will try the max amount received in the call descriptor
If the user has no credit then it will return 0.
If the user has postpayed plan it returns -1.
*/
func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Duration, error) {
	// clone the account for discarding chenges on debit dry run
	//log.Printf("ORIG CD: %+v", origCD)
	account := origAcc.Clone()
	if account.AllowNegative {
		return -1, nil
	}
	// for zero duration index
	if origCD.DurationIndex < origCD.TimeEnd.Sub(origCD.TimeStart) {
		origCD.DurationIndex = origCD.TimeEnd.Sub(origCD.TimeStart)
	}
	if origCD.TOR == "" {
		origCD.TOR = utils.VOICE
	}
	cd := origCD.Clone()
	initialDuration := cd.TimeEnd.Sub(cd.TimeStart)
	defaultBalance := account.GetDefaultMoneyBalance()

	//use this to check what increment was payed with debt
	initialDefaultBalanceValue := defaultBalance.GetValue()

	cc, err := cd.debit(account, true, false)
	if err != nil {
		return 0, err
	}

	// not enough credit for connect fee
	if cc.negativeConnectFee == true {
		return 0, nil
	}

	var totalCost float64
	var totalDuration time.Duration
	cc.Timespans.Decompress()
	for _, ts := range cc.Timespans {
		if cd.MaxRate > 0 && cd.MaxRateUnit > 0 {
			rate, _, rateUnit := ts.RateInterval.GetRateParameters(ts.GetGroupStart())
			if rate/rateUnit.Seconds() > cd.MaxRate/cd.MaxRateUnit.Seconds() {
				return utils.MinDuration(initialDuration, totalDuration), nil
			}
		}
		if ts.Increments == nil {
			ts.createIncrementsSlice()
		}
		for _, incr := range ts.Increments {
			totalCost += incr.Cost
			if incr.BalanceInfo.Monetary != nil && incr.BalanceInfo.Monetary.UUID == defaultBalance.Uuid {
				initialDefaultBalanceValue -= incr.Cost
				if initialDefaultBalanceValue < 0 {
					// this increment was payed with debt
					// TODO: improve this check
					return utils.MinDuration(initialDuration, totalDuration), nil

				}
			}
			totalDuration += incr.Duration
			//log.Print("INC: ", utils.ToJSON(incr))
			if totalDuration >= initialDuration {
				// we have enough, return
				return initialDuration, nil
			}
		}
	}
	return utils.MinDuration(initialDuration, totalDuration), nil
}
Esempio n. 2
0
/*
Returns the approximate max allowed session for user balance. It will try the max amount received in the call descriptor
If the user has no credit then it will return 0.
If the user has postpayed plan it returns -1.
*/
func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Duration, error) {
	// clone the account for discarding chenges on debit dry run
	//log.Printf("ORIG CD: %+v", origCD)
	account := origAcc.Clone()
	if account.AllowNegative {
		return -1, nil
	}
	if origCD.DurationIndex < origCD.TimeEnd.Sub(origCD.TimeStart) {
		origCD.DurationIndex = origCD.TimeEnd.Sub(origCD.TimeStart)
	}
	if origCD.TOR == "" {
		origCD.TOR = utils.VOICE
	}
	//utils.Logger.Debug("ORIG: " + utils.ToJSON(origCD))
	cd := origCD.Clone()
	initialDuration := cd.TimeEnd.Sub(cd.TimeStart)
	//utils.Logger.Debug(fmt.Sprintf("INITIAL_DURATION: %v", initialDuration))
	defaultBalance := account.GetDefaultMoneyBalance()

	//use this to check what increment was payed with debt
	initialDefaultBalanceValue := defaultBalance.GetValue()

	//utils.Logger.Debug("ACCOUNT: " + utils.ToJSON(account))
	//utils.Logger.Debug("DEFAULT_BALANCE: " + utils.ToJSON(defaultBalance))

	//
	cc, err := cd.debit(account, true, false)
	//utils.Logger.Debug("CC: " + utils.ToJSON(cc))
	//log.Print("CC: ", utils.ToIJSON(cc))
	//utils.Logger.Debug(fmt.Sprintf("ERR: %v", err))
	if err != nil {
		return 0, err
	}

	//log.Printf("CC: %+v", cc)
	// not enough credit for connect fee
	if cc.negativeConnectFee == true {
		return 0, nil
	}

	var totalCost float64
	var totalDuration time.Duration
	cc.Timespans.Decompress()
	//log.Printf("ACC: %+v", account)
	for _, ts := range cc.Timespans {
		//if ts.RateInterval != nil {
		//log.Printf("TS: %+v", ts)
		//utils.Logger.Debug("TS: " + utils.ToJSON(ts))
		//}
		if cd.MaxRate > 0 && cd.MaxRateUnit > 0 {
			rate, _, rateUnit := ts.RateInterval.GetRateParameters(ts.GetGroupStart())
			if rate/rateUnit.Seconds() > cd.MaxRate/cd.MaxRateUnit.Seconds() {
				//utils.Logger.Debug(fmt.Sprintf("0_INIT DUR %v, TOTAL DUR: %v", initialDuration, totalDuration))
				return utils.MinDuration(initialDuration, totalDuration), nil
			}
		}
		if ts.Increments == nil {
			ts.createIncrementsSlice()
		}
		for _, incr := range ts.Increments {
			//utils.Logger.Debug("INCR: " + utils.ToJSON(incr))
			totalCost += incr.Cost
			if incr.BalanceInfo.MoneyBalanceUuid == defaultBalance.Uuid {
				initialDefaultBalanceValue -= incr.Cost
				if initialDefaultBalanceValue < 0 {
					// this increment was payed with debt
					// TODO: improve this check
					//utils.Logger.Debug(fmt.Sprintf("1_INIT DUR %v, TOTAL DUR: %v", initialDuration, totalDuration))
					return utils.MinDuration(initialDuration, totalDuration), nil

				}
			}
			totalDuration += incr.Duration
			if totalDuration >= initialDuration {
				// we have enough, return
				//utils.Logger.Debug(fmt.Sprintf("2_INIT DUR %v, TOTAL DUR: %v", initialDuration, totalDuration))
				return initialDuration, nil
			}
		}
	}
	//utils.Logger.Debug(fmt.Sprintf("3_INIT DUR %v, TOTAL DUR: %v", initialDuration, totalDuration))
	return utils.MinDuration(initialDuration, totalDuration), nil
}
Esempio n. 3
0
/*
Returns the approximate max allowed session for user balance. It will try the max amount received in the call descriptor
If the user has no credit then it will return 0.
If the user has postpayed plan it returns -1.
*/
func (origCD *CallDescriptor) getMaxSessionDuration(account *Account) (time.Duration, error) {
	if origCD.DurationIndex < origCD.TimeEnd.Sub(origCD.TimeStart) {
		origCD.DurationIndex = origCD.TimeEnd.Sub(origCD.TimeStart)
	}
	if origCD.TOR == "" {
		origCD.TOR = MINUTES
	}
	cd := origCD.Clone()
	//Logger.Debug(fmt.Sprintf("MAX SESSION cd: %+v", cd))
	err := cd.LoadRatingPlans()
	if err != nil {
		Logger.Err(fmt.Sprintf("error getting cost for key %v: %v", cd.GetAccountKey(), err))
		return 0, err
	}
	var availableDuration time.Duration
	availableCredit := 0.0
	if account.AllowNegative {
		return -1, nil
	} else {
		availableDuration, availableCredit, _ = account.getCreditForPrefix(cd)
		// Logger.Debug(fmt.Sprintf("available sec: %v credit: %v", availableSeconds, availableCredit))
	}
	if cd.MaxCost > 0 {
		// limit availableCredit
		if cd.MaxCostSoFar+availableCredit > cd.MaxCost {
			availableCredit = cd.MaxCost - cd.MaxCostSoFar
		}
	}
	//Logger.Debug(fmt.Sprintf("availableDuration: %v, availableCredit: %v", availableDuration, availableCredit))
	initialDuration := cd.TimeEnd.Sub(cd.TimeStart)
	if initialDuration <= availableDuration {
		// there are enough minutes for requested interval
		return initialDuration, nil
	}
	//Logger.Debug(fmt.Sprintf("initial Duration: %v", initialDuration))
	// we must move the timestart for the interval with the available duration because
	// that was already checked
	cd.TimeStart = cd.TimeStart.Add(availableDuration)

	// substract the connect fee
	cc, err := cd.GetCost()
	if availableDuration == 0 && cc.deductConnectFee { // only if we did not already used minutes
		availableCredit -= cc.GetConnectFee()
	}
	// check for zero balance
	if (availableCredit < 0) || (availableCredit == 0 && cc.Cost > 0) {
		return utils.MinDuration(initialDuration, availableDuration), nil
	}
	if err != nil {
		Logger.Err(fmt.Sprintf("Could not get cost for %s: %s.", cd.GetKey(cd.Subject), err.Error()))
		return 0, err
	}
	// now let's check how many increments are covered with the avilableCredit
	// also check for max rate/max rate unit
	for _, ts := range cc.Timespans {
		ts.createIncrementsSlice()
		//Logger.Debug(fmt.Sprintf("TS: %+v", ts))
		if cd.MaxRate > 0 && cd.MaxRateUnit > 0 {
			rate, _, rateUnit := ts.RateInterval.GetRateParameters(ts.GetGroupStart())
			if rate/rateUnit.Seconds() > cd.MaxRate/cd.MaxRateUnit.Seconds() {
				return availableDuration, nil
			}
		}
		for _, incr := range ts.Increments {
			if incr.Cost <= availableCredit {
				availableCredit -= incr.Cost
				availableDuration += incr.Duration
			} else {
				return availableDuration, nil
			}
		}
	}
	if initialDuration < availableDuration {
		return initialDuration, nil
	}
	return utils.MinDuration(initialDuration, availableDuration), nil
}