mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
added priced units
This commit is contained in:
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
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 (
|
||||
"bufio"
|
||||
"database/sql"
|
||||
"encoding/csv"
|
||||
"flag"
|
||||
"fmt"
|
||||
_ "github.com/bmizerany/pq"
|
||||
"github.com/cgrates/cgrates/timespans"
|
||||
"log"
|
||||
"net/rpc/jsonrpc"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
cdrFile = flag.String("freeswitchcdr", "Master.csv", "Freeswitch Master CSV CDR file.")
|
||||
resultFile = flag.String("resultfile", "out.csv", "Generated file containing CDR and price info.")
|
||||
host = flag.String("host", "localhost", "The host to connect to. Values that start with / are for UNIX domain sockets.")
|
||||
port = flag.String("port", "5432", "The port to bind to.")
|
||||
dbName = flag.String("dbname", "cgrates", "The name of the database to connect to.")
|
||||
user = flag.String("user", "", "The user to sign in as.")
|
||||
password = flag.String("password", "", "The user's password.")
|
||||
)
|
||||
|
||||
func readDbRecord(db *sql.DB, searchedUUID string) (cc *timespans.CallCost, timespansText string, err error) {
|
||||
row := db.QueryRow(fmt.Sprintf("SELECT * FROM callcosts WHERE uuid='%s'", searchedUUID))
|
||||
var uuid string
|
||||
cc = ×pans.CallCost{}
|
||||
err = row.Scan(&uuid, &cc.Direction, &cc.Tenant, &cc.TOR, &cc.Subject, &cc.Destination, &cc.Cost, &cc.ConnectFee, ×pansText)
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
useDB := true
|
||||
file, err := os.Open(*cdrFile)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
db, err := sql.Open("postgres", fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s sslmode=disable", *host, *port, *dbName, *user, *password))
|
||||
defer db.Close()
|
||||
if err != nil {
|
||||
log.Printf("failed to open the database: %v", err)
|
||||
useDB = false
|
||||
}
|
||||
csvReader := csv.NewReader(bufio.NewReader(file))
|
||||
client, err := jsonrpc.Dial("tcp", "localhost:2001")
|
||||
useRPC := true
|
||||
if err != nil {
|
||||
log.Printf("Could not connect to rater server: %v!", err)
|
||||
useRPC = false
|
||||
}
|
||||
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
|
||||
uuid := record[10]
|
||||
t, _ := time.Parse("2012-05-21 17:48:20", record[5])
|
||||
fmt.Println(t)
|
||||
if useDB {
|
||||
cc, timespansText, err := readDbRecord(db, uuid)
|
||||
if err != nil && useRPC {
|
||||
// try getting the price from the rater
|
||||
|
||||
tenant := record[0]
|
||||
subject := record[1]
|
||||
dest := record[2]
|
||||
t1, _ := time.Parse("2012-05-21 17:48:20", record[5])
|
||||
t2, _ := time.Parse("2012-05-21 17:48:20", record[6])
|
||||
cd := timespans.CallDescriptor{
|
||||
Direction: "OUT",
|
||||
Tenant: tenant,
|
||||
TOR: "0",
|
||||
Subject: subject,
|
||||
Destination: dest,
|
||||
TimeStart: t1,
|
||||
TimeEnd: t2}
|
||||
client.Call("Responder.GetCost", cd, cc)
|
||||
}
|
||||
_ = timespansText
|
||||
//log.Print(cc, timespansText)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,11 +27,11 @@ import (
|
||||
)
|
||||
|
||||
type Rate struct {
|
||||
DestinationsTag string
|
||||
ConnectFee, Price, BillingUnit float64
|
||||
DestinationsTag string
|
||||
ConnectFee, Price, PricedUnits, RateIncrements float64
|
||||
}
|
||||
|
||||
func NewRate(destinationsTag, connectFee, price, billingUnit string) (r *Rate, err error) {
|
||||
func NewRate(destinationsTag, connectFee, price, pricedUnits, rateIncrements string) (r *Rate, err error) {
|
||||
cf, err := strconv.ParseFloat(connectFee, 64)
|
||||
if err != nil {
|
||||
log.Printf("Error parsing connect fee from: %v", connectFee)
|
||||
@@ -42,16 +42,22 @@ func NewRate(destinationsTag, connectFee, price, billingUnit string) (r *Rate, e
|
||||
log.Printf("Error parsing price from: %v", price)
|
||||
return
|
||||
}
|
||||
bu, err := strconv.ParseFloat(billingUnit, 64)
|
||||
pu, err := strconv.ParseFloat(pricedUnits, 64)
|
||||
if err != nil {
|
||||
log.Printf("Error parsing billing unit from: %v", billingUnit)
|
||||
log.Printf("Error parsing priced units from: %v", pricedUnits)
|
||||
return
|
||||
}
|
||||
ri, err := strconv.ParseFloat(rateIncrements, 64)
|
||||
if err != nil {
|
||||
log.Printf("Error parsing rates increments from: %v", rateIncrements)
|
||||
return
|
||||
}
|
||||
r = &Rate{
|
||||
DestinationsTag: destinationsTag,
|
||||
ConnectFee: cf,
|
||||
Price: p,
|
||||
BillingUnit: bu,
|
||||
PricedUnits: pu,
|
||||
RateIncrements: ri,
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -99,14 +105,15 @@ func NewRateTiming(ratesTag string, timing *Timing, weight string) (rt *RateTimi
|
||||
|
||||
func (rt *RateTiming) GetInterval(r *Rate) (i *timespans.Interval) {
|
||||
i = ×pans.Interval{
|
||||
Months: rt.timing.Months,
|
||||
MonthDays: rt.timing.MonthDays,
|
||||
WeekDays: rt.timing.WeekDays,
|
||||
StartTime: rt.timing.StartTime,
|
||||
Weight: rt.Weight,
|
||||
ConnectFee: r.ConnectFee,
|
||||
Price: r.Price,
|
||||
BillingUnit: r.BillingUnit,
|
||||
Months: rt.timing.Months,
|
||||
MonthDays: rt.timing.MonthDays,
|
||||
WeekDays: rt.timing.WeekDays,
|
||||
StartTime: rt.timing.StartTime,
|
||||
Weight: rt.Weight,
|
||||
ConnectFee: r.ConnectFee,
|
||||
Price: r.Price,
|
||||
PricedUnits: r.PricedUnits,
|
||||
RateIncrements: r.RateIncrements,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cgrates/cgrates/timespans"
|
||||
"log"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -78,7 +78,7 @@ func (csvr *CSVReader) loadRates(fn string) {
|
||||
// skip header line
|
||||
continue
|
||||
}
|
||||
r, err := NewRate(record[1], record[2], record[3], record[4])
|
||||
r, err := NewRate(record[1], record[2], record[3], record[4], record[5])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Tag,DestinationsTag,ConnectFee,Price,BillingUnit
|
||||
RT_STANDARD,GERMANY,0,0.2,1
|
||||
RT_STANDARD,GERMANY_O2,0,0.1,1
|
||||
RT_STANDARD,GERMANY_PREMIUM,0,0.1,1
|
||||
RT_DEFAULT,ALL,0,0.1,1
|
||||
RT_STD_WEEKEND,GERMANY,0,0.1,1
|
||||
RT_STD_WEEKEND,GERMANY_O2,0,0.05,1
|
||||
P1,NAT,0,1,1
|
||||
P2,NAT,0,0.5,1
|
||||
Tag,DestinationsTag,ConnectFee,Price,PricedUnits,RateIncrements
|
||||
RT_STANDARD,GERMANY,0,0.2,60,1
|
||||
RT_STANDARD,GERMANY_O2,0,0.1,60,1
|
||||
RT_STANDARD,GERMANY_PREMIUM,0,0.1,60,1
|
||||
RT_DEFAULT,ALL,0,0.1,60,1
|
||||
RT_STD_WEEKEND,GERMANY,0,0.1,60,1
|
||||
RT_STD_WEEKEND,GERMANY_O2,0,0.05,60,1
|
||||
P1,NAT,0,1,1,1
|
||||
P2,NAT,0,0.5,1,1
|
||||
|
||||
|
@@ -31,15 +31,16 @@ func init() {
|
||||
|
||||
func TestActionTimingStoreRestore(t *testing.T) {
|
||||
i := &Interval{
|
||||
Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
|
||||
MonthDays: MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
|
||||
WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
|
||||
StartTime: "18:00:00",
|
||||
EndTime: "00:00:00",
|
||||
Weight: 10.0,
|
||||
ConnectFee: 0.0,
|
||||
Price: 1.0,
|
||||
BillingUnit: 1.0,
|
||||
Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
|
||||
MonthDays: MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
|
||||
WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
|
||||
StartTime: "18:00:00",
|
||||
EndTime: "00:00:00",
|
||||
Weight: 10.0,
|
||||
ConnectFee: 0.0,
|
||||
Price: 1.0,
|
||||
PricedUnits: 60,
|
||||
RateIncrements: 1,
|
||||
}
|
||||
at := &ActionTiming{
|
||||
Id: "some uuid",
|
||||
@@ -50,7 +51,7 @@ func TestActionTimingStoreRestore(t *testing.T) {
|
||||
ActionsId: "Commando",
|
||||
}
|
||||
r := at.store()
|
||||
if string(r) != "some uuid|test|one,two,three|1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;1|10|Commando" {
|
||||
if string(r) != "some uuid|test|one,two,three|1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;60;1|10|Commando" {
|
||||
t.Errorf("Error serializing action timing: %v", string(r))
|
||||
}
|
||||
o := &ActionTiming{}
|
||||
|
||||
@@ -19,9 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package timespans
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
"encoding/json"
|
||||
"time"
|
||||
//"log"
|
||||
)
|
||||
@@ -42,7 +42,7 @@ func TestApStoreRestore(t *testing.T) {
|
||||
ap := &ActivationPeriod{ActivationTime: d}
|
||||
ap.AddInterval(i)
|
||||
result := ap.store()
|
||||
expected := "1328106601000000000|2;1;3,4;14:30:00;15:00:00;0;0;0;0"
|
||||
expected := "1328106601000000000|2;1;3,4;14:30:00;15:00:00;0;0;0;0;0"
|
||||
if result != expected {
|
||||
t.Errorf("Expected %q was %q", expected, result)
|
||||
}
|
||||
@@ -76,7 +76,7 @@ func TestApStoreRestoreJson(t *testing.T) {
|
||||
ap := &ActivationPeriod{ActivationTime: d}
|
||||
ap.AddInterval(i)
|
||||
result, _ := json.Marshal(ap)
|
||||
expected := "{\"ActivationTime\":\"2012-02-01T14:30:01Z\",\"Intervals\":[{\"Months\":[2],\"MonthDays\":[1],\"WeekDays\":[3,4],\"StartTime\":\"14:30:00\",\"EndTime\":\"15:00:00\",\"Weight\":0,\"ConnectFee\":0,\"Price\":0,\"BillingUnit\":0}]}"
|
||||
expected := "{\"ActivationTime\":\"2012-02-01T14:30:01Z\",\"Intervals\":[{\"Months\":[2],\"MonthDays\":[1],\"WeekDays\":[3,4],\"StartTime\":\"14:30:00\",\"EndTime\":\"15:00:00\",\"Weight\":0,\"ConnectFee\":0,\"Price\":0,\"PricedUnits\":0,\"RateIncrements\":0}]}"
|
||||
if string(result) != expected {
|
||||
t.Errorf("Expected %q was %q", expected, result)
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func TestApStoreRestoreBlank(t *testing.T) {
|
||||
ap := &ActivationPeriod{ActivationTime: d}
|
||||
ap.AddInterval(i)
|
||||
result, _ := json.Marshal(ap)
|
||||
expected := "{\"ActivationTime\":\"2012-02-01T14:30:01Z\",\"Intervals\":[{\"Months\":null,\"MonthDays\":null,\"WeekDays\":null,\"StartTime\":\"\",\"EndTime\":\"\",\"Weight\":0,\"ConnectFee\":0,\"Price\":0,\"BillingUnit\":0}]}"
|
||||
expected := "{\"ActivationTime\":\"2012-02-01T14:30:01Z\",\"Intervals\":[{\"Months\":null,\"MonthDays\":null,\"WeekDays\":null,\"StartTime\":\"\",\"EndTime\":\"\",\"Weight\":0,\"ConnectFee\":0,\"Price\":0,\"PricedUnits\":0,\"RateIncrements\":0}]}"
|
||||
if string(result) != expected {
|
||||
t.Errorf("Expected %q was %q", expected, result)
|
||||
}
|
||||
|
||||
@@ -31,11 +31,11 @@ import (
|
||||
Defines a time interval for which a certain set of prices will apply
|
||||
*/
|
||||
type Interval struct {
|
||||
Months Months
|
||||
MonthDays MonthDays
|
||||
WeekDays WeekDays
|
||||
StartTime, EndTime string // ##:##:## format
|
||||
Weight, ConnectFee, Price, BillingUnit float64
|
||||
Months Months
|
||||
MonthDays MonthDays
|
||||
WeekDays WeekDays
|
||||
StartTime, EndTime string // ##:##:## format
|
||||
Weight, ConnectFee, Price, PricedUnits, RateIncrements float64
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -139,7 +139,8 @@ func (i *Interval) store() (result string) {
|
||||
result += strconv.FormatFloat(i.Weight, 'f', -1, 64) + ";"
|
||||
result += strconv.FormatFloat(i.ConnectFee, 'f', -1, 64) + ";"
|
||||
result += strconv.FormatFloat(i.Price, 'f', -1, 64) + ";"
|
||||
result += strconv.FormatFloat(i.BillingUnit, 'f', -1, 64)
|
||||
result += strconv.FormatFloat(i.PricedUnits, 'f', -1, 64) + ";"
|
||||
result += strconv.FormatFloat(i.RateIncrements, 'f', -1, 64)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -156,5 +157,6 @@ func (i *Interval) restore(input string) {
|
||||
i.Weight, _ = strconv.ParseFloat(is[5], 64)
|
||||
i.ConnectFee, _ = strconv.ParseFloat(is[6], 64)
|
||||
i.Price, _ = strconv.ParseFloat(is[7], 64)
|
||||
i.BillingUnit, _ = strconv.ParseFloat(is[8], 64)
|
||||
i.PricedUnits, _ = strconv.ParseFloat(is[8], 64)
|
||||
i.RateIncrements, _ = strconv.ParseFloat(is[9], 64)
|
||||
}
|
||||
|
||||
@@ -26,18 +26,19 @@ import (
|
||||
|
||||
func TestIntervalStoreRestore(t *testing.T) {
|
||||
i := &Interval{
|
||||
Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
|
||||
MonthDays: MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
|
||||
WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
|
||||
StartTime: "18:00:00",
|
||||
EndTime: "00:00:00",
|
||||
Weight: 10.0,
|
||||
ConnectFee: 0.0,
|
||||
Price: 1.0,
|
||||
BillingUnit: 1.0,
|
||||
Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
|
||||
MonthDays: MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
|
||||
WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday},
|
||||
StartTime: "18:00:00",
|
||||
EndTime: "00:00:00",
|
||||
Weight: 10.0,
|
||||
ConnectFee: 0.0,
|
||||
Price: 1.0,
|
||||
PricedUnits: 60,
|
||||
RateIncrements: 1,
|
||||
}
|
||||
r := i.store()
|
||||
if string(r) != "1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;1" {
|
||||
if string(r) != "1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;60;1" {
|
||||
t.Errorf("Error serializing interval: %v", string(r))
|
||||
}
|
||||
o := &Interval{}
|
||||
|
||||
@@ -21,6 +21,7 @@ package timespans
|
||||
import (
|
||||
"fmt"
|
||||
//"log"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -59,10 +60,15 @@ func (ts *TimeSpan) getCost(cd *CallDescriptor) (cost float64) {
|
||||
if ts.Interval == nil {
|
||||
return 0
|
||||
}
|
||||
if ts.Interval.BillingUnit > 0 {
|
||||
cost = (ts.GetDuration().Seconds() / ts.Interval.BillingUnit) * ts.Interval.Price
|
||||
duration := ts.GetDuration().Seconds()
|
||||
i := ts.Interval
|
||||
if i.RateIncrements == 0 {
|
||||
i.RateIncrements = 1
|
||||
}
|
||||
if i.PricedUnits != 0 {
|
||||
cost = math.Ceil(duration/i.RateIncrements) * i.RateIncrements * (i.Price / i.PricedUnits)
|
||||
} else {
|
||||
cost = ts.GetDuration().Seconds() * ts.Interval.Price
|
||||
cost = math.Ceil(duration/i.RateIncrements) * i.RateIncrements * i.Price
|
||||
}
|
||||
// if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
// userBalance.mux.RLock()
|
||||
|
||||
@@ -196,8 +196,9 @@ func TestTimespanGetCost(t *testing.T) {
|
||||
if ts1.getCost(cd) != 600 {
|
||||
t.Error("Expected 10 got ", ts1.getCost(cd))
|
||||
}
|
||||
ts1.Interval.BillingUnit = .1
|
||||
if ts1.getCost(cd) != 6000 {
|
||||
ts1.Interval.PricedUnits = 60
|
||||
ts1.Interval.RateIncrements = 1
|
||||
if ts1.getCost(cd) != 10 {
|
||||
t.Error("Expected 6000 got ", ts1.getCost(cd))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user