netsuite_rails 0.3.5 → 0.3.6
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/lib/netsuite_rails/poll_timestamp.rb +1 -1
- data/lib/netsuite_rails/record_sync/poll_manager.rb +33 -14
- data/lib/netsuite_rails/transformations.rb +45 -1
- data/lib/netsuite_rails/url_helper.rb +4 -0
- data/netsuite_rails.gemspec +1 -1
- data/spec/models/poll_manager_spec.rb +94 -4
- data/spec/models/routines_spec.rb +1 -1
- data/spec/models/transformations_spec.rb +9 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94e9ec288d54f908a10fda708db7194307ccbb88
|
4
|
+
data.tar.gz: c65b576effc53fd1f6f9247990db9a811f5bf0b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e147f957716a59cf85c4e05a75487e44ae8d16361f4ff2139517f30d8b49de9b9405815917ac6a606fe9544828c2d8327a2926193849fe1ed1ec85a63a04c028
|
7
|
+
data.tar.gz: d48cd14ca541d80bde208b0b6c0f2943df3f284b5841d3b6c14d006c7c8f43718bc288b6a8360b4a6ca167291a216a40dd723398104f8170df7f72d9e32038e7
|
data/.gitignore
CHANGED
@@ -5,7 +5,7 @@ module NetSuiteRails
|
|
5
5
|
validates :key, presence: true, uniqueness: true
|
6
6
|
|
7
7
|
def self.for_class(klass)
|
8
|
-
self.where(key: "netsuite_poll_#{klass.to_s.downcase}
|
8
|
+
self.where(key: "netsuite_poll_#{klass.to_s.downcase}").first_or_initialize
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.table_name_prefix
|
@@ -31,21 +31,14 @@ module NetSuiteRails
|
|
31
31
|
def poll(klass, opts = {})
|
32
32
|
opts = {
|
33
33
|
import_all: false,
|
34
|
-
page_size: NetSuiteRails::Configuration.polling_page_size,
|
35
34
|
}.merge(opts)
|
36
35
|
|
37
36
|
opts[:netsuite_record_class] ||= klass.netsuite_record_class
|
38
37
|
opts[:netsuite_custom_record_type_id] ||= klass.netsuite_custom_record_type_id if opts[:netsuite_record_class] == NetSuite::Records::CustomRecord
|
39
38
|
opts[:saved_search_id] ||= klass.netsuite_sync_options[:saved_search_id]
|
40
|
-
opts[:body_fields_only] ||= false
|
41
39
|
|
42
40
|
search = opts[:netsuite_record_class].search(
|
43
|
-
poll_criteria(klass, opts)
|
44
|
-
preferences: {
|
45
|
-
body_fields_only: opts[:body_fields_only],
|
46
|
-
page_size: opts[:page_size]
|
47
|
-
}
|
48
|
-
})
|
41
|
+
poll_criteria(klass, opts)
|
49
42
|
)
|
50
43
|
|
51
44
|
# TODO more robust error reporting
|
@@ -57,6 +50,9 @@ module NetSuiteRails
|
|
57
50
|
end
|
58
51
|
|
59
52
|
def poll_criteria(klass, opts)
|
53
|
+
opts[:body_fields_only] ||= false
|
54
|
+
opts[:page_size] ||= NetSuiteRails::Configuration.polling_page_size
|
55
|
+
|
60
56
|
search_criteria = {
|
61
57
|
criteria: {
|
62
58
|
basic: poll_basic_criteria(klass, opts)
|
@@ -75,6 +71,13 @@ module NetSuiteRails
|
|
75
71
|
}
|
76
72
|
end
|
77
73
|
|
74
|
+
search_criteria.merge!({
|
75
|
+
preferences: {
|
76
|
+
body_fields_only: opts[:body_fields_only],
|
77
|
+
page_size: opts[:page_size]
|
78
|
+
}
|
79
|
+
})
|
80
|
+
|
78
81
|
search_criteria
|
79
82
|
end
|
80
83
|
|
@@ -100,13 +103,29 @@ module NetSuiteRails
|
|
100
103
|
}
|
101
104
|
end
|
102
105
|
|
106
|
+
# CustomRecordSearchBasic uses lastModified instead of the standard lastModifiedDate
|
107
|
+
opts[:netsuite_poll_field] ||= (klass.netsuite_custom_record?) ? 'lastModified' : 'lastModifiedDate'
|
108
|
+
|
109
|
+
# TODO investigate if defining a date range for `import_all` increases peformance
|
110
|
+
|
103
111
|
unless opts[:import_all]
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
112
|
+
if opts[:updated_before].present?
|
113
|
+
criteria << {
|
114
|
+
field: opts[:netsuite_poll_field],
|
115
|
+
operator: 'within',
|
116
|
+
type: 'SearchDateField',
|
117
|
+
value: [
|
118
|
+
opts[:last_poll],
|
119
|
+
opts[:updated_before]
|
120
|
+
]
|
121
|
+
}
|
122
|
+
else
|
123
|
+
criteria << {
|
124
|
+
field: opts[:netsuite_poll_field],
|
125
|
+
operator: 'after',
|
126
|
+
value: opts[:last_poll]
|
127
|
+
}
|
128
|
+
end
|
110
129
|
end
|
111
130
|
|
112
131
|
criteria
|
@@ -6,6 +6,32 @@ module NetSuiteRails
|
|
6
6
|
self.send(type, value, direction)
|
7
7
|
end
|
8
8
|
|
9
|
+
def memo(memo, direction = :push)
|
10
|
+
if direction == :push
|
11
|
+
memo[0..999]
|
12
|
+
else
|
13
|
+
memo
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# gift certificate codes have a maximum of 9 characters
|
18
|
+
def gift_card_code(code, direction = :push)
|
19
|
+
if direction == :push
|
20
|
+
code[0..8]
|
21
|
+
else
|
22
|
+
code
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# company_name field has a 83 character limit
|
27
|
+
def company_name(company_name, direction = :push)
|
28
|
+
if direction == :push
|
29
|
+
company_name[0..82]
|
30
|
+
else
|
31
|
+
company_name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
9
35
|
# NS limits firstname fields to 33 characters
|
10
36
|
def firstname(firstname, direction = :push)
|
11
37
|
if direction == :push
|
@@ -15,6 +41,20 @@ module NetSuiteRails
|
|
15
41
|
end
|
16
42
|
end
|
17
43
|
|
44
|
+
# same limitations as firstname
|
45
|
+
def lastname(lastname, direction = :push)
|
46
|
+
firstname(lastname, direction)
|
47
|
+
end
|
48
|
+
|
49
|
+
def integer(number, direction = :push)
|
50
|
+
number.to_i
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO consider adding precision?
|
54
|
+
def float(number, direction = :push)
|
55
|
+
number.to_f
|
56
|
+
end
|
57
|
+
|
18
58
|
def phone(phone, direction = :push)
|
19
59
|
if direction == :push
|
20
60
|
return nil if phone.nil?
|
@@ -58,7 +98,11 @@ module NetSuiteRails
|
|
58
98
|
# an error will be thrown if period is on the end of a sentence
|
59
99
|
gsub(/[^A-Za-z]+$/, '').
|
60
100
|
# any commas in the email with throw an error
|
61
|
-
gsub(',', '')
|
101
|
+
gsub(',', '').
|
102
|
+
# double periods anywhere in the email cause issues
|
103
|
+
gsub('..', '.').
|
104
|
+
# a period before the @ seems to cause issues
|
105
|
+
gsub('.@', '@')
|
62
106
|
|
63
107
|
email
|
64
108
|
else
|
@@ -25,6 +25,8 @@ module NetSuiteRails
|
|
25
25
|
# dependent record links
|
26
26
|
# https://system.na1.netsuite.com/core/pages/itemchildrecords.nl?id=12413&t=InvtItem%05ProjectCostCategory&rectype=-10
|
27
27
|
# https://system.na1.netsuite.com/app/accounting/transactions/payments.nl?id=91964&label=Customer+Refund&type=custrfnd&alllinks=T
|
28
|
+
|
29
|
+
# # tax schedule: https://system.na1.netsuite.com/app/common/item/taxschedule.nl?id=1
|
28
30
|
|
29
31
|
suffix = if is_custom_record
|
30
32
|
"/common/custom/custrecordentry.nl?id=#{internal_id}&rectype=#{record.class.netsuite_custom_record_type_id}"
|
@@ -64,6 +66,8 @@ module NetSuiteRails
|
|
64
66
|
"/accounting/account/account.nl?id=#{internal_id}"
|
65
67
|
elsif NetSuite::Records::Subsidiary == record_class
|
66
68
|
"/common/otherlists/subsidiarytype.nl?id=#{internal_id}"
|
69
|
+
elsif NetSuite::Records::PaymentMethod == record_class
|
70
|
+
"/app/common/otherlists/accountingotherlist.nl?id=#{internal_id}"
|
67
71
|
else
|
68
72
|
# TODO unsupported record type error?
|
69
73
|
end
|
data/netsuite_rails.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "netsuite_rails"
|
7
|
-
s.version = "0.3.
|
7
|
+
s.version = "0.3.6"
|
8
8
|
s.authors = ["Michael Bianco"]
|
9
9
|
s.email = ["mike@cliffsidemedia.com"]
|
10
10
|
s.summary = %q{Write Rails applications that integrate with NetSuite}
|
@@ -7,12 +7,102 @@ describe NetSuiteRails::RecordSync::PollManager do
|
|
7
7
|
|
8
8
|
let(:empty_search_results) { OpenStruct.new(results: [ OpenStruct.new(internal_id: 0) ]) }
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
describe 'polling ranges' do
|
11
|
+
let(:updated_after) { DateTime.new(2016, 01, 01) }
|
12
|
+
let(:updated_before) { DateTime.new(2016, 01, 02) }
|
12
13
|
|
13
|
-
|
14
|
+
it 'does not restrict poll by date if import_all is specified' do
|
15
|
+
expect(NetSuite::Records::Customer).to receive(:search)
|
16
|
+
.with(hash_including(
|
17
|
+
criteria: hash_including(
|
18
|
+
basic: []
|
19
|
+
)
|
20
|
+
))
|
21
|
+
.and_return(empty_search_results)
|
22
|
+
|
23
|
+
StandardRecord.netsuite_poll(import_all: true)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'restricts polling within a range' do
|
27
|
+
expect(NetSuite::Records::Customer).to receive(:search)
|
28
|
+
.with(hash_including(
|
29
|
+
criteria: hash_including(
|
30
|
+
basic: array_including(
|
31
|
+
{
|
32
|
+
field: 'lastModifiedDate',
|
33
|
+
type: 'SearchDateField',
|
34
|
+
operator: 'within',
|
35
|
+
value: [
|
36
|
+
updated_after,
|
37
|
+
updated_before
|
38
|
+
]
|
39
|
+
}
|
40
|
+
)
|
41
|
+
)
|
42
|
+
))
|
43
|
+
.and_return(empty_search_results)
|
44
|
+
|
45
|
+
StandardRecord.netsuite_poll(
|
46
|
+
last_poll: updated_after,
|
47
|
+
updated_before: updated_before
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'restricts polling after a date' do
|
52
|
+
expect(NetSuite::Records::Customer).to receive(:search)
|
53
|
+
.with(hash_including(
|
54
|
+
criteria: hash_including(
|
55
|
+
basic: array_including(
|
56
|
+
{
|
57
|
+
field: 'lastModifiedDate',
|
58
|
+
operator: 'after',
|
59
|
+
value: updated_after
|
60
|
+
}
|
61
|
+
)
|
62
|
+
)
|
63
|
+
))
|
64
|
+
.and_return(empty_search_results)
|
65
|
+
|
66
|
+
StandardRecord.netsuite_poll(last_poll: updated_after)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'allows the polling field to be customized' do
|
70
|
+
expect(NetSuite::Records::Customer).to receive(:search)
|
71
|
+
.with(hash_including(
|
72
|
+
criteria: hash_including(
|
73
|
+
basic: array_including(
|
74
|
+
{
|
75
|
+
field: 'lastQuantityAvailableChange',
|
76
|
+
operator: 'after',
|
77
|
+
value: updated_after
|
78
|
+
}
|
79
|
+
)
|
80
|
+
)
|
81
|
+
))
|
82
|
+
.and_return(empty_search_results)
|
83
|
+
|
84
|
+
StandardRecord.netsuite_poll(
|
85
|
+
last_poll: updated_after,
|
86
|
+
netsuite_poll_field: 'lastQuantityAvailableChange'
|
87
|
+
)
|
88
|
+
end
|
89
|
+
end
|
14
90
|
|
15
|
-
|
91
|
+
it 'allows search preferences to be customized' do
|
92
|
+
expect(NetSuite::Records::Customer).to receive(:search)
|
93
|
+
.with(hash_including(
|
94
|
+
preferences: hash_including(
|
95
|
+
body_fields_only: true,
|
96
|
+
page_size: 13
|
97
|
+
)
|
98
|
+
))
|
99
|
+
.and_return(empty_search_results)
|
100
|
+
|
101
|
+
StandardRecord.netsuite_poll(
|
102
|
+
import_all: true,
|
103
|
+
body_fields_only: true,
|
104
|
+
page_size: 13
|
105
|
+
)
|
16
106
|
end
|
17
107
|
|
18
108
|
skip "should poll and then get_list on saved search" do
|
@@ -68,5 +68,14 @@ describe NetSuiteRails::Transformations do
|
|
68
68
|
netsuite_email = ' example,second@example.com '
|
69
69
|
transformed_netsuite_email = NetSuiteRails::Transformations.email(netsuite_email, :push)
|
70
70
|
expect(transformed_netsuite_email.to_s).to eq('examplesecond@example.com')
|
71
|
+
|
72
|
+
netsuite_email = 'boom.@gmail.com'
|
73
|
+
transformed_netsuite_email = NetSuiteRails::Transformations.email(netsuite_email, :push)
|
74
|
+
expect(transformed_netsuite_email.to_s).to eq('boom@gmail.com')
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'truncates gift card code' do
|
78
|
+
code = Faker::Lorem.characters(10)
|
79
|
+
expect(NetSuiteRails::Transformations.gift_card_code(code, :push).size).to eq(9)
|
71
80
|
end
|
72
81
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: netsuite_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bianco
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: netsuite
|