mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-16 21:59:53 +05:00
AddAccount API method
This commit is contained in:
235
apier/apier.go
235
apier/apier.go
@@ -19,10 +19,245 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package apier
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/cgrates/cgrates/rater"
|
||||
"github.com/cgrates/cgrates/scheduler"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"log"
|
||||
)
|
||||
|
||||
type Apier struct {
|
||||
StorDb rater.DataStorage
|
||||
Getter rater.DataStorage
|
||||
Sched *scheduler.Scheduler
|
||||
}
|
||||
|
||||
type AttrDestination struct {
|
||||
Id string
|
||||
Prefixes []string
|
||||
}
|
||||
|
||||
func (self *Apier) GetDestination(attr *AttrDestination, reply *AttrDestination) error {
|
||||
if dst, err := self.Getter.GetDestination(attr.Id); err != nil {
|
||||
return errors.New(utils.ERR_NOT_FOUND)
|
||||
} else {
|
||||
reply.Id = dst.Id
|
||||
reply.Prefixes = dst.Prefixes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Apier) SetDestination(attr *AttrDestination, reply *float64) error {
|
||||
d := &rater.Destination{
|
||||
Id: attr.Id,
|
||||
Prefixes: attr.Prefixes,
|
||||
}
|
||||
if err := self.Getter.SetDestination(d); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrGetBalance struct {
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceId string
|
||||
Direction string
|
||||
}
|
||||
|
||||
// Get balance
|
||||
func (self *Apier) GetBalance(attr *AttrGetBalance, reply *float64) error {
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
userBalance, err := self.Getter.GetUserBalance(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if attr.Direction == "" {
|
||||
attr.Direction = rater.OUTBOUND
|
||||
}
|
||||
|
||||
if balance, balExists := userBalance.BalanceMap[attr.BalanceId+attr.Direction]; !balExists {
|
||||
*reply = 0.0
|
||||
} else {
|
||||
*reply = balance
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrAddBalance struct {
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceId string
|
||||
Direction string
|
||||
Value float64
|
||||
}
|
||||
|
||||
func (self *Apier) AddBalance(attr *AttrAddBalance, reply *float64) error {
|
||||
// what storage instance do we use?
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
|
||||
if _, err := self.Getter.GetUserBalance(tag); err != nil {
|
||||
// create user balance if not exists
|
||||
ub := &rater.UserBalance{
|
||||
Id: tag,
|
||||
}
|
||||
if err := self.Getter.SetUserBalance(ub); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
at := &rater.ActionTiming{
|
||||
UserBalanceIds: []string{tag},
|
||||
}
|
||||
|
||||
if attr.Direction == "" {
|
||||
attr.Direction = rater.OUTBOUND
|
||||
}
|
||||
|
||||
at.SetActions(rater.Actions{&rater.Action{ActionType: rater.TOPUP, BalanceId: attr.BalanceId, Direction: attr.Direction, Units: attr.Value}})
|
||||
|
||||
if err := at.Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
// what to put in replay?
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrExecuteAction struct {
|
||||
Direction string
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceId string
|
||||
ActionsId string
|
||||
}
|
||||
|
||||
func (self *Apier) ExecuteAction(attr *AttrExecuteAction, reply *float64) error {
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
at := &rater.ActionTiming{
|
||||
UserBalanceIds: []string{tag},
|
||||
ActionsId: attr.ActionsId,
|
||||
}
|
||||
|
||||
if err := at.Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
// what to put in replay
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrSetRatingProfile struct {
|
||||
Direction string
|
||||
Tenant string
|
||||
TOR string
|
||||
Subject string
|
||||
SourceSubject string
|
||||
}
|
||||
|
||||
func (self *Apier) SetRatingProfile(attr *AttrSetRatingProfile, reply *float64) error {
|
||||
cd := &rater.CallDescriptor{
|
||||
Direction: attr.Direction,
|
||||
Tenant: attr.Tenant,
|
||||
TOR: attr.TOR,
|
||||
Subject: attr.Subject,
|
||||
}
|
||||
destination, err := self.Getter.GetRatingProfile(cd.GetKey())
|
||||
log.Print("1: " + cd.GetKey())
|
||||
if err != nil {
|
||||
destination = &rater.RatingProfile{Id: cd.GetKey()}
|
||||
}
|
||||
cd.Subject = attr.SourceSubject
|
||||
source, err := self.Getter.GetRatingProfile(cd.GetKey())
|
||||
log.Print("2: " + cd.GetKey())
|
||||
if err != nil {
|
||||
log.Print("here: " + err.Error())
|
||||
return err
|
||||
}
|
||||
destination.DestinationMap = source.DestinationMap
|
||||
destination.FallbackKey = source.FallbackKey
|
||||
err = self.Getter.SetRatingProfile(destination)
|
||||
return err
|
||||
}
|
||||
|
||||
type AttrActionTrigger struct {
|
||||
Tenant string
|
||||
Account string
|
||||
Direction string
|
||||
BalanceId string
|
||||
ThresholdValue float64
|
||||
DestinationId string
|
||||
Weight float64
|
||||
ActionsId string
|
||||
}
|
||||
|
||||
func (self *Apier) AddTriggeredAction(attr *AttrActionTrigger, reply *float64) error {
|
||||
if attr.Direction == "" {
|
||||
attr.Direction = rater.OUTBOUND
|
||||
}
|
||||
|
||||
at := &rater.ActionTrigger{
|
||||
Id: utils.GenUUID(),
|
||||
BalanceId: attr.BalanceId,
|
||||
Direction: attr.Direction,
|
||||
ThresholdValue: attr.ThresholdValue,
|
||||
DestinationId: attr.DestinationId,
|
||||
Weight: attr.Weight,
|
||||
ActionsId: attr.ActionsId,
|
||||
Executed: false,
|
||||
}
|
||||
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
var dbErr error
|
||||
rater.AccLock.Guard(tag, func() (float64, error) {
|
||||
userBalance, err := self.Getter.GetUserBalance(tag)
|
||||
if err != nil {
|
||||
dbErr = err
|
||||
return 0, err
|
||||
}
|
||||
|
||||
userBalance.ActionTriggers = append(userBalance.ActionTriggers, at)
|
||||
|
||||
if err = self.Getter.SetUserBalance(userBalance); err != nil {
|
||||
dbErr = err
|
||||
return 0, err
|
||||
}
|
||||
return 0, nil
|
||||
})
|
||||
|
||||
return dbErr
|
||||
}
|
||||
|
||||
type AttrAccount struct {
|
||||
Tenant string
|
||||
Direction string
|
||||
Account string
|
||||
Type string // prepaid-postpaid
|
||||
ActionTimingsId string
|
||||
}
|
||||
|
||||
func (self *Apier) AddAccount(attr *AttrAccount, reply *float64) error {
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
ub := &rater.UserBalance{
|
||||
Id: tag,
|
||||
Type: attr.Type,
|
||||
}
|
||||
if err := self.Getter.SetUserBalance(ub); err != nil {
|
||||
return err
|
||||
}
|
||||
if attr.ActionTimingsId != "" {
|
||||
if ats, err := self.Getter.GetActionTimings(attr.ActionTimingsId); err == nil {
|
||||
for _, at := range ats {
|
||||
at.UserBalanceIds = append(at.UserBalanceIds, tag)
|
||||
}
|
||||
self.Getter.SetActionTimings(attr.ActionTimingsId, ats)
|
||||
if self.Sched != nil {
|
||||
self.Sched.LoadActionTimings(self.Getter)
|
||||
self.Sched.Restart()
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ package apier
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/cgrates/cgrates/rater"
|
||||
"github.com/cgrates/cgrates/rater"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type AttrGetTPDestinations struct {
|
||||
TPid string
|
||||
DestinationsTag string
|
||||
DestinationsTag string
|
||||
}
|
||||
|
||||
// Return destinations profile for a destination tag received as parameter
|
||||
@@ -44,184 +44,3 @@ func (self *Apier) GetTPDestinations(attrs AttrGetTPDestinations, reply *rater.D
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrDestination struct {
|
||||
Id string
|
||||
Prefixes []string
|
||||
}
|
||||
|
||||
func (self *Apier) GetDestination(attr *AttrDestination, reply *AttrDestination) error {
|
||||
if dst, err := self.Getter.GetDestination(attr.Id); err != nil {
|
||||
return errors.New(utils.ERR_NOT_FOUND)
|
||||
} else {
|
||||
reply.Id = dst.Id
|
||||
reply.Prefixes = dst.Prefixes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Apier) SetDestination(attr *AttrDestination, reply *float64) error {
|
||||
d := &rater.Destination{
|
||||
Id: attr.Id,
|
||||
Prefixes: attr.Prefixes,
|
||||
}
|
||||
if err := self.Getter.SetDestination(d); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrGetBalance struct {
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceId string
|
||||
Direction string
|
||||
}
|
||||
|
||||
// Get balance
|
||||
func (self *Apier) GetBalance(attr *AttrGetBalance, reply *float64) error {
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
userBalance, err := self.Getter.GetUserBalance(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if attr.Direction == "" {
|
||||
attr.Direction = rater.OUTBOUND
|
||||
}
|
||||
|
||||
if balance, balExists := userBalance.BalanceMap[attr.BalanceId+attr.Direction]; !balExists {
|
||||
// No match, balanceId not found
|
||||
return errors.New(utils.ERR_NOT_FOUND)
|
||||
} else {
|
||||
*reply = balance
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrAddBalance struct {
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceId string
|
||||
Direction string
|
||||
Value float64
|
||||
}
|
||||
|
||||
func (self *Apier) AddBalance(attr *AttrAddBalance, reply *float64) error {
|
||||
// what storage instance do we use?
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
|
||||
at := &rater.ActionTiming{
|
||||
UserBalanceIds: []string{tag},
|
||||
}
|
||||
|
||||
if attr.Direction == "" {
|
||||
attr.Direction = rater.OUTBOUND
|
||||
}
|
||||
|
||||
at.SetActions(rater.Actions{&rater.Action{BalanceId: attr.BalanceId, Direction: attr.Direction, Units: attr.Value}})
|
||||
|
||||
if err := at.Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
// what to put in replay?
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrExecuteAction struct {
|
||||
Direction string
|
||||
Tenant string
|
||||
Account string
|
||||
BalanceId string
|
||||
ActionsId string
|
||||
}
|
||||
|
||||
func (self *Apier) ExecuteAction(attr *AttrExecuteAction, reply *float64) error {
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
at := &rater.ActionTiming{
|
||||
UserBalanceIds: []string{tag},
|
||||
ActionsId: attr.ActionsId,
|
||||
}
|
||||
|
||||
if err := at.Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
// what to put in replay
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttrSetRatingProfile struct {
|
||||
Direction string
|
||||
Tenant string
|
||||
TOR string
|
||||
Subject string
|
||||
RatingProfileId string
|
||||
}
|
||||
|
||||
func (self *Apier) SetRatingProfile(attr *AttrSetRatingProfile, reply *float64) error {
|
||||
cd := &rater.CallDescriptor{
|
||||
Direction: attr.Direction,
|
||||
Tenant: attr.Tenant,
|
||||
TOR: attr.TOR,
|
||||
Subject: attr.Subject,
|
||||
}
|
||||
subject, err := self.Getter.GetRatingProfile(cd.GetKey())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rp, err := self.Getter.GetRatingProfile(attr.RatingProfileId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subject.DestinationMap = rp.DestinationMap
|
||||
err = self.Getter.SetRatingProfile(subject)
|
||||
return err
|
||||
}
|
||||
|
||||
type AttrActionTrigger struct {
|
||||
Tenant string
|
||||
Account string
|
||||
Direction string
|
||||
BalanceId string
|
||||
ThresholdValue float64
|
||||
DestinationId string
|
||||
Weight float64
|
||||
ActionsId string
|
||||
}
|
||||
|
||||
func (self *Apier) AddTriggeredAction(attr *AttrActionTrigger, reply *float64) error {
|
||||
if attr.Direction == "" {
|
||||
attr.Direction = rater.OUTBOUND
|
||||
}
|
||||
|
||||
at := &rater.ActionTrigger{
|
||||
Id: utils.GenUUID(),
|
||||
BalanceId: attr.BalanceId,
|
||||
Direction: attr.Direction,
|
||||
ThresholdValue: attr.ThresholdValue,
|
||||
DestinationId: attr.DestinationId,
|
||||
Weight: attr.Weight,
|
||||
ActionsId: attr.ActionsId,
|
||||
Executed: false,
|
||||
}
|
||||
|
||||
tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account)
|
||||
var dbErr error
|
||||
rater.AccLock.Guard(tag, func() (float64, error) {
|
||||
userBalance, err := self.Getter.GetUserBalance(tag)
|
||||
if err != nil {
|
||||
dbErr = err
|
||||
return 0, err
|
||||
}
|
||||
|
||||
userBalance.ActionTriggers = append(userBalance.ActionTriggers, at)
|
||||
|
||||
if err = self.Getter.SetUserBalance(userBalance); err != nil {
|
||||
dbErr = err
|
||||
return 0, err
|
||||
}
|
||||
return 0, nil
|
||||
})
|
||||
|
||||
return dbErr
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ var (
|
||||
err error
|
||||
)
|
||||
|
||||
func listenToRPCRequests(rpcResponder interface{}, rpcAddress string, rpc_encoding string, getter rater.DataStorage, loggerDb rater.DataStorage) {
|
||||
func listenToRPCRequests(rpcResponder interface{}, apier *apier.Apier, rpcAddress string, rpc_encoding string, getter rater.DataStorage, loggerDb rater.DataStorage) {
|
||||
l, err := net.Listen("tcp", rpcAddress)
|
||||
if err != nil {
|
||||
rater.Logger.Crit(fmt.Sprintf("<Rater> Could not listen to %v: %v", rpcAddress, err))
|
||||
@@ -75,7 +75,7 @@ func listenToRPCRequests(rpcResponder interface{}, rpcAddress string, rpc_encodi
|
||||
|
||||
rater.Logger.Info(fmt.Sprintf("<Rater> Listening for incomming RPC requests on %v", l.Addr()))
|
||||
rpc.Register(rpcResponder)
|
||||
rpc.Register(&apier.Apier{StorDb: loggerDb, Getter: getter})
|
||||
rpc.Register(apier)
|
||||
var serveFunc func(io.ReadWriteCloser)
|
||||
if rpc_encoding == JSON {
|
||||
serveFunc = jsonrpc.ServeConn
|
||||
@@ -296,15 +296,16 @@ func main() {
|
||||
go stopRaterSingnalHandler()
|
||||
}
|
||||
responder := &rater.Responder{ExitChan: exitChan}
|
||||
apier := &apier.Apier{StorDb: loggerDb, Getter: getter}
|
||||
if cfg.RaterEnabled && !cfg.BalancerEnabled && cfg.RaterListen != INTERNAL {
|
||||
rater.Logger.Info(fmt.Sprintf("Starting CGRateS Rater on %s.", cfg.RaterListen))
|
||||
go listenToRPCRequests(responder, cfg.RaterListen, cfg.RPCEncoding, getter, loggerDb)
|
||||
go listenToRPCRequests(responder, apier, cfg.RaterListen, cfg.RPCEncoding, getter, loggerDb)
|
||||
}
|
||||
if cfg.BalancerEnabled {
|
||||
rater.Logger.Info(fmt.Sprintf("Starting CGRateS Balancer on %s.", cfg.BalancerListen))
|
||||
go stopBalancerSingnalHandler()
|
||||
responder.Bal = bal
|
||||
go listenToRPCRequests(responder, cfg.BalancerListen, cfg.RPCEncoding, getter, loggerDb)
|
||||
go listenToRPCRequests(responder, apier, cfg.BalancerListen, cfg.RPCEncoding, getter, loggerDb)
|
||||
if cfg.RaterEnabled {
|
||||
rater.Logger.Info("Starting internal rater.")
|
||||
bal.AddClient("local", new(rater.ResponderWorker))
|
||||
@@ -316,6 +317,7 @@ func main() {
|
||||
go func() {
|
||||
sched := scheduler.NewScheduler()
|
||||
go reloadSchedulerSingnalHandler(sched, getter)
|
||||
apier.Sched = sched
|
||||
sched.LoadActionTimings(getter)
|
||||
sched.Loop()
|
||||
}()
|
||||
|
||||
@@ -428,6 +428,22 @@ AddTriggeredAction
|
||||
Example
|
||||
AddTriggeredAction(attr \*AttrActionTrigger, reply \*float64)
|
||||
|
||||
AddAcount
|
||||
+++++++++
|
||||
|
||||
::
|
||||
|
||||
type AttrAccount struct {
|
||||
Tenant string
|
||||
Direction string
|
||||
Account string
|
||||
Type string // prepaid-postpaid
|
||||
ActionTimingsId string
|
||||
}
|
||||
|
||||
Example
|
||||
AddAccount(attr \*AttrAccount, reply \*float64)
|
||||
|
||||
SetRatingProfile
|
||||
++++++++++++++++
|
||||
|
||||
@@ -440,7 +456,7 @@ Sets the rating profile for the specified subject.
|
||||
Tenant string
|
||||
TOR string
|
||||
Subject string
|
||||
RatingProfileId string
|
||||
SourceSubject string
|
||||
}
|
||||
|
||||
Example
|
||||
|
||||
@@ -36,31 +36,45 @@ type Action struct {
|
||||
MinuteBucket *MinuteBucket
|
||||
}
|
||||
|
||||
const (
|
||||
LOG = "LOG"
|
||||
RESET_TRIGGERS = "RESET_TRIGGERS"
|
||||
SET_POSTPAID = "SET_POSTPAID"
|
||||
RESET_POSTPAID = "RESET_POSTPAID"
|
||||
SET_PREPAID = "SET_PREPAID"
|
||||
RESET_PREPAID = "RESET_PREPAID"
|
||||
TOPUP_RESET = "TOPUP_RESET"
|
||||
TOPUP = "TOPUP"
|
||||
DEBIT = "DEBIT"
|
||||
RESET_COUNTER = "RESET_COUNTER"
|
||||
RESET_COUNTERS = "RESET_COUNTERS"
|
||||
)
|
||||
|
||||
type actionTypeFunc func(*UserBalance, *Action) error
|
||||
|
||||
func getActionFunc(typ string) (actionTypeFunc, bool) {
|
||||
switch typ {
|
||||
case "LOG":
|
||||
case LOG:
|
||||
return logAction, true
|
||||
case "RESET_TRIGGERS":
|
||||
case RESET_TRIGGERS:
|
||||
return resetTriggersAction, true
|
||||
case "SET_POSTPAID":
|
||||
case SET_POSTPAID:
|
||||
return setPostpaidAction, true
|
||||
case "RESET_POSTPAID":
|
||||
case RESET_POSTPAID:
|
||||
return resetPostpaidAction, true
|
||||
case "SET_PREPAID":
|
||||
case SET_PREPAID:
|
||||
return setPrepaidAction, true
|
||||
case "RESET_PREPAID":
|
||||
case RESET_PREPAID:
|
||||
return resetPrepaidAction, true
|
||||
case "TOPUP_RESET":
|
||||
case TOPUP_RESET:
|
||||
return topupResetAction, true
|
||||
case "TOPUP":
|
||||
case TOPUP:
|
||||
return topupAction, true
|
||||
case "DEBIT":
|
||||
case DEBIT:
|
||||
return debitAction, true
|
||||
case "RESET_COUNTER":
|
||||
case RESET_COUNTER:
|
||||
return resetCounterAction, true
|
||||
case "RESET_COUNTERS":
|
||||
case RESET_COUNTERS:
|
||||
return resetCountersAction, true
|
||||
}
|
||||
return nil, false
|
||||
|
||||
Reference in New Issue
Block a user