netsuite 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -1
  3. data/HISTORY.md +35 -0
  4. data/README.md +2 -2
  5. data/lib/netsuite/actions/abstract_action.rb +32 -0
  6. data/lib/netsuite/actions/add.rb +5 -5
  7. data/lib/netsuite/actions/attach_file.rb +5 -5
  8. data/lib/netsuite/actions/delete.rb +14 -10
  9. data/lib/netsuite/actions/delete_list.rb +14 -10
  10. data/lib/netsuite/actions/get.rb +14 -10
  11. data/lib/netsuite/actions/get_all.rb +11 -7
  12. data/lib/netsuite/actions/get_deleted.rb +14 -10
  13. data/lib/netsuite/actions/get_list.rb +5 -5
  14. data/lib/netsuite/actions/get_select_value.rb +16 -8
  15. data/lib/netsuite/actions/initialize.rb +15 -11
  16. data/lib/netsuite/actions/search.rb +16 -19
  17. data/lib/netsuite/actions/update.rb +5 -5
  18. data/lib/netsuite/actions/update_list.rb +11 -7
  19. data/lib/netsuite/actions/upsert.rb +5 -5
  20. data/lib/netsuite/actions/upsert_list.rb +11 -7
  21. data/lib/netsuite/configuration.rb +3 -3
  22. data/lib/netsuite/records/estimate_item.rb +8 -1
  23. data/lib/netsuite/records/invoice.rb +3 -2
  24. data/lib/netsuite/records/vendor_return_authorization.rb +1 -1
  25. data/lib/netsuite/records/vendor_return_authorization_item.rb +1 -1
  26. data/lib/netsuite/support/requests.rb +0 -4
  27. data/lib/netsuite/support/search_result.rb +2 -1
  28. data/lib/netsuite/utilities.rb +4 -4
  29. data/lib/netsuite/version.rb +1 -1
  30. data/lib/netsuite.rb +1 -0
  31. data/spec/netsuite/actions/search_spec.rb +13 -30
  32. data/spec/netsuite/configuration_spec.rb +9 -1
  33. data/spec/netsuite/records/estimate_item_spec.rb +8 -1
  34. data/spec/netsuite/records/invoice_spec.rb +3 -2
  35. data/spec/netsuite/support/search_result_spec.rb +17 -0
  36. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5aad2f60c62b40aaa3e86460dc81283d470a3293d1568fe41d78e431b3d6ec61
4
- data.tar.gz: 411b9bbfaa28f9c76ad886245afe83334758d5b3b360d70e405bd1897a0c1a53
3
+ metadata.gz: 954fbfc75bb1bbce5dcae995d19a5cfc6cf862dc5b70c71ef445bdfb05321629
4
+ data.tar.gz: 959ea56ff63e5da0dfdb602a422dc8fd2dab8aecaf5742910f3d85e9333f7649
5
5
  SHA512:
6
- metadata.gz: 72ace4cda9656efd8592ed824ccb788c136aac912c5d9ec2fac38b817f00658979a29dae19c7a298108be49c9d1c386598a7476e05a61a25a05d18a53232c930
7
- data.tar.gz: 3fb702a8c3cca1c6896603769027022136b38af973820ae7f098d68f8ec0e4f07f45175d4b4cfd5fb8b189079f7a5ba5255becf166d0640bee5d067430ac3fe4
6
+ metadata.gz: 3470bae8218194017073f9ff4d52e781d0f5390b3d4b1c44e766fee8d13737da52f891f5f4ae9ce8e865d99d55fb47ebef0cedd115c64a908628ab65077a8940
7
+ data.tar.gz: ba3d6369e168926b02d51b2faa045bed59a7d4f45874e4a17dedec74f5f3c09d2ba356c962671b977c49412b4397d60017936323efc80a6340ed3fda119e6da4
@@ -7,7 +7,7 @@ jobs:
7
7
  runs-on: ubuntu-latest
8
8
  strategy:
9
9
  matrix:
10
- ruby-version: [3.1, 3.0, 2.7, 2.6, 2.5, 2.4, 2.3, 2.2, 2.1]
10
+ ruby-version: [3.2, 3.1, 3.0, 2.7, 2.6, 2.5, 2.4, 2.3, 2.2, 2.1]
11
11
  bundle-tzinfo: [true, false]
12
12
  env:
13
13
  BUNDLE_TZINFO: "${{ matrix.bundle-tzinfo }}"
data/HISTORY.md CHANGED
@@ -1,13 +1,45 @@
1
1
  ## Unreleased
2
2
 
3
+ ### Added
4
+
5
+ ### Fixed
6
+
7
+ ### Breaking Changes
8
+
9
+ ## v0.9.3
10
+
11
+ ### Added
12
+ * Create abstract action parent class by @andrewdicken-stripe in https://github.com/NetSweet/netsuite/pull/568
13
+
14
+ ### Fixed
15
+ * Add department, klass and location EstimateItem/record_refs by @nickdufresne in https://github.com/NetSweet/netsuite/pull/572
16
+ * Invoice shipping_tax_code should be a record_ref by @stevewoodcock in https://github.com/NetSweet/netsuite/pull/573
17
+ * dont crash if suitetalk returns empty <platformCore:searchRowList/> by @ericcj in https://github.com/NetSweet/netsuite/pull/574
18
+ * Add :klass field to record VendorReturnAuthorizationItem & VendorReturnAuthorization by @shubhrathasetty in https://github.com/NetSweet/netsuite/pull/576
19
+ * Optionally pass in `proxy` parameter to Savon by @dbecker-stripe in https://github.com/NetSweet/netsuite/pull/548
20
+
21
+ ## v0.9.2
22
+
23
+ ### Fixed
24
+
25
+ * Update rspec requirement from ~> 3.11.0 to ~> 3.12.0 by @dependabot in https://github.com/NetSweet/netsuite/pull/567
26
+ * [Adding UK country mapping](https://github.com/NetSweet/netsuite/commit/5fe96ed28fb8341b6926e169cf50d817632b5b8d)
27
+
28
+ ### Breaking Changes
29
+
30
+ * [remove country mapping hack for old API versions](https://github.com/NetSweet/netsuite/commit/a0357f0a9e08eb3a4a80f1d1e7a37f95bcb17d4f)
31
+
32
+ ## v0.9.1
3
33
 
4
34
  ### Added
5
35
  * Add `Configuration#multi_tenant!` for opting into multi-tentant support where configuration/caching is per-thread (#556)
6
36
 
7
37
  ### Fixed
8
38
  * Avoid Savon version `2.13.0` to prevent generating invalid envelopes. (#558, #563)
39
+ * Retry on `HTTPI::SSLError` and `HTTPI::TimeoutError` in backoff (#566)
9
40
 
10
41
  ### Breaking Changes
42
+ * Update default API version to 2016_2 from 2015_1 when `api_version` is not explicitly set (#554)
11
43
 
12
44
  ## 0.9.0
13
45
 
@@ -21,6 +53,9 @@ The following were removed as `fields` since their sublist class is not yet impl
21
53
  * Add `update` action to `File` records (#544)
22
54
  * Expose `errors` after calls to `delete` action (#545)
23
55
  * Add `update_list` action where missing on supported item records (#546)
56
+ * Add `proxy` attribute to `NetSuite::Configuration` to set a proxy used by the savon client (#547)
57
+
58
+ ### Fixed
24
59
  * Ignore `after_submit_failed` status details (>= 2018.2) when collating errors in add action (#550)
25
60
  * Add `NullFieldList` to `SalesOrder` (#552)
26
61
  * Add thread safety to NetSuite configuration and utilities (#549)
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  [![Ruby](https://github.com/NetSweet/netsuite/actions/workflows/main.yml/badge.svg)](https://github.com/NetSweet/netsuite/actions/workflows/main.yml)
2
- [![Slack Status](https://opensuite-slackin.herokuapp.com/badge.svg)](http://opensuite-slackin.herokuapp.com)
2
+ [![Slack Status](https://netsuite-slackin.fly.dev/badge.svg)](https://netsuite-slackin.fly.dev)
3
3
  [![Gem Version](https://badge.fury.io/rb/netsuite.svg)](http://badge.fury.io/rb/netsuite)
4
4
 
5
5
  # NetSuite SuiteTalk API Ruby Gem
@@ -10,7 +10,7 @@
10
10
 
11
11
  # Help & Support
12
12
 
13
- Join the [Slack channel](http://opensuite-slackin.herokuapp.com) for help with any NetSuite issues. Please do not post usage questions as issues in GitHub.
13
+ Join the [Slack channel](https://netsuite-slackin.fly.dev) for help with any NetSuite issues. Please do not post usage questions as issues in GitHub.
14
14
 
15
15
  There is some additional helpful resources for NetSuite development [listed here](https://dashboard.suitesync.io/docs/resources#netsuite).
16
16
 
@@ -0,0 +1,32 @@
1
+ module NetSuite
2
+ module Actions
3
+ class AbstractAction
4
+ def request(credentials={})
5
+ NetSuite::Configuration.connection(request_options, credentials, soap_header_extra_info).call(action_name, message: request_body)
6
+ end
7
+
8
+ protected
9
+
10
+ def action_name
11
+ raise NotImplementedError, 'Not implemented on abstract class'
12
+ end
13
+
14
+ def initialize
15
+ raise NotImplementedError, 'Not implemented on abstract class'
16
+ end
17
+
18
+ def request_body
19
+ raise NotImplementedError, 'Not implemented on abstract class'
20
+ end
21
+
22
+ def request_options
23
+ {}
24
+ end
25
+
26
+ def soap_header_extra_info
27
+ {}
28
+ end
29
+ end
30
+ end
31
+ end
32
+
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/add.html
2
2
  module NetSuite
3
3
  module Actions
4
- class Add
4
+ class Add < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  attr_reader :response_hash
@@ -12,10 +12,6 @@ module NetSuite
12
12
 
13
13
  private
14
14
 
15
- def request(credentials={})
16
- NetSuite::Configuration.connection({}, credentials).call(:add, :message => request_body)
17
- end
18
-
19
15
  # <soap:Body>
20
16
  # <platformMsgs:add>
21
17
  # <platformMsgs:record xsi:type="listRel:Customer">
@@ -66,6 +62,10 @@ module NetSuite
66
62
  @response_hash ||= @response.to_hash[:add_response][:write_response]
67
63
  end
68
64
 
65
+ def action_name
66
+ :add
67
+ end
68
+
69
69
  def errors
70
70
  error_obj = response_hash[:status][:status_detail]
71
71
  error_obj = [error_obj] if error_obj.class == Hash
@@ -1,6 +1,6 @@
1
1
  module NetSuite
2
2
  module Actions
3
- class AttachFile
3
+ class AttachFile < AbstractAction
4
4
  include Support::Requests
5
5
 
6
6
  def initialize(object, file)
@@ -10,10 +10,6 @@ module NetSuite
10
10
 
11
11
  private
12
12
 
13
- def request(credentials = {})
14
- NetSuite::Configuration.connection({}, credentials).call(:attach, :message => request_body)
15
- end
16
-
17
13
  # <soap:Body>
18
14
  # <platformMsgs:attach>
19
15
  # <platformCore:attachReference xsi:type="platformCore:AttachContactReference">
@@ -60,6 +56,10 @@ module NetSuite
60
56
  @response_hash ||= @response.to_hash[:attach_response][:write_response]
61
57
  end
62
58
 
59
+ def action_name
60
+ :attach
61
+ end
62
+
63
63
  def errors
64
64
  error_obj = response_hash[:status][:status_detail]
65
65
  error_obj = [error_obj] if error_obj.class == Hash
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/delete.html
2
2
  module NetSuite
3
3
  module Actions
4
- class Delete
4
+ class Delete < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(object = nil, options = {})
@@ -11,15 +11,6 @@ module NetSuite
11
11
 
12
12
  private
13
13
 
14
- def request(credentials={})
15
- NetSuite::Configuration.connection(
16
- {namespaces: {
17
- 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
18
- 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
19
- }}, credentials
20
- ).call :delete, message: request_body
21
- end
22
-
23
14
  def soap_type
24
15
  NetSuite::Support::Records.netsuite_type(@object)
25
16
  end
@@ -71,6 +62,19 @@ module NetSuite
71
62
  end
72
63
  end
73
64
 
65
+ def request_options
66
+ {
67
+ namespaces: {
68
+ 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
69
+ 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
70
+ }
71
+ }
72
+ end
73
+
74
+ def action_name
75
+ :delete
76
+ end
77
+
74
78
  def errors
75
79
  error_obj = response_hash[:status][:status_detail]
76
80
  error_obj = [error_obj] if error_obj.class == Hash
@@ -1,6 +1,6 @@
1
1
  module NetSuite
2
2
  module Actions
3
- class DeleteList
3
+ class DeleteList < AbstractAction
4
4
  include Support::Requests
5
5
 
6
6
  def initialize(klass, options = { })
@@ -10,15 +10,6 @@ module NetSuite
10
10
 
11
11
  private
12
12
 
13
- def request(credentials={})
14
- NetSuite::Configuration.connection(
15
- {namespaces: {
16
- 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
17
- 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
18
- }}, credentials
19
- ).call :delete_list, message: request_body
20
- end
21
-
22
13
  # <soap:Body>
23
14
  # <platformMsgs:deleteList>
24
15
  # <platformMsgs:baseRef internalId="1" type="customer" xsi:type="platformCore:RecordRef"/>
@@ -71,6 +62,19 @@ module NetSuite
71
62
  end
72
63
  end
73
64
 
65
+ def request_options
66
+ {
67
+ namespaces: {
68
+ 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
69
+ 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
70
+ }
71
+ }
72
+ end
73
+
74
+ def action_name
75
+ :delete_list
76
+ end
77
+
74
78
  def errors
75
79
  errors = response_list.select { |r| r[:status] && r[:status][:status_detail] }.map do |obj|
76
80
  error_obj = obj[:status][:status_detail]
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/get.html
2
2
  module NetSuite
3
3
  module Actions
4
- class Get
4
+ class Get < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(klass, options = {})
@@ -11,15 +11,6 @@ module NetSuite
11
11
 
12
12
  private
13
13
 
14
- def request(credentials={})
15
- NetSuite::Configuration.connection(
16
- {namespaces: {
17
- 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
18
- 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
19
- }}, credentials
20
- ).call :get, message: request_body
21
- end
22
-
23
14
  def soap_type
24
15
  NetSuite::Support::Records.netsuite_type(@klass)
25
16
  end
@@ -56,6 +47,19 @@ module NetSuite
56
47
  @response_hash = @response.body[:get_response][:read_response]
57
48
  end
58
49
 
50
+ def request_options
51
+ {
52
+ namespaces: {
53
+ 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
54
+ 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
55
+ }
56
+ }
57
+ end
58
+
59
+ def action_name
60
+ :get
61
+ end
62
+
59
63
  module Support
60
64
 
61
65
  def self.included(base)
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/getAll.html
2
2
  module NetSuite
3
3
  module Actions
4
- class GetAll
4
+ class GetAll < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(klass)
@@ -10,12 +10,6 @@ module NetSuite
10
10
 
11
11
  private
12
12
 
13
- def request(credentials={})
14
- NetSuite::Configuration.connection(
15
- { element_form_default: :unqualified }, credentials
16
- ).call(:get_all, message: request_body)
17
- end
18
-
19
13
  # <soap:Body>
20
14
  # <platformMsgs:getAll>
21
15
  # <record>
@@ -49,6 +43,16 @@ module NetSuite
49
43
  @response_hash ||= @response.body[:get_all_response][:get_all_result]
50
44
  end
51
45
 
46
+ def request_options
47
+ {
48
+ element_form_default: :unqualified
49
+ }
50
+ end
51
+
52
+ def action_name
53
+ :get_all
54
+ end
55
+
52
56
  module Support
53
57
 
54
58
  def self.included(base)
@@ -1,6 +1,6 @@
1
1
  module NetSuite
2
2
  module Actions
3
- class GetDeleted
3
+ class GetDeleted < AbstractAction
4
4
  include Support::Requests
5
5
 
6
6
  def initialize(object = nil, options = {})
@@ -10,15 +10,6 @@ module NetSuite
10
10
 
11
11
  private
12
12
 
13
- def request(credentials={})
14
- NetSuite::Configuration.connection(
15
- {namespaces: {
16
- 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
17
- 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
18
- }}, credentials
19
- ).call :get_deleted, message: request_body
20
- end
21
-
22
13
  def soap_type
23
14
  NetSuite::Support::Records.netsuite_type(@object)
24
15
  end
@@ -72,6 +63,19 @@ module NetSuite
72
63
  @response_body ||= response_hash[:get_deleted_result]
73
64
  end
74
65
 
66
+ def request_options
67
+ {
68
+ namespaces: {
69
+ 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
70
+ 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
71
+ }
72
+ }
73
+ end
74
+
75
+ def action_name
76
+ :get_deleted
77
+ end
78
+
75
79
  module Support
76
80
  def self.included(base)
77
81
  base.extend(ClassMethods)
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/getList.html
2
2
  module NetSuite
3
3
  module Actions
4
- class GetList
4
+ class GetList < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(klass, options = { })
@@ -11,10 +11,6 @@ module NetSuite
11
11
 
12
12
  private
13
13
 
14
- def request(credentials={})
15
- NetSuite::Configuration.connection({}, credentials).call(:get_list, :message => request_body)
16
- end
17
-
18
14
  def request_body
19
15
  # list of all netsuite types; useful for debugging
20
16
  # https://webservices.netsuite.com/xsd/platform/v2014_1_0/coreTypes.xsd
@@ -64,6 +60,10 @@ module NetSuite
64
60
  @response_body
65
61
  end
66
62
 
63
+ def action_name
64
+ :get_list
65
+ end
66
+
67
67
  def success?
68
68
  # each returned record has its own status;
69
69
  if @options[:allow_incomplete]
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/getSelectValue.html
2
2
  module NetSuite
3
3
  module Actions
4
- class GetSelectValue
4
+ class GetSelectValue < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(klass, options = {})
@@ -11,13 +11,8 @@ module NetSuite
11
11
 
12
12
  private
13
13
 
14
- def request(credentials={})
15
- NetSuite::Configuration.connection(
16
- {namespaces: {
17
- 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
18
- 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
19
- }}, credentials
20
- ).call :get_select_value, :message => @options
14
+ def request_body
15
+ @options
21
16
  end
22
17
 
23
18
  def success?
@@ -32,6 +27,19 @@ module NetSuite
32
27
  @response_hash = @response.body[:get_select_value_response][:get_select_value_result]
33
28
  end
34
29
 
30
+ def request_options
31
+ {
32
+ namespaces: {
33
+ 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
34
+ 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com"
35
+ }
36
+ }
37
+ end
38
+
39
+ def action_name
40
+ :get_select_value
41
+ end
42
+
35
43
  module Support
36
44
 
37
45
  def self.included(base)
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/initializeinitializeList.html
2
2
  module NetSuite
3
3
  module Actions
4
- class Initialize
4
+ class Initialize < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(klass, object)
@@ -9,16 +9,6 @@ module NetSuite
9
9
  @object = object
10
10
  end
11
11
 
12
- def request(credentials={})
13
- NetSuite::Configuration.connection(
14
- {namespaces: {
15
- 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
16
- 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
17
- 'xmlns:platformCoreTyp' => "urn:types.core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
18
- }}, credentials
19
- ).call :initialize, :message => request_body
20
- end
21
-
22
12
  # <platformMsgs:initializeRecord>
23
13
  # <platformCore:type>invoice</platformCore:type>
24
14
  # <platformCore:reference internalId="1513" type="salesOrder">
@@ -52,6 +42,20 @@ module NetSuite
52
42
  @response_body ||= response_hash[:record]
53
43
  end
54
44
 
45
+ def request_options
46
+ {
47
+ namespaces: {
48
+ 'xmlns:platformMsgs' => "urn:messages_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
49
+ 'xmlns:platformCore' => "urn:core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
50
+ 'xmlns:platformCoreTyp' => "urn:types.core_#{NetSuite::Configuration.api_version}.platform.webservices.netsuite.com",
51
+ }
52
+ }
53
+ end
54
+
55
+ def action_name
56
+ :initialize
57
+ end
58
+
55
59
  module Support
56
60
 
57
61
  def self.included(base)
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/search.html
2
2
  module NetSuite
3
3
  module Actions
4
- class Search
4
+ class Search < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(klass, options = { })
@@ -18,24 +18,6 @@ module NetSuite
18
18
  end
19
19
 
20
20
  private
21
- def request(credentials={})
22
- # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/SettingSearchPreferences.html
23
- # https://webservices.netsuite.com/xsd/platform/v2012_2_0/messages.xsd
24
-
25
- preferences = NetSuite::Configuration.auth_header(credentials)
26
- .update(NetSuite::Configuration.soap_header)
27
- .merge(
28
- (@options.delete(:preferences) || {}).inject({'platformMsgs:SearchPreferences' => {}}) do |h, (k, v)|
29
- h['platformMsgs:SearchPreferences'][NetSuite::Utilities::Strings.lower_camelcase(k.to_s)] = v
30
- h
31
- end
32
- )
33
-
34
- NetSuite::Configuration
35
- .connection({ soap_header: preferences }, credentials)
36
- .call (@options.has_key?(:search_id)? :search_more_with_id : :search), :message => request_body
37
- end
38
-
39
21
  # basic search XML
40
22
 
41
23
  # <soap:Body>
@@ -239,6 +221,21 @@ module NetSuite
239
221
  end[:search_result]
240
222
  end
241
223
 
224
+ def action_name
225
+ @options.has_key?(:search_id)? :search_more_with_id : :search
226
+ end
227
+
228
+ def soap_header_extra_info
229
+ # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/SettingSearchPreferences.html
230
+ # https://webservices.netsuite.com/xsd/platform/v2012_2_0/messages.xsd
231
+
232
+ (@options.delete(:preferences) || {})
233
+ .inject({'platformMsgs:SearchPreferences' => {}}) do |h, (k, v)|
234
+ h['platformMsgs:SearchPreferences'][NetSuite::Utilities::Strings.lower_camelcase(k.to_s)] = v
235
+ h
236
+ end
237
+ end
238
+
242
239
  def success?
243
240
  @success ||= search_result[:status][:@is_success] == 'true'
244
241
  end
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/update.html
2
2
  module NetSuite
3
3
  module Actions
4
- class Update
4
+ class Update < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  attr_reader :response_hash
@@ -11,10 +11,6 @@ module NetSuite
11
11
  @attributes = attributes
12
12
  end
13
13
 
14
- def request(credentials={})
15
- NetSuite::Configuration.connection({}, credentials).call :update, :message => request_body
16
- end
17
-
18
14
  # <platformMsgs:update>
19
15
  # <platformMsgs:record internalId="980" xsi:type="listRel:Customer">
20
16
  # <listRel:companyName>Shutter Fly Corporation</listRel:companyName>
@@ -69,6 +65,10 @@ module NetSuite
69
65
  end
70
66
  end
71
67
 
68
+ def action_name
69
+ :update
70
+ end
71
+
72
72
  module Support
73
73
  def update(options = {}, credentials={})
74
74
  options[:internal_id] = internal_id if respond_to?(:internal_id) && internal_id
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/updateList.html
2
2
  module NetSuite
3
3
  module Actions
4
- class UpdateList
4
+ class UpdateList < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(*objects)
@@ -10,12 +10,6 @@ module NetSuite
10
10
 
11
11
  private
12
12
 
13
- def request(credentials={})
14
- NetSuite::Configuration.connection(
15
- { element_form_default: :unqualified }, credentials
16
- ).call(:update_list, message: request_body)
17
- end
18
-
19
13
  # <soap:Body>
20
14
  # <updateList>
21
15
  # <record xsi:type="listRel:Customer" externalId="ext1">
@@ -79,6 +73,16 @@ module NetSuite
79
73
  @success ||= response_hash.all? { |h| h[:status][:@is_success] == 'true' }
80
74
  end
81
75
 
76
+ def request_options
77
+ {
78
+ element_form_default: :unqualified
79
+ }
80
+ end
81
+
82
+ def action_name
83
+ :update_list
84
+ end
85
+
82
86
  module Support
83
87
 
84
88
  def self.included(base)
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/upsert.html
2
2
  module NetSuite
3
3
  module Actions
4
- class Upsert
4
+ class Upsert < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  attr_reader :response_hash
@@ -12,10 +12,6 @@ module NetSuite
12
12
 
13
13
  private
14
14
 
15
- def request(credentials={})
16
- NetSuite::Configuration.connection({}, credentials).call :upsert, :message => request_body
17
- end
18
-
19
15
  # <soap:Body>
20
16
  # <platformMsgs:upsert>
21
17
  # <platformMsgs:record xsi:type="listRel:Customer">
@@ -68,6 +64,10 @@ module NetSuite
68
64
  end
69
65
  end
70
66
 
67
+ def action_name
68
+ :upsert
69
+ end
70
+
71
71
  module Support
72
72
  def upsert(credentials={})
73
73
  response = NetSuite::Actions::Upsert.call([self], credentials)
@@ -1,7 +1,7 @@
1
1
  # https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteCloudCustomizationScriptingWebServices/SuiteTalkWebServices/upsertList.html
2
2
  module NetSuite
3
3
  module Actions
4
- class UpsertList
4
+ class UpsertList < AbstractAction
5
5
  include Support::Requests
6
6
 
7
7
  def initialize(*objects)
@@ -10,12 +10,6 @@ module NetSuite
10
10
 
11
11
  private
12
12
 
13
- def request(credentials={})
14
- NetSuite::Configuration.connection(
15
- { element_form_default: :unqualified }, credentials
16
- ).call(:upsert_list, message: request_body)
17
- end
18
-
19
13
  # <soap:Body>
20
14
  # <upsertList>
21
15
  # <record xsi:type="listRel:Customer" externalId="ext1">
@@ -75,6 +69,16 @@ module NetSuite
75
69
  @success ||= response_hash.all? { |h| h[:status][:@is_success] == 'true' }
76
70
  end
77
71
 
72
+ def request_options
73
+ {
74
+ element_form_default: :unqualified
75
+ }
76
+ end
77
+
78
+ def action_name
79
+ :upsert_list
80
+ end
81
+
78
82
  module Support
79
83
 
80
84
  def self.included(base)
@@ -18,21 +18,21 @@ module NetSuite
18
18
  end
19
19
  end
20
20
 
21
- def connection(params={}, credentials={})
21
+ def connection(params={}, credentials={}, soap_header_extra_info={})
22
22
  client = Savon.client({
23
23
  wsdl: cached_wsdl || wsdl,
24
24
  endpoint: endpoint,
25
25
  read_timeout: read_timeout,
26
26
  open_timeout: open_timeout,
27
27
  namespaces: namespaces,
28
- soap_header: auth_header(credentials).update(soap_header),
28
+ soap_header: auth_header(credentials).update(soap_header).merge(soap_header_extra_info),
29
29
  pretty_print_xml: true,
30
30
  filters: filters,
31
31
  logger: logger,
32
32
  log_level: log_level,
33
33
  log: !silent, # turn off logging entirely if configured
34
- proxy: proxy,
35
34
  }.update(params))
35
+ client.globals.proxy(proxy) if proxy
36
36
  cache_wsdl(client)
37
37
  return client
38
38
  end
@@ -13,7 +13,14 @@ module NetSuite
13
13
 
14
14
  field :custom_field_list, CustomFieldList
15
15
 
16
- record_refs :item, :job, :price, :tax_code, :units
16
+ record_refs :department,
17
+ :item,
18
+ :job,
19
+ :klass,
20
+ :location,
21
+ :price,
22
+ :tax_code,
23
+ :units
17
24
 
18
25
  def initialize(attributes_or_record = {})
19
26
  case attributes_or_record
@@ -25,7 +25,7 @@ module NetSuite
25
25
  :other_ref_num, :partners_list, :rev_rec_end_date,
26
26
  :rev_rec_on_rev_commitment, :rev_rec_schedule, :rev_rec_start_date, :revenue_status, :sales_effective_date,
27
27
  :sales_group, :sales_team_list, :ship_date, :ship_group_list,
28
- :shipping_cost, :shipping_tax_1_rate, :shipping_tax_2_rate, :shipping_tax_code, :source, :start_date,
28
+ :shipping_cost, :shipping_tax_1_rate, :shipping_tax_2_rate, :source, :start_date,
29
29
  :status, :sync_partner_teams, :sync_sales_teams, :tax_2_total,
30
30
  :tax_total, :time_disc_amount, :time_disc_print, :time_disc_rate, :time_disc_tax_1_amt, :time_disc_taxable,
31
31
  :time_discount, :time_list, :time_tax_code, :time_tax_rate_1, :time_tax_rate_2, :to_be_emailed, :to_be_faxed,
@@ -138,7 +138,8 @@ module NetSuite
138
138
 
139
139
  record_refs :account, :bill_address_list, :custom_form, :department, :entity, :klass, :partner,
140
140
  :posting_period, :ship_address_list, :terms, :location, :sales_rep, :tax_item, :created_from,
141
- :ship_method, :lead_source, :promo_code, :subsidiary, :currency, :approval_status, :job, :discount_item
141
+ :ship_method, :lead_source, :promo_code, :subsidiary, :currency, :approval_status, :job, :discount_item,
142
+ :shipping_tax_code
142
143
 
143
144
  attr_reader :internal_id
144
145
  attr_accessor :external_id
@@ -9,7 +9,7 @@ module NetSuite
9
9
 
10
10
  actions :get, :get_list, :add, :initialize, :delete, :update, :upsert, :search
11
11
 
12
- fields :billing_address, :created_date, :memo, :tran_date, :tran_id
12
+ fields :billing_address, :created_date, :memo, :tran_date, :tran_id, :klass
13
13
 
14
14
  record_refs :bill_address_list, :department, :entity, :location
15
15
 
@@ -8,7 +8,7 @@ module NetSuite
8
8
 
9
9
  fields :amortization_end_date, :amortization_residual, :amount, :bin_numbers, :description,
10
10
  :gross_amt, :is_billable, :is_closed, :is_drop_shipment, :line, :order_line, :quantity,
11
- :rate, :vendor_name
11
+ :rate, :vendor_name, :klass
12
12
 
13
13
  field :inventory_detail, InventoryDetail
14
14
 
@@ -22,10 +22,6 @@ module NetSuite
22
22
 
23
23
  private
24
24
 
25
- def request
26
- raise NotImplementedError, 'Please implement a #request method'
27
- end
28
-
29
25
  def build_response
30
26
  Response.new(success: success?, header: response_header, body: response_body, errors: response_errors)
31
27
  end
@@ -48,7 +48,8 @@ module NetSuite
48
48
  end
49
49
  elsif response.body.has_key? :search_row_list
50
50
  # advanced search results
51
- record_list = response.body[:search_row_list][:search_row]
51
+ record_list = response.body[:search_row_list]
52
+ record_list = record_list ? record_list[:search_row] : []
52
53
  record_list = [record_list] unless record_list.is_a?(Array)
53
54
 
54
55
  record_list.each do |record|
@@ -56,12 +56,12 @@ module NetSuite
56
56
  ns_record
57
57
  end
58
58
 
59
- def netsuite_server_time
60
- server_time_response = NetSuite::Utilities.backoff { NetSuite::Configuration.connection.call(:get_server_time) }
59
+ def netsuite_server_time(credentials={})
60
+ server_time_response = NetSuite::Utilities.backoff { NetSuite::Configuration.connection({}, credentials).call(:get_server_time) }
61
61
  server_time_response.body[:get_server_time_response][:get_server_time_result][:server_time]
62
62
  end
63
63
 
64
- def netsuite_data_center_urls(account_id)
64
+ def netsuite_data_center_urls(account_id, credentials={})
65
65
  data_center_call_response = NetSuite::Configuration.connection({
66
66
  # NOTE force a production WSDL so the sandbox settings are ignored
67
67
  # as of 1/20/18 NS will start using the account ID to determine
@@ -75,7 +75,7 @@ module NetSuite
75
75
  },
76
76
 
77
77
  soap_header: {}
78
- }).call(:get_data_center_urls, message: {
78
+ }, credentials).call(:get_data_center_urls, message: {
79
79
  'platformMsgs:account' => account_id
80
80
  })
81
81
 
@@ -1,3 +1,3 @@
1
1
  module NetSuite
2
- VERSION = '0.9.2'
2
+ VERSION = '0.9.3'
3
3
  end
data/lib/netsuite.rb CHANGED
@@ -48,6 +48,7 @@ module NetSuite
48
48
  end
49
49
 
50
50
  module Actions
51
+ autoload :AbstractAction, 'netsuite/actions/abstract_action'
51
52
  autoload :Add, 'netsuite/actions/add'
52
53
  autoload :AttachFile, 'netsuite/actions/attach_file'
53
54
  autoload :Delete, 'netsuite/actions/delete'
@@ -5,22 +5,29 @@ describe NetSuite::Actions::Search do
5
5
  after(:all) { savon.unmock! }
6
6
 
7
7
  it "handles custom auth credentials" do
8
- allow(NetSuite::Configuration).to receive(:connection).and_return(double().as_null_object)
9
-
10
8
  credentials = {
11
9
  email: 'fake@domain.com',
12
10
  password: 'fake'
13
11
  }
14
- NetSuite::Records::Customer.search({}, credentials)
15
12
 
16
- expect(NetSuite::Configuration).to have_received(:connection).with({:soap_header=>{
13
+ connection = NetSuite::Configuration.connection({}, credentials)
14
+
15
+ soap_header = {
17
16
  "platformMsgs:passport"=>{
18
17
  "platformCore:email"=>"fake@domain.com",
19
18
  "platformCore:password"=>"fake",
20
19
  "platformCore:account"=>"1234",
21
20
  "platformCore:role"=>{:@internalId=>"3"}
22
- }, "platformMsgs:SearchPreferences"=>{}}}, credentials
23
- )
21
+ }
22
+ }
23
+
24
+ expect(connection.instance_variable_get('@globals')[:soap_header]).to eq soap_header
25
+
26
+ allow(NetSuite::Configuration).to receive(:connection).and_return(double().as_null_object)
27
+
28
+ NetSuite::Records::Customer.search({}, credentials)
29
+
30
+ expect(NetSuite::Configuration).to have_received(:connection).with({}, credentials, { "platformMsgs:SearchPreferences"=>{} })
24
31
  end
25
32
 
26
33
  context "search class name" do
@@ -193,30 +200,6 @@ describe NetSuite::Actions::Search do
193
200
  expect(search.results.first.location_re_order_point).to eq('2565.0')
194
201
  expect(search.results.first.location_quantity_on_order).to eq('40000.0')
195
202
  end
196
-
197
- it "should handle an ID search with basic non-field result columns" do
198
- response = File.read('spec/support/fixtures/search/saved_search_item_2.xml')
199
- savon.expects(:search)
200
- .with(message: {
201
- "searchRecord"=>{
202
- "@xsi:type" =>"listAcct:ItemSearchAdvanced",
203
- "@savedSearchId" =>42,
204
- :content! =>{"listAcct:criteria"=>{}},
205
- }
206
- }).returns(response)
207
-
208
- search = NetSuite::Records::InventoryItem.search(saved: 42)
209
-
210
- results = search.results
211
- custom_fields = results.map do |record|
212
- record.custom_field_list.custom_fields.map(&:internal_id)
213
- end.flatten.uniq
214
- [
215
- :location_quantity_available,
216
- :location_re_order_point,
217
- :location_quantity_on_order,
218
- ].each {|field| expect(custom_fields).to include(field)}
219
- end
220
203
  end
221
204
 
222
205
  context "advanced search" do
@@ -519,13 +519,21 @@ describe NetSuite::Configuration do
519
519
  expect(config.proxy).to be_nil
520
520
  end
521
521
 
522
+ it 'does not pass in nil proxy to savon' do
523
+ connection = config.connection
524
+
525
+ expect(connection.globals.include?(:proxy)).to eql(false)
526
+ end
527
+
522
528
  it 'can be set with proxy=' do
523
529
  config.proxy = "https://my-proxy"
524
530
 
525
531
  expect(config.proxy).to eql("https://my-proxy")
526
532
 
527
533
  # ensure no exception is raised
528
- config.connection
534
+ connection = config.connection
535
+
536
+ expect(connection.globals.include?(:proxy)).to eql(true)
529
537
  end
530
538
 
531
539
  it 'can be set with proxy(value)' do
@@ -16,7 +16,14 @@ describe NetSuite::Records::EstimateItem do
16
16
 
17
17
  it 'has all the right record refs' do
18
18
  [
19
- :item, :job, :price, :tax_code, :units
19
+ :department,
20
+ :item,
21
+ :job,
22
+ :klass,
23
+ :location,
24
+ :price,
25
+ :tax_code,
26
+ :units,
20
27
  ].each do |record_ref|
21
28
  expect(item).to have_record_ref(record_ref)
22
29
  end
@@ -21,7 +21,7 @@ describe NetSuite::Records::Invoice do
21
21
  :other_ref_num, :partners_list, :rev_rec_end_date,
22
22
  :rev_rec_on_rev_commitment, :rev_rec_schedule, :rev_rec_start_date, :revenue_status, :sales_effective_date,
23
23
  :sales_group, :sales_team_list, :ship_address, :ship_date, :ship_group_list,
24
- :shipping_cost, :shipping_tax_1_rate, :shipping_tax_2_rate, :shipping_tax_code, :source, :start_date,
24
+ :shipping_cost, :shipping_tax_1_rate, :shipping_tax_2_rate, :source, :start_date,
25
25
  :status, :sync_partner_teams, :sync_sales_teams, :tax_2_total,
26
26
  :tax_total, :time_disc_amount, :time_disc_print, :time_disc_rate, :time_disc_tax_1_amt, :time_disc_taxable,
27
27
  :time_discount, :time_list, :time_tax_code, :time_tax_rate_1, :time_tax_rate_2, :to_be_emailed, :to_be_faxed,
@@ -151,7 +151,8 @@ describe NetSuite::Records::Invoice do
151
151
  it 'has the right record_refs' do
152
152
  [
153
153
  :account, :bill_address_list, :job, :custom_form, :department, :entity, :klass, :posting_period, :ship_address_list, :terms,
154
- :created_from, :location, :sales_rep, :ship_method, :tax_item, :partner, :lead_source, :promo_code, :subsidiary, :discount_item
154
+ :created_from, :location, :sales_rep, :ship_method, :tax_item, :partner, :lead_source, :promo_code, :subsidiary, :discount_item,
155
+ :shipping_tax_code
155
156
  ].each do |record_ref|
156
157
  expect(invoice).to have_record_ref(record_ref)
157
158
  end
@@ -22,6 +22,23 @@ describe NetSuite::Support::SearchResult do
22
22
  results = described_class.new(response, NetSuite::Actions::Search, {}).results
23
23
  expect(results).to eq []
24
24
  end
25
+
26
+ it 'returns empty search_row_list' do
27
+ response_body = {
28
+ :status => {:@is_success=>"true"},
29
+ :total_records => "242258",
30
+ :page_size => "10",
31
+ :total_pages => "24226",
32
+ :page_index => "99",
33
+ :search_id => "WEBSERVICES_4132604_SB1_051620191060155623420663266_336cbf12",
34
+ :search_row_list => nil,
35
+ :"@xmlns:platform_core" => "urn:core_2016_2.platform.webservices.netsuite.com"
36
+ }
37
+ response = NetSuite::Response.new(body: response_body)
38
+
39
+ results = described_class.new(response, NetSuite::Actions::Search, {}).results
40
+ expect(results).to eq []
41
+ end
25
42
  end
26
43
 
27
44
  it 'handles a recordList with a single element' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: netsuite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Moran
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-12-23 00:00:00.000000000 Z
13
+ date: 2023-03-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: savon
@@ -83,6 +83,7 @@ files:
83
83
  - README.md
84
84
  - Rakefile
85
85
  - lib/netsuite.rb
86
+ - lib/netsuite/actions/abstract_action.rb
86
87
  - lib/netsuite/actions/add.rb
87
88
  - lib/netsuite/actions/attach_file.rb
88
89
  - lib/netsuite/actions/delete.rb