netsuite 0.7.6 → 0.7.7

Sign up to get free protection for your applications and to get access to all the features.
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