netsuite_rails 0.2.2 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +4 -2
- data/README.md +186 -10
- data/circle.yml +3 -0
- data/lib/netsuite_rails/configuration.rb +7 -5
- data/lib/netsuite_rails/netsuite_rails.rb +24 -4
- data/lib/netsuite_rails/poll_trigger.rb +10 -9
- data/lib/netsuite_rails/record_sync/poll_manager.rb +23 -11
- data/lib/netsuite_rails/record_sync/pull_manager.rb +2 -0
- data/lib/netsuite_rails/record_sync/push_manager.rb +76 -38
- data/lib/netsuite_rails/record_sync.rb +28 -11
- data/lib/netsuite_rails/routines/company_contact_match.rb +98 -0
- data/lib/netsuite_rails/spec/disabler.rb +27 -0
- data/lib/netsuite_rails/spec/query_helpers.rb +93 -0
- data/lib/netsuite_rails/spec/spec_helper.rb +2 -79
- data/lib/netsuite_rails/sync_trigger.rb +40 -17
- data/lib/netsuite_rails/tasks/netsuite.rb +33 -4
- data/lib/netsuite_rails/transformations.rb +59 -19
- data/lib/netsuite_rails/url_helper.rb +45 -12
- data/netsuite_rails.gemspec +2 -2
- data/spec/models/configuration_spec.rb +11 -0
- data/spec/models/poll_manager_spec.rb +11 -2
- data/spec/models/poll_trigger_spec.rb +31 -11
- data/spec/models/record_sync/push_manager_spec.rb +51 -0
- data/spec/models/record_sync_spec.rb +16 -0
- data/spec/models/spec_helper_spec.rb +1 -2
- data/spec/models/transformations_spec.rb +62 -0
- data/spec/models/url_helper_spec.rb +20 -9
- data/spec/spec_helper.rb +19 -0
- data/spec/support/example_models.rb +33 -1
- metadata +19 -25
- data/.travis.yml +0 -3
- data/lib/netsuite_rails/netsuite_configure.rb +0 -14
- data/spec/support/netsuite_rails.rb +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YTVkYzk2NDQyNzI5MGZjODkxOTM4MWFkYjExYTNlZWZkNGFjNjFmMQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NjdmOWIxMmE0MjNkYjE2MTU2ZDBmMzg4MDViNWZjMzdmZGIwZjgzOQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OWJlMzFhMGJhNTM1NGZkMjRmMGMwNmU2ZmUzZTFhODQxMGQzYjZhMWNmMjE2
|
10
|
+
M2NlYjgwMTc0MWU4Y2FhMTBjNWVjZGM0NzU2NWIxNDY1NjMzYTE2N2ZlYWM4
|
11
|
+
N2NkOTY2ZTJhNzBiMDg2NjY0MTY4ZWYyYmMxNjk4NDc3NzQ5NjQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MDE5NmE5OWZmYjhjYzIyMGQ3ZmFmMzljZDc1ZTkwZDQ1MjRjYjUyZTk4MjAx
|
14
|
+
YjI2NTM1YmZmNWE5NjE0MGZhMzg1NmZlOTA5ZDA0NWU0OWU2ODgyNmM4NzMx
|
15
|
+
YzUxOTY5ODQ1MDQ0YWE3NTNkY2YwYjA1NmY4YThlNjUyNTgwMDc=
|
data/Gemfile
CHANGED
@@ -8,6 +8,8 @@ group :test do
|
|
8
8
|
# gem 'rack-test'
|
9
9
|
# gem 'webmock'
|
10
10
|
|
11
|
+
gem 'simplecov', :require => false
|
12
|
+
|
11
13
|
gem 'faker'
|
12
14
|
gem 'shoulda-matchers'
|
13
15
|
gem 'rails', '3.2.16'
|
@@ -15,7 +17,7 @@ group :test do
|
|
15
17
|
|
16
18
|
gem 'rspec-rails', '~> 3.1'
|
17
19
|
gem 'pry-nav'
|
18
|
-
|
20
|
+
|
19
21
|
gem 'rerun'
|
20
22
|
gem 'rb-fsevent'
|
21
|
-
end
|
23
|
+
end
|
data/README.md
CHANGED
@@ -1,10 +1,90 @@
|
|
1
|
-
[![
|
1
|
+
[![Circle CI](https://circleci.com/gh/NetSweet/netsuite_rails.svg?style=svg)](https://circleci.com/gh/NetSweet/netsuite_rails)
|
2
|
+
[![Slack Status](https://opensuite-slackin.herokuapp.com/badge.svg)](http://opensuite-slackin.herokuapp.com)
|
2
3
|
|
3
4
|
# NetSuite Rails
|
4
5
|
|
5
|
-
|
6
|
+
**<span style="color: red">Note:</span>** Documentation is horrible: PRs welcome. Look at the code for details.
|
6
7
|
|
7
|
-
Build
|
8
|
+
Build Ruby on Rails applications that sync ActiveRecord (ActiveModel and plain old ruby objects too) in real-time to NetSuite. Here's an example:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
class Item < ActiveRecord::Base
|
12
|
+
include NetSuiteRails::RecordSync
|
13
|
+
|
14
|
+
# specify the NS record that your rails model maps to
|
15
|
+
netsuite_record_class NetSuite::Records::InventoryItem
|
16
|
+
|
17
|
+
netsuite_sync :read_write,
|
18
|
+
# specify the frequency that your app should poll NetSuite for updates
|
19
|
+
frequency: 1.day,
|
20
|
+
# it's possible to base syncing off of a saved search. Be sure that "Internal ID" is one of your search result columns
|
21
|
+
saved_search_id: 123,
|
22
|
+
# limit pushing to NetSuite based on conditional
|
23
|
+
if: -> { self.a_condition? },
|
24
|
+
# limit pulling from NetSuite based on conditional. This is only
|
25
|
+
# considered when handling a single pull
|
26
|
+
pull_if: -> { self.another_condition? },
|
27
|
+
|
28
|
+
# accepted values are :async and :sync. Default is :async
|
29
|
+
mode: :sync
|
30
|
+
|
31
|
+
|
32
|
+
# local => remote field mapping
|
33
|
+
netsuite_field_map({
|
34
|
+
:item_number => :item_id,
|
35
|
+
:name => :display_name,
|
36
|
+
|
37
|
+
# the corresponding NetSuite field must be manually specified in before_netsuite_push
|
38
|
+
:user => Proc.new do |local_rails_record, netsuite_record, sync_direction|
|
39
|
+
if direction == :pull
|
40
|
+
|
41
|
+
elsif direction == :push
|
42
|
+
|
43
|
+
end
|
44
|
+
end,
|
45
|
+
|
46
|
+
:custom_field_list => {
|
47
|
+
:a_local_field => :custrecord_remote_field
|
48
|
+
:a_special_local_field => Proc.new do |local, ns_record, direction|
|
49
|
+
if direction == :push
|
50
|
+
# if proc is used with a field mapping, the field must be specified in `netsuite_manual_fields`
|
51
|
+
ns_record.custom_field_list.custentity_special_long = 1
|
52
|
+
ns_record.custom_field_list.custentity_special_long.type = 'platformCore:LongCustomFieldRef'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
}
|
56
|
+
})
|
57
|
+
|
58
|
+
# sanitizes input from rails to ensure NS doesn't throw a fatal error
|
59
|
+
netsuite_field_hints({
|
60
|
+
:phone => :phone,
|
61
|
+
:email => :email
|
62
|
+
})
|
63
|
+
|
64
|
+
before_netsuite_push do |netsuite_record|
|
65
|
+
self.netsuite_manual_fields = [ :entity, :custom_field_list ]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
Your ruby model:
|
71
|
+
|
72
|
+
* Needs to have a `netsuite_id` and `netsuite_id=` method
|
73
|
+
* Does not need to be an `ActiveRecord` model. If you don't use ActiveRecord it is your responsibility
|
74
|
+
to trigger `Model#netsuite_push`.
|
75
|
+
|
76
|
+
Notes:
|
77
|
+
|
78
|
+
* If `sync_mode == :async` `model.save` will be run if a record is created referencing an existing NetSuite object: `model.create! netsuite_id: 123`
|
79
|
+
* If you are using `update`, a `update` call will not be run if no changed fields are detected. If you are manually using fields specify them with `netsuite_manual_fields`
|
80
|
+
|
81
|
+
## Using Upsert
|
82
|
+
|
83
|
+
TODO generating external ID tag
|
84
|
+
|
85
|
+
TODO configuring upsert
|
86
|
+
|
87
|
+
TODO add vs upsert consideration
|
8
88
|
|
9
89
|
## Installation
|
10
90
|
|
@@ -12,43 +92,121 @@ Build custom Ruby on Rails applications that sync to NetSuite.
|
|
12
92
|
gem 'netsuite_rails'
|
13
93
|
```
|
14
94
|
|
15
|
-
Install the database migration
|
95
|
+
Install the database migration to persist poll timestamps:
|
16
96
|
|
17
97
|
```bash
|
18
98
|
rails g netsuite_rails:install
|
19
99
|
```
|
20
100
|
|
21
|
-
|
101
|
+
This helps netsuite_rails to know when the last time your rails DB was synced with the NS.
|
102
|
+
|
103
|
+
## Date
|
104
|
+
|
105
|
+
|
106
|
+
## Time
|
107
|
+
|
108
|
+
"Time of Day" fields in NetSuite are especially tricky. To ensure that times don't shift when you push them to NetSuite here are some tips:
|
109
|
+
|
110
|
+
1. Take a look at the company time zone setup. This is in Setup
|
111
|
+
2. Ensure your WebService's Employee record has either:
|
112
|
+
* No time zone set
|
113
|
+
* The same time zone as the company
|
114
|
+
3. Ensure that the WebService's GUI preferences have the same time zone settings as the company. This effects how times are translated via SuiteTalk.
|
115
|
+
4. Set the `netsuite_instance_time_zone_offset` setting to your company's time zone
|
22
116
|
|
23
117
|
```ruby
|
24
118
|
# set your timezone offset
|
25
119
|
NetSuiteRails::Configuration.netsuite_instance_time_zone_offset(-6)
|
26
120
|
```
|
27
121
|
|
122
|
+
### Changing WebService User's TimeZone Preferences
|
123
|
+
|
124
|
+
It might take a couple hours for time zone changes to take effect. [From my experience](http://mikebian.co/netsuite-suitetalk-user-role-edits-are-delayed/), either the time zone changes have some delay associated with them or the time zone implementation is extremely buggy.
|
125
|
+
|
28
126
|
## Usage
|
29
127
|
|
30
|
-
|
128
|
+
### Syncing Options
|
129
|
+
|
130
|
+
```
|
131
|
+
netsuite_record_class NetSuite::Records::Customer
|
132
|
+
netsuite_record_class NetSuite::Records::CustomRecord, 123
|
133
|
+
|
134
|
+
netsuite_sync: :read
|
135
|
+
netsuite_sync: :read_write
|
136
|
+
# TODO not after_netsuite_push replacement for aggressive sync
|
137
|
+
|
138
|
+
netsuite_sync: :read, frequency: :never
|
139
|
+
netsuite_sync: :read, frequency: 5.minutes
|
140
|
+
netsuite_sync: :read, if: -> { self.condition_met? }
|
141
|
+
|
142
|
+
```
|
31
143
|
|
32
144
|
When using a proc in a NS mapping, you are responsible for setting local and remote values
|
33
145
|
|
146
|
+
The default sync frequency is [one day](https://github.com/NetSweet/netsuite_rails/blob/c453326a4190e68a2fd9d7690b2b1f2f105ec8b9/lib/netsuite_rails/poll_trigger.rb#L27).
|
147
|
+
|
34
148
|
for pushing tasks to DJ https://github.com/collectiveidea/delayed_job/wiki/Rake-Task-as-a-Delayed-Job
|
35
149
|
|
36
150
|
`:if` for controlling when syncing occurs
|
37
151
|
|
38
|
-
|
152
|
+
Easily disable/enable syncing via env vars:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
NetSuiteRails.configure do
|
156
|
+
netsuite_pull_disabled ENV['NETSUITE_PULL_DISABLED'].present? && ENV['NETSUITE_PULL_DISABLED'] == "true"
|
157
|
+
netsuite_push_disabled ENV['NETSUITE_PUSH_DISABLED'].present? && ENV['NETSUITE_PUSH_DISABLED'] == "true"
|
158
|
+
|
159
|
+
if ENV['NETSUITE_DISABLE_SYNC'].present? && ENV['NETSUITE_DISABLE_SYNC'] == "true"
|
160
|
+
netsuite_pull_disabled true
|
161
|
+
netsuite_push_disabled true
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
```
|
166
|
+
|
167
|
+
### Hooks
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
# the netsuite record is passed a single argument to this block (or method reference)
|
171
|
+
# this provides the opportunity to set custom fields or run custom logic to prepare
|
172
|
+
# the record for the NetSuite envoirnment
|
173
|
+
before_netsuite_push
|
174
|
+
after_netsuite_push
|
175
|
+
|
176
|
+
# netsuite_pulling? is true when this callback is executed
|
177
|
+
after_netsuite_pull
|
178
|
+
```
|
39
179
|
|
40
|
-
### Syncing
|
180
|
+
### Rake Tasks for Syncing
|
41
181
|
|
42
182
|
```bash
|
183
|
+
# update & create local records modified in netsuite sync the last sync time
|
43
184
|
rake netsuite:sync
|
44
185
|
|
186
|
+
# pull all records in NetSuite and update/create local records
|
45
187
|
rake netsuite:fresh_sync
|
188
|
+
|
189
|
+
# only update records that have already been synced
|
190
|
+
rake netsuite:sync_local RECORD_MODELS=YourModel LIST_MODELS=YourListModel
|
46
191
|
```
|
47
192
|
|
48
193
|
Caveats:
|
49
194
|
|
50
195
|
* If you have date time fields, or custom fields that will trigger `changed_attributes` this might cause issues when pulling an existing record
|
51
|
-
* `changed_attributes` doesn't work well with store
|
196
|
+
* `changed_attributes` doesn't work well with `store`s
|
197
|
+
|
198
|
+
### Delayed Job
|
199
|
+
|
200
|
+
The more records that use netsuite_rails, the longer you'll need your job timeout to be:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
# config/initializers/delayed_job.rb
|
204
|
+
Delayed::Worker.max_run_time = 80.minutes
|
205
|
+
```
|
206
|
+
|
207
|
+
## Non-AR Backed Model
|
208
|
+
|
209
|
+
Implement `changed_attributes` in your non-AR backed model
|
52
210
|
|
53
211
|
## Testing
|
54
212
|
|
@@ -57,6 +215,24 @@ Caveats:
|
|
57
215
|
require 'netsuite_rails/spec/spec_helper'
|
58
216
|
```
|
59
217
|
|
218
|
+
# Syncing Using Rake Tasks
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
# clockwork.rb
|
222
|
+
every(1.minutes, 'netsuite sync') {
|
223
|
+
# prevent multiple netsuite:sync DJ commands from being added; only one is needed in the queue at a time
|
224
|
+
unless Delayed::Job.where(failed_at: nil, locked_by: nil).detect { |j| j.payload_object.class == DelayedRake && j.payload_object.task == 'netsuite:sync'}
|
225
|
+
Delayed::Job.enqueue DelayedRake.new("netsuite:sync")
|
226
|
+
end
|
227
|
+
}
|
228
|
+
|
229
|
+
# schedule.rb
|
230
|
+
# DelayedRake: https://github.com/collectiveidea/delayed_job/wiki/Rake-Task-as-a-Delayed-Job
|
231
|
+
every 2.minutes do
|
232
|
+
runner 'Delayed::Job.enqueue(DelayedRake.new("netsuite:sync"),priority:1,run_at: Time.now);'
|
233
|
+
end
|
234
|
+
```
|
235
|
+
|
60
236
|
## Author
|
61
237
|
|
62
|
-
* Michael Bianco @iloveitaly
|
238
|
+
* Michael Bianco @iloveitaly
|
data/circle.yml
ADDED
@@ -14,7 +14,7 @@ module NetSuiteRails
|
|
14
14
|
|
15
15
|
def netsuite_sync_mode(mode = nil)
|
16
16
|
if mode.nil?
|
17
|
-
attributes[:sync_mode] ||= :
|
17
|
+
attributes[:sync_mode] ||= :async
|
18
18
|
else
|
19
19
|
attributes[:sync_mode] = mode
|
20
20
|
end
|
@@ -22,17 +22,19 @@ module NetSuiteRails
|
|
22
22
|
|
23
23
|
def netsuite_push_disabled(flag = nil)
|
24
24
|
if flag.nil?
|
25
|
-
attributes[:
|
25
|
+
attributes[:push_disabled] = false if attributes[:push_disabled].nil?
|
26
|
+
attributes[:push_disabled]
|
26
27
|
else
|
27
|
-
attributes[:
|
28
|
+
attributes[:push_disabled] = flag
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
31
32
|
def netsuite_pull_disabled(flag = nil)
|
32
33
|
if flag.nil?
|
33
|
-
attributes[:
|
34
|
+
attributes[:pull_disabled] = false if attributes[:pull_disabled].nil?
|
35
|
+
attributes[:pull_disabled]
|
34
36
|
else
|
35
|
-
attributes[:
|
37
|
+
attributes[:pull_disabled] = flag
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
@@ -14,6 +14,8 @@ require 'netsuite_rails/record_sync/poll_manager'
|
|
14
14
|
require 'netsuite_rails/record_sync/pull_manager'
|
15
15
|
require 'netsuite_rails/record_sync/push_manager'
|
16
16
|
|
17
|
+
require 'netsuite_rails/routines/company_contact_match'
|
18
|
+
|
17
19
|
require 'netsuite_rails/list_sync'
|
18
20
|
require 'netsuite_rails/list_sync/poll_manager'
|
19
21
|
|
@@ -23,14 +25,32 @@ module NetSuiteRails
|
|
23
25
|
Rails::VERSION::MAJOR >= 4
|
24
26
|
end
|
25
27
|
|
28
|
+
def self.configure_from_env(&block)
|
29
|
+
self.configure do
|
30
|
+
reset!
|
31
|
+
|
32
|
+
netsuite_pull_disabled ENV['NETSUITE_PULL_DISABLED'].present? && ENV['NETSUITE_PULL_DISABLED'] == "true"
|
33
|
+
netsuite_push_disabled ENV['NETSUITE_PUSH_DISABLED'].present? && ENV['NETSUITE_PUSH_DISABLED'] == "true"
|
34
|
+
|
35
|
+
if ENV['NETSUITE_DISABLE_SYNC'].present? && ENV['NETSUITE_DISABLE_SYNC'] == "true"
|
36
|
+
netsuite_pull_disabled true
|
37
|
+
netsuite_push_disabled true
|
38
|
+
end
|
39
|
+
|
40
|
+
polling_page_size if ENV['NETSUITE_POLLING_PAGE_SIZE'].present?
|
41
|
+
end
|
42
|
+
|
43
|
+
self.configure(&block) if block
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.configure(&block)
|
47
|
+
NetSuiteRails::Configuration.instance_eval(&block)
|
48
|
+
end
|
49
|
+
|
26
50
|
class Railtie < ::Rails::Railtie
|
27
51
|
rake_tasks do
|
28
52
|
load 'netsuite_rails/tasks/netsuite.rb'
|
29
53
|
end
|
30
|
-
|
31
|
-
config.before_configuration do
|
32
|
-
require 'netsuite_rails/netsuite_configure'
|
33
|
-
end
|
34
54
|
end
|
35
55
|
|
36
56
|
end
|
@@ -27,32 +27,33 @@ module NetSuiteRails
|
|
27
27
|
sync_frequency = klass.netsuite_sync_options[:frequency] || 1.day
|
28
28
|
|
29
29
|
if sync_frequency == :never
|
30
|
-
Rails.logger.info "Not syncing #{klass.to_s}"
|
30
|
+
Rails.logger.info "NetSuite: Not syncing #{klass.to_s}"
|
31
31
|
next
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
preference = PollTimestamp.for_class(klass)
|
34
|
+
last_class_poll = PollTimestamp.for_class(klass)
|
35
|
+
poll_execution_time = DateTime.now
|
37
36
|
|
38
37
|
# check if we've never synced before
|
39
|
-
if
|
38
|
+
if last_class_poll.new_record?
|
39
|
+
Rails.logger.info "NetSuite: Syncing #{klass} for the first time"
|
40
40
|
klass.netsuite_poll({ import_all: true }.merge(opts))
|
41
41
|
else
|
42
42
|
# TODO look into removing the conditional parsing; I don't think this is needed
|
43
|
-
last_poll_date =
|
43
|
+
last_poll_date = last_class_poll.value
|
44
44
|
last_poll_date = DateTime.parse(last_poll_date) unless last_poll_date.is_a?(DateTime)
|
45
45
|
|
46
46
|
if DateTime.now.to_i - last_poll_date.to_i > sync_frequency
|
47
|
-
Rails.logger.info "NetSuite:
|
47
|
+
Rails.logger.info "NetSuite: #{klass} is due to be synced, last checked #{last_poll_date}"
|
48
48
|
klass.netsuite_poll({ last_poll: last_poll_date }.merge(opts))
|
49
49
|
else
|
50
50
|
Rails.logger.info "NetSuite: Skipping #{klass} because of syncing frequency"
|
51
|
+
next
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
-
|
55
|
+
last_class_poll.value = poll_execution_time
|
56
|
+
last_class_poll.save!
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
@@ -19,7 +19,7 @@ module NetSuiteRails
|
|
19
19
|
end
|
20
20
|
|
21
21
|
unless netsuite_batch
|
22
|
-
|
22
|
+
raise "NetSuite: #{klass}. Error running NS search. No Netsuite batch found. Most likely a search timeout."
|
23
23
|
end
|
24
24
|
|
25
25
|
netsuite_batch.each do |netsuite_record|
|
@@ -35,12 +35,14 @@ module NetSuiteRails
|
|
35
35
|
}.merge(opts)
|
36
36
|
|
37
37
|
opts[:netsuite_record_class] ||= klass.netsuite_record_class
|
38
|
+
opts[:netsuite_custom_record_type_id] ||= klass.netsuite_custom_record_type_id if opts[:netsuite_record_class] == NetSuite::Records::CustomRecord
|
38
39
|
opts[:saved_search_id] ||= klass.netsuite_sync_options[:saved_search_id]
|
40
|
+
opts[:body_fields_only] ||= false
|
39
41
|
|
40
42
|
search = opts[:netsuite_record_class].search(
|
41
43
|
poll_criteria(klass, opts).merge({
|
42
44
|
preferences: {
|
43
|
-
body_fields_only:
|
45
|
+
body_fields_only: opts[:body_fields_only],
|
44
46
|
page_size: opts[:page_size]
|
45
47
|
}
|
46
48
|
})
|
@@ -48,7 +50,7 @@ module NetSuiteRails
|
|
48
50
|
|
49
51
|
# TODO more robust error reporting
|
50
52
|
unless search
|
51
|
-
raise
|
53
|
+
raise "NetSuite: #{klass}. Error running NS search. Most likely a search timeout."
|
52
54
|
end
|
53
55
|
|
54
56
|
process_search_results(klass, opts, search)
|
@@ -90,7 +92,7 @@ module NetSuiteRails
|
|
90
92
|
|
91
93
|
if opts[:netsuite_record_class] == NetSuite::Records::CustomRecord
|
92
94
|
opts[:netsuite_custom_record_type_id] ||= klass.netsuite_custom_record_type_id
|
93
|
-
|
95
|
+
|
94
96
|
criteria << {
|
95
97
|
field: 'recType',
|
96
98
|
operator: 'is',
|
@@ -116,14 +118,14 @@ module NetSuiteRails
|
|
116
118
|
full_record_data: -1,
|
117
119
|
}.merge(opts)
|
118
120
|
|
119
|
-
Rails.logger.info "NetSuite: Processing #{search.total_records} over #{search.total_pages} pages"
|
120
|
-
|
121
121
|
# TODO need to improve the conditional here to match the get_list call conditional belo
|
122
122
|
if opts[:import_all] && opts[:skip_existing]
|
123
123
|
synced_netsuite_list = klass.pluck(:netsuite_id)
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
search.results_in_batches do |batch|
|
127
|
+
Rails.logger.info "NetSuite: Syncing #{klass}. Current Page: #{search.current_page}. Processing #{search.total_records} over #{search.total_pages} pages."
|
128
|
+
|
127
129
|
# a saved search is processed as a advanced search; advanced search often does not allow you to retrieve
|
128
130
|
# all of the fields (ex: addressbooklist on customer) that a normal search does
|
129
131
|
# the only way to get those fields is to pull down the full record again using getAll
|
@@ -136,7 +138,16 @@ module NetSuiteRails
|
|
136
138
|
end
|
137
139
|
|
138
140
|
if filtered_netsuite_id_list.present?
|
139
|
-
|
141
|
+
Rails.logger.info "NetSuite: Syncing #{klass}. Running get_list for #{filtered_netsuite_id_list.length} records"
|
142
|
+
|
143
|
+
if opts[:netsuite_record_class] == NetSuite::Records::CustomRecord
|
144
|
+
NetSuite::Records::CustomRecord.get_list(
|
145
|
+
list: filtered_netsuite_id_list,
|
146
|
+
type_id: opts[:netsuite_custom_record_type_id]
|
147
|
+
)
|
148
|
+
else
|
149
|
+
opts[:netsuite_record_class].get_list(list: filtered_netsuite_id_list)
|
150
|
+
end
|
140
151
|
else
|
141
152
|
[]
|
142
153
|
end
|
@@ -164,7 +175,8 @@ module NetSuiteRails
|
|
164
175
|
end
|
165
176
|
|
166
177
|
def needs_get_list?(opts)
|
167
|
-
(opts[:saved_search_id].present? && opts[:full_record_data] != false) ||
|
178
|
+
(opts[:saved_search_id].present? && opts[:full_record_data] != false) ||
|
179
|
+
opts[:full_record_data] == true
|
168
180
|
end
|
169
181
|
|
170
182
|
# TODO this should remain in the pull manager
|
@@ -180,7 +192,7 @@ module NetSuiteRails
|
|
180
192
|
|
181
193
|
custom_field_value
|
182
194
|
end
|
183
|
-
|
195
|
+
|
184
196
|
end
|
185
197
|
end
|
186
|
-
end
|
198
|
+
end
|
@@ -3,6 +3,8 @@ module NetSuiteRails
|
|
3
3
|
module PullManager
|
4
4
|
extend self
|
5
5
|
|
6
|
+
# TODO pull relevant methods out of poll manager and into this class
|
7
|
+
|
6
8
|
def extract_custom_field_value(custom_field_value)
|
7
9
|
if custom_field_value.present? && custom_field_value.is_a?(Hash) && custom_field_value.has_key?(:name)
|
8
10
|
custom_field_value = custom_field_value[:name]
|