Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,33 @@ NetSuite::Records::CustomRecord.get_list(
# do your thing...
end

# If your search returns fields that aren't typically available on the record
# (ie. Invoice search can return close_date via TransactionSearchRowBasic,
# InventoryItem can return location_quantity_available via a saved search),
# those non-standard fields are available on the result object as custom fields:

search = NetSuite::Records::Invoice.search(
criteria: {
basic: [
{
field: 'type',
operator: 'anyOf',
value: ['_invoice'],
}
],
},
columns: {
'tranSales:basic' => [
'platformCommon:internalId/' => {},
'platformCommon:closeDate/' => {},
]
},
)

search.results_in_batches do |batch|
puts batch.map { |invoice| invoice.custom_field_list.close_date.attributes.fetch(:search_value) }
end

# Adding a Customer Deposit example. The customer associated with the
# sales order would be linked to the deposit.

Expand Down
6 changes: 5 additions & 1 deletion lib/netsuite/records/custom_field_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ module Records
class CustomFieldList
include Namespaces::PlatformCore

def self.reference_id_type
Configuration.api_version >= '2013_2' ? :script_id : :internal_id
end

def initialize(attributes = {})
case attributes[:custom_field]
when Hash
Expand Down Expand Up @@ -100,7 +104,7 @@ def to_record
private

def reference_id_type
@reference_id_type ||= Configuration.api_version >= '2013_2' ? :script_id : :internal_id
@reference_id_type ||= self.class.reference_id_type
end

def extract_custom_field(custom_field_data)
Expand Down
32 changes: 29 additions & 3 deletions lib/netsuite/support/search_result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,22 @@ 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|
# 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:
# {
# :department=>{
# :search_value=>{:@internal_id=>"113"},
# :custom_label=>"Business Unit"
# }
# }

# all return values are wrapped in a <SearchValue/>
# extract the value from <SearchValue/> 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

# <platformCommon:entity>
Expand All @@ -78,7 +89,18 @@ 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]
if %i[internal_id external_id].include?(attr_name) || 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
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(NetSuite::Records::CustomFieldList.reference_id_type => 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
Expand All @@ -89,6 +111,10 @@ def initialize(response, result_class, credentials)
record[:basic][:internal_id] = record[:basic][:internal_id][:@internal_id]
end

if record[:basic][:external_id]
record[:basic][:external_id] = record[:basic][:external_id][:@external_id]
end

result_wrapper = result_class.new(record.delete(:basic))
result_wrapper.search_joins = record
results << result_wrapper
Expand Down
53 changes: 53 additions & 0 deletions spec/netsuite/actions/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,59 @@
expect(search.results.first.alt_name).to eq('A Awesome Name')
expect(search.results.last.email).to eq('alessawesome@gmail.com')
end

context "with basic non-field result columns" do
before do
savon.expects(:search).with(message: {
"searchRecord"=>{
"@xsi:type" =>"listAcct:ItemSearchAdvanced",
"@savedSearchId" =>42,
:content! =>{"listAcct:criteria"=>{}},
}
}).returns(File.read('spec/support/fixtures/search/saved_search_item.xml'))
end

it "should handle an ID search" do
NetSuite::Configuration.api_version = '2013_1'

search = NetSuite::Records::InventoryItem.search(saved: 42)
results = search.results

result = results.first
expect(result.internal_id).to eq('123')
expect(result.external_id).to eq('456')

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)}

[
:internal_id,
:external_id,
].each {|field| expect(custom_fields).to_not include(field)}
end

it "uses script_id for custom fields when API >= 2013_2" do
NetSuite::Configuration.api_version = '2013_2'

search = NetSuite::Records::InventoryItem.search(saved: 42)
results = search.results

custom_fields = results.map do |record|
record.custom_field_list.custom_fields.map(&:script_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
end

context "advanced search" do
Expand Down
Loading