netsuite 0.8.5 → 0.8.9

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 (84) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/main.yml +20 -0
  3. data/.ruby-version +1 -1
  4. data/.tool-versions +1 -0
  5. data/Gemfile +1 -5
  6. data/HISTORY.md +32 -0
  7. data/README.md +48 -21
  8. data/Rakefile +1 -1
  9. data/lib/netsuite/configuration.rb +21 -4
  10. data/lib/netsuite/records/accounting_period.rb +2 -2
  11. data/lib/netsuite/records/assembly_unbuild.rb +1 -3
  12. data/lib/netsuite/records/classification.rb +4 -1
  13. data/lib/netsuite/records/contact.rb +1 -1
  14. data/lib/netsuite/records/cost_category.rb +28 -0
  15. data/lib/netsuite/records/credit_memo.rb +1 -1
  16. data/lib/netsuite/records/currency_rate.rb +1 -1
  17. data/lib/netsuite/records/custom_field_list.rb +9 -3
  18. data/lib/netsuite/records/custom_record.rb +1 -1
  19. data/lib/netsuite/records/customer.rb +2 -1
  20. data/lib/netsuite/records/customer_credit_cards.rb +36 -0
  21. data/lib/netsuite/records/customer_credit_cards_list.rb +10 -0
  22. data/lib/netsuite/records/customer_deposit.rb +5 -5
  23. data/lib/netsuite/records/customer_payment.rb +6 -2
  24. data/lib/netsuite/records/customer_payment_credit.rb +17 -0
  25. data/lib/netsuite/records/customer_payment_credit_list.rb +12 -0
  26. data/lib/netsuite/records/employee.rb +1 -1
  27. data/lib/netsuite/records/estimate.rb +42 -0
  28. data/lib/netsuite/records/estimate_item.rb +40 -0
  29. data/lib/netsuite/records/estimate_item_list.rb +11 -0
  30. data/lib/netsuite/records/inventory_item.rb +62 -1
  31. data/lib/netsuite/records/invoice.rb +97 -4
  32. data/lib/netsuite/records/invoice_item.rb +1 -1
  33. data/lib/netsuite/records/item_fulfillment.rb +1 -1
  34. data/lib/netsuite/records/item_fulfillment_item.rb +1 -1
  35. data/lib/netsuite/records/item_receipt_item.rb +1 -1
  36. data/lib/netsuite/records/member_list.rb +0 -2
  37. data/lib/netsuite/records/non_inventory_purchase_item.rb +1 -1
  38. data/lib/netsuite/records/non_inventory_resale_item.rb +2 -1
  39. data/lib/netsuite/records/non_inventory_sale_item.rb +1 -1
  40. data/lib/netsuite/records/opportunity.rb +2 -2
  41. data/lib/netsuite/records/partner.rb +7 -5
  42. data/lib/netsuite/records/phone_call.rb +1 -1
  43. data/lib/netsuite/records/serialized_assembly_item.rb +3 -2
  44. data/lib/netsuite/records/service_resale_item.rb +2 -2
  45. data/lib/netsuite/records/service_sale_item.rb +1 -1
  46. data/lib/netsuite/records/transfer_order_item.rb +1 -1
  47. data/lib/netsuite/records/vendor.rb +6 -5
  48. data/lib/netsuite/records/vendor_currency.rb +26 -0
  49. data/lib/netsuite/records/vendor_currency_list.rb +9 -0
  50. data/lib/netsuite/support/fields.rb +17 -0
  51. data/lib/netsuite/support/records.rb +1 -1
  52. data/lib/netsuite/support/search_result.rb +23 -4
  53. data/lib/netsuite/utilities.rb +2 -1
  54. data/lib/netsuite/version.rb +1 -1
  55. data/lib/netsuite.rb +10 -0
  56. data/netsuite.gemspec +5 -3
  57. data/spec/netsuite/actions/search_spec.rb +22 -0
  58. data/spec/netsuite/configuration_spec.rb +93 -6
  59. data/spec/netsuite/records/basic_record_spec.rb +8 -1
  60. data/spec/netsuite/records/classification_spec.rb +10 -1
  61. data/spec/netsuite/records/cost_category_spec.rb +105 -0
  62. data/spec/netsuite/records/custom_field_list_spec.rb +46 -6
  63. data/spec/netsuite/records/custom_record_spec.rb +1 -1
  64. data/spec/netsuite/records/customer_credit_cards_list_spec.rb +23 -0
  65. data/spec/netsuite/records/customer_payment_credit_list_spec.rb +26 -0
  66. data/spec/netsuite/records/customer_payment_spec.rb +1 -6
  67. data/spec/netsuite/records/customer_spec.rb +22 -1
  68. data/spec/netsuite/records/employee_spec.rb +2 -2
  69. data/spec/netsuite/records/estimate_item_list_spec.rb +26 -0
  70. data/spec/netsuite/records/estimate_item_spec.rb +40 -0
  71. data/spec/netsuite/records/estimate_spec.rb +216 -0
  72. data/spec/netsuite/records/inventory_item_spec.rb +65 -0
  73. data/spec/netsuite/records/invoice_spec.rb +94 -0
  74. data/spec/netsuite/records/non_inventory_resale_item_spec.rb +165 -0
  75. data/spec/netsuite/records/partner_spec.rb +143 -0
  76. data/spec/netsuite/records/service_resale_item_spec.rb +134 -0
  77. data/spec/netsuite/records/vendor_spec.rb +1 -1
  78. data/spec/netsuite/support/fields_spec.rb +36 -1
  79. data/spec/support/fixtures/custom_fields/multi_select.xml +47 -0
  80. data/spec/support/fixtures/search/saved_search_item.xml +55 -0
  81. data/spec/support/fixtures/search/saved_search_joined_custom_customer.xml +15 -1
  82. data/spec/support/search_only_field_matcher.rb +7 -0
  83. metadata +68 -12
  84. data/circle.yml +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 89b1dc6dad276f5db8f657634a3d125643ca198b
4
- data.tar.gz: 586f0a9f83e7b1919a637a34f2d8fce536b8f2b4
2
+ SHA256:
3
+ metadata.gz: 322dc4e1ca618901cbe11d81ed9d22351557188e4c64db465e433d9a26079e19
4
+ data.tar.gz: dd9aebc4902c3fbb61ad2df4feb2d0ea634606e6778bf2981b2722803596af99
5
5
  SHA512:
6
- metadata.gz: 76be28871d569715347328833f9521f8178879f17b93bb940fc10b9c960ef70652110ee85c4a277d02c6c21128f52c7cd762913331edcdacdc1463c853b81c7a
7
- data.tar.gz: a9b49255201b452651df24646fc4d96e96b6d90b1b723a4170eb7f3fc276ea2f9281c609c440702be11e732f1a6e9145cfa67fdcb8537fca3c8f48d94d4057bb
6
+ metadata.gz: 0b9f90448959b2ee6abf9d93480700bf15cca9758d2e9632ac3e755edc09eec033a2248f9ee40bfbd21dfb8b992c4bd53bc1af3d7bb322aa9e8428a6ca055553
7
+ data.tar.gz: 15666ea4627c96749dfa5bc9f664466f78aeeaf54d0f9bf95c21d568e4e5f429b44edc2bad5b4336507c068aa1657cd4cabbe8d13a54360b4722611122d585e1
@@ -0,0 +1,20 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ ruby-version: [2.7, 2.6, 2.5, 2.4, 2.3, 2.2, 2.1]
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ - name: Set up Ruby ${{ matrix.ruby-version }}
14
+ uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: ${{ matrix.ruby-version }}
17
+ - name: Install dependencies
18
+ run: bundle install
19
+ - name: Run tests
20
+ run: bundle exec rake
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.0
1
+ 2.7.3
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 2.7.3
data/Gemfile CHANGED
@@ -8,8 +8,4 @@ gem 'pry-rescue'
8
8
 
9
9
  # optional dependency for more accurate timezone conversion
10
10
  gem 'tzinfo', '1.2.5'
11
- # gem 'tzinfo', '2.0.0'
12
-
13
- # required for CircleCI to build properly with ruby 1.9.3
14
- gem 'json', '~> 1.8.3'
15
- gem 'rack', '~> 1.6.4'
11
+ # gem 'tzinfo', '2.0.0'
data/HISTORY.md ADDED
@@ -0,0 +1,32 @@
1
+ ## Unreleased
2
+
3
+ ### Added
4
+
5
+ *
6
+ *
7
+
8
+ ### Fixed
9
+
10
+ *
11
+ *
12
+
13
+ ## 0.8.9
14
+
15
+ ### Fixed
16
+
17
+ * Fixed issue where search only fields could be specified when an existing field exists. https://github.com/NetSweet/netsuite/pull/488
18
+
19
+ ## 0.8.8
20
+
21
+ ### Added
22
+
23
+ * Adding serialized assembly item to get_item
24
+ * Add CostCategory record (#482)
25
+ * Introduce search only fields (#483)
26
+
27
+ ### Fixed
28
+
29
+ * Fix accessing custom field values returned in advanced search results (#480)
30
+ * Fixing bug where single-selection custom multi select fields would incorrectly be parsed 3377c971d0cb727d81f4b4bc6e30edfbdfaccfd1
31
+ * Fixed some field definitions on serialized assembly item
32
+ * Properly extract external_id from advanced search results (#478)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
2
2
  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
3
- **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
3
+ **Table of Contents**
4
4
 
5
5
  - [NetSuite SuiteTalk API Ruby Gem](#netsuite-suitetalk-api-ruby-gem)
6
6
  - [Help & Support](#help--support)
@@ -13,35 +13,33 @@
13
13
  - [Custom Records & Fields](#custom-records--fields)
14
14
  - [Searching](#searching)
15
15
  - [Non-standard Operations](#non-standard-operations)
16
- - [About SuiteSync](#about-suitesync)
17
16
 
18
17
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
19
18
 
20
- [![Circle CI](https://circleci.com/gh/NetSweet/netsuite/tree/master.svg?style=svg)](https://circleci.com/gh/NetSweet/netsuite/tree/master)
19
+ [![Ruby](https://github.com/NetSweet/netsuite/actions/workflows/main.yml/badge.svg)](https://github.com/NetSweet/netsuite/actions/workflows/main.yml)
21
20
  [![Slack Status](https://opensuite-slackin.herokuapp.com/badge.svg)](http://opensuite-slackin.herokuapp.com)
22
21
  [![Gem Version](https://badge.fury.io/rb/netsuite.svg)](http://badge.fury.io/rb/netsuite)
23
22
 
24
23
  # NetSuite SuiteTalk API Ruby Gem
25
24
 
26
25
  * This gem will act as a wrapper around the NetSuite SuiteTalk WebServices API.
27
- * The gem does not cover the entire API, only the subset contributors have used so far.
28
- * NetSuite is a complex system. There's a lot to learn and sparse resources available to learn from. Here's a list of [NetSuite Development Resources](https://github.com/NetSweet/netsuite/wiki/NetSuite-Development-Resources) that might make things a bit less painful.
26
+ * The gem does not cover the entire API, only the subset contributors have used so far. Please submit a PR for any functionality that's missing!
27
+ * NetSuite is a complex system. There's a lot to learn and sparse resources available to learn from. Here's a list of [NetSuite Development Resources](https://github.com/NetSweet/netsuite/wiki/NetSuite-Development-Resources).
29
28
 
30
29
  # Help & Support
31
30
 
32
31
  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.
33
32
 
34
- Messages in the Slack ground are [archived here](https://suitechat.slackarchive.io). Search the archives to see if your question has been answered before.
35
-
36
33
  There is some additional helpful resources for NetSuite development [listed here](https://dashboard.suitesync.io/docs/resources#netsuite).
37
34
 
38
35
  # Testing
39
36
 
40
37
  Before contributing a patch make sure all existing tests pass.
41
38
 
42
- ```
39
+ ```shell
43
40
  git clone git://github.com/NetSweet/netsuite.git
44
41
  cd netsuite
42
+
45
43
  bundle
46
44
  bundle exec rspec
47
45
  ```
@@ -56,28 +54,44 @@ gem 'netsuite'
56
54
 
57
55
  If you'd like more accurate time conversion support, include the `tzinfo` gem.
58
56
 
59
- This gem is built for ruby 1.9.x+, checkout the [1-8-stable](https://github.com/NetSweet/netsuite/tree/1-8-stable) branch for ruby 1.8.x support.
57
+ This gem is built for ruby 2.6.x+, but should work on older versions down to 1.9. There's a [1-8-stable](https://github.com/NetSweet/netsuite/tree/1-8-stable) branch for ruby 1.8.x support.
60
58
 
61
59
  ## Configuration
62
60
 
63
61
  The most important thing you'll need is your NetSuite account ID. Not sure how to find your account id? [Here's a guide.](http://mikebian.co/find-netsuite-web-services-account-number/)
64
62
 
65
- For most use-cases, the following configuration will be sufficient:
63
+ How you connect to NetSuite has changed a lot over the years and differs between API versions. For instance:
64
+
65
+ * Older API versions (~2015) allowed authentication via username and password
66
+ * Newever API versions (> 2016) still allowed for username and password authentication, but required an application ID
67
+ * "OAuth", which requires four separate keys to be manually generated, was supported sometime after 2015
68
+ * API versions greater than 2018_2 require `endpoint` to be set directly ([more info](https://github.com/NetSweet/netsuite/pull/473))
69
+
70
+ Here's an example connection configuration. You don't want to actually use username + password config; token based authentication is detailed below in a separate section:
66
71
 
67
72
  ```ruby
68
73
  NetSuite.configure do
69
74
  reset!
70
75
 
76
+ # production & sandbox account numbers will differ
71
77
  account 'TSTDRV1576318'
72
78
  api_version '2018_2'
73
79
 
80
+ # password-based login information
81
+ # in most cases you should use token based authentication instead
74
82
  email 'email@example.com'
75
83
  password 'password'
76
84
  role 10
77
85
 
78
- # use `NetSuite::Utilities.netsuite_data_center_urls('TSTDRV1576318')` to retrieve the URL
79
- # you'll want to do this in a background proces and strip the protocol out of the return string
86
+ # recent API versions require a account-specific endpoint o be set
87
+ # use `NetSuite::Utilities.data_center_url('TSTDRV1576318')` to retrieve wsdl URL
88
+ # you'll want to do this in a background process and strip the protocol out of the return string
80
89
  wsdl_domain 'tstdrv1576318.suitetalk.api.netsuite.com'
90
+
91
+ # the endpoint indicated in the > 2018_2 wsdl is invalid
92
+ # you must set the endpoint directly
93
+ # https://github.com/NetSweet/netsuite/pull/473
94
+ endpoint "https://#{wsdl_domain}/services/NetSuitePort_#{api_version}"
81
95
  end
82
96
  ```
83
97
 
@@ -106,9 +120,16 @@ NetSuite.configure do
106
120
  read_timeout 100_000
107
121
 
108
122
  # you can specify a file or file descriptor to send the log output to (defaults to STDOUT)
123
+ # If using within a Rails app, consider setting to `Rails.logger` to leverage existing
124
+ # application-level log configuration
109
125
  log File.join(Rails.root, 'log/netsuite.log')
110
126
 
127
+ # Defaults to :debug level logging for Savon API calls. Decrease the verbosity
128
+ # by setting log_level to `:info`, for example
129
+ # log_level :debug
130
+
111
131
  # password-based login information
132
+ # in most cases you should use token based authentication instead
112
133
  email 'email@domain.com'
113
134
  password 'password'
114
135
  account '12345'
@@ -121,9 +142,9 @@ NetSuite.configure do
121
142
  end
122
143
  ```
123
144
 
124
- If you'd like to use a API endpoints greater than 2015_1 you'll need to specify an application ID:
145
+ If are using username + password authentication (which you shouldn't be!) *and* you'd like to use a API endpoints greater than 2015_1 you'll need to specify an application ID:
125
146
 
126
- ```
147
+ ```ruby
127
148
  NetSuite::Configuration.soap_header = {
128
149
  'platformMsgs:ApplicationInfo' => {
129
150
  'platformMsgs:applicationId' => 'your-netsuite-app-id'
@@ -133,7 +154,7 @@ NetSuite::Configuration.soap_header = {
133
154
 
134
155
  ### Token based Authentication
135
156
 
136
- OAuth credentials are also supported. [Learn more about how to set up token based authentication here](http://mikebian.co/using-netsuites-token-based-authentication-with-suitetalk/).
157
+ OAuth credentials are supported and the recommended authentication approach. [Learn more about how to set up token based authentication here](http://mikebian.co/using-netsuites-token-based-authentication-with-suitetalk/).
137
158
 
138
159
  ```ruby
139
160
  NetSuite.configure do
@@ -148,6 +169,11 @@ NetSuite.configure do
148
169
 
149
170
  # oauth does not work with API versions less than 2015_2
150
171
  api_version '2016_2'
172
+
173
+ # the endpoint indicated in the > 2018_2 wsdl is invalid
174
+ # you must set the endpoint directly
175
+ # https://github.com/NetSweet/netsuite/pull/473
176
+ endpoint "https://#{wsdl_domain}/services/NetSuitePort_#{api_version}"
151
177
  end
152
178
  ```
153
179
 
@@ -395,7 +421,10 @@ NetSuite::Records::SalesOrder.search({
395
421
  'tranSales:basic' => [
396
422
  'platformCommon:internalId/' => {},
397
423
  'platformCommon:email/' => {},
398
- 'platformCommon:tranDate/' => {}
424
+ 'platformCommon:tranDate/' => {},
425
+ # If you include columns that are only part of the *SearchRowBasic (ie. TransactionSearchRowBasic),
426
+ # they'll be readable on the resulting record just like regular fields (my_record.close_date).
427
+ 'platformCommon:closeDate/' => {}
399
428
  ],
400
429
  'tranSales:accountJoin' => [
401
430
  'platformCommon:internalId/' => {}
@@ -409,7 +438,9 @@ NetSuite::Records::SalesOrder.search({
409
438
  'tranSales:itemJoin' => [
410
439
  'platformCommon:customFieldList' => [
411
440
  'platformCore:customField/' => {
412
- '@internalId' => 'custitem_apcategoryforsales',
441
+ '@scriptId' => 'custitem_apcategoryforsales',
442
+ # Or, for API versions 2013.1 and older:
443
+ # '@internalId' => 'custitem_apcategoryforsales',
413
444
  '@xsi:type' => "platformCore:SearchColumnSelectCustomField"
414
445
  }
415
446
  ]
@@ -587,7 +618,3 @@ states = NetSuite::Configuration.connection.call(:get_all, message: {
587
618
  })
588
619
  states.to_array.first[:get_all_response][:get_all_result][:record_list][:record].map { |r| { country: r[:country], abbr: r[:shortname], name: r[:full_name] } }
589
620
  ```
590
-
591
- # About SuiteSync
592
-
593
- [SuiteSync, the Stripe-NetSuite integration](http://suitesync.io) uses this gem and funds the majority of it's development and maintenance.
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ task :default => :spec
7
7
 
8
8
  desc 'Run specs'
9
9
  RSpec::Core::RakeTask.new do |t|
10
- t.pattern = './spec/**/*_spec.rb'
10
+ # t.pattern = './spec/**/*_spec.rb'
11
11
  end
12
12
 
13
13
  desc 'Generate code coverage'
@@ -17,6 +17,7 @@ module NetSuite
17
17
  def connection(params={}, credentials={})
18
18
  client = Savon.client({
19
19
  wsdl: cached_wsdl || wsdl,
20
+ endpoint: endpoint,
20
21
  read_timeout: read_timeout,
21
22
  open_timeout: open_timeout,
22
23
  namespaces: namespaces,
@@ -94,6 +95,18 @@ module NetSuite
94
95
  attributes[:api_version] = version
95
96
  end
96
97
 
98
+ def endpoint=(endpoint)
99
+ attributes[:endpoint] = endpoint
100
+ end
101
+
102
+ def endpoint(endpoint=nil)
103
+ if endpoint
104
+ self.endpoint = endpoint
105
+ else
106
+ attributes[:endpoint]
107
+ end
108
+ end
109
+
97
110
  def sandbox=(flag)
98
111
  if attributes[:sandbox] != flag
99
112
  attributes[:wsdl] = nil
@@ -350,7 +363,10 @@ module NetSuite
350
363
 
351
364
  def logger(value = nil)
352
365
  if value.nil?
353
- attributes[:logger] ||= ::Logger.new((log && !log.empty?) ? log : $stdout)
366
+ # if passed a IO object (like StringIO) `empty?` won't exist
367
+ valid_log = log && !(log.respond_to?(:empty?) && log.empty?)
368
+
369
+ attributes[:logger] ||= ::Logger.new(valid_log ? log : $stdout)
354
370
  else
355
371
  attributes[:logger] = value
356
372
  end
@@ -370,12 +386,13 @@ module NetSuite
370
386
  end
371
387
 
372
388
  def log_level(value = nil)
373
- self.log_level = value || :debug
374
- attributes[:log_level]
389
+ self.log_level = value if value
390
+
391
+ attributes[:log_level] || :debug
375
392
  end
376
393
 
377
394
  def log_level=(value)
378
- attributes[:log_level] ||= value
395
+ attributes[:log_level] = value
379
396
  end
380
397
  end
381
398
  end
@@ -8,12 +8,12 @@ module NetSuite
8
8
 
9
9
  actions :get, :get_list, :add, :delete, :upsert, :search
10
10
 
11
- fields :allow_non_gl_changes, :end_date, :is_adjust, :is_quarter, :is_year, :period_name, :start_date
11
+ fields :allow_non_gl_changes, :end_date, :is_adjust, :is_quarter, :is_year, :period_name, :start_date, :closed
12
12
 
13
13
  record_refs :parent
14
14
 
15
15
  attr_reader :internal_id
16
- attr_accessor :external_id
16
+ attr_accessor :external_id, :search_joins
17
17
 
18
18
  def initialize(attributes = {})
19
19
  @internal_id = attributes.delete(:internal_id) || attributes.delete(:@internal_id)
@@ -12,7 +12,7 @@ module NetSuite
12
12
  :search
13
13
 
14
14
  fields :bin_numbers, :built, :created_date, :expiration_date,
15
- :last_modified_date, :memo, :quantity, :serial_numbers, :total,
15
+ :last_modified_date, :memo, :quantity, :serial_numbers,
16
16
  :tran_date, :tran_id
17
17
 
18
18
  read_only_fields :total
@@ -36,5 +36,3 @@ module NetSuite
36
36
  end
37
37
  end
38
38
  end
39
-
40
-
@@ -9,9 +9,12 @@ module NetSuite
9
9
 
10
10
  actions :add, :get, :get_list, :delete, :upsert, :search
11
11
 
12
- fields :name, :include_children, :is_inactive, :class_translation_list, :custom_field_list, :parent
12
+ fields :name, :include_children, :is_inactive, :class_translation_list
13
13
 
14
14
  field :subsidiary_list, RecordRefList
15
+ field :custom_field_list, CustomFieldList
16
+
17
+ record_refs :parent
15
18
 
16
19
  attr_reader :internal_id
17
20
  attr_accessor :external_id
@@ -7,7 +7,7 @@ module NetSuite
7
7
  include Support::Actions
8
8
  include Namespaces::ListRel
9
9
 
10
- actions :get, :get_list, :add, :delete, :delete_list, :search, :update, :upsert
10
+ actions :get, :get_deleted, :get_list, :add, :delete, :delete_list, :search, :update, :upsert, :upsert_list
11
11
 
12
12
  fields :salutation, :first_name, :middle_name, :last_name, :title, :phone, :fax, :email, :default_address,
13
13
  :entity_id, :phonetic_name, :alt_email, :office_phone, :home_phone, :mobile_phone, :supervisor_phone,
@@ -0,0 +1,28 @@
1
+ module NetSuite
2
+ module Records
3
+ class CostCategory
4
+ include Support::Fields
5
+ include Support::RecordRefs
6
+ include Support::Records
7
+ include Support::Actions
8
+ include Namespaces::ListAcct
9
+
10
+ actions :add, :delete, :delete_list, :get, :get_all, :get_list, :get_select_value, :search, :update, :update_list, :upsert, :upsert_list
11
+ # TODO: Add add_list when supported by gem
12
+
13
+ fields :is_inactive, :item_cost_type, :name
14
+
15
+ record_refs :account
16
+
17
+ attr_reader :internal_id
18
+ attr_accessor :external_id
19
+
20
+ def initialize(attributes = {})
21
+ @internal_id = attributes.delete(:internal_id) || attributes.delete(:@internal_id)
22
+ @external_id = attributes.delete(:external_id) || attributes.delete(:@external_id)
23
+ initialize_from_attributes_hash(attributes)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -17,7 +17,7 @@ module NetSuite
17
17
  :sales_effective_date, :shipping_cost, :shipping_tax1_rate, :shipping_tax2_rate, :source, :status,
18
18
  :sync_partner_teams, :sync_sales_teams, :tax2_total, :tax_rate, :to_be_emailed, :to_be_faxed,
19
19
  :to_be_printed, :total_cost_estimate, :tran_date, :tran_id, :tran_is_vsoe_bundle, :vat_reg_num,
20
- :vsoe_auto_calc
20
+ :vsoe_auto_calc, :tax_details_override, :tax_reg_override
21
21
 
22
22
  field :custom_field_list, CustomFieldList
23
23
  field :item_list, CreditMemoItemList
@@ -12,7 +12,7 @@ module NetSuite
12
12
 
13
13
  actions :get, :get_list, :search
14
14
 
15
- fields :base_currency, :effective_date, :exchange_rate, :transaction_currency
15
+ fields :effective_date, :exchange_rate
16
16
 
17
17
  record_refs :base_currency, :transaction_currency
18
18
 
@@ -110,10 +110,16 @@ module NetSuite
110
110
  attrs = custom_field_data.clone
111
111
  type = (custom_field_data[:"@xsi:type"] || custom_field_data[:type])
112
112
 
113
- if type == "platformCore:SelectCustomFieldRef"
113
+ case type
114
+ when "platformCore:SelectCustomFieldRef", "platformCore:SearchColumnSelectCustomField"
114
115
  attrs[:value] = CustomRecordRef.new(custom_field_data[:value])
115
- elsif type == 'platformCore:MultiSelectCustomFieldRef'
116
- attrs[:value] = custom_field_data[:value].map do |entry|
116
+ when 'platformCore:MultiSelectCustomFieldRef', 'platformCore:SearchColumnMultiSelectCustomField'
117
+ # if there is only a single selection, `:value` will be hash not an array
118
+ attrs[:value] = if custom_field_data[:value].is_a?(Array)
119
+ custom_field_data[:value]
120
+ else
121
+ [custom_field_data[:value]]
122
+ end.map do |entry|
117
123
  CustomRecordRef.new(entry)
118
124
  end
119
125
  end