mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Ensure AccountSummary is of *AccountSummary type when parsing ddp
This commit is contained in:
committed by
Dan Christian Bogos
parent
cdcf55f971
commit
41b9b719d5
@@ -1084,7 +1084,9 @@ func (acc *Account) Publish(initBal map[string]float64) {
|
||||
Tenant: acntSummary.Tenant,
|
||||
ID: utils.GenUUID(),
|
||||
Time: utils.TimePointer(time.Now()),
|
||||
Event: acntSummary.AsMapInterface(),
|
||||
Event: map[string]any{
|
||||
utils.AccountSummary: acntSummary,
|
||||
},
|
||||
APIOpts: map[string]any{
|
||||
utils.MetaEventType: utils.AccountUpdate,
|
||||
},
|
||||
@@ -1195,29 +1197,6 @@ func (as *AccountSummary) SetInitialValue(old *AccountSummary) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetBalanceWithID returns a Balance given balance type and balance ID
|
||||
func (acc *Account) GetBalanceWithID(blcType, blcID string) (blc *Balance) {
|
||||
for _, blc = range acc.BalanceMap[blcType] {
|
||||
if blc.ID == blcID {
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindBalanceByID searches through all balance types for a balance with the
|
||||
// specified ID and returns it alongside its type.
|
||||
func (acc *Account) FindBalanceByID(balanceID string) (blnc *Balance, blncType string) {
|
||||
for balanceType, balances := range acc.BalanceMap {
|
||||
for _, balance := range balances {
|
||||
if balance.ID == balanceID {
|
||||
return balance, balanceType
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
// FieldAsInterface func to help EventCost FieldAsInterface
|
||||
func (as *AccountSummary) FieldAsInterface(fldPath []string) (val any, err error) {
|
||||
if as == nil || len(fldPath) == 0 {
|
||||
@@ -1297,6 +1276,61 @@ func (as *AccountSummary) AsMapInterface() map[string]any {
|
||||
}
|
||||
}
|
||||
|
||||
// processAccountSummaryField ensures accSummary is an AccountSummary and calls FieldAsInterface on it.
|
||||
func processAccountSummaryField(fldPath []string, accSummary any, event map[string]any) (any, error) {
|
||||
var err error
|
||||
var accSummaryBytes []byte
|
||||
switch accSum := accSummary.(type) {
|
||||
case *AccountSummary:
|
||||
// Directly proceed if already *AccountSummary.
|
||||
return accSum.FieldAsInterface(fldPath)
|
||||
case string:
|
||||
// Convert string to bytes for unmarshalling
|
||||
// if it's a serialized *AccountSummary.
|
||||
accSummaryBytes = []byte(accSum)
|
||||
default:
|
||||
// Marshal non-string types to JSON bytes
|
||||
// for unmarshalling into *AccountSummary.
|
||||
accSummaryBytes, err = json.Marshal(accSum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var as AccountSummary
|
||||
if err = json.Unmarshal(accSummaryBytes, &as); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update AccountSummary with the unmarshalled *AccountSummary
|
||||
// to avoid repetitive serialization.
|
||||
event[utils.AccountSummary] = &as
|
||||
|
||||
return as.FieldAsInterface(fldPath)
|
||||
}
|
||||
|
||||
// GetBalanceWithID returns a Balance given balance type and balance ID
|
||||
func (acc *Account) GetBalanceWithID(blcType, blcID string) (blc *Balance) {
|
||||
for _, blc = range acc.BalanceMap[blcType] {
|
||||
if blc.ID == blcID {
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindBalanceByID searches through all balance types for a balance with the
|
||||
// specified ID and returns it alongside its type.
|
||||
func (acc *Account) FindBalanceByID(balanceID string) (blnc *Balance, blncType string) {
|
||||
for balanceType, balances := range acc.BalanceMap {
|
||||
for _, balance := range balances {
|
||||
if balance.ID == balanceID {
|
||||
return balance, balanceType
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func (acc *Account) String() string {
|
||||
return utils.ToJSON(acc)
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/nyaruka/phonenumbers"
|
||||
|
||||
@@ -73,39 +73,19 @@ func (dDP *dynamicDP) FieldAsInterface(fldPath []string) (val any, err error) {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
|
||||
// Parsing deeper than the first level in *req.CostDetails requires it to be
|
||||
// of type *EventCost. If not, we serialize and deserialize into an *EventCost.
|
||||
if len(fldPath) > 3 &&
|
||||
fldPath[0] == utils.MetaReq && fldPath[1] == utils.CostDetails {
|
||||
// Ensure type for supported path elements to allow calling their specific
|
||||
// FieldAsInterface method.
|
||||
if len(fldPath) > 3 && fldPath[0] == utils.MetaReq &&
|
||||
slices.Contains([]string{utils.CostDetails, utils.AccountSummary}, fldPath[1]) {
|
||||
if mp, canCast := dDP.initialDP.(utils.MapStorage); canCast {
|
||||
if event, canCast := mp[utils.MetaReq].(map[string]any); canCast {
|
||||
if cd, has := event[utils.CostDetails]; has {
|
||||
var cdBytes []byte
|
||||
switch cd := cd.(type) {
|
||||
case *EventCost:
|
||||
// Directly proceed if already *EventCost.
|
||||
return cd.FieldAsInterface(fldPath[2:])
|
||||
case string:
|
||||
// Convert string to bytes for unmarshalling
|
||||
// if it's a serialized *EventCost.
|
||||
cdBytes = []byte(cd)
|
||||
default:
|
||||
// Marshal non-string types to JSON bytes
|
||||
// for unmarshalling into *EventCost.
|
||||
cdBytes, err = json.Marshal(cd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if field, has := event[fldPath[1]]; has {
|
||||
switch fldPath[1] {
|
||||
case utils.CostDetails:
|
||||
return processEventCostField(fldPath[2:], field, event)
|
||||
case utils.AccountSummary:
|
||||
return processAccountSummaryField(fldPath[2:], field, event)
|
||||
}
|
||||
var ec EventCost
|
||||
if err = json.Unmarshal(cdBytes, &ec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update CostDetails with the unmarshalled *EventCost
|
||||
// to avoid repetitive serialization.
|
||||
event[utils.CostDetails] = &ec
|
||||
return ec.FieldAsInterface(fldPath[2:])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
@@ -1216,3 +1217,35 @@ func (ec *EventCost) Remove(fldPath []string) error {
|
||||
func (ec *EventCost) GetKeys(nested bool, nesteedLimit int, prefix string) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// processEventCostField ensures cd is an EventCost and calls FieldAsInterface on it.
|
||||
func processEventCostField(fldPath []string, cd any, event map[string]any) (any, error) {
|
||||
var err error
|
||||
var cdBytes []byte
|
||||
switch cd := cd.(type) {
|
||||
case *EventCost:
|
||||
// Directly proceed if already *EventCost.
|
||||
return cd.FieldAsInterface(fldPath)
|
||||
case string:
|
||||
// Convert string to bytes for unmarshalling
|
||||
// if it's a serialized *EventCost.
|
||||
cdBytes = []byte(cd)
|
||||
default:
|
||||
// Marshal non-string types to JSON bytes
|
||||
// for unmarshalling into *EventCost.
|
||||
cdBytes, err = json.Marshal(cd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var ec EventCost
|
||||
if err = json.Unmarshal(cdBytes, &ec); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update CostDetails with the unmarshalled *EventCost
|
||||
// to avoid repetitive serialization.
|
||||
event[utils.CostDetails] = &ec
|
||||
|
||||
return ec.FieldAsInterface(fldPath)
|
||||
}
|
||||
|
||||
@@ -147,6 +147,8 @@ func TestEEsExportEventChanges(t *testing.T) {
|
||||
FilterIDs: []string{
|
||||
"*string:~*req.CostDetails.Charges[0].Increments[0].Accounting.Balance.ID:BALANCE_TEST",
|
||||
"*string:~*req.CostDetails.Charges[0].Increments[0].Accounting.Balance.Type:*voice",
|
||||
"*string:~*req.AccountSummary.BalanceSummaries.BALANCE_TEST.ID:BALANCE_TEST",
|
||||
"*string:~*req.AccountSummary.BalanceSummaries.BALANCE_TEST.Type:*voice",
|
||||
},
|
||||
Path: "*req.BalanceFound",
|
||||
Type: utils.MetaVariable,
|
||||
@@ -202,6 +204,15 @@ func TestEEsExportEventChanges(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
utils.AccountSummary: &engine.AccountSummary{
|
||||
BalanceSummaries: engine.BalanceSummaries{
|
||||
{
|
||||
ID: "BALANCE_TEST",
|
||||
Type: utils.MetaVoice,
|
||||
UUID: "123456",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user