qbwc 0.0.5 → 0.1.0
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 +7 -0
- data/.gitignore +5 -1
- data/.travis.yml +6 -0
- data/README.md +152 -144
- data/Rakefile +7 -1
- data/lib/generators/qbwc/install/install_generator.rb +20 -4
- data/lib/generators/qbwc/install/templates/config/qbwc.rb +42 -26
- data/lib/generators/qbwc/install/templates/controllers/qbwc_controller.rb +2 -38
- data/lib/generators/qbwc/install/templates/db/migrate/create_qbwc_jobs.rb +15 -0
- data/lib/generators/qbwc/install/templates/db/migrate/create_qbwc_sessions.rb +16 -0
- data/lib/qbwc.rb +107 -71
- data/lib/qbwc/active_record.rb +6 -0
- data/lib/qbwc/active_record/job.rb +111 -0
- data/lib/qbwc/active_record/session.rb +52 -0
- data/lib/qbwc/controller.rb +176 -0
- data/lib/qbwc/job.rb +81 -18
- data/lib/qbwc/railtie.rb +8 -0
- data/lib/qbwc/request.rb +14 -23
- data/lib/qbwc/session.rb +100 -72
- data/lib/qbwc/version.rb +1 -1
- data/lib/qbwc/worker.rb +16 -0
- data/qbwc.gemspec +11 -5
- data/test/qbwc/controllers/controller_test.rb +157 -0
- data/test/qbwc/integration/job_management_test.rb +86 -0
- data/test/qbwc/integration/request_generation_test.rb +340 -0
- data/test/qbwc/integration/response_test.rb +303 -0
- data/test/qbwc/integration/routes_test.rb +38 -0
- data/test/qbwc/integration/session_test.rb +94 -0
- data/test/test_helper.rb +248 -0
- data/test/wash_out_helper.rb +76 -0
- metadata +133 -55
- data/Gemfile.lock +0 -72
- data/lib/qbwc/soap_wrapper.rb +0 -35
- data/lib/qbwc/soap_wrapper/QBWebConnectorSvc.rb +0 -69
- data/lib/qbwc/soap_wrapper/QBWebConnectorSvc.wsdl +0 -312
- data/lib/qbwc/soap_wrapper/default.rb +0 -198
- data/lib/qbwc/soap_wrapper/defaultMappingRegistry.rb +0 -163
- data/lib/qbwc/soap_wrapper/defaultServant.rb +0 -133
- data/spec/spec_helper.rb +0 -17
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'wash_out/version'
|
2
|
+
include WashOut
|
3
|
+
|
4
|
+
module QBWC
|
5
|
+
module Controller
|
6
|
+
|
7
|
+
AUTHENTICATE_NOT_VALID_USER = 'nvu'
|
8
|
+
AUTHENTICATE_NO_WORK = 'none'
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.class_eval do
|
12
|
+
include WashOut::SOAP
|
13
|
+
skip_before_filter :_parse_soap_parameters, :_authenticate_wsse, :_map_soap_parameters, :only => :qwc
|
14
|
+
before_filter :get_session, :except => [:qwc, :authenticate, :_generate_wsdl]
|
15
|
+
after_filter :save_session, :except => [:qwc, :authenticate, :_generate_wsdl, :close_connection, :connection_error]
|
16
|
+
|
17
|
+
# wash_out changed the format of app/views/wash_with_soap/rpc/response.builder in commit
|
18
|
+
# https://github.com/inossidabile/wash_out/commit/24a77f4a3d874562732c6e8c3a30e8defafea7cb
|
19
|
+
wash_out_xml_namespace = (Gem::Version.new(WashOut::VERSION) < Gem::Version.new('0.9.1') ? 'tns:' : '')
|
20
|
+
|
21
|
+
soap_action 'serverVersion', :to => :server_version,
|
22
|
+
:return => {'tns:serverVersionResult' => :string},
|
23
|
+
:response_tag => "#{wash_out_xml_namespace}serverVersionResponse"
|
24
|
+
|
25
|
+
soap_action 'clientVersion', :to => :client_version,
|
26
|
+
:args => {:strVersion => :string},
|
27
|
+
:return => {'tns:clientVersionResult' => :string},
|
28
|
+
:response_tag => "#{wash_out_xml_namespace}clientVersionResponse"
|
29
|
+
|
30
|
+
soap_action 'authenticate',
|
31
|
+
:args => {:strUserName => :string, :strPassword => :string},
|
32
|
+
:return => {'tns:authenticateResult' => StringArray},
|
33
|
+
:response_tag => "#{wash_out_xml_namespace}authenticateResponse"
|
34
|
+
|
35
|
+
soap_action 'sendRequestXML', :to => :send_request,
|
36
|
+
:args => {:ticket => :string, :strHCPResponse => :string, :strCompanyFilename => :string, :qbXMLCountry => :string, :qbXMLMajorVers => :string, :qbXMLMinorVers => :string},
|
37
|
+
:return => {'tns:sendRequestXMLResult' => :string},
|
38
|
+
:response_tag => "#{wash_out_xml_namespace}sendRequestXMLResponse"
|
39
|
+
|
40
|
+
soap_action 'receiveResponseXML', :to => :receive_response,
|
41
|
+
:args => {:ticket => :string, :response => :string, :hresult => :string, :message => :string},
|
42
|
+
:return => {'tns:receiveResponseXMLResult' => :integer},
|
43
|
+
:response_tag => "#{wash_out_xml_namespace}receiveResponseXMLResponse"
|
44
|
+
|
45
|
+
soap_action 'closeConnection', :to => :close_connection,
|
46
|
+
:args => {:ticket => :string},
|
47
|
+
:return => {'tns:closeConnectionResult' => :string},
|
48
|
+
:response_tag => "#{wash_out_xml_namespace}closeConnectionResponse"
|
49
|
+
|
50
|
+
soap_action 'connectionError', :to => :connection_error,
|
51
|
+
:args => {:ticket => :string, :hresult => :string, :message => :string},
|
52
|
+
:return => {'tns:connectionErrorResult' => :string},
|
53
|
+
:response_tag => "#{wash_out_xml_namespace}connectionErrorResponse"
|
54
|
+
|
55
|
+
soap_action 'getLastError', :to => :get_last_error,
|
56
|
+
:args => {:ticket => :string},
|
57
|
+
:return => {'tns:getLastErrorResult' => :string},
|
58
|
+
:response_tag => "#{wash_out_xml_namespace}getLastErrorResponse"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def qwc
|
63
|
+
# Optional tag
|
64
|
+
scheduler_block = ''
|
65
|
+
if !QBWC.minutes_to_run.nil?
|
66
|
+
scheduler_block = <<SB
|
67
|
+
<Scheduler>
|
68
|
+
<RunEveryNMinutes>#{QBWC.minutes_to_run}</RunEveryNMinutes>
|
69
|
+
</Scheduler>
|
70
|
+
SB
|
71
|
+
end
|
72
|
+
|
73
|
+
qwc = <<QWC
|
74
|
+
<QBWCXML>
|
75
|
+
<AppName>#{Rails.application.class.parent_name} #{Rails.env} #{@app_name_suffix}</AppName>
|
76
|
+
<AppID></AppID>
|
77
|
+
<AppURL>#{qbwc_action_url(:only_path => false)}</AppURL>
|
78
|
+
<AppDescription>Quickbooks integration</AppDescription>
|
79
|
+
<AppSupport>#{QBWC.support_site_url || root_url(:protocol => 'https://')}</AppSupport>
|
80
|
+
<UserName>#{@username || QBWC.username}</UserName>
|
81
|
+
<OwnerID>#{QBWC.owner_id}</OwnerID>
|
82
|
+
<FileID>{90A44FB5-33D9-4815-AC85-BC87A7E7D1EB}</FileID>
|
83
|
+
<QBType>QBFS</QBType>
|
84
|
+
<Style>Document</Style>
|
85
|
+
#{scheduler_block}
|
86
|
+
</QBWCXML>
|
87
|
+
QWC
|
88
|
+
send_data qwc, :filename => "#{@filename || Rails.application.class.parent_name}.qwc", :content_type => 'application/x-qwc'
|
89
|
+
end
|
90
|
+
|
91
|
+
class StringArray < WashOut::Type
|
92
|
+
map "tns:string" => [:string]
|
93
|
+
end
|
94
|
+
|
95
|
+
def server_version
|
96
|
+
render :soap => {"tns:serverVersionResult" => server_version_response}
|
97
|
+
end
|
98
|
+
|
99
|
+
def client_version
|
100
|
+
render :soap => {"tns:clientVersionResult" => check_client_version}
|
101
|
+
end
|
102
|
+
|
103
|
+
def authenticate
|
104
|
+
username = params[:strUserName]
|
105
|
+
password = params[:strPassword]
|
106
|
+
if !QBWC.authenticator.nil?
|
107
|
+
company_file_path = QBWC.authenticator.call(username, password)
|
108
|
+
elsif username == QBWC.username && password == QBWC.password
|
109
|
+
company_file_path = QBWC.company_file_path
|
110
|
+
else
|
111
|
+
company_file_path = nil
|
112
|
+
end
|
113
|
+
|
114
|
+
ticket = nil
|
115
|
+
if company_file_path.nil?
|
116
|
+
QBWC.logger.info "Authentication of user '#{username}' failed."
|
117
|
+
company_file_path = AUTHENTICATE_NOT_VALID_USER
|
118
|
+
elsif !QBWC.pending_jobs(company_file_path).present?
|
119
|
+
QBWC.logger.info "Authentication of user '#{username}' succeeded, but no jobs pending for '#{company_file_path}'."
|
120
|
+
company_file_path = AUTHENTICATE_NO_WORK
|
121
|
+
else
|
122
|
+
QBWC.logger.info "Authentication of user '#{username}' succeeded, jobs are pending for '#{company_file_path}'."
|
123
|
+
ticket = QBWC.storage_module::Session.new(username, company_file_path).ticket
|
124
|
+
QBWC.session_initializer.call(get_session(ticket)) unless QBWC.session_initializer.nil?
|
125
|
+
end
|
126
|
+
render :soap => {"tns:authenticateResult" => {"tns:string" => [ticket || '', company_file_path]}}
|
127
|
+
end
|
128
|
+
|
129
|
+
def send_request
|
130
|
+
request = @session.request_to_send
|
131
|
+
render :soap => {'tns:sendRequestXMLResult' => request}
|
132
|
+
end
|
133
|
+
|
134
|
+
def receive_response
|
135
|
+
if params[:hresult]
|
136
|
+
QBWC.logger.warn "#{params[:hresult]}: #{params[:message]}"
|
137
|
+
@session.error = params[:message]
|
138
|
+
@session.status_code = params[:hresult]
|
139
|
+
@session.status_severity = 'Error'
|
140
|
+
end
|
141
|
+
@session.response = params[:response]
|
142
|
+
render :soap => {'tns:receiveResponseXMLResult' => (QBWC::on_error == 'continueOnError' || @session.error.nil?) ? @session.progress : -1}
|
143
|
+
end
|
144
|
+
|
145
|
+
def close_connection
|
146
|
+
@session.destroy
|
147
|
+
render :soap => {'tns:closeConnectionResult' => 'OK'}
|
148
|
+
end
|
149
|
+
|
150
|
+
def connection_error
|
151
|
+
@session.destroy
|
152
|
+
logger.warn "#{params[:hresult]}: #{params[:message]}"
|
153
|
+
render :soap => {'tns:connectionErrorResult' => 'done'}
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_last_error
|
157
|
+
render :soap => {'tns:getLastErrorResult' => @session.error || ''}
|
158
|
+
end
|
159
|
+
|
160
|
+
protected
|
161
|
+
|
162
|
+
def get_session(ticket = params[:ticket])
|
163
|
+
@session = QBWC.storage_module::Session.get(ticket)
|
164
|
+
end
|
165
|
+
|
166
|
+
def save_session
|
167
|
+
@session.save if @session
|
168
|
+
end
|
169
|
+
|
170
|
+
def server_version_response
|
171
|
+
end
|
172
|
+
|
173
|
+
def check_client_version
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
data/lib/qbwc/job.rb
CHANGED
@@ -1,47 +1,110 @@
|
|
1
1
|
class QBWC::Job
|
2
2
|
|
3
|
-
attr_reader :name, :
|
3
|
+
attr_reader :name, :company, :worker_class
|
4
4
|
|
5
|
-
def initialize(name,
|
5
|
+
def initialize(name, enabled, company, worker_class, requests = [], data = nil)
|
6
6
|
@name = name
|
7
|
-
@enabled =
|
8
|
-
@
|
7
|
+
@enabled = enabled
|
8
|
+
@company = company || QBWC.company_file_path
|
9
|
+
@worker_class = worker_class
|
10
|
+
@requests = requests
|
11
|
+
@data = data
|
12
|
+
@request_index = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def worker
|
16
|
+
worker_class.constantize.new
|
17
|
+
end
|
9
18
|
|
10
|
-
|
19
|
+
def process_response(qbxml_response, response, session, advance)
|
20
|
+
QBWC.logger.info "Processing response."
|
21
|
+
completed_request = requests[request_index]
|
22
|
+
advance_next_request if advance
|
23
|
+
QBWC.logger.info "Job '#{name}' received response: '#{qbxml_response}'." if QBWC.log_requests_and_responses
|
24
|
+
worker.handle_response(response, session, self, completed_request, data)
|
11
25
|
end
|
12
26
|
|
13
|
-
def
|
14
|
-
|
27
|
+
def advance_next_request
|
28
|
+
new_index = request_index + 1
|
29
|
+
QBWC.logger.info "Job '#{name}' advancing to request #'#{new_index}'."
|
30
|
+
self.request_index = new_index
|
15
31
|
end
|
16
32
|
|
17
33
|
def enable
|
18
|
-
|
34
|
+
self.enabled = true
|
19
35
|
end
|
20
36
|
|
21
37
|
def disable
|
22
|
-
|
38
|
+
self.enabled = false
|
39
|
+
end
|
40
|
+
|
41
|
+
def pending?
|
42
|
+
if !enabled?
|
43
|
+
QBWC.logger.info "Job '#{name}' not enabled."
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
sr = worker.should_run?(self)
|
47
|
+
QBWC.logger.info "Job '#{name}' should_run?: #{sr}."
|
48
|
+
return sr
|
23
49
|
end
|
24
50
|
|
25
51
|
def enabled?
|
26
52
|
@enabled
|
27
53
|
end
|
28
54
|
|
29
|
-
def
|
30
|
-
@
|
55
|
+
def requests
|
56
|
+
@requests
|
31
57
|
end
|
32
58
|
|
33
|
-
def
|
34
|
-
@
|
59
|
+
def requests=(r)
|
60
|
+
@requests = r
|
35
61
|
end
|
36
62
|
|
37
|
-
|
63
|
+
def data
|
64
|
+
@data
|
65
|
+
end
|
38
66
|
|
39
|
-
def
|
40
|
-
|
67
|
+
def data=(d)
|
68
|
+
@data = d
|
41
69
|
end
|
42
70
|
|
43
|
-
def
|
44
|
-
|
71
|
+
def request_index
|
72
|
+
@request_index
|
73
|
+
end
|
74
|
+
|
75
|
+
def request_index=(ri)
|
76
|
+
@request_index = ri
|
77
|
+
end
|
78
|
+
|
79
|
+
def requests_provided_when_job_added
|
80
|
+
@requests_provided_when_job_added
|
81
|
+
end
|
82
|
+
|
83
|
+
def requests_provided_when_job_added=(value)
|
84
|
+
@requests_provided_when_job_added = value
|
85
|
+
end
|
86
|
+
|
87
|
+
def next_request
|
88
|
+
# Generate and save the requests to run when starting the job.
|
89
|
+
if (requests.nil? || requests.empty?) && ! self.requests_provided_when_job_added
|
90
|
+
r = worker.requests(self)
|
91
|
+
r = [r] unless r.nil? || r.is_a?(Array)
|
92
|
+
self.requests = r
|
93
|
+
end
|
94
|
+
|
95
|
+
QBWC.logger.info("Requests available are '#{requests}'.") if QBWC.log_requests_and_responses
|
96
|
+
ri = request_index
|
97
|
+
QBWC.logger.info("Request index is '#{ri}'.")
|
98
|
+
return nil if ri.nil? || requests.nil? || ri >= requests.length
|
99
|
+
nr = requests[ri]
|
100
|
+
QBWC.logger.info("Next request is '#{nr}'.") if QBWC.log_requests_and_responses
|
101
|
+
return QBWC::Request.new(nr)
|
102
|
+
end
|
103
|
+
alias :next :next_request # Deprecated method name 'next'
|
104
|
+
|
105
|
+
def reset
|
106
|
+
self.request_index = 0
|
107
|
+
self.requests = [] unless self.requests_provided_when_job_added
|
45
108
|
end
|
46
109
|
|
47
110
|
end
|
data/lib/qbwc/railtie.rb
ADDED
data/lib/qbwc/request.rb
CHANGED
@@ -1,46 +1,37 @@
|
|
1
1
|
class QBWC::Request
|
2
2
|
|
3
3
|
attr_reader :request, :response_proc
|
4
|
-
attr_accessor :response, :error
|
5
4
|
|
6
|
-
def initialize(request
|
5
|
+
def initialize(request)
|
7
6
|
#Handle Cases for a request passed in as a Hash or String
|
8
7
|
#If it's a hash verify that it is properly wrapped with qbxml_msg_rq and xml_attributes for on_error events
|
9
8
|
#Allow strings of QBXML to be passed in directly.
|
10
9
|
case
|
11
10
|
when request.is_a?(Hash)
|
12
|
-
|
13
|
-
|
14
|
-
wrapped_request = { :qbxml_msgs_rq => {:xml_attributes => {"onError"=> QBWC::on_error } } }
|
15
|
-
wrapped_request[:qbxml_msgs_rq] = wrapped_request[:qbxml_msgs_rq].merge(request)
|
16
|
-
request = wrapped_request
|
17
|
-
end
|
18
|
-
|
19
|
-
@request = QBWC.parser.hash_to_qbxml(request)
|
11
|
+
request = self.class.wrap_request(request)
|
12
|
+
@request = QBWC.parser.to_qbxml(request, {:validate => true})
|
20
13
|
when request.is_a?(String)
|
21
14
|
@request = request
|
15
|
+
else
|
16
|
+
raise "Request '#{request}' must be a Hash or a String."
|
22
17
|
end
|
23
|
-
@response_proc = response_proc
|
24
|
-
end
|
25
|
-
|
26
|
-
def process_response
|
27
|
-
@response_proc && @response && @response_proc.call(response)
|
28
18
|
end
|
29
19
|
|
30
20
|
def to_qbxml
|
31
|
-
QBWC.parser.
|
21
|
+
QBWC.parser.to_qbxml(request)
|
32
22
|
end
|
33
23
|
|
34
24
|
def to_hash
|
35
|
-
QBWC.parser.
|
25
|
+
hash = QBWC.parser.from_qbxml(@request.to_s)["qbxml"]["qbxml_msgs_rq"]
|
26
|
+
hash.except('xml_attributes')
|
36
27
|
end
|
37
28
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
29
|
+
# Wrap a Hash request with qbxml_msgs_rq, if it's not already.
|
30
|
+
def self.wrap_request(request)
|
31
|
+
return request if request.keys.include?(:qbxml_msgs_rq)
|
32
|
+
wrapped_request = { :qbxml_msgs_rq => {:xml_attributes => {"onError"=> QBWC::on_error } } }
|
33
|
+
wrapped_request[:qbxml_msgs_rq] = wrapped_request[:qbxml_msgs_rq].merge(request)
|
34
|
+
return wrapped_request
|
44
35
|
end
|
45
36
|
|
46
37
|
end
|
data/lib/qbwc/session.rb
CHANGED
@@ -1,115 +1,143 @@
|
|
1
1
|
class QBWC::Session
|
2
|
-
include Enumerable
|
3
2
|
|
4
|
-
attr_reader :
|
5
|
-
|
3
|
+
attr_reader :user, :company, :ticket, :progress
|
4
|
+
attr_accessor :error, :status_code, :status_severity
|
6
5
|
|
7
6
|
@@session = nil
|
8
7
|
|
9
|
-
|
8
|
+
def self.get(ticket)
|
9
|
+
@@session
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(user = nil, company = nil, ticket = nil)
|
13
|
+
@user = user
|
14
|
+
@company = company
|
10
15
|
@current_job = nil
|
11
|
-
@
|
12
|
-
@
|
16
|
+
@error = nil
|
17
|
+
@progress = 0
|
18
|
+
@iterator_id = nil
|
19
|
+
@initial_job_count = pending_jobs.length
|
13
20
|
|
14
|
-
@
|
15
|
-
@qbwc_iterating = false
|
21
|
+
@ticket = ticket || Digest::SHA1.hexdigest("#{Rails.application.config.secret_token}#{Time.now.to_i}")
|
16
22
|
|
17
23
|
@@session = self
|
18
|
-
reset
|
24
|
+
reset(ticket.nil?)
|
25
|
+
end
|
26
|
+
|
27
|
+
def response_is_error?
|
28
|
+
self.error && self.status_severity == 'Error'
|
19
29
|
end
|
20
30
|
|
21
|
-
def
|
22
|
-
|
23
|
-
enabled_jobs.map { |j| j.reset }
|
24
|
-
@requests = build_request_generator(enabled_jobs)
|
31
|
+
def error_and_stop_requested?
|
32
|
+
response_is_error? && QBWC::on_error == 'stopOnError'
|
25
33
|
end
|
26
34
|
|
27
35
|
def finished?
|
28
|
-
|
36
|
+
self.progress == 100
|
37
|
+
end
|
38
|
+
|
39
|
+
def next_request
|
40
|
+
if current_job.nil? || error_and_stop_requested?
|
41
|
+
self.progress = 100
|
42
|
+
return nil
|
43
|
+
end
|
44
|
+
until (request = current_job.next_request) do
|
45
|
+
pending_jobs.shift
|
46
|
+
reset(true) or break
|
47
|
+
end
|
48
|
+
jobs_completed = @initial_job_count - pending_jobs.length
|
49
|
+
self.progress = ((jobs_completed.to_f / @initial_job_count.to_f ) * 100).to_i
|
50
|
+
request
|
29
51
|
end
|
52
|
+
alias :next :next_request # Deprecated method name 'next'
|
53
|
+
|
54
|
+
def current_request
|
55
|
+
request = self.next_request
|
56
|
+
if request && self.iterator_id.present?
|
57
|
+
request = request.to_hash
|
58
|
+
request.delete('xml_attributes')
|
59
|
+
request.values.first['xml_attributes'] = {'iterator' => 'Continue', 'iteratorID' => self.iterator_id}
|
60
|
+
request = QBWC::Request.new(request)
|
61
|
+
end
|
62
|
+
request
|
63
|
+
end
|
64
|
+
|
65
|
+
def request_to_send
|
66
|
+
current_job_name = current_job.name
|
67
|
+
request = current_request.try(:request) || ''
|
68
|
+
QBWC.logger.info("Sending request from job #{current_job_name}")
|
69
|
+
QBWC.logger.info(request) if QBWC.log_requests_and_responses
|
30
70
|
|
31
|
-
|
32
|
-
@requests.alive? ? @requests.resume : nil
|
71
|
+
request
|
33
72
|
end
|
34
73
|
|
35
74
|
def response=(qbxml_response)
|
36
75
|
begin
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
else
|
43
|
-
@current_request.process_response
|
76
|
+
QBWC.logger.info 'Parsing response.'
|
77
|
+
unless qbxml_response.nil?
|
78
|
+
response = QBWC.parser.from_qbxml(qbxml_response)["qbxml"]["qbxml_msgs_rs"].except("xml_attributes")
|
79
|
+
response = response[response.keys.first]
|
80
|
+
parse_response_header(response)
|
44
81
|
end
|
82
|
+
self.current_job.process_response(qbxml_response, response, self, iterator_id.blank?) unless self.current_job.nil?
|
83
|
+
self.next_request # search next request
|
84
|
+
|
45
85
|
rescue => e
|
46
|
-
|
47
|
-
|
48
|
-
|
86
|
+
self.error = e.message
|
87
|
+
QBWC.logger.warn "An error occured in QBWC::Session: #{e.message}"
|
88
|
+
QBWC.logger.warn e.backtrace.join("\n")
|
49
89
|
end
|
90
|
+
end
|
50
91
|
|
92
|
+
def save
|
51
93
|
end
|
52
94
|
|
53
|
-
def
|
54
|
-
|
95
|
+
def destroy
|
96
|
+
self.freeze
|
97
|
+
@@session = nil
|
55
98
|
end
|
56
99
|
|
57
|
-
|
100
|
+
protected
|
58
101
|
|
59
|
-
|
60
|
-
|
61
|
-
end
|
102
|
+
attr_accessor :current_job, :iterator_id
|
103
|
+
attr_writer :progress
|
62
104
|
|
63
|
-
|
64
|
-
Fiber.new do
|
65
|
-
jobs.each do |j|
|
66
|
-
@current_job = j
|
67
|
-
while (r = next_request)
|
68
|
-
@current_request = r
|
69
|
-
Fiber.yield r
|
70
|
-
end
|
71
|
-
end
|
105
|
+
private
|
72
106
|
|
73
|
-
|
74
|
-
|
75
|
-
|
107
|
+
def reset(reset_job = false)
|
108
|
+
self.current_job = pending_jobs.first
|
109
|
+
self.current_job.reset if reset_job && self.current_job
|
110
|
+
return self.current_job
|
76
111
|
end
|
77
112
|
|
78
|
-
def
|
79
|
-
|
113
|
+
def pending_jobs
|
114
|
+
@pending_jobs ||= QBWC.pending_jobs(@company)
|
80
115
|
end
|
81
116
|
|
82
117
|
def parse_response_header(response)
|
83
|
-
|
118
|
+
QBWC.logger.info 'Parsing headers.'
|
84
119
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
if iterator_remaining_count.to_i > 0
|
93
|
-
@qbwc_iterating = true
|
94
|
-
new_request = @current_request.to_hash
|
95
|
-
new_request.delete('xml_attributes')
|
96
|
-
new_request.values.first['xml_attributes'] = {'iterator' => 'Continue', 'iteratorID' => iterator_id}
|
97
|
-
@qbwc_iterator_queue << QBWC::Request.new(new_request, @current_request.response_proc)
|
98
|
-
else
|
99
|
-
@qbwc_iterating = false
|
100
|
-
end
|
120
|
+
self.iterator_id = nil
|
121
|
+
self.error = nil
|
122
|
+
self.status_code = nil
|
123
|
+
self.status_severity = nil
|
124
|
+
|
125
|
+
if response.is_a? Array
|
126
|
+
response = response.find {|r| r.is_a?(Hash) && r['xml_attributes'] && r['xml_attributes']['statusCode'].to_i > 1} || response.first
|
101
127
|
end
|
102
|
-
|
128
|
+
return unless response.is_a?(Hash) && response['xml_attributes']
|
103
129
|
|
104
|
-
|
130
|
+
@status_code, @status_severity, status_message, iterator_remaining_count, iterator_id = \
|
131
|
+
response['xml_attributes'].values_at('statusCode', 'statusSeverity', 'statusMessage',
|
132
|
+
'iteratorRemainingCount', 'iteratorID')
|
133
|
+
QBWC.logger.info "Parsed headers. statusSeverity: '#{status_severity}'. statusCode: '#{@status_code}'"
|
105
134
|
|
106
|
-
|
107
|
-
|
108
|
-
|
135
|
+
if @status_severity == 'Error' || @status_severity == 'Warn'
|
136
|
+
self.error = "QBWC #{@status_severity.upcase}: #{@status_code} - #{status_message}"
|
137
|
+
@status_severity == 'Error' ? QBWC.logger.error(self.error) : QBWC.logger.warn(self.error)
|
138
|
+
end
|
109
139
|
|
110
|
-
|
140
|
+
self.iterator_id = iterator_id if iterator_remaining_count.to_i > 0 && @status_severity != 'Error'
|
111
141
|
|
112
|
-
|
113
|
-
@@session
|
114
|
-
end
|
142
|
+
end
|
115
143
|
end
|