Skip to content

Commit

Permalink
Add support for NullFieldList (starting with invoices)
Browse files Browse the repository at this point in the history
NullFieldList is used to either clear an existing value on update, or
avoid a default being applied on adding a record.

My use case only required support for invoices, so I started there, but
this could likely be added to most records.

This was heavily inspired by @gmike11's work in NetSweet#481, but that seems to
lump a bunch of changes together. This also solves NetSweet#398.

Where NetSweet#481 manipulated the XML request body to address that the
`<platformCore:nullFieldList>` needs to always use the `platformCore`
namespace, as opposed to the records normal namespace (ie `transSale`
for invoice) as happens for any other field, I tried to address that on
the `#to_record` side.
  • Loading branch information
cgunther committed Feb 24, 2022
1 parent 73c9618 commit 5e181d9
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 9 deletions.
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* Update NonInventoryResaleItem record fields/record refs for 2021.2. `item_options_list`, `presentation_item_list`, `product_feed_list`, `site_category_list`, `translations_list` were all removed as fields as the are not simple fields, they require special classes. (#508)
* Add `attach_file` action for Invoice and SalesOrder. (#509)
* Add ItemOptionCustomField recrd (#512)
* Add NullFieldList record (invoices only) (#)

### Fixed
* Fix "undefined method `[]` for #<Nori::StringIOFile>" when adding File (#495)
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,20 @@ NetSuite::Records::BaseRefList.get_select_value(
)
```

## Null Fields

```ruby
# updating a field on a record to be null
invoice = NetSuite::Records::Invoice.get(12345)
invoice.update(null_field_list: 'shipMethod')

# updating multiple fields on a record to be null
invoice.update(null_field_list: ['shipAddressList', 'shipMethod'])

# updating a custom fields on a record to be null, using custom field ID
invoice.update(null_field_list: 'custBody9')
```

## Searching

```ruby
Expand Down Expand Up @@ -436,7 +450,7 @@ NetSuite::Records::SalesOrder.search({
'platformCommon:internalId/' => {},
'platformCommon:email/' => {},
'platformCommon:tranDate/' => {},
# If you include columns that are only part of the *SearchRowBasic (ie. TransactionSearchRowBasic),
# If you include columns that are only part of the *SearchRowBasic (ie. TransactionSearchRowBasic),
# they'll be readable on the resulting record just like regular fields (my_record.close_date).
'platformCommon:closeDate/' => {}
],
Expand Down
1 change: 1 addition & 0 deletions lib/netsuite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ module Records
autoload :NonInventoryResaleItem, 'netsuite/records/non_inventory_resale_item'
autoload :Note, 'netsuite/records/note'
autoload :NoteType, 'netsuite/records/note_type'
autoload :NullFieldList, 'netsuite/records/null_field_list'
autoload :Opportunity, 'netsuite/records/opportunity'
autoload :OpportunityItem, 'netsuite/records/opportunity_item'
autoload :OpportunityItemList, 'netsuite/records/opportunity_item_list'
Expand Down
1 change: 1 addition & 0 deletions lib/netsuite/records/invoice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Invoice
field :custom_field_list, CustomFieldList
field :shipping_address, Address
field :billing_address, Address
field :null_field_list, NullFieldList

read_only_fields :sub_total, :discount_total, :total, :recognized_revenue, :amount_remaining, :amount_paid,
:alt_shipping_cost, :gift_cert_applied, :handling_cost, :alt_handling_cost
Expand Down
15 changes: 15 additions & 0 deletions lib/netsuite/records/null_field_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module NetSuite
module Records
class NullFieldList
include Support::Fields
include Support::Records
include Namespaces::PlatformCore

fields :name

def initialize(attributes = {})
initialize_from_attributes_hash(attributes)
end
end
end
end
2 changes: 1 addition & 1 deletion lib/netsuite/support/records.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Records

def to_record
attributes.reject { |k,v| self.class.read_only_fields.include?(k) || self.class.search_only_fields.include?(k) }.inject({}) do |hash, (k,v)|
kname = "#{record_namespace}:"
kname = "#{v.is_a?(NetSuite::Records::NullFieldList) ? v.record_namespace : record_namespace}:"
kname += k == :klass ? 'class' : k.to_s.lower_camelcase

to_attributes!(hash, kname, v)
Expand Down
30 changes: 30 additions & 0 deletions spec/netsuite/records/null_field_list_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'spec_helper'

describe NetSuite::Records::RecordRef do
let(:null_field_list) { NetSuite::Records::NullFieldList.new }

describe '#to_record' do
it 'can represent itself as a SOAP record for single value' do
null_field_list.name = 'blah'
record = {
'platformCore:name' => 'blah'
}
expect(null_field_list.to_record).to eql(record)
end

it 'can represent itself as a SOAP record for multiple values' do
null_field_list.name = ['blah', 'foo']
record = {
'platformCore:name' => ['blah', 'foo']
}
expect(null_field_list.to_record).to eql(record)
end
end

describe '#record_type' do
it 'returns a string of the SOAP type' do
expect(null_field_list.record_type).to eql('platformCore:NullFieldList')
end
end

end
40 changes: 33 additions & 7 deletions spec/netsuite/support/records_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,56 @@ module Foo
module Bar
class Baz
include NetSuite::Support::Fields
include NetSuite::Support::RecordRefs
include NetSuite::Support::Records
include NetSuite::Namespaces::TranSales

def attributes
{ :source => 'Google', :total => 100.0 }
end
fields :source, :total
field :null_field_list, NetSuite::Records::NullFieldList

record_ref :related_record
end
end
end

describe NetSuite::Support::Records do
let(:instance) { Foo::Bar::Baz.new }

describe '#record_type' do
describe '#to_record' do
it 'returns a hash of attributes to be used in a SOAP request' do
instance.source = 'Google'
instance.total = 100.0

expect(instance.to_record).to eql({
'platformCore:source' => 'Google',
'platformCore:total' => 100.0
'tranSales:source' => 'Google',
'tranSales:total' => 100.0
})
end

it 'uses the records namespace for the outer elements namespace and the field values namespace for the inner elements namespace' do
instance.related_record = NetSuite::Records::RecordRef.new(name: 'blah')

expect(instance.to_record).to eq({
'tranSales:relatedRecord' => {
'platformCore:name' => 'blah',
},
})
end

it 'uses the fields namespace for the outer elements namespace for NullFieldList value' do
instance.null_field_list.name = 'source'

expect(instance.to_record).to eq({
'platformCore:nullFieldList' => {
'platformCore:name' => 'source',
},
})
end
end

describe '#record_type' do
it 'returns a string of the record type to be used in a SOAP request' do
expect(instance.record_type).to eql('platformCore:Baz')
expect(instance.record_type).to eql('tranSales:Baz')
end
end

Expand Down

0 comments on commit 5e181d9

Please sign in to comment.