netsuite 0.7.6 → 0.7.7

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.
data/circle.yml CHANGED
@@ -0,0 +1,16 @@
1
+ # https://leonid.shevtsov.me/post/multiple-rubies-on-circleci/
2
+
3
+ machine:
4
+ environment:
5
+ RUBY_VERSIONS: 2.0.0,2.1.10,2.2.5,2.3.1,2.4.0
6
+
7
+ dependencies:
8
+ override:
9
+ - rvm get head
10
+ - rvm install $RUBY_VERSIONS
11
+ - rvm $RUBY_VERSIONS --verbose do gem install bundler
12
+ - rvm $RUBY_VERSIONS --verbose do bundle install
13
+
14
+ test:
15
+ override:
16
+ - rvm $RUBY_VERSIONS --verbose do bundle exec rspec spec
@@ -10,7 +10,7 @@ module NetSuite
10
10
  actions :get, :get_list, :add, :update, :delete, :search, :upsert
11
11
 
12
12
  fields :acct_name, :acct_number, :acct_type, :cash_flow_rate, :cur_doc_num, :description, :eliminate, :exchange_rate,
13
- :general_rate, :include_children, :inventory, :is_inactive, :opening_balance, :revalue, :tran_date
13
+ :general_rate, :include_children, :inventory, :is_inactive, :opening_balance, :revalue, :tran_date, :balance
14
14
 
15
15
  record_refs :billable_expenses_acct, :category1099misc, :currency, :deferral_acct, :department, :klass, :location, :parent
16
16
 
@@ -18,6 +18,7 @@ module NetSuite
18
18
 
19
19
  attr_reader :internal_id
20
20
  attr_accessor :external_id
21
+ attr_accessor :search_joins
21
22
 
22
23
  def initialize(attributes = {})
23
24
  @internal_id = attributes.delete(:internal_id) || attributes.delete(:@internal_id)
@@ -10,8 +10,7 @@ module NetSuite
10
10
  include Support::Records
11
11
  include Namespaces::TranCust
12
12
 
13
-
14
- actions :get, :get_list, :initialize, :add, :delete, :update, :upsert
13
+ actions :get, :get_list, :initialize, :add, :delete, :update, :upsert, :search
15
14
 
16
15
  fields :created_date, :last_modified_date, :status, :payment, :tran_date, :exchange_rate, :undep_funds, :memo,
17
16
  :check_num, :klass, :currency_name, :is_recurring_payment, :charge_it
@@ -29,6 +28,14 @@ module NetSuite
29
28
  @external_id = attributes.delete(:external_id) || attributes.delete(:@external_id)
30
29
  initialize_from_attributes_hash(attributes)
31
30
  end
31
+
32
+ def self.search_class_name
33
+ "Transaction"
34
+ end
35
+
36
+ def self.search_class_namespace
37
+ 'tranSales'
38
+ end
32
39
  end
33
40
  end
34
41
  end
@@ -26,7 +26,7 @@ module NetSuite
26
26
  record_refs :billing_schedule, :cost_category, :custom_form, :deferred_revenue_account, :department, :income_account,
27
27
  :issue_product, :item_options_list, :klass, :location, :parent, :pricing_group, :purchase_tax_code,
28
28
  :quantity_pricing_schedule, :rev_rec_schedule, :sale_unit, :sales_tax_code, :store_display_image,
29
- :store_display_thumbnail, :store_item_template, :tax_schedule, :units_type, :subsidiary
29
+ :store_display_thumbnail, :store_item_template, :tax_schedule, :units_type
30
30
 
31
31
  field :pricing_matrix, PricingMatrix
32
32
  field :custom_field_list, CustomFieldList
@@ -33,21 +33,64 @@ module NetSuite
33
33
  end
34
34
 
35
35
  def backoff(options = {})
36
+ # TODO the default backoff attempts should be customizable the global config
37
+ options[:attempts] ||= 8
38
+
36
39
  count = 0
40
+
37
41
  begin
38
42
  count += 1
39
43
  yield
40
- rescue options[:exception] || Savon::SOAPFault => e
41
- if !e.message.include?("Only one request may be made against a session at a time") &&
42
- !e.message.include?('java.util.ConcurrentModificationException') &&
43
- !e.message.include?('SuiteTalk concurrent request limit exceeded. Request blocked.')
44
- raise e
44
+ rescue Exception => e
45
+ exceptions_to_retry = [
46
+ Errno::ECONNRESET,
47
+ Errno::ETIMEDOUT,
48
+ Errno::EHOSTUNREACH,
49
+ EOFError,
50
+ Wasabi::Resolver::HTTPError,
51
+ Savon::SOAPFault,
52
+ Savon::InvalidResponseError,
53
+ Zlib::BufError,
54
+ Savon::HTTPError
55
+ ]
56
+
57
+ # available in ruby > 1.9
58
+ if defined?(Net::ReadTimeout)
59
+ exceptions_to_retry << Net::ReadTimeout
60
+ end
61
+
62
+ # available in ruby > 2.2.0
63
+ if defined?(OpenSSL::SSL::SSLErrorWaitReadable)
64
+ exceptions_to_retry << OpenSSL::SSL::SSLErrorWaitReadable
65
+ end
66
+
67
+ if !exceptions_to_retry.include?(e.class)
68
+ raise
69
+ end
70
+
71
+ # whitelist certain SOAPFaults; all other network errors should automatically retry
72
+ if e.is_a?(Savon::SOAPFault)
73
+ # https://github.com/stripe/stripe-netsuite/issues/815
74
+ if !e.message.include?("Only one request may be made against a session at a time") &&
75
+ !e.message.include?('java.util.ConcurrentModificationException') &&
76
+ !e.message.include?('com.netledger.common.exceptions.NLDatabaseOfflineException') &&
77
+ !e.message.include?('An unexpected error occurred.') &&
78
+ !e.message.include?('Session invalidation is in progress with different thread') &&
79
+ !e.message.include?('SuiteTalk concurrent request limit exceeded. Request blocked.') &&
80
+ !e.message.include?('The Connection Pool is not intialized.') &&
81
+ # it looks like NetSuite mispelled their error message...
82
+ !e.message.include?('The Connection Pool is not intiialized.')
83
+ raise
84
+ end
45
85
  end
46
- if count >= (options[:attempts] || 8)
47
- raise e
86
+
87
+ if count >= options[:attempts]
88
+ raise
48
89
  end
90
+
49
91
  # log.warn("concurrent request failure", sleep: count, attempt: count)
50
92
  sleep(count)
93
+
51
94
  retry
52
95
  end
53
96
  end
@@ -92,8 +135,8 @@ module NetSuite
92
135
  @netsuite_get_record_cache ||= {}
93
136
  @netsuite_get_record_cache[record_klass.to_s] ||= {}
94
137
 
95
- if cached_record = @netsuite_get_record_cache[record_klass.to_s][id.to_i]
96
- return cached_record
138
+ if @netsuite_get_record_cache[record_klass.to_s].has_key?(id.to_i)
139
+ return @netsuite_get_record_cache[record_klass.to_s][id.to_i]
97
140
  end
98
141
  end
99
142
 
@@ -113,6 +156,10 @@ module NetSuite
113
156
  return ns_record
114
157
  rescue ::NetSuite::RecordNotFound
115
158
  # log.warn("record not found", ns_record_type: record_klass.name, ns_record_id: id)
159
+ if opts[:cache]
160
+ @netsuite_get_record_cache[record_klass.to_s][id.to_i] = nil
161
+ end
162
+
116
163
  return nil
117
164
  end
118
165
  end
@@ -1,3 +1,3 @@
1
1
  module Netsuite
2
- VERSION = '0.7.6'
2
+ VERSION = '0.7.7'
3
3
  end
@@ -2,17 +2,36 @@ require 'spec_helper'
2
2
 
3
3
  describe NetSuite::Utilities do
4
4
  describe '#get_record' do
5
- it 'does not hit the netsuite API when caching is enabled' do
6
- ns_account_id = 123
7
- allow(NetSuite::Records::Account).to receive(:get).with(ns_account_id).once.and_return(
8
- NetSuite::Records::Account.new(internal_id: ns_account_id)
9
- )
5
+ context 'caching' do
6
+ it 'does not hit the netsuite API' do
7
+ ns_account_id = 123
8
+ allow(NetSuite::Records::Account).to receive(:get).with(ns_account_id).once.and_return(
9
+ NetSuite::Records::Account.new(internal_id: ns_account_id)
10
+ )
10
11
 
11
- ns_account = NetSuite::Utilities.get_record(NetSuite::Records::Account, ns_account_id, cache: true)
12
- expect(ns_account.internal_id).to eq(ns_account_id)
12
+ ns_account = NetSuite::Utilities.get_record(NetSuite::Records::Account, ns_account_id, cache: true)
13
+ expect(ns_account.internal_id).to eq(ns_account_id)
13
14
 
14
- ns_account = NetSuite::Utilities.get_record(NetSuite::Records::Account, ns_account_id, cache: true)
15
- expect(ns_account.internal_id).to eq(ns_account_id)
15
+ ns_account = NetSuite::Utilities.get_record(NetSuite::Records::Account, ns_account_id, cache: true)
16
+ expect(ns_account.internal_id).to eq(ns_account_id)
17
+ end
18
+
19
+ it 'works on missing records' do
20
+ ns_account_id = 123
21
+ allow(NetSuite::Records::Account).to receive(:get).with(ns_account_id) do
22
+ raise NetSuite::RecordNotFound
23
+ end
24
+
25
+ 20.times do
26
+ expect(
27
+ NetSuite::Utilities.get_record(
28
+ NetSuite::Records::Account, ns_account_id, cache: true
29
+ )
30
+ ).to eq nil
31
+ end
32
+
33
+ expect(NetSuite::Records::Account).to have_received(:get).exactly(1).times
34
+ end
16
35
  end
17
36
 
18
37
  it 'pulls a record by internal id' 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.7.6
4
+ version: 0.7.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-01-01 00:00:00.000000000 Z
13
+ date: 2017-02-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: savon