Example #1
0
func (self *ApierV1) RemoveRatingProfile(attr AttrRemoveRatingProfile, reply *string) error {
	log.Printf("ATTR: %+v", attr)
	if attr.Direction == "" {
		attr.Direction = utils.OUT
	}
	if (attr.Subject != "" && utils.IsSliceMember([]string{attr.Direction, attr.Tenant, attr.Category}, "")) ||
		(attr.Category != "" && utils.IsSliceMember([]string{attr.Direction, attr.Tenant}, "")) ||
		attr.Tenant != "" && attr.Direction == "" {
		return utils.ErrMandatoryIeMissing
	}
	_, err := engine.Guardian.Guard(func() (interface{}, error) {
		log.Print("RPID: ", attr.GetId())
		err := self.RatingDb.RemoveRatingProfile(attr.GetId())
		if err != nil {
			return 0, err
		}
		return 0, nil
	}, 0, "RemoveRatingProfile")
	if err != nil {
		*reply = err.Error()
		return utils.NewErrServerError(err)
	}
	*reply = utils.OK
	return nil
}
Example #2
0
// sessionRelocate is used when an update will relocate an initial session (eg multiple data streams)
func (smg *SMGeneric) sessionRelocate(initialID, cgrID, newOriginID string) error {
	_, err := engine.Guardian.Guard(func() (interface{}, error) { // Lock it on initialID level
		if utils.IsSliceMember([]string{initialID, cgrID, newOriginID}, "") { // Not allowed empty params here
			return nil, utils.ErrMandatoryIeMissing
		}
		ssNew := smg.getSessions(cgrID, false)
		if len(ssNew) != 0 { // Already relocated
			return nil, nil
		}
		if pSSNew := smg.getSessions(cgrID, true); len(pSSNew) != 0 { // passive sessions recorded, will be recovered so no need of relocation
			return nil, nil
		}
		ss := smg.getSessions(initialID, false)
		if len(ss) == 0 { // No need of relocation
			if ss = smg.passiveToActive(initialID); len(ss) == 0 {
				return nil, utils.ErrNotFound
			}
		}
		for i, s := range ss[initialID] {
			s.CGRID = cgrID                         // Overwrite initial CGRID with new one
			s.EventStart[utils.ACCID] = newOriginID // Overwrite OriginID for session indexing
			smg.recordASession(s)
			if i == 0 {
				smg.unrecordASession(initialID)
			}
		}
		return nil, nil
	}, smg.cgrCfg.LockingTimeout, initialID)
	return err
}
Example #3
0
func NewRequestFilter(rfType, fieldName string, vals []string) (*RequestFilter, error) {
	if !utils.IsSliceMember([]string{MetaStringPrefix, MetaTimings, MetaRSRFields, MetaCDRStats, MetaDestinations}, rfType) {
		return nil, fmt.Errorf("Unsupported filter Type: %s", rfType)
	}
	if fieldName == "" && utils.IsSliceMember([]string{MetaStringPrefix, MetaTimings, MetaDestinations}, rfType) {
		return nil, fmt.Errorf("FieldName is mandatory for Type: %s", rfType)
	}
	if len(vals) == 0 && utils.IsSliceMember([]string{MetaStringPrefix, MetaTimings, MetaRSRFields, MetaDestinations, MetaDestinations}, rfType) {
		return nil, fmt.Errorf("Values is mandatory for Type: %s", rfType)
	}
	rf := &RequestFilter{Type: rfType, FieldName: fieldName, Values: vals}
	if err := rf.CompileValues(); err != nil {
		return nil, err
	}
	return rf, nil
}
Example #4
0
// Retrive the cost from engine
func (self *Mediator) getCostFromRater(storedCdr *utils.StoredCdr) (*CallCost, error) {
	cc := &CallCost{}
	var err error
	if storedCdr.Usage == time.Duration(0) { // failed call,  returning empty callcost, no error
		return cc, nil
	}
	cd := CallDescriptor{
		TOR:           storedCdr.TOR,
		Direction:     storedCdr.Direction,
		Tenant:        storedCdr.Tenant,
		Category:      storedCdr.Category,
		Subject:       storedCdr.Subject,
		Account:       storedCdr.Account,
		Destination:   storedCdr.Destination,
		TimeStart:     storedCdr.AnswerTime,
		TimeEnd:       storedCdr.AnswerTime.Add(storedCdr.Usage),
		DurationIndex: storedCdr.Usage,
	}
	if utils.IsSliceMember([]string{utils.PSEUDOPREPAID, utils.POSTPAID}, storedCdr.ReqType) {
		err = self.connector.Debit(cd, cc)
	} else {
		err = self.connector.GetCost(cd, cc)
	}
	if err != nil {
		self.logDb.LogError(storedCdr.CgrId, MEDIATOR_SOURCE, storedCdr.MediationRunId, err.Error())
	} else {
		// If the mediator calculated a price it will write it to logdb
		self.logDb.LogCallCost(storedCdr.CgrId, MEDIATOR_SOURCE, storedCdr.MediationRunId, cc)
	}
	return cc, err
}
Example #5
0
// Returns error if not able to properly store the CDR, mediation is async since we can always recover offline
func (self *CdrServer) deriveRateStoreStatsReplicate(storedCdr *StoredCdr) error {
	cdrRuns, err := self.deriveCdrs(storedCdr)
	if err != nil {
		return err
	}
	for _, cdr := range cdrRuns {
		if cdr.MediationRunId != utils.META_DEFAULT { // Process Aliases and Users for derived CDRs
			if err := LoadAlias(&AttrMatchingAlias{
				Destination: cdr.Destination,
				Direction:   cdr.Direction,
				Tenant:      cdr.Tenant,
				Category:    cdr.Category,
				Account:     cdr.Account,
				Subject:     cdr.Subject,
				Context:     utils.ALIAS_CONTEXT_RATING,
			}, cdr, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound {
				return err
			}
			if err := LoadUserProfile(cdr, utils.EXTRA_FIELDS); err != nil {
				return err
			}
		}
		// Rate CDR
		if self.rater != nil && !cdr.Rated {
			if err := self.rateCDR(cdr); err != nil {
				cdr.Cost = -1.0 // If there was an error, mark the CDR
				cdr.ExtraInfo = err.Error()
			}
		}
		if cdr.MediationRunId == utils.META_SURETAX { // Request should be processed by SureTax
			if err := SureTaxProcessCdr(cdr); err != nil {
				cdr.Cost = -1.0
				cdr.ExtraInfo = err.Error() // Something failed, write the error in the ExtraInfo
			}
		}
		if self.cgrCfg.CDRSStoreCdrs { // Store CDRs
			// Store RatedCDR
			if err := self.cdrDb.SetRatedCdr(cdr); err != nil {
				utils.Logger.Err(fmt.Sprintf("<CDRS> Storing rated CDR %+v, got error: %s", cdr, err.Error()))
			}
			// Store CostDetails
			if cdr.Rated || utils.IsSliceMember([]string{utils.RATED, utils.META_RATED}, cdr.ReqType) { // Account related CDRs are saved automatically, so save the others here if requested
				if err := self.cdrDb.LogCallCost(cdr.CgrId, utils.CDRS_SOURCE, cdr.MediationRunId, cdr.CostDetails); err != nil {
					utils.Logger.Err(fmt.Sprintf("<CDRS> Storing costs for CDR %+v, costDetails: %+v, got error: %s", cdr, cdr.CostDetails, err.Error()))
				}
			}
		}
		// Attach CDR to stats
		if self.stats != nil { // Send CDR to stats
			if err := self.stats.AppendCDR(cdr, nil); err != nil {
				utils.Logger.Err(fmt.Sprintf("<CDRS> Could not append cdr to stats: %s", err.Error()))
			}
		}
		if len(self.cgrCfg.CDRSCdrReplication) != 0 {
			self.replicateCdr(cdr)
		}
	}

	return nil
}
Example #6
0
func (self *CdrServer) rateCDR(storedCdr *StoredCdr) error {
	var qryCC *CallCost
	var err error
	if storedCdr.ReqType == utils.META_NONE {
		return nil
	}
	if utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, storedCdr.ReqType) && storedCdr.Usage != 0 { // ToDo: Get rid of PREPAID as soon as we don't want to support it backwards
		// Should be previously calculated and stored in DB
		delay := utils.Fib()
		for i := 0; i < 4; i++ {
			qryCC, err = self.cdrDb.GetCallCostLog(storedCdr.CgrId, utils.SESSION_MANAGER_SOURCE, storedCdr.MediationRunId)
			if err == nil {
				break
			}
			time.Sleep(delay())
		}
		if err != nil && err == gorm.RecordNotFound { //calculate CDR as for pseudoprepaid
			utils.Logger.Warning(fmt.Sprintf("<Cdrs> WARNING: Could not find CallCostLog for cgrid: %s, source: %s, runid: %s, will recalculate", storedCdr.CgrId, utils.SESSION_MANAGER_SOURCE, storedCdr.MediationRunId))
			qryCC, err = self.getCostFromRater(storedCdr)
		}

	} else {
		qryCC, err = self.getCostFromRater(storedCdr)
	}
	if err != nil {
		return err
	} else if qryCC != nil {
		storedCdr.Cost = qryCC.Cost
		storedCdr.CostDetails = qryCC
	}
	return nil
}
Example #7
0
func (account *Account) GetUniqueSharedGroupMembers(destination, direction, category, unitType string) ([]string, error) {
	creditBalances := account.getBalancesForPrefix(destination, category, account.BalanceMap[CREDIT+direction], "")
	unitBalances := account.getBalancesForPrefix(destination, category, account.BalanceMap[unitType+direction], "")
	// gather all shared group ids
	var sharedGroupIds []string
	for _, cb := range creditBalances {
		if cb.SharedGroup != "" {
			sharedGroupIds = append(sharedGroupIds, cb.SharedGroup)
		}
	}
	for _, mb := range unitBalances {
		if mb.SharedGroup != "" {
			sharedGroupIds = append(sharedGroupIds, mb.SharedGroup)
		}
	}
	var memberIds []string
	for _, sgID := range sharedGroupIds {
		sharedGroup, err := accountingStorage.GetSharedGroup(sgID, false)
		if err != nil {
			Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID))
			return nil, err
		}
		for _, memberId := range sharedGroup.GetMembersExceptUser(account.Id) {
			if !utils.IsSliceMember(memberIds, memberId) {
				memberIds = append(memberIds, memberId)
			}
		}
	}
	return memberIds, nil
}
Example #8
0
func NewRPCPool(dispatchStrategy string, connAttempts, reconnects int, connectTimeout, replyTimeout time.Duration,
	rpcConnCfgs []*config.HaPoolConfig, internalConnChan chan rpcclient.RpcClientConnection, ttl time.Duration) (*rpcclient.RpcClientPool, error) {
	var rpcClient *rpcclient.RpcClient
	var err error
	rpcPool := rpcclient.NewRpcClientPool(dispatchStrategy, replyTimeout)
	atLestOneConnected := false // If one connected we don't longer return errors
	for _, rpcConnCfg := range rpcConnCfgs {
		if rpcConnCfg.Address == utils.MetaInternal {
			var internalConn rpcclient.RpcClientConnection
			select {
			case internalConn = <-internalConnChan:
				internalConnChan <- internalConn
			case <-time.After(ttl):
				return nil, errors.New("TTL triggered")
			}
			rpcClient, err = rpcclient.NewRpcClient("", "", connAttempts, reconnects, connectTimeout, replyTimeout, rpcclient.INTERNAL_RPC, internalConn, false)
		} else if utils.IsSliceMember([]string{utils.MetaJSONrpc, utils.MetaGOBrpc, ""}, rpcConnCfg.Transport) {
			codec := utils.GOB
			if rpcConnCfg.Transport != "" {
				codec = rpcConnCfg.Transport[1:] // Transport contains always * before codec understood by rpcclient
			}
			rpcClient, err = rpcclient.NewRpcClient("tcp", rpcConnCfg.Address, connAttempts, reconnects, connectTimeout, replyTimeout, codec, nil, false)
		} else {
			return nil, fmt.Errorf("Unsupported transport: <%s>", rpcConnCfg.Transport)
		}
		if err == nil {
			atLestOneConnected = true
		}
		rpcPool.AddClient(rpcClient)
	}
	if atLestOneConnected {
		err = nil
	}
	return rpcPool, err
}
Example #9
0
func NewTPExporter(storDb LoadStorage, tpID, expPath, fileFormat, sep string, compress bool) (*TPExporter, error) {
	if len(tpID) == 0 {
		return nil, errors.New("Missing TPid")
	}
	if !utils.IsSliceMember(TPExportFormats, fileFormat) {
		return nil, errors.New("Unsupported file format")
	}
	tpExp := &TPExporter{
		storDb:     storDb,
		tpID:       tpID,
		exportPath: expPath,
		fileFormat: fileFormat,
		compress:   compress,
		cacheBuff:  new(bytes.Buffer),
	}
	runeSep, _ := utf8.DecodeRuneInString(sep)
	if runeSep == utf8.RuneError {
		return nil, fmt.Errorf("Invalid field separator: %s", sep)
	} else {
		tpExp.sep = runeSep
	}
	if compress {
		if len(tpExp.exportPath) == 0 {
			tpExp.zipWritter = zip.NewWriter(tpExp.cacheBuff)
		} else {
			if fileOut, err := os.Create(path.Join(tpExp.exportPath, "tpexport.zip")); err != nil {
				return nil, err
			} else {
				tpExp.zipWritter = zip.NewWriter(fileOut)
			}
		}
	}
	return tpExp, nil
}
Example #10
0
File: csv.go Project: bhepp/cgrates
// Takes the record out of csv and turns it into storedCdr which can be processed by CDRS
func (self *CsvRecordsProcessor) recordToStoredCdr(record []string, cdrcId string) (*engine.CDR, error) {
	storedCdr := &engine.CDR{OriginHost: "0.0.0.0", Source: self.cdrcCfgs[cdrcId].CdrSourceId, ExtraFields: make(map[string]string), Cost: -1}
	var err error
	var lazyHttpFields []*config.CfgCdrField
	for _, cdrFldCfg := range self.cdrcCfgs[cdrcId].ContentFields {
		if utils.IsSliceMember([]string{utils.KAM_FLATSTORE, utils.OSIPS_FLATSTORE}, self.dfltCdrcCfg.CdrFormat) { // Hardcode some values in case of flatstore
			switch cdrFldCfg.FieldId {
			case utils.ACCID:
				cdrFldCfg.Value = utils.ParseRSRFieldsMustCompile("3;1;2", utils.INFIELD_SEP) // in case of flatstore, accounting id is made up out of callid, from_tag and to_tag
			case utils.USAGE:
				cdrFldCfg.Value = utils.ParseRSRFieldsMustCompile(strconv.Itoa(len(record)-1), utils.INFIELD_SEP) // in case of flatstore, last element will be the duration computed by us
			}

		}
		var fieldVal string
		if cdrFldCfg.Type == utils.META_COMPOSED {
			for _, cfgFieldRSR := range cdrFldCfg.Value {
				if cfgFieldRSR.IsStatic() {
					fieldVal += cfgFieldRSR.ParseValue("")
				} else { // Dynamic value extracted using index
					if cfgFieldIdx, _ := strconv.Atoi(cfgFieldRSR.Id); len(record) <= cfgFieldIdx {
						return nil, fmt.Errorf("Ignoring record: %v - cannot extract field %s", record, cdrFldCfg.Tag)
					} else {
						fieldVal += cfgFieldRSR.ParseValue(record[cfgFieldIdx])
					}
				}
			}
		} else if cdrFldCfg.Type == utils.META_HTTP_POST {
			lazyHttpFields = append(lazyHttpFields, cdrFldCfg) // Will process later so we can send an estimation of storedCdr to http server
		} else {
			return nil, fmt.Errorf("Unsupported field type: %s", cdrFldCfg.Type)
		}
		if err := storedCdr.ParseFieldValue(cdrFldCfg.FieldId, fieldVal, self.timezone); err != nil {
			return nil, err
		}
	}
	storedCdr.CGRID = utils.Sha1(storedCdr.OriginID, storedCdr.SetupTime.UTC().String())
	if storedCdr.ToR == utils.DATA && self.cdrcCfgs[cdrcId].DataUsageMultiplyFactor != 0 {
		storedCdr.Usage = time.Duration(float64(storedCdr.Usage.Nanoseconds()) * self.cdrcCfgs[cdrcId].DataUsageMultiplyFactor)
	}
	for _, httpFieldCfg := range lazyHttpFields { // Lazy process the http fields
		var outValByte []byte
		var fieldVal, httpAddr string
		for _, rsrFld := range httpFieldCfg.Value {
			httpAddr += rsrFld.ParseValue("")
		}
		if outValByte, err = utils.HttpJsonPost(httpAddr, self.httpSkipTlsCheck, storedCdr); err != nil && httpFieldCfg.Mandatory {
			return nil, err
		} else {
			fieldVal = string(outValByte)
			if len(fieldVal) == 0 && httpFieldCfg.Mandatory {
				return nil, fmt.Errorf("MandatoryIeMissing: Empty result for http_post field: %s", httpFieldCfg.Tag)
			}
			if err := storedCdr.ParseFieldValue(httpFieldCfg.FieldId, fieldVal, self.timezone); err != nil {
				return nil, err
			}
		}
	}
	return storedCdr, nil
}
Example #11
0
// Retrive the cost from engine
func (self *CdrServer) getCostFromRater(cdr *CDR) (*CallCost, error) {
	cc := new(CallCost)
	var err error
	timeStart := cdr.AnswerTime
	if timeStart.IsZero() { // Fix for FreeSWITCH unanswered calls
		timeStart = cdr.SetupTime
	}
	cd := &CallDescriptor{
		TOR:             cdr.ToR,
		Direction:       cdr.Direction,
		Tenant:          cdr.Tenant,
		Category:        cdr.Category,
		Subject:         cdr.Subject,
		Account:         cdr.Account,
		Destination:     cdr.Destination,
		TimeStart:       timeStart,
		TimeEnd:         timeStart.Add(cdr.Usage),
		DurationIndex:   cdr.Usage,
		PerformRounding: true,
	}
	if utils.IsSliceMember([]string{utils.META_PSEUDOPREPAID, utils.META_POSTPAID, utils.META_PREPAID, utils.PSEUDOPREPAID, utils.POSTPAID, utils.PREPAID}, cdr.RequestType) { // Prepaid - Cost can be recalculated in case of missing records from SM
		err = self.rals.Call("Responder.Debit", cd, cc)
	} else {
		err = self.rals.Call("Responder.GetCost", cd, cc)
	}
	if err != nil {
		return cc, err
	}
	return cc, nil
}
Example #12
0
// Retrive the cost from engine
func (self *CdrServer) getCostFromRater(storedCdr *StoredCdr) (*CallCost, error) {
	cc := new(CallCost)
	var err error
	timeStart := storedCdr.AnswerTime
	if timeStart.IsZero() { // Fix for FreeSWITCH unanswered calls
		timeStart = storedCdr.SetupTime
	}
	cd := &CallDescriptor{
		TOR:           storedCdr.TOR,
		Direction:     storedCdr.Direction,
		Tenant:        storedCdr.Tenant,
		Category:      storedCdr.Category,
		Subject:       storedCdr.Subject,
		Account:       storedCdr.Account,
		Destination:   storedCdr.Destination,
		TimeStart:     timeStart,
		TimeEnd:       timeStart.Add(storedCdr.Usage),
		DurationIndex: storedCdr.Usage,
	}
	if utils.IsSliceMember([]string{utils.META_PSEUDOPREPAID, utils.META_POSTPAID, utils.META_PREPAID, utils.PSEUDOPREPAID, utils.POSTPAID, utils.PREPAID}, storedCdr.ReqType) { // Prepaid - Cost can be recalculated in case of missing records from SM
		if err = self.rater.Debit(cd, cc); err == nil { // Debit has occured, we are forced to write the log, even if CDR store is disabled
			self.cdrDb.LogCallCost(storedCdr.CgrId, utils.CDRS_SOURCE, storedCdr.MediationRunId, cc)
		}
	} else {
		err = self.rater.GetCost(cd, cc)
	}
	if err != nil {
		return cc, err
	}
	return cc, nil
}
Example #13
0
func (account *Account) GetUniqueSharedGroupMembers(cd *CallDescriptor) ([]string, error) {
	var balances []*Balance
	balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, account.BalanceMap[utils.MONETARY+cd.Direction], "")...)
	balances = append(balances, account.getBalancesForPrefix(cd.Destination, cd.Category, account.BalanceMap[cd.TOR+cd.Direction], "")...)
	// gather all shared group ids
	var sharedGroupIds []string
	for _, b := range balances {
		if b.SharedGroup != "" {
			sharedGroupIds = append(sharedGroupIds, b.SharedGroup)
		}
	}
	var memberIds []string
	for _, sgID := range sharedGroupIds {
		sharedGroup, err := ratingStorage.GetSharedGroup(sgID, false)
		if err != nil {
			Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID))
			return nil, err
		}
		for _, memberId := range sharedGroup.MemberIds {
			if !utils.IsSliceMember(memberIds, memberId) {
				memberIds = append(memberIds, memberId)
			}
		}
	}
	return memberIds, nil
}
Example #14
0
// Retrive the cost from engine
func (self *CdrServer) getCostFromRater(storedCdr *StoredCdr) (*CallCost, error) {
	//if storedCdr.Usage == time.Duration(0) { // failed call,  nil cost
	//	return nil, nil // No costs present, better than empty call cost since could lead us to 0 costs
	//}
	cc := new(CallCost)
	var err error
	cd := &CallDescriptor{
		TOR:           storedCdr.TOR,
		Direction:     storedCdr.Direction,
		Tenant:        storedCdr.Tenant,
		Category:      storedCdr.Category,
		Subject:       storedCdr.Subject,
		Account:       storedCdr.Account,
		Destination:   storedCdr.Destination,
		TimeStart:     storedCdr.AnswerTime,
		TimeEnd:       storedCdr.AnswerTime.Add(storedCdr.Usage),
		DurationIndex: storedCdr.Usage,
	}
	if utils.IsSliceMember([]string{utils.META_PSEUDOPREPAID, utils.META_POSTPAID, utils.META_PREPAID, utils.PSEUDOPREPAID, utils.POSTPAID, utils.PREPAID}, storedCdr.ReqType) { // Prepaid - Cost can be recalculated in case of missing records from SM
		if err = self.rater.Debit(cd, cc); err == nil { // Debit has occured, we are forced to write the log, even if CDR store is disabled
			self.cdrDb.LogCallCost(storedCdr.CgrId, utils.CDRS_SOURCE, storedCdr.MediationRunId, cc)
		}
	} else {
		err = self.rater.GetCost(cd, cc)
	}
	if err != nil {
		return nil, err
	}
	return cc, nil
}
Example #15
0
// Takes the record out of csv and turns it into http form which can be posted
func (self *Cdrc) recordToStoredCdr(record []string) (*utils.StoredCdr, error) {
	storedCdr := &utils.StoredCdr{CdrHost: "0.0.0.0", CdrSource: self.cdrSourceId, ExtraFields: make(map[string]string), Cost: -1}
	var err error
	for cfgFieldName, cfgFieldRSRs := range self.cdrFields {
		var fieldVal string
		if utils.IsSliceMember([]string{CSV, FS_CSV}, self.cdrType) {
			for _, cfgFieldRSR := range cfgFieldRSRs {
				if strings.HasPrefix(cfgFieldRSR.Id, utils.STATIC_VALUE_PREFIX) {
					fieldVal += cfgFieldRSR.ParseValue("PLACEHOLDER")
				} else { // Dynamic value extracted using index
					if cfgFieldIdx, _ := strconv.Atoi(cfgFieldRSR.Id); len(record) <= cfgFieldIdx {
						return nil, fmt.Errorf("Ignoring record: %v - cannot extract field %s", record, cfgFieldName)
					} else {
						fieldVal += cfgFieldRSR.ParseValue(record[cfgFieldIdx])
					}
				}
			}
		} else { // Modify here when we add more supported cdr formats
			fieldVal = "UNKNOWN"
		}
		switch cfgFieldName {
		case utils.TOR:
			storedCdr.TOR = fieldVal
		case utils.ACCID:
			storedCdr.AccId = fieldVal
		case utils.REQTYPE:
			storedCdr.ReqType = fieldVal
		case utils.DIRECTION:
			storedCdr.Direction = fieldVal
		case utils.TENANT:
			storedCdr.Tenant = fieldVal
		case utils.CATEGORY:
			storedCdr.Category = fieldVal
		case utils.ACCOUNT:
			storedCdr.Account = fieldVal
		case utils.SUBJECT:
			storedCdr.Subject = fieldVal
		case utils.DESTINATION:
			storedCdr.Destination = fieldVal
		case utils.SETUP_TIME:
			if storedCdr.SetupTime, err = utils.ParseTimeDetectLayout(fieldVal); err != nil {
				return nil, fmt.Errorf("Cannot parse answer time field with value: %s, err: %s", fieldVal, err.Error())
			}
		case utils.ANSWER_TIME:
			if storedCdr.AnswerTime, err = utils.ParseTimeDetectLayout(fieldVal); err != nil {
				return nil, fmt.Errorf("Cannot parse answer time field with value: %s, err: %s", fieldVal, err.Error())
			}
		case utils.USAGE:
			if storedCdr.Usage, err = utils.ParseDurationWithNanosecs(fieldVal); err != nil {
				return nil, fmt.Errorf("Cannot parse duration field with value: %s, err: %s", fieldVal, err.Error())
			}
		default: // Extra fields will not match predefined so they all show up here
			storedCdr.ExtraFields[cfgFieldName] = fieldVal
		}

	}
	storedCdr.CgrId = utils.Sha1(storedCdr.AccId, storedCdr.SetupTime.String())
	return storedCdr, nil
}
Example #16
0
func (storedCdr *StoredCdr) GetTenant(fieldName string) string {
	if utils.IsSliceMember([]string{utils.TENANT, utils.META_DEFAULT}, fieldName) {
		return storedCdr.Tenant
	}
	if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
		return fieldName[len(utils.STATIC_VALUE_PREFIX):]
	}
	return storedCdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
Example #17
0
File: cdr.go Project: rinor/cgrates
// Formats usage on export
func (cdr *CDR) FormatUsage(layout string) string {
	if utils.IsSliceMember([]string{utils.DATA, utils.SMS, utils.MMS, utils.GENERIC}, cdr.ToR) {
		return strconv.FormatFloat(utils.Round(cdr.Usage.Seconds(), 0, utils.ROUNDING_MIDDLE), 'f', -1, 64)
	}
	switch layout {
	default:
		return strconv.FormatFloat(float64(cdr.Usage.Nanoseconds())/1000000000, 'f', -1, 64)
	}
}
Example #18
0
func (cgrCdr CgrCdr) getExtraFields() map[string]string {
	extraFields := make(map[string]string)
	for k, v := range cgrCdr {
		if !utils.IsSliceMember(utils.PrimaryCdrFields, k) {
			extraFields[k] = v
		}
	}
	return extraFields
}
Example #19
0
File: cdr.go Project: rinor/cgrates
func (cdr *CDR) GetCallDestNr(fieldName string) string {
	if utils.IsSliceMember([]string{utils.DESTINATION, utils.META_DEFAULT, ""}, fieldName) {
		return cdr.Destination
	}
	if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
		return fieldName[len(utils.STATIC_VALUE_PREFIX):]
	}
	return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
Example #20
0
File: cdr.go Project: rinor/cgrates
func (cdr *CDR) GetReqType(fieldName string) string {
	if utils.IsSliceMember([]string{utils.REQTYPE, utils.META_DEFAULT, ""}, fieldName) {
		return cdr.RequestType
	}
	if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
		return fieldName[len(utils.STATIC_VALUE_PREFIX):]
	}
	return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
Example #21
0
func (kev KamEvent) GetExtraFields() map[string]string {
	extraFields := make(map[string]string)
	for field, val := range kev {
		if !utils.IsSliceMember(primaryFields, field) {
			extraFields[field] = val
		}
	}
	return extraFields
}
Example #22
0
File: cdr.go Project: rinor/cgrates
func (cdr *CDR) GetCategory(fieldName string) string {
	if utils.IsSliceMember([]string{utils.CATEGORY, utils.META_DEFAULT, ""}, fieldName) {
		return cdr.Category
	}
	if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
		return fieldName[len(utils.STATIC_VALUE_PREFIX):]
	}
	return cdr.FieldAsString(&utils.RSRField{Id: fieldName})
}
Example #23
0
// Debits some amount of user's specified balance adding the balance if it does not exists.
// Returns the remaining credit in user's balance.
func (ub *Account) debitBalanceAction(a *Action, reset bool) error {
	if a == nil {
		return errors.New("nil action")
	}
	bClone := a.Balance.Clone()

	if ub.BalanceMap == nil {
		ub.BalanceMap = make(map[string]BalanceChain, 1)
	}
	found := false
	if a.Direction == "" {
		a.Direction = utils.OUT
	}
	id := a.BalanceType + a.Direction
	ub.CleanExpiredBalances()
	for _, b := range ub.BalanceMap[id] {
		if b.IsExpired() {
			continue // just to be safe (cleaned expired balances above)
		}
		b.account = ub
		if b.MatchFilter(a.Balance) {
			if reset {
				b.SetValue(0)
			}
			b.SubstractValue(bClone.GetValue())
			found = true
		}
	}
	// if it is not found then we add it to the list
	if !found {
		if bClone.GetValue() != 0 {
			bClone.SetValue(-bClone.GetValue())
		}
		bClone.dirty = true // Mark the balance as dirty since we have modified and it should be checked by action triggers
		if bClone.Uuid == "" {
			bClone.Uuid = utils.GenUUID()
		}
		ub.BalanceMap[id] = append(ub.BalanceMap[id], bClone)
	}
	if a.Balance.SharedGroup != "" {
		// add shared group member
		sg, err := ratingStorage.GetSharedGroup(a.Balance.SharedGroup, false)
		if err != nil || sg == nil {
			//than problem
			utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", a.Balance.SharedGroup))
		} else {
			if !utils.IsSliceMember(sg.MemberIds, ub.Id) {
				// add member and save
				sg.MemberIds = append(sg.MemberIds, ub.Id)
				ratingStorage.SetSharedGroup(sg)
			}
		}
	}
	ub.executeActionTriggers(nil)
	return nil //ub.BalanceMap[id].GetTotalValue()
}
Example #24
0
func NewRequestFilter(rfType, fieldName string, vals []string, cdrStats rpcclient.RpcClientConnection) (*RequestFilter, error) {
	if !utils.IsSliceMember([]string{MetaStringPrefix, MetaTimings, MetaRSRFields, MetaCDRStats, MetaDestinations}, rfType) {
		return nil, fmt.Errorf("Unsupported filter Type: %s", rfType)
	}
	if fieldName == "" && utils.IsSliceMember([]string{MetaStringPrefix, MetaTimings, MetaDestinations}, rfType) {
		return nil, fmt.Errorf("FieldName is mandatory for Type: %s", rfType)
	}
	if len(vals) == 0 && utils.IsSliceMember([]string{MetaStringPrefix, MetaTimings, MetaRSRFields, MetaDestinations, MetaDestinations}, rfType) {
		return nil, fmt.Errorf("Values is mandatory for Type: %s", rfType)
	}
	rf := &RequestFilter{Type: rfType, FieldName: fieldName, Values: vals, cdrStats: cdrStats, cdrStatSThresholds: make([]*RFStatSThreshold, len(vals))}
	if rfType == MetaCDRStats {
		if cdrStats == nil {
			return nil, errors.New("Missing cdrStats information")
		}
		for i, val := range vals {
			valSplt := strings.Split(val, utils.InInFieldSep)
			if len(valSplt) != 3 {
				return nil, fmt.Errorf("Value %s needs to contain at least 3 items", val)
			}
			st := &RFStatSThreshold{QueueID: valSplt[0], ThresholdType: strings.ToUpper(valSplt[1])}
			if len(st.ThresholdType) < len(MetaMinCapPrefix)+1 {
				return nil, fmt.Errorf("Value %s contains a unsupported ThresholdType format", val)
			} else if !strings.HasPrefix(st.ThresholdType, MetaMinCapPrefix) && !strings.HasPrefix(st.ThresholdType, MetaMaxCapPrefix) {
				return nil, fmt.Errorf("Value %s contains unsupported ThresholdType prefix", val)
			}
			if tv, err := strconv.ParseFloat(valSplt[2], 64); err != nil {
				return nil, err
			} else {
				st.ThresholdValue = tv
			}
			rf.cdrStatSThresholds[i] = st
		}
	}
	if rfType == MetaRSRFields {
		var err error
		if rf.rsrFields, err = utils.ParseRSRFieldsFromSlice(vals); err != nil {
			return nil, err
		}
	}
	return rf, nil
}
Example #25
0
func (kev KamEvent) GetPdd(fieldName string) (time.Duration, error) {
	var pddStr string
	if utils.IsSliceMember([]string{utils.PDD, utils.META_DEFAULT}, fieldName) {
		pddStr = kev[CGR_PDD]
	} else if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
		pddStr = fieldName[len(utils.STATIC_VALUE_PREFIX):]
	} else {
		pddStr = kev[fieldName]
	}
	return utils.ParseDurationWithSecs(pddStr)
}
Example #26
0
func (osipsev *OsipsEvent) GetExtraFields() map[string]string {
	primaryFields := []string{"to_tag", "setuptime", "created", "method", "callid", "sip_reason", "time", "sip_code", "duration", "from_tag",
		"cgr_tenant", "cgr_category", "cgr_reqtype", "cgr_account", "cgr_subject", "cgr_destination"}
	extraFields := make(map[string]string)
	for field, val := range osipsev.osipsEvent.AttrValues {
		if !utils.IsSliceMember(primaryFields, field) {
			extraFields[field] = val
		}
	}
	return extraFields
}
Example #27
0
func (osipsev *OsipsEvent) GetExtraFields() map[string]string {
	primaryFields := []string{TO_TAG, SETUP_DURATION, OSIPS_SETUP_TIME, "method", "callid", "sip_reason", OSIPS_EVENT_TIME, "sip_code", "duration", "from_tag", "dialog_id",
		CGR_TENANT, CGR_CATEGORY, CGR_REQTYPE, CGR_ACCOUNT, CGR_SUBJECT, CGR_DESTINATION, utils.CGR_SUPPLIER, CGR_PDD, CGR_ANSWERTIME}
	extraFields := make(map[string]string)
	for field, val := range osipsev.osipsEvent.AttrValues {
		if !utils.IsSliceMember(primaryFields, field) {
			extraFields[field] = val
		}
	}
	return extraFields
}
Example #28
0
func (smaEv *SMAsteriskEvent) ExtraParameters() (extraParams map[string]string) {
	extraParams = make(map[string]string)
	primaryFields := []string{eventType, channelID, timestamp, utils.CGR_ACCOUNT, utils.CGR_DESTINATION, utils.CGR_REQTYPE,
		utils.CGR_TENANT, utils.CGR_CATEGORY, utils.CGR_SUBJECT, utils.CGR_PDD, utils.CGR_SUPPLIER, utils.CGR_DISCONNECT_CAUSE}
	for cachedKey, cachedVal := range smaEv.cachedFields {
		if !utils.IsSliceMember(primaryFields, cachedKey) {
			extraParams[cachedKey] = cachedVal
		}
	}
	return
}
Example #29
0
func (self SMGenericEvent) GetExtraFields() map[string]string {
	extraFields := make(map[string]string)
	for key, val := range self {
		primaryFields := append(utils.PrimaryCdrFields, utils.EVENT_NAME)
		if utils.IsSliceMember(primaryFields, key) {
			continue
		}
		result, _ := utils.ConvertIfaceToString(val)
		extraFields[key] = result
	}
	return extraFields
}
Example #30
0
File: cdr.go Project: rinor/cgrates
func (cdr *CDR) GetPdd(fieldName string) (time.Duration, error) {
	if utils.IsSliceMember([]string{utils.PDD, utils.META_DEFAULT, ""}, fieldName) {
		return cdr.PDD, nil
	}
	var PDDVal string
	if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
		PDDVal = fieldName[len(utils.STATIC_VALUE_PREFIX):]
	} else {
		PDDVal = cdr.FieldAsString(&utils.RSRField{Id: fieldName})
	}
	return utils.ParseDurationWithSecs(PDDVal)
}