quickbooks-ruby 0.6.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f0f3695093279eed43fc6d76197a6b5cf69142ef0edc91f680981c1c9b30300
4
- data.tar.gz: 04321daa044502c5bea12a6530323e50fc61e6838b6290598ad535ab11cfa885
3
+ metadata.gz: d1f6e851cfb68ae7f6acf08a355b9d3e917d92f98a0bac9c53098f1a4c8b2f6f
4
+ data.tar.gz: 9db0566d15faef2b617f35c288eee7762ef0e7714586f6c6b9b6dd5add1cb3b3
5
5
  SHA512:
6
- metadata.gz: 2a0c35ff4ccbaf55a1846b00118c6e20de33f0780f477e459c68d6b6a12804c6e97de05c6e00a2a0a8da9c7faaa9ea0d330cf623a8d1036d985b7c2c18a542da
7
- data.tar.gz: 283064cdffe11bbddb36b52d237a25635da700b6cb850391570c803a63d053adc473b458df57c66cdc0e7058ed2b997ad5e2a033d7aa64b609cb2ee4fb25306b
6
+ metadata.gz: 61f501677c4c382b9d4e1200158dc9daac57e12d51274c7eeeabb4415d41bec14a80e32b2cdea40923dcc962aac9e4593bbc83f60f389552aaac3301e241e6c2
7
+ data.tar.gz: 966a4d88b2f45eaa8d6bea233cca742b5d3cdeee1b9340f0b060ea03efade653b432d38e222fd47a13057f502991c477946347dfed4f155868756060260229e1
@@ -7,12 +7,20 @@ require 'uri'
7
7
  require 'date'
8
8
  require 'forwardable'
9
9
  require 'oauth'
10
+ require 'oauth2'
10
11
  require 'net/http/post/multipart'
11
12
  require 'quickbooks/util/collection'
12
13
  require 'quickbooks/util/logging'
13
14
  require 'quickbooks/util/http_encoding_helper'
14
15
  require 'quickbooks/util/name_entity'
15
16
  require 'quickbooks/util/query_builder'
17
+ require 'quickbooks/faraday/middleware/gzip'
18
+
19
+ #== OAuth Responses
20
+ require 'quickbooks/service/responses/oauth_http_response'
21
+ require 'quickbooks/service/responses/methods'
22
+ require 'quickbooks/service/responses/oauth1_http_response'
23
+ require 'quickbooks/service/responses/oauth2_http_response'
16
24
 
17
25
  #== Models
18
26
  require 'quickbooks/model/definition'
@@ -176,9 +184,11 @@ require 'quickbooks/service/transfer'
176
184
  require 'quickbooks/service/change_data_capture'
177
185
  require 'quickbooks/service/refund_receipt_change'
178
186
 
187
+ # Register Faraday Middleware
188
+ Faraday::Middleware.register_middleware :gzip => lambda { Gzip }
189
+
179
190
  module Quickbooks
180
191
  @@sandbox_mode = false
181
-
182
192
  @@logger = nil
183
193
 
184
194
  class << self
@@ -239,4 +249,10 @@ module Quickbooks
239
249
  end
240
250
  end
241
251
 
252
+ class InvalidOauthAccessTokenObject < StandardError
253
+ def initialize(access_token)
254
+ super("Expected access token to be an instance of OAuth::AccessToken or OAuth2::AccessToken, got #{access_token.class}.")
255
+ end
256
+ end
257
+
242
258
  end
@@ -0,0 +1,72 @@
1
+ # https://github.com/lostisland/faraday_middleware/blob/master/lib/faraday_middleware/gzip.rb
2
+
3
+ require 'faraday'
4
+
5
+ # Middleware to automatically decompress response bodies. If the
6
+ # "Accept-Encoding" header wasn't set in the request, this sets it to
7
+ # "gzip,deflate" and appropriately handles the compressed response from the
8
+ # server. This resembles what Ruby 1.9+ does internally in Net::HTTP#get.
9
+ #
10
+ # This middleware is NOT necessary when these adapters are used:
11
+ # - net_http on Ruby 1.9+
12
+ # - net_http_persistent on Ruby 2.0+
13
+ # - em_http
14
+ class Gzip < Faraday::Middleware
15
+ dependency 'zlib'
16
+
17
+ ACCEPT_ENCODING = 'Accept-Encoding'.freeze
18
+ CONTENT_ENCODING = 'Content-Encoding'.freeze
19
+ CONTENT_LENGTH = 'Content-Length'.freeze
20
+ SUPPORTED_ENCODINGS = 'gzip,deflate,br'.freeze
21
+ RUBY_ENCODING = '1.9'.respond_to?(:force_encoding)
22
+
23
+ def call(env)
24
+ env[:request_headers][ACCEPT_ENCODING] ||= SUPPORTED_ENCODINGS
25
+ @app.call(env).on_complete do |response_env|
26
+ case response_env[:response_headers][CONTENT_ENCODING]
27
+ when 'gzip'
28
+ reset_body(response_env, &method(:uncompress_gzip))
29
+ when 'deflate'
30
+ reset_body(response_env, &method(:inflate))
31
+ when 'br'
32
+ reset_body(response_env, &method(:brotli_inflate))
33
+ end
34
+ end
35
+ end
36
+
37
+ def reset_body(env)
38
+ env[:body] = yield(env[:body])
39
+ env[:response_headers].delete(CONTENT_ENCODING)
40
+ env[:response_headers][CONTENT_LENGTH] = env[:body].length
41
+ end
42
+
43
+ def uncompress_gzip(body)
44
+ io = StringIO.new(body)
45
+ gzip_reader = if RUBY_ENCODING
46
+ Zlib::GzipReader.new(io, :encoding => 'ASCII-8BIT')
47
+ else
48
+ Zlib::GzipReader.new(io)
49
+ end
50
+ gzip_reader.read
51
+ end
52
+
53
+ def inflate(body)
54
+ # Inflate as a DEFLATE (RFC 1950+RFC 1951) stream
55
+ Zlib::Inflate.inflate(body)
56
+ rescue Zlib::DataError
57
+ # Fall back to inflating as a "raw" deflate stream which
58
+ # Microsoft servers return
59
+ inflate = Zlib::Inflate.new(-Zlib::MAX_WBITS)
60
+ begin
61
+ inflate.inflate(body)
62
+ ensure
63
+ inflate.close
64
+ end
65
+ end
66
+
67
+ def brotli_inflate(body)
68
+ self.class.dependency 'brotli'
69
+
70
+ Brotli.inflate(body)
71
+ end
72
+ end
@@ -2,6 +2,7 @@ module Quickbooks
2
2
  module Model
3
3
  class BaseModel
4
4
  include Definition
5
+ include ActiveModel::AttributeMethods
5
6
  include ActiveModel::Validations
6
7
  include Validator
7
8
  include ROXML
@@ -54,7 +55,7 @@ module Quickbooks
54
55
  def inspect
55
56
  # it would be nice if we could inspect all the children,
56
57
  # but it's likely to blow the stack in some cases
57
- "#<#{self.class} " +
58
+ "#<#{self.class} " +
58
59
  "#{attributes.map{|k,v| "#{k}: #{v.nil? ? 'nil' : v.to_s }"}.join ", "}>"
59
60
  end
60
61
  class << self
@@ -3,7 +3,8 @@ module Quickbooks
3
3
  class GroupLineDetail < BaseModel
4
4
  include HasLineItems
5
5
 
6
- xml_accessor :group_item_ref, :from => 'CustomerRef', :as => BaseReference
6
+ xml_accessor :id, :from => 'Id'
7
+ xml_accessor :group_item_ref, :from => 'GroupItemRef', :as => BaseReference
7
8
  xml_accessor :quantity, :from => 'Quantity', :as => BigDecimal, :to_xml => to_xml_big_decimal
8
9
  xml_accessor :line_items, :from => 'Line', :as => [Line]
9
10
 
@@ -17,6 +17,7 @@ module Quickbooks
17
17
  XML_COLLECTION_NODE = "Invoice"
18
18
  XML_NODE = "Invoice"
19
19
  EMAIL_STATUS_NEED_TO_SEND = 'NeedToSend'
20
+ MINORVERSION = 37
20
21
 
21
22
  xml_accessor :id, :from => 'Id'
22
23
  xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
@@ -24,6 +25,7 @@ module Quickbooks
24
25
  xml_accessor :custom_fields, :from => 'CustomField', :as => [CustomField]
25
26
  xml_accessor :auto_doc_number, :from => 'AutoDocNumber' # See auto_doc_number! method below for usage
26
27
  xml_accessor :doc_number, :from => 'DocNumber'
28
+ xml_accessor :invoice_link, :from => 'InvoiceLink'
27
29
  xml_accessor :txn_date, :from => 'TxnDate', :as => Date
28
30
  xml_accessor :currency_ref, :from => 'CurrencyRef', :as => BaseReference
29
31
  xml_accessor :exchange_rate, :from => 'ExchangeRate', :as => BigDecimal, :to_xml => to_xml_big_decimal
@@ -1,12 +1,15 @@
1
1
  module Quickbooks
2
2
  module Model
3
3
  class Line < BaseModel
4
+ require 'quickbooks/model/group_line_detail'
5
+
4
6
  #== Constants
5
7
  SALES_ITEM_LINE_DETAIL = 'SalesItemLineDetail'
6
8
  SUB_TOTAL_LINE_DETAIL = 'SubTotalLineDetail'
7
9
  PAYMENT_LINE_DETAIL = 'PaymentLineDetail'
8
10
  DISCOUNT_LINE_DETAIL = 'DiscountLineDetail'
9
11
  JOURNAL_ENTRY_LINE_DETAIL = 'JournalEntryLineDetail'
12
+ GROUP_LINE_DETAIL = 'GroupLineDetail'
10
13
 
11
14
  xml_accessor :id, :from => 'Id'
12
15
  xml_accessor :line_num, :from => 'LineNum', :as => Integer
@@ -22,6 +25,7 @@ module Quickbooks
22
25
  xml_accessor :payment_line_detail, :from => 'PaymentLineDetail', :as => PaymentLineDetail
23
26
  xml_accessor :discount_line_detail, :from => 'DiscountLineDetail', :as => DiscountOverride
24
27
  xml_accessor :journal_entry_line_detail, :from => 'JournalEntryLineDetail', :as => JournalEntryLineDetail
28
+ xml_accessor :group_line_detail, :from => 'GroupLineDetail', :as => GroupLineDetail
25
29
 
26
30
  def initialize(*args)
27
31
  self.linked_transactions ||= []
@@ -73,6 +77,13 @@ module Quickbooks
73
77
  yield self.journal_entry_line_detail if block_given?
74
78
  end
75
79
 
80
+ def group_line!
81
+ self.detail_type = GROUP_LINE_DETAIL
82
+ self.group_line_detail = GroupLineDetail.new
83
+
84
+ yield self.group_line_detail if block_given?
85
+ end
86
+
76
87
  private
77
88
 
78
89
  def update_linked_transactions(txn_ids, txn_type)
@@ -43,6 +43,7 @@ module Quickbooks
43
43
  validates_inclusion_of :name_of, :in => NAMEOF_OPTIONS
44
44
  validate :existence_of_employee_ref, :if => Proc.new { |ta| ta.name_of == "Employee" }
45
45
  validate :existence_of_vendor_ref, :if => Proc.new { |ta| ta.name_of == "Vendor" }
46
+ validates :description, length: { maximum: 4000 }
46
47
 
47
48
  def existence_of_employee_ref
48
49
  if employee_ref.nil? || (employee_ref && employee_ref.value == 0)
@@ -3,7 +3,8 @@ module Quickbooks
3
3
  class AccessToken < BaseService
4
4
 
5
5
  RENEW_URL = "https://appcenter.intuit.com/api/v1/connection/reconnect"
6
- DISCONNECT_URL = "https://appcenter.intuit.com/api/v1/connection/disconnect"
6
+ DISCONNECT_URL_OAUTH1 = "https://appcenter.intuit.com/api/v1/connection/disconnect"
7
+ DISCONNECT_URL_OAUTH2 = "https://developer.api.intuit.com/v2/oauth2/tokens/revoke"
7
8
 
8
9
  # https://developer.intuit.com/docs/0025_quickbooksapi/0053_auth_auth/oauth_management_api#Reconnect
9
10
  def renew
@@ -21,16 +22,24 @@ module Quickbooks
21
22
 
22
23
  # https://developer.intuit.com/docs/0025_quickbooksapi/0053_auth_auth/oauth_management_api#Disconnect
23
24
  def disconnect
24
- result = nil
25
- response = do_http_get(DISCONNECT_URL)
26
- if response
27
- code = response.code.to_i
28
- if code == 200
29
- result = Quickbooks::Model::AccessTokenResponse.from_xml(response.plain_body)
25
+ if oauth_v1?
26
+ response = do_http_get(DISCONNECT_URL_OAUTH1)
27
+ if response && response.code.to_i == 200
28
+ Quickbooks::Model::AccessTokenResponse.from_xml(response.plain_body)
30
29
  end
31
- end
30
+ elsif oauth_v2?
31
+ conn = Faraday.new
32
+ conn.basic_auth oauth.client.id, oauth.client.secret
33
+ response = conn.post(DISCONNECT_URL_OAUTH2, token: oauth.refresh_token || oauth.token)
32
34
 
33
- result
35
+ if response.success?
36
+ Quickbooks::Model::AccessTokenResponse.new(error_code: "0")
37
+ else
38
+ Quickbooks::Model::AccessTokenResponse.new(
39
+ error_code: response.status.to_s, error_message: response.reason_phrase
40
+ )
41
+ end
42
+ end
34
43
  end
35
44
 
36
45
  end
@@ -25,6 +25,7 @@ module Quickbooks
25
25
 
26
26
  def access_token=(token)
27
27
  @oauth = token
28
+ rebuild_connection!
28
29
  end
29
30
 
30
31
  def company_id=(company_id)
@@ -36,6 +37,27 @@ module Quickbooks
36
37
  @company_id = company_id
37
38
  end
38
39
 
40
+ def oauth_v1?
41
+ @oauth.is_a? OAuth::AccessToken
42
+ end
43
+
44
+ def oauth_v2?
45
+ @oauth.is_a? OAuth2::AccessToken
46
+ end
47
+
48
+ # [OAuth2] The default Faraday connection does not have gzip or multipart support.
49
+ # We need to reset the existing connection and build a new one.
50
+ def rebuild_connection!
51
+ return unless oauth_v2?
52
+ @oauth.client.connection = nil
53
+ @oauth.client.connection.build do |builder|
54
+ builder.use :gzip
55
+ builder.request :multipart
56
+ builder.request :url_encoded
57
+ builder.adapter :net_http
58
+ end
59
+ end
60
+
39
61
  def url_for_resource(resource)
40
62
  "#{url_for_base}/#{resource}"
41
63
  end
@@ -61,7 +83,7 @@ module Quickbooks
61
83
  query ||= default_model_query
62
84
  query = "#{query} STARTPOSITION #{start_position} MAXRESULTS #{max_results}"
63
85
 
64
- "#{url_for_base}/query?query=#{URI.encode_www_form_component(query)}"
86
+ "#{url_for_base}/query?query=#{CGI.escape(query)}"
65
87
  end
66
88
 
67
89
  private
@@ -189,7 +211,8 @@ module Quickbooks
189
211
  unless headers.has_key?('Accept-Encoding')
190
212
  headers['Accept-Encoding'] = HTTP_ACCEPT_ENCODING
191
213
  end
192
- @oauth.get(url, headers)
214
+ raw_response = oauth_get(url, headers)
215
+ Quickbooks::Service::Responses::OAuthHttpResponse.wrap(raw_response)
193
216
  end
194
217
 
195
218
  def do_http_file_upload(uploadIO, url, metadata = nil)
@@ -229,21 +252,48 @@ module Quickbooks
229
252
  log_request_body(body)
230
253
  log "REQUEST HEADERS = #{headers.inspect}"
231
254
 
232
- response = case method
233
- when :get
234
- @oauth.get(url, headers)
235
- when :post
236
- @oauth.post(url, body, headers)
237
- when :upload
238
- @oauth.post_with_multipart(url, body, headers)
239
- else
240
- raise "Do not know how to perform that HTTP operation"
241
- end
255
+ raw_response = case method
256
+ when :get
257
+ oauth_get(url, headers)
258
+ when :post
259
+ oauth_post(url, body, headers)
260
+ when :upload
261
+ oauth_post_with_multipart(url, body, headers)
262
+ else
263
+ raise "Do not know how to perform that HTTP operation"
264
+ end
242
265
 
243
- if response.code.to_i == 302 && [:get, :post].include?(method)
244
- do_http(method, response['location'], body, headers)
266
+ response = Quickbooks::Service::Responses::OAuthHttpResponse.wrap(raw_response)
267
+ check_response(response, request: body)
268
+ end
269
+
270
+ def oauth_get(url, headers)
271
+ if oauth_v1?
272
+ @oauth.get(url, headers)
273
+ elsif oauth_v2?
274
+ @oauth.get(url, headers: headers, raise_errors: false)
245
275
  else
246
- check_response(response, :request => body)
276
+ raise InvalidOauthAccessTokenObject.new(@oauth)
277
+ end
278
+ end
279
+
280
+ def oauth_post(url, body, headers)
281
+ if oauth_v1?
282
+ @oauth.post(url, body, headers)
283
+ elsif oauth_v2?
284
+ @oauth.post(url, headers: headers, body: body, raise_errors: false)
285
+ else
286
+ raise InvalidOauthAccessTokenObject.new(@oauth)
287
+ end
288
+ end
289
+
290
+ def oauth_post_with_multipart(url, body, headers)
291
+ if oauth_v1?
292
+ @oauth.post_with_multipart(url, body, headers)
293
+ elsif oauth_v2?
294
+ @oauth.post_with_multipart(url, headers: headers, body: body, raise_errors: false)
295
+ else
296
+ raise InvalidOauthAccessTokenObject.new(@oauth)
247
297
  end
248
298
  end
249
299
 
@@ -258,12 +308,11 @@ module Quickbooks
258
308
  end
259
309
 
260
310
  def check_response(response, options = {})
261
- log "------ RESPONSE_HEADERS -----"
262
- if log?
263
- response.each_header {|h| log "#{h}: #{response[h]}"}
264
- end
265
311
  log "------ QUICKBOOKS-RUBY RESPONSE ------"
266
312
  log "RESPONSE CODE = #{response.code}"
313
+ if response.respond_to?(:headers)
314
+ log "RESPONSE HEADERS = #{response.headers}"
315
+ end
267
316
  log_response_body(response)
268
317
  status = response.code.to_i
269
318
  case status
@@ -293,7 +342,7 @@ module Quickbooks
293
342
  when 429
294
343
  message = parse_intuit_error[:message]
295
344
  raise Quickbooks::TooManyRequests, message
296
- when 502, 503, 504
345
+ when 503, 504
297
346
  raise Quickbooks::ServiceUnavailable
298
347
  else
299
348
  raise "HTTP Error Code: #{status}, Msg: #{response.plain_body}"
@@ -305,6 +354,8 @@ module Quickbooks
305
354
  if is_json?
306
355
  log ">>>>#{response.plain_body.inspect}"
307
356
  parse_json(response.plain_body)
357
+ elsif is_pdf?
358
+ log("BODY is a PDF : not dumping")
308
359
  else
309
360
  log(log_xml(response.plain_body))
310
361
  parse_xml(response.plain_body)
@@ -315,8 +366,26 @@ module Quickbooks
315
366
  log "REQUEST BODY:"
316
367
  if is_json?
317
368
  log(body.inspect)
369
+ elsif is_pdf?
370
+ log("BODY is a PDF : not dumping")
318
371
  else
319
- log(log_xml(body))
372
+ #multipart request for uploads arrive here in a Hash with UploadIO vals
373
+ if body.is_a?(Hash)
374
+ body.each do |k,v|
375
+ log('BODY PART:')
376
+ val_content = v.inspect
377
+ if v.is_a?(UploadIO)
378
+ if v.content_type == 'application/xml'
379
+ if v.io.is_a?(StringIO)
380
+ val_content = log_xml(v.io.string)
381
+ end
382
+ end
383
+ end
384
+ log("#{k}: #{val_content}")
385
+ end
386
+ else
387
+ log(log_xml(body))
388
+ end
320
389
  end
321
390
  end
322
391
 
@@ -335,9 +404,13 @@ module Quickbooks
335
404
  end
336
405
 
337
406
  def response_is_error?
338
- @last_response_xml.xpath("//xmlns:IntuitResponse/xmlns:Fault")[0] != nil
339
- rescue Nokogiri::XML::XPath::SyntaxError => exception
340
- true
407
+ begin
408
+ @last_response_xml.xpath("//xmlns:IntuitResponse/xmlns:Fault")[0] != nil
409
+ rescue Nokogiri::XML::XPath::SyntaxError => exception
410
+ #puts @last_response_xml.to_xml.to_s
411
+ #puts "WTF: #{exception.inspect}:#{exception.backtrace.join("\n")}"
412
+ true
413
+ end
341
414
  end
342
415
 
343
416
  def parse_intuit_error
@@ -6,10 +6,24 @@ module Quickbooks
6
6
  delete_by_query_string(invoice)
7
7
  end
8
8
 
9
+ def url_for_resource(resource)
10
+ url = super(resource)
11
+ end
12
+
13
+ def fetch_by_id(id, params = {})
14
+ url = "#{url_for_base}/invoice/#{id}?minorversion=#{Quickbooks::Model::Invoice::MINORVERSION}"
15
+ fetch_object(model, url, params)
16
+ end
17
+
18
+ def url_for_query(query = nil, start_position = 1, max_results = 20, options = {})
19
+ url = super(query, start_position, max_results, options)
20
+ "#{url}&minorversion=#{Quickbooks::Model::Invoice::MINORVERSION}"
21
+ end
22
+
9
23
  def send(invoice, email_address=nil)
10
24
  query = email_address.present? ? "?sendTo=#{email_address}" : ""
11
25
  url = "#{url_for_resource(model::REST_RESOURCE)}/#{invoice.id}/send#{query}"
12
- response = do_http_post(url,{})
26
+ response = do_http_post(url, "", {}, { 'Content-Type' => 'application/octet-stream' })
13
27
  if response.code.to_i == 200
14
28
  model.from_xml(parse_singular_entity_response(model, response.plain_body))
15
29
  else
@@ -0,0 +1,17 @@
1
+ module Quickbooks
2
+ module Service
3
+ module Responses
4
+ module Methods
5
+
6
+ def body
7
+ raise "implement me"
8
+ end
9
+
10
+ def code
11
+ raise "implement me"
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,42 @@
1
+ module Quickbooks
2
+ module Service
3
+ module Responses
4
+
5
+ class OAuth1HttpResponse < OAuthHttpResponse
6
+
7
+ attr_accessor :real_response
8
+
9
+ # net/http response
10
+ def initialize(response)
11
+ @real_response = response
12
+ end
13
+
14
+ def version
15
+ 1
16
+ end
17
+
18
+ def code
19
+ @real_response.code.to_i
20
+ end
21
+
22
+ def plain_body
23
+ if @real_response.respond_to?(:plain_body)
24
+ @real_response.plain_body
25
+ else
26
+ nil
27
+ end
28
+ end
29
+
30
+ def headers
31
+ if @real_response.respond_to?(:headers)
32
+ @real_response.headers
33
+ else
34
+ nil
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ module Quickbooks
2
+ module Service
3
+ module Responses
4
+
5
+ class OAuth2HttpResponse
6
+ include Quickbooks::Service::Responses::Methods
7
+
8
+ attr_accessor :real_response
9
+
10
+ # response : Faraday response
11
+ def initialize(response)
12
+ @real_response = response
13
+ end
14
+
15
+ def version
16
+ 2
17
+ end
18
+
19
+ def body
20
+ @real_response.body
21
+ end
22
+
23
+ def plain_body
24
+ body
25
+ end
26
+
27
+ def code
28
+ @real_response.status.to_i
29
+ end
30
+
31
+ def headers
32
+ if @real_response.respond_to?(:headers)
33
+ @real_response.headers
34
+ else
35
+ nil
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ module Quickbooks
2
+ module Service
3
+ module Responses
4
+
5
+ # This class just proxies and returns a wrapped response so that callers
6
+ # can invoke a common interface
7
+ class OAuthHttpResponse
8
+
9
+ def self.wrap(response)
10
+ if response.is_a?(OAuth2::Response)
11
+ Quickbooks::Service::Responses::OAuth2HttpResponse.new(response)
12
+ else
13
+ Quickbooks::Service::Responses::OAuth1HttpResponse.new(response)
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -25,6 +25,10 @@ module Quickbooks
25
25
  end until results.count < per_page
26
26
  end
27
27
 
28
+ def exists?(field, selector, options={})
29
+ find_by(field, selector, options).count > 0
30
+ end
31
+
28
32
  def find_by(field, selector, options={})
29
33
  if field.class == Symbol
30
34
  field = field.to_s.camelcase
@@ -9,7 +9,7 @@ module Quickbooks
9
9
  # attachable: Quickbooks::Model::Attachable meta-data details, can be null
10
10
  def upload(path_to_file, mime_type, attachable = nil)
11
11
  url = url_for_resource("upload")
12
- uploadIO = UploadIO.new(path_to_file, mime_type)
12
+ uploadIO = class_for_io.new(path_to_file, mime_type)
13
13
  response = do_http_file_upload(uploadIO, url, attachable)
14
14
  prefix = "AttachableResponse/xmlns:Attachable"
15
15
  if response.code.to_i == 200
@@ -19,6 +19,10 @@ module Quickbooks
19
19
  end
20
20
  end
21
21
 
22
+ def class_for_io
23
+ oauth.is_a?(OAuth2::AccessToken) ? Faraday::UploadIO : UploadIO
24
+ end
25
+
22
26
  def download(uploadId)
23
27
  url = url_for_resource("download/#{uploadId}")
24
28
  do_http_get(url, {}, headers)
@@ -72,3 +72,14 @@ OAuth::AccessToken.class_eval do
72
72
  request(:multipart_post, *args)
73
73
  end
74
74
  end
75
+
76
+ OAuth2::AccessToken.class_eval do
77
+
78
+ def post_with_multipart(*args)
79
+ multipart_post *args
80
+ end
81
+
82
+ def multipart_post(*args)
83
+ request(:post, *args)
84
+ end
85
+ end
@@ -1,5 +1,5 @@
1
1
  module Quickbooks
2
2
 
3
- VERSION = "0.6.7"
3
+ VERSION = "1.0.0"
4
4
 
5
5
  end
metadata CHANGED
@@ -1,49 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quickbooks-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.7
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Caughlan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-24 00:00:00.000000000 Z
11
+ date: 2019-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: oauth2
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - "~>"
18
32
  - !ruby/object:Gem::Version
19
- version: 0.4.5
33
+ version: '1.4'
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: 0.4.5
40
+ version: '1.4'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: roxml
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 3.3.1
34
- - - "<"
45
+ - - '='
35
46
  - !ruby/object:Gem::Version
36
- version: '4.1'
47
+ version: 4.0.0
37
48
  type: :runtime
38
49
  prerelease: false
39
50
  version_requirements: !ruby/object:Gem::Requirement
40
51
  requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 3.3.1
44
- - - "<"
52
+ - - '='
45
53
  - !ruby/object:Gem::Version
46
- version: '4.1'
54
+ version: 4.0.0
47
55
  - !ruby/object:Gem::Dependency
48
56
  name: nokogiri
49
57
  requirement: !ruby/object:Gem::Requirement
@@ -143,19 +151,33 @@ dependencies:
143
151
  - !ruby/object:Gem::Version
144
152
  version: 2.14.1
145
153
  - !ruby/object:Gem::Dependency
146
- name: fakeweb
154
+ name: webmock
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: dotenv
147
169
  requirement: !ruby/object:Gem::Requirement
148
170
  requirements:
149
171
  - - '='
150
172
  - !ruby/object:Gem::Version
151
- version: 1.3.0
173
+ version: 2.2.1
152
174
  type: :development
153
175
  prerelease: false
154
176
  version_requirements: !ruby/object:Gem::Requirement
155
177
  requirements:
156
178
  - - '='
157
179
  - !ruby/object:Gem::Version
158
- version: 1.3.0
180
+ version: 2.2.1
159
181
  description: QBO V3 REST API to Quickbooks Online
160
182
  email: toolbag@gmail.com
161
183
  executables: []
@@ -163,6 +185,7 @@ extensions: []
163
185
  extra_rdoc_files: []
164
186
  files:
165
187
  - lib/quickbooks-ruby.rb
188
+ - lib/quickbooks/faraday/middleware/gzip.rb
166
189
  - lib/quickbooks/model/access_token_response.rb
167
190
  - lib/quickbooks/model/account.rb
168
191
  - lib/quickbooks/model/account_based_expense_line_detail.rb
@@ -305,6 +328,10 @@ files:
305
328
  - lib/quickbooks/service/refund_receipt.rb
306
329
  - lib/quickbooks/service/refund_receipt_change.rb
307
330
  - lib/quickbooks/service/reports.rb
331
+ - lib/quickbooks/service/responses/methods.rb
332
+ - lib/quickbooks/service/responses/oauth1_http_response.rb
333
+ - lib/quickbooks/service/responses/oauth2_http_response.rb
334
+ - lib/quickbooks/service/responses/oauth_http_response.rb
308
335
  - lib/quickbooks/service/sales_receipt.rb
309
336
  - lib/quickbooks/service/service_crud.rb
310
337
  - lib/quickbooks/service/service_crud_json.rb