diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 2f602fe8b..35ac9b2a5 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -1535,7 +1535,7 @@ func (apierSv1 *APIerSv1) ExportToFolder(arg *utils.ArgExportToFolder, reply *st if len(arg.Items) == 0 { arg.Items = []string{utils.MetaAttributes, utils.MetaChargers, utils.MetaDispatchers, utils.MetaDispatcherHosts, utils.MetaFilters, utils.MetaResources, utils.MetaStats, - utils.MetaRoutes, utils.MetaThresholds, utils.MetaRateProfiles, utils.MetaActionProfiles} + utils.MetaRoutes, utils.MetaThresholds, utils.MetaRateProfiles, utils.MetaActionProfiles, utils.MetaAccountProfiles} } if _, err := os.Stat(arg.Path); os.IsNotExist(err) { os.Mkdir(arg.Path, os.ModeDir) @@ -1989,7 +1989,11 @@ func (apierSv1 *APIerSv1) ExportToFolder(arg *utils.ArgExportToFolder, reply *st if err != nil { return err } - for _, model := range engine.APItoModelTPAccountProfile(engine.AccountProfileToAPI(accPrf)) { + apiActPrf, err := engine.AccountProfileToAPI(accPrf) + if err != nil { + return err + } + for _, model := range engine.APItoModelTPAccountProfile(apiActPrf) { if record, err := engine.CsvDump(model); err != nil { return err } else if err := csvWriter.Write(record); err != nil { @@ -1998,9 +2002,7 @@ func (apierSv1 *APIerSv1) ExportToFolder(arg *utils.ArgExportToFolder, reply *st } } csvWriter.Flush() - } - } *reply = utils.OK return nil diff --git a/data/tariffplans/testit/AccountProfiles.csv b/data/tariffplans/testit/AccountProfiles.csv new file mode 100644 index 000000000..d11676ed2 --- /dev/null +++ b/data/tariffplans/testit/AccountProfiles.csv @@ -0,0 +1,3 @@ +#Tenant,ID,FilterIDs,ActivationInterval,Weight,BalanceID,BalanceFilterIDs,BalanceWeight,BalanceBlocker,BalanceType,BalanceOpts,BalanceCostIncrements,BalanceCostAttributes,BalanceUnitFactors,BalanceUnits,ThresholdIDs +cgrates.org,ACC_PRF_1,,,20,MonetaryBalance,,10,,*monetary,,fltr1&fltr2;1.3;2.3;3.3,attr1;attr2,fltr1&fltr2;100;fltr3;200,14,*none +cgrates.org,1001,,,,VoiceBalance,,10,,*voice,,,,,3600000000000, \ No newline at end of file diff --git a/engine/model_helpers.go b/engine/model_helpers.go index 94199ad97..5753a458b 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -3695,7 +3695,7 @@ func APItoAccountProfile(tpAp *utils.TPAccountProfile, timezone string) (ap *uti return } -func AccountProfileToAPI(ap *utils.AccountProfile) (tpAp *utils.TPAccountProfile) { +func AccountProfileToAPI(ap *utils.AccountProfile) (tpAp *utils.TPAccountProfile, err error) { tpAp = &utils.TPAccountProfile{ Tenant: ap.Tenant, ID: ap.ID, @@ -3719,17 +3719,70 @@ func AccountProfileToAPI(ap *utils.AccountProfile) (tpAp *utils.TPAccountProfile for i, bal := range ap.Balances { tpAp.Balances[i] = &utils.TPAccountBalance{ - ID: bal.ID, - FilterIDs: bal.FilterIDs, - Weight: bal.Weight, - Blocker: bal.Blocker, - Type: bal.Type, + ID: bal.ID, + FilterIDs: make([]string, len(bal.FilterIDs)), + Weight: bal.Weight, + Blocker: bal.Blocker, + Type: bal.Type, + CostIncrement: make([]*utils.TPBalanceCostIncrement, len(bal.CostIncrements)), + CostAttributes: make([]string, len(bal.CostAttributes)), + UnitFactors: make([]*utils.TPBalanceUnitFactor, len(bal.UnitFactors)), + } + for k, fli := range bal.FilterIDs { + tpAp.Balances[i].FilterIDs[k] = fli } tpAp.Balances[i].Units, _ = bal.Units.Float64() elems := make([]string, 0, len(bal.Opts)) for k, v := range bal.Opts { elems = append(elems, utils.ConcatenatedKey(k, utils.IfaceAsString(v))) } + for k, cIncrement := range bal.CostIncrements { + tpAp.Balances[i].CostIncrement[k] = &utils.TPBalanceCostIncrement{ + FilterIDs: make([]string, len(cIncrement.FilterIDs)), + } + for kk, fli := range cIncrement.FilterIDs { + tpAp.Balances[i].CostIncrement[k].FilterIDs[kk] = fli + } + if cIncrement.Increment != nil { + incr, ok := cIncrement.Increment.Float64() + if !ok { + return nil, fmt.Errorf("cannot convert <%+v> to float64", cIncrement.Increment) + } + tpAp.Balances[i].CostIncrement[k].Increment = &incr + } + if cIncrement.FixedFee != nil { + fxdFee, ok := cIncrement.FixedFee.Float64() + if !ok { + return nil, fmt.Errorf("cannot convert <%+v> to float64", cIncrement.FixedFee) + } + tpAp.Balances[i].CostIncrement[k].FixedFee = &fxdFee + } + if cIncrement.RecurrentFee != nil { + rcrFee, ok := cIncrement.RecurrentFee.Float64() + if !ok { + return nil, fmt.Errorf("cannot convert <%+v> to float64", cIncrement.RecurrentFee) + } + tpAp.Balances[i].CostIncrement[k].RecurrentFee = &rcrFee + } + } + for k, cAttributes := range bal.CostAttributes { + tpAp.Balances[i].CostAttributes[k] = cAttributes + } + for k, uFactor := range bal.UnitFactors { + tpAp.Balances[i].UnitFactors[k] = &utils.TPBalanceUnitFactor{ + FilterIDs: make([]string, len(uFactor.FilterIDs)), + } + for kk, fli := range uFactor.FilterIDs { + tpAp.Balances[i].UnitFactors[k].FilterIDs[kk] = fli + } + if uFactor.Factor != nil { + untFctr, ok := uFactor.Factor.Float64() + if !ok { + return nil, fmt.Errorf("cannot convert <%+v> to float64", uFactor.Factor) + } + tpAp.Balances[i].UnitFactors[k].Factor = untFctr + } + } tpAp.Balances[i].Opts = strings.Join(elems, utils.InfieldSep) } for i, fli := range ap.ThresholdIDs { diff --git a/general_tests/export_it_test.go b/general_tests/export_it_test.go index 23fe834ab..3984d7a5f 100644 --- a/general_tests/export_it_test.go +++ b/general_tests/export_it_test.go @@ -61,6 +61,7 @@ var ( testExpVerifyRoutes, testExpVerifyRateProfiles, testExpVerifyActionProfiles, + testExpVerifyAccountProfiles, testExpCleanFiles, testExpStopCgrEngine, } @@ -364,14 +365,6 @@ func testExpVerifyRoutes(t *testing.T) { } func testExpVerifyRateProfiles(t *testing.T) { - minDec, err := utils.NewDecimalFromUnit("1m") - if err != nil { - t.Error(err) - } - secDec, err := utils.NewDecimalFromUnit("1s") - if err != nil { - t.Error(err) - } var reply *engine.RateProfile minDecimal, err := utils.NewDecimalFromUnit("1m") if err != nil { @@ -402,8 +395,8 @@ func testExpVerifyRateProfiles(t *testing.T) { { IntervalStart: 0 * time.Second, RecurrentFee: utils.NewDecimal(1, 2), - Unit: minDec, - Increment: secDec, + Unit: minDecimal, + Increment: secDecimal, }, }, }, @@ -491,6 +484,52 @@ func testExpVerifyActionProfiles(t *testing.T) { } } } + +func testExpVerifyAccountProfiles(t *testing.T) { + var reply *utils.AccountProfile + acctPrf := &utils.AccountProfile{ + Tenant: "cgrates.org", + ID: "ACC_PRF_1", + FilterIDs: []string{}, + Weight: 20, + Balances: map[string]*utils.Balance{ + "MonetaryBalance": { + ID: "MonetaryBalance", + FilterIDs: []string{}, + Weight: 10, + Type: "*monetary", + CostIncrements: []*utils.CostIncrement{ + { + FilterIDs: []string{"fltr1", "fltr2"}, + Increment: utils.NewDecimal(13, 1), + FixedFee: utils.NewDecimal(23, 1), + RecurrentFee: utils.NewDecimal(33, 1), + }, + }, + CostAttributes: []string{"attr1", "attr2"}, + UnitFactors: []*utils.UnitFactor{ + { + FilterIDs: []string{"fltr1", "fltr2"}, + Factor: utils.NewDecimal(100, 0), + }, + { + FilterIDs: []string{"fltr3"}, + Factor: utils.NewDecimal(200, 0), + }, + }, + Units: utils.NewDecimal(14, 0), + }, + }, + ThresholdIDs: []string{"*none"}, + } + if err := expRpc.Call(utils.APIerSv1GetAccountProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ACC_PRF_1"}}, &reply); err != nil { + t.Fatal(err) + } else if !reflect.DeepEqual(acctPrf, reply) { + t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(acctPrf), utils.ToJSON(reply)) + } +} + func testExpCleanFiles(t *testing.T) { if err := os.RemoveAll("/tmp/tp/"); err != nil { t.Error(err)