netsuite 0.5.8 → 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby-version +1 -0
- data/README.md +52 -12
- data/lib/netsuite/records/address.rb +2 -1
- data/lib/netsuite/records/cash_refund_item.rb +11 -2
- data/lib/netsuite/records/customer_deposit.rb +3 -2
- data/lib/netsuite/records/item_fulfillment.rb +6 -1
- data/lib/netsuite/records/sales_order_item.rb +1 -1
- data/lib/netsuite/utilities.rb +116 -2
- data/lib/netsuite/version.rb +1 -1
- data/spec/netsuite/records/address_spec.rb +1 -1
- metadata +20 -13
- checksums.yaml +0 -7
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p550
|
data/README.md
CHANGED
@@ -178,13 +178,16 @@ search = NetSuite::Records::Customer.search({
|
|
178
178
|
`open https://system.netsuite.com/app/common/entity/custjob.nl?id=#{search.results.first.internal_id}`
|
179
179
|
|
180
180
|
# searching for custom records
|
181
|
-
NetSuite::Records::CustomRecord.search(
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
181
|
+
NetSuite::Records::CustomRecord.search(
|
182
|
+
basic: [
|
183
|
+
{
|
184
|
+
field: 'recType',
|
185
|
+
operator: 'is',
|
186
|
+
# custom record type
|
187
|
+
value: NetSuite::Records::CustomRecordRef.new(:internal_id => 10),
|
188
|
+
}
|
189
|
+
]
|
190
|
+
).results
|
188
191
|
|
189
192
|
# advanced search building on saved search
|
190
193
|
NetSuite::Records::Customer.search({
|
@@ -216,11 +219,11 @@ NetSuite::Records::Customer.search({
|
|
216
219
|
NetSuite::Records::CustomRecordRef.new(:internal_id => 2),
|
217
220
|
]
|
218
221
|
},
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
222
|
+
{
|
223
|
+
field: 'custbody_internetorder',
|
224
|
+
type: 'SearchBooleanCustomField',
|
225
|
+
value: true
|
226
|
+
}
|
224
227
|
]
|
225
228
|
}
|
226
229
|
]
|
@@ -316,6 +319,43 @@ NetSuite::Records::Transaction.search({
|
|
316
319
|
}
|
317
320
|
}).results
|
318
321
|
|
322
|
+
NetSuite::Records::ItemFulfillment.search({
|
323
|
+
criteria: {
|
324
|
+
basic: [
|
325
|
+
{
|
326
|
+
field: 'type',
|
327
|
+
operator: 'anyOf',
|
328
|
+
type: 'SearchEnumMultiSelectField',
|
329
|
+
value: ["_itemFulfillment"]
|
330
|
+
},
|
331
|
+
{
|
332
|
+
field: 'lastModifiedDate',
|
333
|
+
type: 'SearchDateField',
|
334
|
+
operator: 'within',
|
335
|
+
value: [
|
336
|
+
DateTime.now - 2.hours,
|
337
|
+
DateTime.now
|
338
|
+
]
|
339
|
+
}
|
340
|
+
],
|
341
|
+
createdFromJoin: [
|
342
|
+
{
|
343
|
+
field: 'type',
|
344
|
+
operator: 'anyOf',
|
345
|
+
value: [ '_salesOrder' ]
|
346
|
+
},
|
347
|
+
{
|
348
|
+
field: 'internalIdNumber',
|
349
|
+
operator: 'notEmpty'
|
350
|
+
}
|
351
|
+
]
|
352
|
+
},
|
353
|
+
preferences: {
|
354
|
+
pageSize: 1000,
|
355
|
+
bodyFieldsOnly: false
|
356
|
+
}
|
357
|
+
}).results
|
358
|
+
|
319
359
|
# basic search with pagination / SearchMorewithId
|
320
360
|
search = NetSuite::Records::Customer.search(
|
321
361
|
criteria: {
|
@@ -8,9 +8,10 @@ module NetSuite
|
|
8
8
|
# internalId is a bit strange on this record
|
9
9
|
# https://github.com/NetSweet/netsuite/wiki/Miscellaneous-Web-Services-Quirks#customer
|
10
10
|
|
11
|
-
fields :addr1, :addr2, :addressee, :addr_phone, :attention, :city, :
|
11
|
+
fields :addr1, :addr2, :addr3, :addressee, :addr_phone, :attention, :city, :internal_id, :override, :state, :zip
|
12
12
|
|
13
13
|
field :country, NetSuite::Support::Country
|
14
|
+
field :custom_field_list, CustomFieldList
|
14
15
|
|
15
16
|
read_only_fields :addr_text
|
16
17
|
|
@@ -6,14 +6,23 @@ module NetSuite
|
|
6
6
|
include Support::Records
|
7
7
|
include Namespaces::TranCust
|
8
8
|
|
9
|
-
|
9
|
+
fields :amount, :rate, :quantity
|
10
|
+
field :custom_field_list, CustomFieldList
|
10
11
|
|
11
|
-
record_refs :item, :klass
|
12
|
+
record_refs :item, :klass, :price
|
12
13
|
|
13
14
|
def initialize(attributes_or_record = {})
|
14
15
|
initialize_from_attributes_hash(attributes_or_record)
|
15
16
|
end
|
16
17
|
|
18
|
+
def to_record
|
19
|
+
rec = super
|
20
|
+
if rec["#{record_namespace}:customFieldList"]
|
21
|
+
rec["#{record_namespace}:customFieldList!"] = rec.delete("#{record_namespace}:customFieldList")
|
22
|
+
end
|
23
|
+
rec
|
24
|
+
end
|
25
|
+
|
17
26
|
end
|
18
27
|
end
|
19
28
|
end
|
@@ -14,11 +14,12 @@ module NetSuite
|
|
14
14
|
actions :get, :get_list, :initialize, :add, :delete, :update, :upsert
|
15
15
|
|
16
16
|
fields :created_date, :last_modified_date, :status, :payment, :tran_date, :exchange_rate, :undep_funds, :memo,
|
17
|
-
:check_num, :klass, :currency_name, :is_recurring_payment
|
17
|
+
:check_num, :klass, :currency_name, :is_recurring_payment, :charge_it
|
18
18
|
|
19
19
|
field :custom_field_list, CustomFieldList
|
20
20
|
|
21
|
-
record_refs :customer, :sales_order, :account, :department, :payment_method,
|
21
|
+
record_refs :customer, :sales_order, :account, :department, :payment_method,
|
22
|
+
:custom_form, :currency, :posting_period, :subsidiary
|
22
23
|
|
23
24
|
attr_reader :internal_id
|
24
25
|
attr_accessor :external_id
|
@@ -15,10 +15,15 @@ module NetSuite
|
|
15
15
|
|
16
16
|
read_only_fields :handling_cost
|
17
17
|
|
18
|
-
record_refs :custom_form, :entity, :created_from, :ship_carrier, :ship_method,
|
18
|
+
record_refs :custom_form, :entity, :created_from, :ship_carrier, :ship_method,
|
19
19
|
:ship_address_list, :klass, :ship_country
|
20
20
|
|
21
|
+
# NOTE API version < 2015_1 only
|
21
22
|
field :transaction_ship_address, ShipAddress
|
23
|
+
|
24
|
+
# NOTE API version >= 2015_1
|
25
|
+
field :shipping_address, Address
|
26
|
+
|
22
27
|
field :item_list, ItemFulfillmentItemList
|
23
28
|
field :package_list, ItemFulfillmentPackageList
|
24
29
|
field :custom_field_list, CustomFieldList
|
@@ -13,7 +13,7 @@ module NetSuite
|
|
13
13
|
:gift_cert_message, :gift_cert_number, :gift_cert_recipient_email, :gift_cert_recipient_name, :gross_amt, :is_taxable,
|
14
14
|
:line, :order_line, :po_currency, :quantity, :rate, :rev_rec_end_date, :rev_rec_start_date, :rev_rec_term_in_months,
|
15
15
|
:serial_numbers, :shipping_cost, :tax1_amt, :tax_rate1, :tax_rate2, :vsoe_allocation, :vsoe_amount, :vsoe_deferral,
|
16
|
-
:vsoe_delivered, :vsoe_permit_discount, :vsoe_price, :is_closed
|
16
|
+
:vsoe_delivered, :vsoe_permit_discount, :vsoe_price, :is_closed, :quantity_commited, :quantity_fulfilled
|
17
17
|
|
18
18
|
field :custom_field_list, CustomFieldList
|
19
19
|
|
data/lib/netsuite/utilities.rb
CHANGED
@@ -1,5 +1,119 @@
|
|
1
1
|
module NetSuite
|
2
2
|
module Utilities
|
3
|
+
extend self
|
4
|
+
|
5
|
+
# TODO need structured logger for various statements
|
6
|
+
|
7
|
+
def backoff(options = {})
|
8
|
+
count = 0
|
9
|
+
begin
|
10
|
+
count += 1
|
11
|
+
yield
|
12
|
+
rescue options[:exception] || Savon::SOAPFault => e
|
13
|
+
if !e.message.include?("Only one request may be made against a session at a time")
|
14
|
+
raise e
|
15
|
+
end
|
16
|
+
if count >= (options[:attempts] || 8)
|
17
|
+
raise e
|
18
|
+
end
|
19
|
+
# log.warn("concurrent request failure", sleep: count, attempt: count)
|
20
|
+
sleep(count)
|
21
|
+
retry
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def request_failed?(ns_object)
|
26
|
+
return false if ns_object.errors.nil? || ns_object.errors.empty?
|
27
|
+
|
28
|
+
warnings = ns_object.errors.select { |x| x.type == "WARN" }
|
29
|
+
errors = ns_object.errors.select { |x| x.type == "ERROR" }
|
30
|
+
|
31
|
+
# warnings.each do |warn|
|
32
|
+
# log.warn(warn.message, code: warn.code)
|
33
|
+
# end
|
34
|
+
|
35
|
+
return errors.size > 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_record(record_klass, id, opts = {})
|
39
|
+
opts[:external_id] ||= false
|
40
|
+
|
41
|
+
begin
|
42
|
+
# log.debug("get record", netsuite_record_type: record_klass.name, netsuite_record_id: id)
|
43
|
+
|
44
|
+
if opts[:external_id]
|
45
|
+
return backoff { record_klass.get(external_id: id) }
|
46
|
+
else
|
47
|
+
return backoff { record_klass.get(id) }
|
48
|
+
end
|
49
|
+
rescue ::NetSuite::RecordNotFound
|
50
|
+
# log.warn("record not found", ns_record_type: record_klass.name, ns_record_id: id)
|
51
|
+
return nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_record(record, names, opts = {})
|
56
|
+
field_name = opts[:field_name]
|
57
|
+
|
58
|
+
names = [ names ] if names.is_a?(String)
|
59
|
+
|
60
|
+
# FIXME: Records that have the same name but different types will break
|
61
|
+
# the cache
|
62
|
+
names.each do |name|
|
63
|
+
@netsuite_find_record_cache ||= {}
|
64
|
+
|
65
|
+
if @netsuite_find_record_cache.has_key?(name)
|
66
|
+
return @netsuite_find_record_cache[name]
|
67
|
+
end
|
68
|
+
|
69
|
+
# sniff for an email-like input; useful for employee/customer searches
|
70
|
+
if !field_name && /@.*\./ =~ name
|
71
|
+
field_name = 'email'
|
72
|
+
end
|
73
|
+
|
74
|
+
field_name ||= 'name'
|
75
|
+
|
76
|
+
# TODO remove backoff when it's built-in to search
|
77
|
+
search = backoff { record.search({
|
78
|
+
basic: [
|
79
|
+
{
|
80
|
+
field: field_name,
|
81
|
+
operator: 'contains',
|
82
|
+
value: name,
|
83
|
+
}
|
84
|
+
]
|
85
|
+
}) }
|
86
|
+
|
87
|
+
if search.results.first
|
88
|
+
return @netsuite_find_record_cache[name] = search.results.first
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def data_center_url(netsuite_account)
|
96
|
+
begin
|
97
|
+
data_center_call_response = NetSuite::Configuration.connection({}, {
|
98
|
+
email: '',
|
99
|
+
password: '',
|
100
|
+
account: ''
|
101
|
+
}).call(:get_data_center_urls, message: {
|
102
|
+
'platformMsgs:account' => netsuite_account
|
103
|
+
})
|
104
|
+
|
105
|
+
if data_center_call_response.success?
|
106
|
+
return data_center_call_response.body[:get_data_center_urls_response][:get_data_center_urls_result][:data_center_urls][:webservices_domain]
|
107
|
+
else
|
108
|
+
# log.error "error getting data center url"
|
109
|
+
end
|
110
|
+
rescue Exception => e
|
111
|
+
# log.error "error determining correct datacenter for account #{netsuite_account}. #{e.message}"
|
112
|
+
|
113
|
+
# TODO silence this later: for now we need to investigate when this would occur
|
114
|
+
raise(e)
|
115
|
+
end
|
116
|
+
end
|
3
117
|
|
4
118
|
# Warning this was developed with a Web Services user whose time zone was set to CST
|
5
119
|
# the time zone setting of the user seems to effect how times work in NS
|
@@ -11,7 +125,7 @@ module NetSuite
|
|
11
125
|
# http://stackoverflow.com/questions/279769/convert-to-from-datetime-and-time-in-ruby
|
12
126
|
|
13
127
|
# use when sending times to NS
|
14
|
-
def
|
128
|
+
def normalize_datetime_to_netsuite(datetime)
|
15
129
|
# normalize the time to UCT0
|
16
130
|
# add 6 hours (21600 seconds) of padding (CST offset)
|
17
131
|
# to force the same time to be displayed in the NS UI
|
@@ -22,7 +136,7 @@ module NetSuite
|
|
22
136
|
end
|
23
137
|
|
24
138
|
# use when displaying times from a NS record
|
25
|
-
def
|
139
|
+
def normalize_datetime_from_netsuite(datetime)
|
26
140
|
# the code below eliminates the TimeZone offset then shifts the date forward 2 hours (7200 seconds)
|
27
141
|
# this ensures that ActiveRecord is given a UTC0 DateTime with the exact hour that
|
28
142
|
# was displayed in the NS UI (CST time zone), which will result in the correct display on the web side
|
data/lib/netsuite/version.rb
CHANGED
@@ -21,7 +21,7 @@ describe NetSuite::Records::Address do
|
|
21
21
|
|
22
22
|
it 'has all the right fields' do
|
23
23
|
[
|
24
|
-
:addr1, :addr2, :addressee, :addr_phone, :attention, :city, :
|
24
|
+
:addr1, :addr2, :addressee, :addr_phone, :attention, :city, :internal_id, :override, :state, :zip
|
25
25
|
].each do |field|
|
26
26
|
expect(list).to have_field(field)
|
27
27
|
end
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: netsuite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.9
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Ryan Moran
|
@@ -9,34 +10,38 @@ authors:
|
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2016-
|
13
|
+
date: 2016-05-05 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: savon
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
17
19
|
requirements:
|
18
|
-
- -
|
20
|
+
- - ! '>='
|
19
21
|
- !ruby/object:Gem::Version
|
20
22
|
version: 2.3.0
|
21
23
|
type: :runtime
|
22
24
|
prerelease: false
|
23
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
24
27
|
requirements:
|
25
|
-
- -
|
28
|
+
- - ! '>='
|
26
29
|
- !ruby/object:Gem::Version
|
27
30
|
version: 2.3.0
|
28
31
|
- !ruby/object:Gem::Dependency
|
29
32
|
name: rspec
|
30
33
|
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
31
35
|
requirements:
|
32
|
-
- -
|
36
|
+
- - ~>
|
33
37
|
- !ruby/object:Gem::Version
|
34
38
|
version: 3.1.0
|
35
39
|
type: :development
|
36
40
|
prerelease: false
|
37
41
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
38
43
|
requirements:
|
39
|
-
- -
|
44
|
+
- - ~>
|
40
45
|
- !ruby/object:Gem::Version
|
41
46
|
version: 3.1.0
|
42
47
|
description: NetSuite SuiteTalk API Wrapper
|
@@ -47,8 +52,9 @@ executables: []
|
|
47
52
|
extensions: []
|
48
53
|
extra_rdoc_files: []
|
49
54
|
files:
|
50
|
-
-
|
51
|
-
-
|
55
|
+
- .gitignore
|
56
|
+
- .rspec
|
57
|
+
- .ruby-version
|
52
58
|
- Gemfile
|
53
59
|
- LICENSE
|
54
60
|
- README.md
|
@@ -403,26 +409,27 @@ files:
|
|
403
409
|
- wsdl/2012_1.wsdl
|
404
410
|
homepage: https://github.com/NetSweet/netsuite
|
405
411
|
licenses: []
|
406
|
-
metadata: {}
|
407
412
|
post_install_message:
|
408
413
|
rdoc_options: []
|
409
414
|
require_paths:
|
410
415
|
- lib
|
411
416
|
required_ruby_version: !ruby/object:Gem::Requirement
|
417
|
+
none: false
|
412
418
|
requirements:
|
413
|
-
- -
|
419
|
+
- - ! '>='
|
414
420
|
- !ruby/object:Gem::Version
|
415
421
|
version: '0'
|
416
422
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
423
|
+
none: false
|
417
424
|
requirements:
|
418
|
-
- -
|
425
|
+
- - ! '>='
|
419
426
|
- !ruby/object:Gem::Version
|
420
427
|
version: '0'
|
421
428
|
requirements: []
|
422
429
|
rubyforge_project:
|
423
|
-
rubygems_version:
|
430
|
+
rubygems_version: 1.8.23.2
|
424
431
|
signing_key:
|
425
|
-
specification_version:
|
432
|
+
specification_version: 3
|
426
433
|
summary: NetSuite SuiteTalk API (SOAP) Wrapper
|
427
434
|
test_files:
|
428
435
|
- spec/netsuite/actions/add_spec.rb
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 63eeb2f2515c54bab1663a2683ed3f234f978d44
|
4
|
-
data.tar.gz: 6aaf5ad5cb70cdfb433a4a9c6c9798f2cf6c29ba
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 16405b1ce41bc3b287eebfa347316998d66507bfa6b6dfa6c2bb0c7a9d6ef158adef44bd19ec229d235e7fb7abca7013369450c5c038fdc4b17392cc1c671893
|
7
|
-
data.tar.gz: 1b214d4f1f23e608920b6556f7440286db57fcf8925d0bf9f3af4dd1bf6b28f5a7839bb19c7fe4767b6c62c22b0dee5c4b0a2da3e2b9fc1b931a4dddc0f7e780
|