mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
164 lines
4.0 KiB
Go
164 lines
4.0 KiB
Go
/*
|
|
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
|
Copyright (C) ITsysCOM GmbH
|
|
|
|
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 utils
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// ValueFormula for computing a dynamic value for Value field
|
|
type ValueFormula struct {
|
|
Method string
|
|
Params map[string]interface{}
|
|
Static float64
|
|
}
|
|
|
|
func ParseBalanceFilterValue(tor string, val string) (*ValueFormula, error) {
|
|
if tor == MetaVoice { // Voice balance is parsed as nanoseconds with support for time duration strings
|
|
if d, err := ParseDurationWithNanosecs(val); err == nil {
|
|
return &ValueFormula{Static: float64(d.Nanoseconds())}, err
|
|
}
|
|
} else if u, err := strconv.ParseFloat(val, 64); err == nil {
|
|
return &ValueFormula{Static: u}, err
|
|
}
|
|
var vf ValueFormula
|
|
if err := json.Unmarshal([]byte(val), &vf); err == nil {
|
|
return &vf, err
|
|
}
|
|
return nil, errors.New("Invalid value: " + val)
|
|
}
|
|
|
|
type valueFormula func(map[string]interface{}) float64
|
|
|
|
const (
|
|
INCREMENTAL = "*incremental"
|
|
)
|
|
|
|
var ValueFormulas = map[string]valueFormula{
|
|
INCREMENTAL: incrementalFormula,
|
|
}
|
|
|
|
func (vf *ValueFormula) String() string {
|
|
return ToJSON(vf)
|
|
}
|
|
|
|
func incrementalFormula(params map[string]interface{}) float64 {
|
|
// check parameters
|
|
unitsInterface, unitsFound := params["Units"]
|
|
intervalInterface, intervalFound := params["Interval"]
|
|
incrementInterface, incrementFound := params["Increment"]
|
|
|
|
if !unitsFound || !intervalFound || !incrementFound {
|
|
return 0.0
|
|
}
|
|
units, ok := unitsInterface.(float64)
|
|
if !ok {
|
|
return 0.0
|
|
}
|
|
var interval string
|
|
switch intr := intervalInterface.(type) {
|
|
case string:
|
|
interval = intr
|
|
case []byte:
|
|
interval = string(intr)
|
|
default:
|
|
return 0.0
|
|
}
|
|
var increment string
|
|
switch incr := incrementInterface.(type) {
|
|
case string:
|
|
increment = incr
|
|
case []byte:
|
|
increment = string(incr)
|
|
default:
|
|
return 0.0
|
|
}
|
|
now := time.Now()
|
|
if increment == "day" {
|
|
if interval == "week" {
|
|
return units / 7
|
|
}
|
|
if interval == "month" {
|
|
return units / DaysInMonth(now.Year(), now.Month())
|
|
}
|
|
if interval == "year" {
|
|
return units / DaysInYear(now.Year())
|
|
}
|
|
}
|
|
if increment == "hour" {
|
|
if interval == "day" {
|
|
return units / 24
|
|
}
|
|
if interval == "month" {
|
|
return units / (DaysInMonth(now.Year(), now.Month()) * 24)
|
|
}
|
|
if interval == "year" {
|
|
return units / (DaysInYear(now.Year()) * 24)
|
|
}
|
|
}
|
|
if increment == "minute" {
|
|
if interval == "hour" {
|
|
return units / 60
|
|
}
|
|
}
|
|
return 0.0
|
|
}
|
|
|
|
func (vf *ValueFormula) FieldAsInterface(fldPath []string) (val interface{}, err error) {
|
|
if vf == nil || len(fldPath) == 0 {
|
|
return nil, ErrNotFound
|
|
}
|
|
switch fldPath[0] {
|
|
default:
|
|
opath, indx := GetPathIndexString(fldPath[0])
|
|
if indx != nil && opath == Params {
|
|
return MapStorage(vf.Params).FieldAsInterface(append([]string{*indx}, fldPath[1:]...))
|
|
}
|
|
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
|
|
case Method:
|
|
if len(fldPath) != 1 {
|
|
return nil, ErrNotFound
|
|
}
|
|
return vf.Method, nil
|
|
case Static:
|
|
if len(fldPath) != 1 {
|
|
return nil, ErrNotFound
|
|
}
|
|
return vf.Static, nil
|
|
case Params:
|
|
if len(fldPath) == 1 {
|
|
return vf.Params, nil
|
|
}
|
|
return MapStorage(vf.Params).FieldAsInterface(fldPath[1:])
|
|
}
|
|
}
|
|
|
|
func (vf *ValueFormula) FieldAsString(fldPath []string) (val string, err error) {
|
|
var iface interface{}
|
|
iface, err = vf.FieldAsInterface(fldPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return IfaceAsString(iface), nil
|
|
}
|