Files
cgrates/cmd/cgr-loader/rates.go
2012-07-01 12:11:23 +03:00

333 lines
9.1 KiB
Go

/*
Rating system designed to be used in VoIP Carriers World
Copyright (C) 2012 Radu Ioan Fericean
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package main
import (
"encoding/csv"
"github.com/cgrates/cgrates/timespans"
"log"
"fmt"
"os"
"time"
)
var (
destinations []*timespans.Destination
rates = make(map[string][]*Rate)
timings = make(map[string][]*Timing)
//ratesTimings = make(map[string][]*RateTiming)
activationPeriods = make(map[string]*timespans.ActivationPeriod)
ratingProfiles = make(map[string]CallDescriptors)
)
func loadDestinations() {
fp, err := os.Open(*destinationsFn)
if err != nil {
log.Printf("Could not open destinations file: %v", err)
return
}
defer fp.Close()
csvReader := csv.NewReader(fp)
csvReader.Comma = sep
csvReader.TrailingComma = true
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
tag := record[0]
if tag == "Tag" {
// skip header line
continue
}
var dest *timespans.Destination
for _, d := range destinations {
if d.Id == tag {
dest = d
break
}
}
if dest == nil {
dest = &timespans.Destination{Id: tag}
destinations = append(destinations, dest)
}
dest.Prefixes = append(dest.Prefixes, record[1:]...)
}
}
func loadRates() {
fp, err := os.Open(*ratesFn)
if err != nil {
log.Printf("Could not open rates timing file: %v", err)
return
}
defer fp.Close()
csvReader := csv.NewReader(fp)
csvReader.Comma = sep
csvReader.TrailingComma = true
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
tag := record[0]
if tag == "Tag" {
// skip header line
continue
}
r, err := NewRate(record[1], record[2], record[3], record[4], record[5])
if err != nil {
continue
}
rates[tag] = append(rates[tag], r)
}
}
func loadTimings() {
fp, err := os.Open(*timingsFn)
if err != nil {
log.Printf("Could not open timings file: %v", err)
return
}
defer fp.Close()
csvReader := csv.NewReader(fp)
csvReader.Comma = sep
csvReader.TrailingComma = true
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
tag := record[0]
if tag == "Tag" {
// skip header line
continue
}
t := NewTiming(record[1:]...)
timings[tag] = append(timings[tag], t)
}
}
func loadRatesTimings() {
fp, err := os.Open(*ratestimingsFn)
if err != nil {
log.Printf("Could not open rates timings file: %v", err)
return
}
defer fp.Close()
csvReader := csv.NewReader(fp)
csvReader.Comma = sep
csvReader.TrailingComma = true
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
tag := record[0]
if tag == "Tag" {
// skip header line
continue
}
ts, exists := timings[record[2]]
if !exists {
log.Printf("Could not get timing for tag %v", record[2])
continue
}
for _, t := range ts {
rt := NewRateTiming(record[1], t)
//ratesTimings[tag] = append(ratesTimings[tag], rt)
rs, exists := rates[record[1]]
if !exists {
log.Printf("Could not rate for tag %v", record[2])
continue
}
for _, r := range rs {
_, exists := activationPeriods[tag]
if !exists {
activationPeriods[tag] = &timespans.ActivationPeriod{}
}
activationPeriods[tag].AddIntervalIfNotPresent(rt.GetInterval(r))
}
}
}
}
func loadRatingProfiles() {
fp, err := os.Open(*ratingprofilesFn)
if err != nil {
log.Printf("Could not open destinations rates file: %v", err)
return
}
defer fp.Close()
csvReader := csv.NewReader(fp)
csvReader.Comma = sep
csvReader.TrailingComma = true
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
tag := record[0]
if tag == "Tenant" {
// skip header line
continue
}
if len(record) != 7 {
log.Printf("Malformed rating profile: %v", record)
continue
}
tenant, tor, direction, subject, fallbacksubject := record[0], record[1], record[2], record[3], record[4]
at, err := time.Parse(time.RFC3339, record[6])
if err != nil {
log.Printf("Cannot parse activation time from %v", record[6])
continue
}
for _, d := range destinations {
for _, p := range d.Prefixes { //destinations
// Search for a CallDescriptor with the same key
var cd *timespans.CallDescriptor
key := fmt.Sprintf("%s:%s:%s:%s:%s", direction, tenant, tor, subject, p)
for _, c := range ratingProfiles[p] {
if c.GetKey() == key {
cd = c
}
}
if cd == nil {
cd = &timespans.CallDescriptor{
Direction: direction,
Tenant: tenant,
TOR: tor,
Subject: subject,
Destination: p,
}
ratingProfiles[p] = append(ratingProfiles[p], cd)
}
ap, exists := activationPeriods[record[5]]
if !exists {
log.Print("Could not load ratinTiming for tag: ", record[5])
continue
}
newAP := &timespans.ActivationPeriod{}
//copy(newAP.Intervals, ap.Intervals)
newAP.Intervals = append(newAP.Intervals, ap.Intervals...)
newAP.ActivationTime = at
cd.AddActivationPeriodIfNotPresent(newAP)
if fallbacksubject != "" &&
ratingProfiles[p].getKey(fmt.Sprintf("%s:%s:%s:%s:%s", direction, tenant, tor, subject, timespans.FallbackDestination)) == nil {
cd = &timespans.CallDescriptor{
Direction: direction,
Tenant: tenant,
TOR: tor,
Subject: subject,
Destination: timespans.FallbackDestination,
FallbackKey: fmt.Sprintf("%s:%s:%s:%s", direction, tenant, tor, fallbacksubject),
}
ratingProfiles[p] = append(ratingProfiles[p], cd)
}
}
}
}
}
/*func loadRatingProfiles1() {
fp, err := os.Open(*ratingprofilesFn)
if err != nil {
log.Printf("Could not open destinations rates file: %v", err)
return
}
defer fp.Close()
csvReader := csv.NewReader(fp)
csvReader.Comma = sep
csvReader.TrailingComma = true
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
tag := record[0]
if tag == "Tenant" {
// skip header line
continue
}
if len(record) != 7 {
log.Printf("Malformed rating profile: %v", record)
continue
}
tenant, tor, direction, subject, fallbacksubject := record[0], record[1], record[2], record[3], record[4]
at, err := time.Parse(time.RFC3339, record[6])
if err != nil {
log.Printf("Cannot parse activation time from %v", record[6])
continue
}
rts, exists := ratesTimings[record[5]]
if !exists {
log.Printf("Could not get rate timing for tag %v", record)
continue
}
for _, rt := range rts { // rates timing
rs, exists := rates[rt.RatesTag]
if !exists {
log.Printf("Could not get rates for tag %v", rt.RatesTag)
continue
}
ap := &timespans.ActivationPeriod{
ActivationTime: at,
}
for _, r := range rs { //rates
ap.AddIntervalIfNotPresent(rt.GetInterval(r))
for _, d := range destinations {
if d.Id == r.DestinationsTag {
for _, p := range d.Prefixes { //destinations
// Search for a CallDescriptor with the same key
var cd *timespans.CallDescriptor
key := fmt.Sprintf("%s:%s:%s:%s:%s", direction, tenant, tor, subject, p)
for _, c := range ratingProfiles[p] {
if c.GetKey() == key {
cd = c
}
}
if cd == nil {
cd = &timespans.CallDescriptor{
Direction: direction,
Tenant: tenant,
TOR: tor,
Subject: subject,
Destination: p,
}
ratingProfiles[p] = append(ratingProfiles[p], cd)
}
// check the activation periods for the same activation time
foundAp := false
for _, actPer := range cd.ActivationPeriods {
if actPer.ActivationTime == ap.ActivationTime {
actPer.AddIntervalIfNotPresent(ap.Intervals...)
foundAp = true
break
}
}
// if not found then add a new actvation time
if !foundAp {
cd.ActivationPeriods = append(cd.ActivationPeriods, ap)
}
if fallbacksubject != "" &&
ratingProfiles[p].getKey(fmt.Sprintf("%s:%s:%s:%s:%s", direction, tenant, tor, subject, timespans.FallbackDestination)) == nil {
cd = &timespans.CallDescriptor{
Direction: direction,
Tenant: tenant,
TOR: tor,
Subject: subject,
Destination: timespans.FallbackDestination,
FallbackKey: fmt.Sprintf("%s:%s:%s:%s", direction, tenant, tor, fallbacksubject),
}
ratingProfiles[p] = append(ratingProfiles[p], cd)
}
}
}
}
}
}
}
log.Print("Call descriptors:")
for dest, cds := range ratingProfiles {
log.Print(dest)
//cds.setIntervalEndTime()
for _, cd := range cds {
log.Print(cd)
}
}
}*/