/* 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 */ package main import ( "github.com/cgrates/cgrates/timespans" "log" "fmt" "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 (csvr *CSVReader) loadDestinations(fn string) { csvReader, fp, err := csvr.readerFunc(fn) if err != nil { return } if fp != nil { defer fp.Close() } 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 = ×pans.Destination{Id: tag} destinations = append(destinations, dest) } dest.Prefixes = append(dest.Prefixes, record[1]) } } func (csvr *CSVReader) loadRates(fn string) { csvReader, fp, err := csvr.readerFunc(fn) if err != nil { return } if fp != nil { defer fp.Close() } 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]) if err != nil { continue } rates[tag] = append(rates[tag], r) } } func (csvr *CSVReader) loadTimings(fn string) { csvReader, fp, err := csvr.readerFunc(fn) if err != nil { return } if fp != nil { defer fp.Close() } 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 (csvr *CSVReader) loadRateTimings(fn string) { csvReader, fp, err := csvr.readerFunc(fn) if err != nil { return } if fp != nil { defer fp.Close() } 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, record[3]) 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] = ×pans.ActivationPeriod{} } activationPeriods[tag].AddIntervalIfNotPresent(rt.GetInterval(r)) } } } } func (csvr *CSVReader) loadRatingProfiles(fn string) { csvReader, fp, err := csvr.readerFunc(fn) if err != nil { return } if fp != nil { defer fp.Close() } 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 = ×pans.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 := ×pans.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 = ×pans.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 } if fp != nil {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 := ×pans.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 = ×pans.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 = ×pans.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) } } }*/