added direction to action and updated bootstrap

This commit is contained in:
Radu Ioan Fericean
2012-07-12 13:03:10 +03:00
parent 10fb664a8e
commit 12069f7741
19 changed files with 58 additions and 7143 deletions

View File

@@ -43,6 +43,6 @@ func TestRPCGet(t *testing.T) {
client.Call("Responder.Get", "test", &reply)
const expect = "12223"
if reply != expect {
t.Errorf("replay == %q, want %q", reply, expect)
t.Errorf("replay == %v, want %v", reply, expect)
}
}

View File

@@ -31,8 +31,9 @@ import (
var (
raterAddress = flag.String("rateraddr", "127.0.0.1:2000", "Rater server address (localhost:2000)")
jsonRpcAddress = flag.String("jsonrpcaddr", "127.0.0.1:2001", "Json RPC server address (localhost:2001)")
rpcAddress = flag.String("rpcaddr", "127.0.0.1:2001", "Json RPC server address (localhost:2001)")
httpApiAddress = flag.String("httpapiaddr", "127.0.0.1:8000", "Http API server address (localhost:2002)")
freeswitch = flag.Bool("freeswitch", false, "connect to freeswitch server")
freeswitchsrv = flag.String("freeswitchsrv", "localhost:8021", "freeswitch address host:port")
freeswitchpass = flag.String("freeswitchpass", "ClueCon", "freeswitch address host:port")
js = flag.Bool("json", false, "use JSON for RPC encoding")
@@ -68,8 +69,6 @@ func GetCallCost(key *timespans.CallDescriptor, method string) (reply *timespans
The function that gets the information from the raters using balancer.
*/
func CallMethod(key *timespans.CallDescriptor, method string) (reply float64, err error) {
// balancerRWMutex.Lock()
// defer balancerRWMutex.Unlock()
err = errors.New("") //not nil value
for err != nil {
client := bal.Balance()
@@ -94,12 +93,13 @@ func main() {
runtime.GOMAXPROCS(runtime.NumCPU() - 1)
bal = balancer.NewBalancer()
go StopSingnalHandler()
go stopSingnalHandler()
go listenToRPCRaterRequests()
go listenToRPCRequests()
sm := &sessionmanager.FSSessionManager{}
sm.Connect(sessionmanager.NewRPCBalancerSessionDelegate(bal), *freeswitchsrv, *freeswitchpass)
if *freeswitch {
sm := &sessionmanager.FSSessionManager{}
sm.Connect(sessionmanager.NewRPCBalancerSessionDelegate(bal), *freeswitchsrv, *freeswitchpass)
}
listenToHttpRequests()
}

View File

@@ -42,7 +42,7 @@ func listenToRPCRaterRequests() {
/*
Listens for SIGTERM, SIGINT, SIGQUIT system signals and shuts down all the registered raters.
*/
func StopSingnalHandler() {
func stopSingnalHandler() {
log.Print("Handling stop signals...")
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT)

View File

@@ -100,7 +100,7 @@ func (r *Responder) Status(arg timespans.CallDescriptor, replay *string) (err er
Creates the json rpc server.
*/
func listenToRPCRequests() {
l, err := net.Listen("tcp", *jsonRpcAddress)
l, err := net.Listen("tcp", *rpcAddress)
defer l.Close()
if err != nil {

View File

@@ -1,686 +0,0 @@
/*!
* Bootstrap Responsive v2.0.2
*
* Copyright 2012 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
*/
.clearfix {
*zoom: 1;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
.hide-text {
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
}
.input-block-level {
display: block;
width: 100%;
min-height: 28px;
/* Make inputs at least the height of their button counterpart */
/* Makes inputs behave like true block-level elements */
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.hidden {
display: none;
visibility: hidden;
}
.visible-phone {
display: none;
}
.visible-tablet {
display: none;
}
.visible-desktop {
display: block;
}
.hidden-phone {
display: block;
}
.hidden-tablet {
display: block;
}
.hidden-desktop {
display: none;
}
@media (max-width: 767px) {
.visible-phone {
display: block;
}
.hidden-phone {
display: none;
}
.hidden-desktop {
display: block;
}
.visible-desktop {
display: none;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.visible-tablet {
display: block;
}
.hidden-tablet {
display: none;
}
.hidden-desktop {
display: block;
}
.visible-desktop {
display: none;
}
}
@media (max-width: 480px) {
.nav-collapse {
-webkit-transform: translate3d(0, 0, 0);
}
.page-header h1 small {
display: block;
line-height: 18px;
}
input[type="checkbox"],
input[type="radio"] {
border: 1px solid #ccc;
}
.form-horizontal .control-group > label {
float: none;
width: auto;
padding-top: 0;
text-align: left;
}
.form-horizontal .controls {
margin-left: 0;
}
.form-horizontal .control-list {
padding-top: 0;
}
.form-horizontal .form-actions {
padding-left: 10px;
padding-right: 10px;
}
.modal {
position: absolute;
top: 10px;
left: 10px;
right: 10px;
width: auto;
margin: 0;
}
.modal.fade.in {
top: auto;
}
.modal-header .close {
padding: 10px;
margin: -10px;
}
.carousel-caption {
position: static;
}
}
@media (max-width: 767px) {
body {
padding-left: 20px;
padding-right: 20px;
}
.navbar-fixed-top {
margin-left: -20px;
margin-right: -20px;
}
.container {
width: auto;
}
.row-fluid {
width: 100%;
}
.row {
margin-left: 0;
}
.row > [class*="span"],
.row-fluid > [class*="span"] {
float: none;
display: block;
width: auto;
margin: 0;
}
.thumbnails [class*="span"] {
width: auto;
}
input[class*="span"],
select[class*="span"],
textarea[class*="span"],
.uneditable-input {
display: block;
width: 100%;
min-height: 28px;
/* Make inputs at least the height of their button counterpart */
/* Makes inputs behave like true block-level elements */
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.input-prepend input[class*="span"],
.input-append input[class*="span"] {
width: auto;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.row {
margin-left: -20px;
*zoom: 1;
}
.row:before,
.row:after {
display: table;
content: "";
}
.row:after {
clear: both;
}
[class*="span"] {
float: left;
margin-left: 20px;
}
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 724px;
}
.span12 {
width: 724px;
}
.span11 {
width: 662px;
}
.span10 {
width: 600px;
}
.span9 {
width: 538px;
}
.span8 {
width: 476px;
}
.span7 {
width: 414px;
}
.span6 {
width: 352px;
}
.span5 {
width: 290px;
}
.span4 {
width: 228px;
}
.span3 {
width: 166px;
}
.span2 {
width: 104px;
}
.span1 {
width: 42px;
}
.offset12 {
margin-left: 764px;
}
.offset11 {
margin-left: 702px;
}
.offset10 {
margin-left: 640px;
}
.offset9 {
margin-left: 578px;
}
.offset8 {
margin-left: 516px;
}
.offset7 {
margin-left: 454px;
}
.offset6 {
margin-left: 392px;
}
.offset5 {
margin-left: 330px;
}
.offset4 {
margin-left: 268px;
}
.offset3 {
margin-left: 206px;
}
.offset2 {
margin-left: 144px;
}
.offset1 {
margin-left: 82px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid > [class*="span"] {
float: left;
margin-left: 2.762430939%;
}
.row-fluid > [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid > .span12 {
width: 99.999999993%;
}
.row-fluid > .span11 {
width: 91.436464082%;
}
.row-fluid > .span10 {
width: 82.87292817100001%;
}
.row-fluid > .span9 {
width: 74.30939226%;
}
.row-fluid > .span8 {
width: 65.74585634900001%;
}
.row-fluid > .span7 {
width: 57.182320438000005%;
}
.row-fluid > .span6 {
width: 48.618784527%;
}
.row-fluid > .span5 {
width: 40.055248616%;
}
.row-fluid > .span4 {
width: 31.491712705%;
}
.row-fluid > .span3 {
width: 22.928176794%;
}
.row-fluid > .span2 {
width: 14.364640883%;
}
.row-fluid > .span1 {
width: 5.801104972%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
input.span12, textarea.span12, .uneditable-input.span12 {
width: 714px;
}
input.span11, textarea.span11, .uneditable-input.span11 {
width: 652px;
}
input.span10, textarea.span10, .uneditable-input.span10 {
width: 590px;
}
input.span9, textarea.span9, .uneditable-input.span9 {
width: 528px;
}
input.span8, textarea.span8, .uneditable-input.span8 {
width: 466px;
}
input.span7, textarea.span7, .uneditable-input.span7 {
width: 404px;
}
input.span6, textarea.span6, .uneditable-input.span6 {
width: 342px;
}
input.span5, textarea.span5, .uneditable-input.span5 {
width: 280px;
}
input.span4, textarea.span4, .uneditable-input.span4 {
width: 218px;
}
input.span3, textarea.span3, .uneditable-input.span3 {
width: 156px;
}
input.span2, textarea.span2, .uneditable-input.span2 {
width: 94px;
}
input.span1, textarea.span1, .uneditable-input.span1 {
width: 32px;
}
}
@media (max-width: 979px) {
body {
padding-top: 0;
}
.navbar-fixed-top {
position: static;
margin-bottom: 18px;
}
.navbar-fixed-top .navbar-inner {
padding: 5px;
}
.navbar .container {
width: auto;
padding: 0;
}
.navbar .brand {
padding-left: 10px;
padding-right: 10px;
margin: 0 0 0 -5px;
}
.navbar .nav-collapse {
clear: left;
}
.navbar .nav {
float: none;
margin: 0 0 9px;
}
.navbar .nav > li {
float: none;
}
.navbar .nav > li > a {
margin-bottom: 2px;
}
.navbar .nav > .divider-vertical {
display: none;
}
.navbar .nav .nav-header {
color: #999999;
text-shadow: none;
}
.navbar .nav > li > a,
.navbar .dropdown-menu a {
padding: 6px 15px;
font-weight: bold;
color: #999999;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.navbar .dropdown-menu li + li a {
margin-bottom: 2px;
}
.navbar .nav > li > a:hover,
.navbar .dropdown-menu a:hover {
background-color: #222222;
}
.navbar .dropdown-menu {
position: static;
top: auto;
left: auto;
float: none;
display: block;
max-width: none;
margin: 0 15px;
padding: 0;
background-color: transparent;
border: none;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.navbar .dropdown-menu:before,
.navbar .dropdown-menu:after {
display: none;
}
.navbar .dropdown-menu .divider {
display: none;
}
.navbar-form,
.navbar-search {
float: none;
padding: 9px 15px;
margin: 9px 0;
border-top: 1px solid #222222;
border-bottom: 1px solid #222222;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
}
.navbar .nav.pull-right {
float: none;
margin-left: 0;
}
.navbar-static .navbar-inner {
padding-left: 10px;
padding-right: 10px;
}
.btn-navbar {
display: block;
}
.nav-collapse {
overflow: hidden;
height: 0;
}
}
@media (min-width: 980px) {
.nav-collapse.collapse {
height: auto !important;
overflow: visible !important;
}
}
@media (min-width: 1200px) {
.row {
margin-left: -30px;
*zoom: 1;
}
.row:before,
.row:after {
display: table;
content: "";
}
.row:after {
clear: both;
}
[class*="span"] {
float: left;
margin-left: 30px;
}
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 1170px;
}
.span12 {
width: 1170px;
}
.span11 {
width: 1070px;
}
.span10 {
width: 970px;
}
.span9 {
width: 870px;
}
.span8 {
width: 770px;
}
.span7 {
width: 670px;
}
.span6 {
width: 570px;
}
.span5 {
width: 470px;
}
.span4 {
width: 370px;
}
.span3 {
width: 270px;
}
.span2 {
width: 170px;
}
.span1 {
width: 70px;
}
.offset12 {
margin-left: 1230px;
}
.offset11 {
margin-left: 1130px;
}
.offset10 {
margin-left: 1030px;
}
.offset9 {
margin-left: 930px;
}
.offset8 {
margin-left: 830px;
}
.offset7 {
margin-left: 730px;
}
.offset6 {
margin-left: 630px;
}
.offset5 {
margin-left: 530px;
}
.offset4 {
margin-left: 430px;
}
.offset3 {
margin-left: 330px;
}
.offset2 {
margin-left: 230px;
}
.offset1 {
margin-left: 130px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid > [class*="span"] {
float: left;
margin-left: 2.564102564%;
}
.row-fluid > [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid > .span12 {
width: 100%;
}
.row-fluid > .span11 {
width: 91.45299145300001%;
}
.row-fluid > .span10 {
width: 82.905982906%;
}
.row-fluid > .span9 {
width: 74.358974359%;
}
.row-fluid > .span8 {
width: 65.81196581200001%;
}
.row-fluid > .span7 {
width: 57.264957265%;
}
.row-fluid > .span6 {
width: 48.717948718%;
}
.row-fluid > .span5 {
width: 40.170940171000005%;
}
.row-fluid > .span4 {
width: 31.623931624%;
}
.row-fluid > .span3 {
width: 23.076923077%;
}
.row-fluid > .span2 {
width: 14.529914530000001%;
}
.row-fluid > .span1 {
width: 5.982905983%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
input.span12, textarea.span12, .uneditable-input.span12 {
width: 1160px;
}
input.span11, textarea.span11, .uneditable-input.span11 {
width: 1060px;
}
input.span10, textarea.span10, .uneditable-input.span10 {
width: 960px;
}
input.span9, textarea.span9, .uneditable-input.span9 {
width: 860px;
}
input.span8, textarea.span8, .uneditable-input.span8 {
width: 760px;
}
input.span7, textarea.span7, .uneditable-input.span7 {
width: 660px;
}
input.span6, textarea.span6, .uneditable-input.span6 {
width: 560px;
}
input.span5, textarea.span5, .uneditable-input.span5 {
width: 460px;
}
input.span4, textarea.span4, .uneditable-input.span4 {
width: 360px;
}
input.span3, textarea.span3, .uneditable-input.span3 {
width: 260px;
}
input.span2, textarea.span2, .uneditable-input.span2 {
width: 160px;
}
input.span1, textarea.span1, .uneditable-input.span1 {
width: 60px;
}
.thumbnails {
margin-left: -30px;
}
.thumbnails > li {
margin-left: 30px;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -77,7 +77,7 @@
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="static/js/jquery-1.7.1.min.js"></script>
<script src="static/js/jquery-1.7.2.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
<script src="static/js/jquery.flot.min.js" type="text/javascript"></script>
<script type="text/javascript">

View File

@@ -56,11 +56,12 @@ func (csvr *CSVReader) loadActions(fn string) {
a = &timespans.Action{
ActionType: record[1],
BalanceId: record[2],
Direction: record[3],
Units: units,
}
} else {
price, percent := 0.0, 0.0
value, err := strconv.ParseFloat(record[6], 64)
value, err := strconv.ParseFloat(record[7], 64)
if err != nil {
log.Printf("Could not parse action price: %v", err)
continue
@@ -71,12 +72,12 @@ func (csvr *CSVReader) loadActions(fn string) {
if record[5] == timespans.ABSOLUTE {
price = value
}
minutesWeight, err := strconv.ParseFloat(record[7], 64)
minutesWeight, err := strconv.ParseFloat(record[8], 64)
if err != nil {
log.Printf("Could not parse action minutes weight: %v", err)
continue
}
weight, err := strconv.ParseFloat(record[8], 64)
weight, err := strconv.ParseFloat(record[9], 64)
if err != nil {
log.Printf("Could not parse action weight: %v", err)
continue
@@ -84,13 +85,14 @@ func (csvr *CSVReader) loadActions(fn string) {
a = &timespans.Action{
ActionType: record[1],
BalanceId: record[2],
Direction: record[3],
Weight: weight,
MinuteBucket: &timespans.MinuteBucket{
Seconds: units,
Weight: minutesWeight,
Price: price,
Percent: percent,
DestinationId: record[4],
DestinationId: record[5],
},
}
}

View File

@@ -3,14 +3,15 @@ Api Calls
The general API usage of the CGRateS involves creating a CallDescriptor structure sending it to the balancer via JSON/GOB RPC and getting a response from the balancer in form of a CallCost structure or a numeric value for requested information.
CallDescriptor structure
------------------------
- TOR int
- CstmId, Subject, DestinationPrefix string
------------------------
- Direction, TOR, Tener, Subject, DestinationPrefix string
- TimeStart, TimeEnd time.Time
- Amount float64
Direction
The direction of the call
TOR
Type Of Record, used to differentiate between various type of records
CstmId
Tener
Customer Identification used for multi tenant databases
Subject
Subject for this query

View File

@@ -230,8 +230,8 @@ Action
+ TOPUP_RESET: Add account balance. If previous balance found of the same type, reset it before adding.
+ TOPUP: Add account balance. If the specific balance is not defined, define it (eg: minutes per destination).
+ DEBIT: Debit account balance.
+ RESET_COUNTER: Sets the counter for the BalanceId to 0
+ RESET_ALL_COUNTER: Sets all counters to 0
+ RESET_COUNTER: Sets the counter for the BalanceTag to 0
+ RESET_ALL_COUNTERS: Sets all counters to 0
BalanceTag
The balance on which the action will operate

View File

@@ -31,6 +31,7 @@ Structure to be filled for each tariff plan with the bonus value for received ca
type Action struct {
ActionType string
BalanceId string
Direction string
Units float64
Weight float64
MinuteBucket *MinuteBucket
@@ -40,17 +41,17 @@ type actionTypeFunc func(*UserBalance, *Action) error
var (
actionTypeFuncMap = map[string]actionTypeFunc{
"LOG": logAction,
"RESET_TRIGGERS": resetTriggersAction,
"SET_POSTPAID": setPostpaidAction,
"RESET_POSTPAID": resetPostpaidAction,
"SET_PREPAID": setPrepaidAction,
"RESET_PREPAID": resetPrepaidAction,
"TOPUP_RESET": topupResetAction,
"TOPUP": topupAction,
"DEBIT": debitAction,
"RESET_COUNTER": resetCounterAction,
"RESET_ALL_COUNTERS": resetAllCountersAction,
"LOG": logAction,
"RESET_TRIGGERS": resetTriggersAction,
"SET_POSTPAID": setPostpaidAction,
"RESET_POSTPAID": resetPostpaidAction,
"SET_PREPAID": setPrepaidAction,
"RESET_PREPAID": resetPrepaidAction,
"TOPUP_RESET": topupResetAction,
"TOPUP": topupAction,
"DEBIT": debitAction,
"RESET_COUNTER": resetCounterAction,
"RESET_COUNTERS": resetCountersAction,
}
)
@@ -119,7 +120,7 @@ func resetCounterAction(ub *UserBalance, a *Action) (err error) {
return
}
func resetAllCountersAction(ub *UserBalance, a *Action) (err error) {
func resetCountersAction(ub *UserBalance, a *Action) (err error) {
ub.UnitCounters = make([]*UnitsCounter, 0)
uc := &UnitsCounter{BalanceId: MINUTES}
uc.initMinuteBuckets(ub.ActionTriggers)

View File

@@ -570,7 +570,7 @@ func TestActionResetAllCounters(t *testing.T) {
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Seconds: 10, Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, Percent: 0, DestinationId: "RET"}},
ActionTriggers: ActionTriggerPriotityList{&ActionTrigger{BalanceId: CREDIT, ThresholdValue: 2, ActionsId: "TEST_ACTIONS", Executed: true}},
}
resetAllCountersAction(ub, nil)
resetCountersAction(ub, nil)
if ub.Type != UB_TYPE_POSTPAID ||
ub.BalanceMap[CREDIT] != 100 ||
len(ub.UnitCounters) != 1 ||