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