From 2599f1adebc7f8616f12da1880e3a727156d8c09 Mon Sep 17 00:00:00 2001 From: David Laprade Date: Tue, 19 Mar 2019 16:20:24 -0400 Subject: [PATCH 1/5] Clarify search row_list data components The "records" in the search group are hashes with "keys" that are the attribute names and "values" that the data returned by the search for those attributes (not necessarily the attribute values, though). For example, you'll often see things like this: ``` { :department=>{ :search_value=>{:@internal_id=>"113"}, :custom_label=>"Business Unit" } } ``` I think using `attr_name` and `search_result` instead of `k` and `v`, respectively, makes it clearer what the parts of this data constitute. --- lib/netsuite/support/search_result.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/netsuite/support/search_result.rb b/lib/netsuite/support/search_result.rb index ddf1f2938..458511111 100644 --- a/lib/netsuite/support/search_result.rb +++ b/lib/netsuite/support/search_result.rb @@ -48,11 +48,19 @@ def initialize(response, result_class, credentials) # skip all attributes: look for :basic and all :xxx_join next if search_group.to_s.start_with?('@') - record[search_group].each_pair do |k, v| + record[search_group].each_pair do |attr_name, search_result| + # example pair: + # { + # :department=>{ + # :search_value=>{:@internal_id=>"113"}, + # :custom_label=>"Business Unit" + # } + # } + # all return values are wrapped in a # extract the value from to make results easier to work with - if v.is_a?(Hash) && v.has_key?(:search_value) + if search_result.is_a?(Hash) && search_result.has_key?(:search_value) # Here's an example of a record ref and string response # @@ -67,7 +75,7 @@ def initialize(response, result_class, credentials) # attribute will be transitioned to the parent, and in the case # of a string response the parent node's value will be to the string - record[search_group][k] = v[:search_value] + record[search_group][attr_name] = search_result[:search_value] else # NOTE need to understand this case more, in testing, only the namespace definition hits this condition end From bb09391509bf7ff94ae74294334fc6cf88d505f4 Mon Sep 17 00:00:00 2001 From: David Laprade Date: Wed, 20 Mar 2019 11:48:30 -0400 Subject: [PATCH 2/5] Expose non-field search results within custom field list Sometimes NS makes information available within saved search results that are not record fields. For example, you can run an InventoryItem search through the GUI that returns: * `Location Available` (the quantity available at the default location) * `Location Reorder Point` (quantity at which you should reorder) * `Location On Order` (quantity on order for the location) These are not record fields, as you can see with a quick CTRL-f through the NS schema docs: http://www.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2018_2/schema/record/inventoryitem.html They aren't custom formula results either (which NS doesn't seem to expose through the API). And they also aren't _custom fields_. This information is just default, standard-issue NetSuite. It's perfectly reasonable to have a search that returns them as results, and thus also reasonable to expect to be able to access them through the API. --- lib/netsuite/support/search_result.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/netsuite/support/search_result.rb b/lib/netsuite/support/search_result.rb index 458511111..1cc24cf6c 100644 --- a/lib/netsuite/support/search_result.rb +++ b/lib/netsuite/support/search_result.rb @@ -75,7 +75,19 @@ def initialize(response, result_class, credentials) # attribute will be transitioned to the parent, and in the case # of a string response the parent node's value will be to the string - record[search_group][attr_name] = search_result[:search_value] + if result_class.fields.include?(attr_name) || search_group != :basic + # this is a record field, it will be picked up when we + # intialize the `result_class` + record[search_group][attr_name] = search_result[:search_value] + else + # not a record field -- treat it as if it were a custom field + # otherwise it will be lost when we initialize + record[search_group][:custom_field_list] ||= {custom_field: []} + custom_fields = record[search_group][:custom_field_list][:custom_field] + custom_fields = [custom_fields] if custom_fields.is_a?(Hash) + custom_fields << search_result.merge(internal_id: attr_name) + record[search_group][:custom_field_list][:custom_field] = custom_fields + end else # NOTE need to understand this case more, in testing, only the namespace definition hits this condition end From bdc7a07cb120bc6e3b582f746b759c06096b9e93 Mon Sep 17 00:00:00 2001 From: David Laprade Date: Wed, 20 Mar 2019 12:01:01 -0400 Subject: [PATCH 3/5] Don't attempt to modify object while iterating through it --- lib/netsuite/support/search_result.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/netsuite/support/search_result.rb b/lib/netsuite/support/search_result.rb index 1cc24cf6c..c504452d0 100644 --- a/lib/netsuite/support/search_result.rb +++ b/lib/netsuite/support/search_result.rb @@ -48,6 +48,9 @@ def initialize(response, result_class, credentials) # skip all attributes: look for :basic and all :xxx_join next if search_group.to_s.start_with?('@') + # avoids `RuntimeError: can't add a new key into hash during iteration` + record[search_group][:custom_field_list] ||= {custom_field: []} + record[search_group].each_pair do |attr_name, search_result| # example pair: # { @@ -82,7 +85,6 @@ def initialize(response, result_class, credentials) else # not a record field -- treat it as if it were a custom field # otherwise it will be lost when we initialize - record[search_group][:custom_field_list] ||= {custom_field: []} custom_fields = record[search_group][:custom_field_list][:custom_field] custom_fields = [custom_fields] if custom_fields.is_a?(Hash) custom_fields << search_result.merge(internal_id: attr_name) From b1952f3aa807c9b6c509b6789ab51ae6b5c72358 Mon Sep 17 00:00:00 2001 From: David Laprade Date: Wed, 20 Mar 2019 12:39:30 -0400 Subject: [PATCH 4/5] Test that non-field information returned by searches is not lost --- spec/netsuite/actions/search_spec.rb | 22 + .../fixtures/search/saved_search_item.xml | 1671 +++++++++++++++++ 2 files changed, 1693 insertions(+) create mode 100644 spec/support/fixtures/search/saved_search_item.xml diff --git a/spec/netsuite/actions/search_spec.rb b/spec/netsuite/actions/search_spec.rb index a3cbfea04..83558d5e4 100644 --- a/spec/netsuite/actions/search_spec.rb +++ b/spec/netsuite/actions/search_spec.rb @@ -171,6 +171,28 @@ expect(search.results.first.alt_name).to eq('A Awesome Name') expect(search.results.last.email).to eq('alessawesome@gmail.com') end + + it "should handle an ID search with basic non-field result columns" do + response = File.read('spec/support/fixtures/search/saved_search_item.xml') + savon.expects(:search) + .with(message: { + "searchRecord"=>{ + "@xsi:type" =>"listAcct:ItemSearchAdvanced", + "@savedSearchId" =>42, + :content! =>{"listAcct:criteria"=>{}}, + } + }).returns(response) + search = NetSuite::Records::InventoryItem.search(saved: 42) + results = search.results + custom_fields = results.map do |record| + record.custom_field_list.custom_fields.map(&:internal_id) + end.flatten.uniq + [ + :location_quantity_available, + :location_re_order_point, + :location_quantity_on_order, + ].each {|field| expect(custom_fields).to include(field)} + end end context "advanced search" do diff --git a/spec/support/fixtures/search/saved_search_item.xml b/spec/support/fixtures/search/saved_search_item.xml new file mode 100644 index 000000000..6bbe4c058 --- /dev/null +++ b/spec/support/fixtures/search/saved_search_item.xml @@ -0,0 +1,1671 @@ + + + + WEBSERVICES_3603333_SB1_0320201916835580962038419462_2ce0aa2 + + + + + + + 49 + 1000 + 1 + 1 + WEBSERVICES_3603333_SB1_0320201916835580962038419462_2ce0aa2 + + + + + + Business Unit + + + 9781945179761 + SKU + + + 2.0 + Qty - Available + + + 32.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781945179747 + SKU + + + 3307.0 + Qty - Available + + + 40000.0 + Qty - On Order + + + 2565.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781945179730 + SKU + + + 3838.0 + Qty - Available + + + 45000.0 + Qty - On Order + + + 3507.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-04T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781945179716 + SKU + + + 2748.0 + Qty - Available + + + 1995.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781945179693 + SKU + + + 7520.0 + Qty - On Order + + + 3640.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-24T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781945179600 + SKU + + + 11334.0 + Qty - Available + + + 19366.0 + Qty - Reorder Point + + + + + Product Line + + + + + + + + + Business Unit + + + 9781945179419 + SKU + + + 24525.0 + Qty - Available + + + 50000.0 + Qty - On Order + + + 25035.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-24T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781945179259 + SKU + + + 1256.0 + Qty - Available + + + 7000.0 + Qty - On Order + + + 1583.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-29T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781945179150 + SKU + + + 17864.0 + Qty - Available + + + 3381.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781945179051 + SKU + + + 346.0 + Qty - Available + + + 75.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940999 + SKU + + + 821.0 + Qty - Available + + + 5000.0 + Qty - On Order + + + 1993.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940982 + SKU + + + 13163.0 + Qty - Available + + + 80000.0 + Qty - On Order + + + 20208.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-29T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940883 + SKU + + + 12554.0 + Qty - Available + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940876 + SKU + + + 19748.0 + Qty - Available + + + 7656.0 + Qty - Reorder Point + + + + + Product Line + + + 2018-08-16T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940852 + SKU + + + 2051.0 + Qty - Available + + + 2500.0 + Qty - On Order + + + 2622.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-01T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940845 + SKU + + + 1195.0 + Qty - Available + + + 2063.0 + Qty - On Order + + + 1180.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-13T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940722 + SKU + + + 4786.0 + Qty - Available + + + 669.0 + Qty - Reorder Point + + + + + Product Line + + + 2017-04-10T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940562 + SKU + + + 2720.0 + Qty - Available + + + 26000.0 + Qty - On Order + + + 2316.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-05-13T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940555 + SKU + + + 4438.0 + Qty - Available + + + 22000.0 + Qty - On Order + + + 3306.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-05-14T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940517 + SKU + + + 497.0 + Qty - Available + + + 234.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940340 + SKU + + + 911.0 + Qty - Available + + + 1000.0 + Qty - On Order + + + 363.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-13T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940197 + SKU + + + 1117.0 + Qty - Available + + + 357.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781935940166 + SKU + + + 330.0 + Qty - Available + + + 1000.0 + Qty - On Order + + + 157.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-05-21T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781934217962 + SKU + + + 615.0 + Qty - Available + + + 1000.0 + Qty - On Order + + + 238.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-13T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781934217894 + SKU + + + 1576.0 + Qty - Available + + + 829.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781934217795 + SKU + + + 2199.0 + Qty - Available + + + 567.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781934217757 + SKU + + + 120.0 + Qty - Available + + + 500.0 + Qty - On Order + + + 139.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-24T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781934217610 + SKU + + + 171.0 + Qty - Available + + + 1000.0 + Qty - On Order + + + 162.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-14T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781934217566 + SKU + + + 999.0 + Qty - Available + + + 2000.0 + Qty - On Order + + + 534.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-06-03T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 9781934217160 + SKU + + + 59.0 + Qty - Available + + + 500.0 + Qty - On Order + + + 164.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-01T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661015476 + SKU + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661015469 + SKU + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661015421 + SKU + + + 1394.0 + Qty - Available + + + 210.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-10T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661015360 + SKU + + + 5.0 + Qty - Available + + + 200.0 + Qty - On Order + + + 75.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-21T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661015322 + SKU + + + 10.0 + Qty - Available + + + 35.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661015148 + SKU + + + 445.0 + Qty - Available + + + 200.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661014950 + SKU + + + 359.0 + Qty - Available + + + 500.0 + Qty - On Order + + + 94.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-27T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661014851 + SKU + + + 151.0 + Qty - Available + + + 400.0 + Qty - On Order + + + 184.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-31T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661014844 + SKU + + + 142.0 + Qty - Available + + + 250.0 + Qty - On Order + + + 144.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-04-16T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661013861 + SKU + + + 103.0 + Qty - Available + + + 500.0 + Qty - On Order + + + 275.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-06T22:00:00.000-08:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661013809 + SKU + + + 49.0 + Qty - Available + + + 50.0 + Qty - Reorder Point + + + + + Product Line + + + + + + + + + Business Unit + + + 811661013779 + SKU + + + 734.0 + Qty - Available + + + 175.0 + Qty - Reorder Point + + + + + Product Line + + + 2018-09-10T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661013694 + SKU + + + 5715.0 + Qty - Available + + + 5813.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 8116610135956 + SKU + + + 354.0 + Qty - Available + + + 265.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661013427 + SKU + + + 13231.0 + Qty - Available + + + 4134.0 + Qty - Reorder Point + + + + + Product Line + + + 2018-08-16T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661010952 + SKU + + + 49.0 + Qty - Available + + + 13.0 + Qty - Reorder Point + + + + + Product Line + + + 2017-02-09T22:00:00.000-08:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661010594 + SKU + + + 81.0 + Qty - Available + + + 200.0 + Qty - On Order + + + 65.0 + Qty - Reorder Point + + + + + Product Line + + + 2019-03-27T22:00:00.000-07:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661010266 + SKU + + + 102.0 + Qty - Available + + + 59.0 + Qty - Reorder Point + + + + + Product Line + + + 2017-02-21T22:00:00.000-08:00 + Warehouse Date (Estimated) + + + + Reorder Status + + + + + + + + + Business Unit + + + 811661010044 + SKU + + + 425.0 + Qty - Available + + + 331.0 + Qty - Reorder Point + + + + + Product Line + + + + Reorder Status + + + + + + + + + From d2473432f5b7d6f7f2564b0ea801fd78a306fec5 Mon Sep 17 00:00:00 2001 From: David Laprade Date: Wed, 20 Mar 2019 12:40:25 -0400 Subject: [PATCH 5/5] Replace `should` calls in custom_field_list spec to silence warning --- spec/netsuite/records/custom_field_list_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/netsuite/records/custom_field_list_spec.rb b/spec/netsuite/records/custom_field_list_spec.rb index ea8316c77..10188bad3 100644 --- a/spec/netsuite/records/custom_field_list_spec.rb +++ b/spec/netsuite/records/custom_field_list_spec.rb @@ -37,9 +37,9 @@ context 'writing convience methods' do it "should create a custom field entry when none exists" do list.custrecord_somefield = 'a value' - list.custom_fields.size.should == 1 - list.custom_fields.first.value.should == 'a value' - list.custom_fields.first.type.should == 'platformCore:StringCustomFieldRef' + expect(list.custom_fields.size).to eq(1) + expect(list.custom_fields.first.value).to eq('a value') + expect(list.custom_fields.first.type).to eq('platformCore:StringCustomFieldRef') end # https://github.com/NetSweet/netsuite/issues/325