From 93b849bd8e8f8a9adf244055df2f9a170a72cd3c Mon Sep 17 00:00:00 2001 From: TeoV Date: Tue, 10 Jul 2018 10:24:41 -0400 Subject: [PATCH] Add Charger in LoaderS --- config/config_defaults.go | 13 +++++ config/config_json_test.go | 36 ++++++++++++++ config/config_test.go | 36 ++++++++++++++ dispatcher/chargers.go | 44 +++++++++++++++++ dispatcher/dispatcher.go | 1 + loaders/loader.go | 26 ++++++++++ loaders/loader_test.go | 98 ++++++++++++++++++++++++++++++++++++++ utils/consts.go | 2 +- 8 files changed, 255 insertions(+), 1 deletion(-) create mode 100755 dispatcher/chargers.go diff --git a/config/config_defaults.go b/config/config_defaults.go index 76af82de8..f6dca0c40 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -595,6 +595,19 @@ const CGRATES_CFG_JSON = ` {"tag": "Weight", "field_id": "Weight", "type": "*composed", "value": "15"}, ], }, + { + "type": "*chargers", // data source type + "file_name": "Chargers.csv", // file name in the tp_in_dir + "fields": [ + {"tag": "Tenant", "field_id": "Tenant", "type": "*composed", "value": "0", "mandatory": true}, + {"tag": "ID", "field_id": "ID", "type": "*composed", "value": "1", "mandatory": true}, + {"tag": "FilterIDs", "field_id": "FilterIDs", "type": "*composed", "value": "2"}, + {"tag": "ActivationInterval", "field_id": "ActivationInterval", "type": "*composed", "value": "3"}, + {"tag": "RunID", "field_id": "RunID", "type": "*composed", "value": "4"}, + {"tag": "AttributeIDs", "field_id": "AttributeIDs", "type": "*composed", "value": "5"}, + {"tag": "Weight", "field_id": "Weight", "type": "*composed", "value": "6"}, + ], + }, ], }, ], diff --git a/config/config_json_test.go b/config/config_json_test.go index 3a63cc91e..95329e1b7 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -1133,6 +1133,42 @@ func TestDfLoaderJsonCfg(t *testing.T) { Value: utils.StringPointer("15")}, }, }, + &LoaderJsonDataType{ + Type: utils.StringPointer(utils.MetaChargers), + File_name: utils.StringPointer(utils.ChargersCsv), + Fields: &[]*CdrFieldJsonCfg{ + &CdrFieldJsonCfg{Tag: utils.StringPointer(utils.Tenant), + Field_id: utils.StringPointer(utils.Tenant), + Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer("0"), + Mandatory: utils.BoolPointer(true)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer(utils.ID), + Field_id: utils.StringPointer(utils.ID), + Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer("1"), + Mandatory: utils.BoolPointer(true)}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("FilterIDs"), + Field_id: utils.StringPointer("FilterIDs"), + Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer("2")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("ActivationInterval"), + Field_id: utils.StringPointer("ActivationInterval"), + Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer("3")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("RunID"), + Field_id: utils.StringPointer("RunID"), + Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer("4")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("AttributeIDs"), + Field_id: utils.StringPointer("AttributeIDs"), + Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer("5")}, + &CdrFieldJsonCfg{Tag: utils.StringPointer("Weight"), + Field_id: utils.StringPointer("Weight"), + Type: utils.StringPointer(utils.META_COMPOSED), + Value: utils.StringPointer("6")}, + }, + }, }, }, } diff --git a/config/config_test.go b/config/config_test.go index 9fd1d1f16..bfe30075b 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -1418,6 +1418,42 @@ func TestCgrLoaderCfgITDefaults(t *testing.T) { Value: utils.ParseRSRFieldsMustCompile("15", utils.INFIELD_SEP)}, }, }, + &LoaderDataType{ + Type: utils.MetaChargers, + Filename: utils.ChargersCsv, + Fields: []*CfgCdrField{ + &CfgCdrField{Tag: "Tenant", + FieldId: "Tenant", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("0", utils.INFIELD_SEP), + Mandatory: true}, + &CfgCdrField{Tag: "ID", + FieldId: "ID", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("1", utils.INFIELD_SEP), + Mandatory: true}, + &CfgCdrField{Tag: "FilterIDs", + FieldId: "FilterIDs", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "ActivationInterval", + FieldId: "ActivationInterval", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "RunID", + FieldId: "RunID", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "AttributeIDs", + FieldId: "AttributeIDs", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP)}, + &CfgCdrField{Tag: "Weight", + FieldId: "Weight", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP)}, + }, + }, }, }, } diff --git a/dispatcher/chargers.go b/dispatcher/chargers.go new file mode 100755 index 000000000..f362e060a --- /dev/null +++ b/dispatcher/chargers.go @@ -0,0 +1,44 @@ +/* +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 +*/ + +package dispatcher + +import ( + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +func (dS *DispatcherService) ChargerSv1Ping(ign string, reply *string) error { + if dS.chargerS == nil { + return utils.NewErrNotConnected(utils.AttributeS) + } + return dS.chargerS.Call(utils.ChargerSv1Ping, ign, reply) +} + +func (dS *DispatcherService) ChargerSv1GetChargersForEvent(args *ArgsAttrProcessEventWithApiKey, + reply *engine.AttributeProfile) (err error) { + if dS.attrS == nil { + return utils.NewErrNotConnected(utils.AttributeS) + } + if err = dS.authorize(utils.AttributeSv1GetAttributeForEvent, args.AttrArgsProcessEvent.CGREvent.Tenant, + args.APIKey, args.AttrArgsProcessEvent.CGREvent.Time); err != nil { + return + } + return dS.attrS.Call(utils.AttributeSv1GetAttributeForEvent, args.AttrArgsProcessEvent, reply) + +} diff --git a/dispatcher/dispatcher.go b/dispatcher/dispatcher.go index 701fc4b3f..4cef1a3dd 100755 --- a/dispatcher/dispatcher.go +++ b/dispatcher/dispatcher.go @@ -72,6 +72,7 @@ type DispatcherService struct { splS rpcclient.RpcClientConnection // SupplierS connections attrS rpcclient.RpcClientConnection // AttributeS connections sessionS rpcclient.RpcClientConnection // SessionS server connections + chargerS rpcclient.RpcClientConnection // ChargerS server connections } // ListenAndServe will initialize the service diff --git a/loaders/loader.go b/loaders/loader.go index 14bfeb9a8..1f44e464e 100644 --- a/loaders/loader.go +++ b/loaders/loader.go @@ -398,6 +398,32 @@ func (ldr *Loader) storeLoadedData(loaderType string, } } } + case utils.MetaChargers: + for _, lDataSet := range lds { + cppModels := make(engine.TPChargers, len(lDataSet)) + for i, ld := range lDataSet { + cppModels[i] = new(engine.TPCharger) + if err = utils.UpdateStructWithIfaceMap(cppModels[i], ld); err != nil { + return + } + } + + for _, tpCPP := range cppModels.AsTPChargers() { + cpp, err := engine.APItoChargerProfile(tpCPP, ldr.timezone) + if err != nil { + return err + } + if ldr.dryRun { + utils.Logger.Info( + fmt.Sprintf("<%s-%s> DRY_RUN: ChargerProfile: %s", + utils.LoaderS, ldr.ldrID, utils.ToJSON(cpp))) + continue + } + if err := ldr.dm.SetChargerProfile(cpp, true); err != nil { + return err + } + } + } } return } diff --git a/loaders/loader_test.go b/loaders/loader_test.go index 9e08a09d5..16ee2aeac 100644 --- a/loaders/loader_test.go +++ b/loaders/loader_test.go @@ -928,3 +928,101 @@ cgrates.org,SPL_LEASTCOST_1,,,,,supplier2,,,RP_RETAIL1,resource_spl2,,20,,, utils.ToJSON(eSp3), utils.ToJSON(aps)) } } + +func TestLoaderProcessChargers(t *testing.T) { + chargerCSV := ` +#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],RunID[4],AttributeIDs[5],Weight[6] +cgrates.org,Charge1,*string:Account:1001;*string:Account:1002,2014-07-29T15:00:00Z,*rated,Attr1;Attr2,20 +cgrates.org,Charge2,*string:Account:1003,2014-07-29T15:00:00Z,*default,Attr3,10 +` + data, _ := engine.NewMapStorage() + ldr := &Loader{ + ldrID: "TestLoaderProcessContent", + bufLoaderData: make(map[string][]LoaderData), + dm: engine.NewDataManager(data), + timezone: "UTC", + } + ldr.dataTpls = map[string][]*config.CfgCdrField{ + utils.MetaChargers: []*config.CfgCdrField{ + &config.CfgCdrField{Tag: "TenantID", + FieldId: "Tenant", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("0", utils.INFIELD_SEP), + Mandatory: true}, + &config.CfgCdrField{Tag: "ProfileID", + FieldId: "ID", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("1", utils.INFIELD_SEP), + Mandatory: true}, + &config.CfgCdrField{Tag: "FilterIDs", + FieldId: "FilterIDs", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("2", utils.INFIELD_SEP)}, + &config.CfgCdrField{Tag: "ActivationInterval", + FieldId: "ActivationInterval", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("3", utils.INFIELD_SEP)}, + &config.CfgCdrField{Tag: "RunID", + FieldId: "RunID", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("4", utils.INFIELD_SEP)}, + &config.CfgCdrField{Tag: "AttributeIDs", + FieldId: "AttributeIDs", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("5", utils.INFIELD_SEP)}, + &config.CfgCdrField{Tag: "Weight", + FieldId: "Weight", + Type: utils.META_COMPOSED, + Value: utils.ParseRSRFieldsMustCompile("6", utils.INFIELD_SEP)}, + }, + } + rdr := ioutil.NopCloser(strings.NewReader(chargerCSV)) + csvRdr := csv.NewReader(rdr) + csvRdr.Comment = '#' + ldr.rdrs = map[string]map[string]*openedCSVFile{ + utils.MetaChargers: map[string]*openedCSVFile{ + utils.ChargersCsv: &openedCSVFile{fileName: utils.ChargersCsv, + rdr: rdr, csvRdr: csvRdr}}, + } + if err := ldr.processContent(utils.MetaChargers); err != nil { + t.Error(err) + } + if len(ldr.bufLoaderData) != 0 { + t.Errorf("wrong buffer content: %+v", ldr.bufLoaderData) + } + eCharger1 := &engine.ChargerProfile{ + Tenant: "cgrates.org", + ID: "Charge1", + FilterIDs: []string{"*string:Account:1001", "*string:Account:1002"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 29, 15, 00, 0, 0, time.UTC), + }, + RunID: "*rated", + AttributeIDs: []string{"Attr1", "Attr2"}, + Weight: 20, + } + eCharger2 := &engine.ChargerProfile{ + Tenant: "cgrates.org", + ID: "Charge2", + FilterIDs: []string{"*string:Account:1003"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 29, 15, 00, 0, 0, time.UTC), + }, + RunID: "*default", + AttributeIDs: []string{"Attr3"}, + Weight: 10, + } + if rcv, err := ldr.dm.GetChargerProfile("cgrates.org", "Charge1", + false, utils.NonTransactional); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCharger1, rcv) { + t.Errorf("expecting: %s, received: %s", utils.ToJSON(eCharger1), utils.ToJSON(rcv)) + } + if rcv, err := ldr.dm.GetChargerProfile("cgrates.org", "Charge2", + false, utils.NonTransactional); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCharger2, rcv) { + t.Errorf("expecting: %s, received: %s", eCharger2, rcv) + } + +} diff --git a/utils/consts.go b/utils/consts.go index b8289a382..83d22c441 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -592,6 +592,7 @@ const ( ThresholdS = "ThresholdS" DispatcherS = "DispatcherS" LoaderS = "LoaderS" + ChargerS = "ChargerS" ) // Lower service names @@ -661,7 +662,6 @@ const ( APIKey = "APIKey" APIMethods = "APIMethods" NestingSep = "." - ChargerS = "ChargerS" ) // MetaFilterIndexesAPIs