quickbooks-ruby 1.0.1 → 2.0.7

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/lib/quickbooks/model/account.rb +0 -1
  3. data/lib/quickbooks/model/account_based_expense_line_detail.rb +1 -0
  4. data/lib/quickbooks/model/base_model.rb +1 -0
  5. data/lib/quickbooks/model/bill.rb +2 -0
  6. data/lib/quickbooks/model/bill_line_item.rb +2 -0
  7. data/lib/quickbooks/model/customer.rb +6 -3
  8. data/lib/quickbooks/model/customer_type.rb +15 -0
  9. data/lib/quickbooks/model/invoice.rb +10 -2
  10. data/lib/quickbooks/model/item.rb +2 -4
  11. data/lib/quickbooks/model/item_based_expense_line_detail.rb +1 -0
  12. data/lib/quickbooks/model/preferences.rb +23 -5
  13. data/lib/quickbooks/model/purchase_change.rb +7 -0
  14. data/lib/quickbooks/model/purchase_line_item.rb +1 -0
  15. data/lib/quickbooks/model/purchase_order.rb +2 -1
  16. data/lib/quickbooks/model/report.rb +12 -1
  17. data/lib/quickbooks/model/sales_item_line_detail.rb +1 -0
  18. data/lib/quickbooks/model/sales_receipt.rb +1 -0
  19. data/lib/quickbooks/model/transaction_tax_detail.rb +1 -1
  20. data/lib/quickbooks/model/vendor.rb +1 -0
  21. data/lib/quickbooks/model/vendor_credit.rb +2 -0
  22. data/lib/quickbooks/service/access_token.rb +19 -18
  23. data/lib/quickbooks/service/account.rb +0 -5
  24. data/lib/quickbooks/service/base_service.rb +112 -82
  25. data/lib/quickbooks/service/credit_memo.rb +6 -0
  26. data/lib/quickbooks/service/custom_field.rb +20 -0
  27. data/lib/quickbooks/service/customer.rb +1 -11
  28. data/lib/quickbooks/service/customer_type.rb +20 -0
  29. data/lib/quickbooks/service/invoice.rb +1 -10
  30. data/lib/quickbooks/service/item.rb +1 -11
  31. data/lib/quickbooks/service/payment.rb +6 -0
  32. data/lib/quickbooks/service/preferences.rb +0 -5
  33. data/lib/quickbooks/service/purchase_change.rb +16 -0
  34. data/lib/quickbooks/service/purchase_order.rb +16 -0
  35. data/lib/quickbooks/service/refund_receipt.rb +6 -0
  36. data/lib/quickbooks/service/responses/oauth_http_response.rb +1 -5
  37. data/lib/quickbooks/service/sales_receipt.rb +1 -1
  38. data/lib/quickbooks/service/service_crud.rb +4 -1
  39. data/lib/quickbooks/service/service_crud_json.rb +1 -1
  40. data/lib/quickbooks/service/upload.rb +1 -5
  41. data/lib/quickbooks/util/logging.rb +16 -2
  42. data/lib/quickbooks/util/multipart.rb +0 -72
  43. data/lib/quickbooks/util/query_builder.rb +10 -5
  44. data/lib/quickbooks/version.rb +1 -1
  45. data/lib/quickbooks-ruby.rb +45 -19
  46. metadata +92 -42
  47. data/lib/quickbooks/faraday/middleware/gzip.rb +0 -72
  48. data/lib/quickbooks/service/responses/oauth1_http_response.rb +0 -42
@@ -7,8 +7,11 @@ module Quickbooks
7
7
  attr_accessor :company_id
8
8
  attr_accessor :oauth
9
9
  attr_reader :base_uri
10
- attr_reader :last_response_body
11
10
  attr_reader :last_response_xml
11
+ attr_reader :last_response_intuit_tid
12
+ attr_accessor :before_request
13
+ attr_accessor :around_request
14
+ attr_accessor :after_request
12
15
 
13
16
  XML_NS = %{xmlns="http://schema.intuit.com/finance/v3"}
14
17
  HTTP_CONTENT_TYPE = 'application/xml'
@@ -17,6 +20,8 @@ module Quickbooks
17
20
  BASE_DOMAIN = 'quickbooks.api.intuit.com'
18
21
  SANDBOX_DOMAIN = 'sandbox-quickbooks.api.intuit.com'
19
22
 
23
+ RequestInfo = Struct.new(:url, :headers, :body, :method)
24
+
20
25
  def initialize(attributes = {})
21
26
  domain = Quickbooks.sandbox_mode ? SANDBOX_DOMAIN : BASE_DOMAIN
22
27
  @base_uri = "https://#{domain}/v3/company"
@@ -37,24 +42,18 @@ module Quickbooks
37
42
  @company_id = company_id
38
43
  end
39
44
 
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
45
+ # def oauth_v2?
46
+ # @oauth.is_a? OAuth2::AccessToken
47
+ # end
47
48
 
48
49
  # [OAuth2] The default Faraday connection does not have gzip or multipart support.
49
50
  # We need to reset the existing connection and build a new one.
50
51
  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
52
+ @oauth.client.connection = Faraday.new do |f|
53
+ f.request :multipart
54
+ f.request :gzip
55
+ f.request :url_encoded
56
+ f.adapter ::Quickbooks.http_adapter
58
57
  end
59
58
  end
60
59
 
@@ -225,10 +224,12 @@ module Quickbooks
225
224
  if metadata
226
225
  standalone_prefix = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
227
226
  meta_data_xml = "#{standalone_prefix}\n#{metadata.to_xml_ns.to_s}"
228
- param_part = UploadIO.new(StringIO.new(meta_data_xml), "application/xml")
227
+ param_part = Faraday::UploadIO.new(StringIO.new(meta_data_xml), "application/xml")
229
228
  body['file_metadata_0'] = param_part
230
229
  end
231
230
 
231
+ url = add_query_string_to_url(url, {})
232
+
232
233
  do_http(:upload, url, body, headers)
233
234
  end
234
235
 
@@ -246,58 +247,47 @@ module Quickbooks
246
247
  headers['Accept-Encoding'] = HTTP_ACCEPT_ENCODING
247
248
  end
248
249
 
249
- log "------ QUICKBOOKS-RUBY REQUEST ------"
250
- log "METHOD = #{method}"
251
- log "RESOURCE = #{url}"
252
- log_request_body(body)
253
- log "REQUEST HEADERS = #{headers.inspect}"
254
-
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"
250
+ log_request(method, url, body, headers)
251
+
252
+ request_info = RequestInfo.new(url, headers, body, method)
253
+ before_request.call(request_info) if before_request
254
+
255
+ raw_response = with_around_request(request_info) do
256
+ case method
257
+ when :get
258
+ oauth_get(url, headers)
259
+ when :post
260
+ oauth_post(url, body, headers)
261
+ when :upload
262
+ oauth_post_with_multipart(url, body, headers)
263
+ else
264
+ raise "Do not know how to perform that HTTP operation"
265
+ end
264
266
  end
265
267
 
268
+ after_request.call(request_info, raw_response.body) if after_request
269
+
266
270
  response = Quickbooks::Service::Responses::OAuthHttpResponse.wrap(raw_response)
271
+ log_response(response)
272
+
267
273
  check_response(response, request: body)
268
274
  end
269
275
 
270
276
  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)
275
- else
276
- raise InvalidOauthAccessTokenObject.new(@oauth)
277
- end
277
+ @oauth.get(url, headers: headers, raise_errors: false)
278
278
  end
279
279
 
280
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
281
+ @oauth.post(url, headers: headers, body: body, raise_errors: false)
288
282
  end
289
283
 
290
284
  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)
297
- end
285
+ @oauth.post_with_multipart(url, headers: headers, body: body, raise_errors: false)
298
286
  end
299
287
 
300
- def add_query_string_to_url(url, params)
288
+ def add_query_string_to_url(url, params = {})
289
+ params ||= {}
290
+ params['minorversion'] = Quickbooks.minorversion
301
291
  if params.is_a?(Hash) && !params.empty?
302
292
  keyvalues = params.collect { |k| "#{k.first}=#{k.last}" }.join("&")
303
293
  delim = url.index("?") != nil ? "&" : "?"
@@ -308,12 +298,18 @@ module Quickbooks
308
298
  end
309
299
 
310
300
  def check_response(response, options = {})
311
- log "------ QUICKBOOKS-RUBY RESPONSE ------"
312
- log "RESPONSE CODE = #{response.code}"
313
- if response.respond_to?(:headers)
314
- log "RESPONSE HEADERS = #{response.headers}"
301
+ if is_json?
302
+ parse_json(response.plain_body)
303
+ elsif !is_pdf?
304
+ parse_xml(response.plain_body)
315
305
  end
316
- log_response_body(response)
306
+
307
+ @last_response_intuit_tid = if response.respond_to?(:headers) && response.headers
308
+ response.headers['intuit_tid']
309
+ else
310
+ nil
311
+ end
312
+
317
313
  status = response.code.to_i
318
314
  case status
319
315
  when 200
@@ -326,7 +322,7 @@ module Quickbooks
326
322
  when 302
327
323
  raise "Unhandled HTTP Redirect"
328
324
  when 401
329
- raise Quickbooks::AuthorizationFailure
325
+ raise Quickbooks::AuthorizationFailure, parse_intuit_error
330
326
  when 403
331
327
  message = parse_intuit_error[:message]
332
328
  if message.include?('ThrottleExceeded')
@@ -349,57 +345,84 @@ module Quickbooks
349
345
  end
350
346
  end
351
347
 
352
- def log_response_body(response)
353
- log "RESPONSE BODY:"
354
- if is_json?
355
- log ">>>>#{response.plain_body.inspect}"
356
- parse_json(response.plain_body)
357
- elsif is_pdf?
358
- log("BODY is a PDF : not dumping")
359
- else
360
- log(log_xml(response.plain_body))
361
- parse_xml(response.plain_body)
362
- end
348
+ def log_request(method, url, body, headers)
349
+ messages = []
350
+ messages << "------ QUICKBOOKS-RUBY REQUEST ------"
351
+ messages << "METHOD = #{method}"
352
+ messages << "RESOURCE = #{url}"
353
+ messages.concat(request_body_messages(body))
354
+ messages << "REQUEST HEADERS = #{headers.inspect}"
355
+
356
+ log_multiple(messages)
363
357
  end
364
358
 
365
- def log_request_body(body)
366
- log "REQUEST BODY:"
359
+ def request_body_messages(body)
360
+ messages = []
361
+ messages << "REQUEST BODY:"
367
362
  if is_json?
368
- log(body.inspect)
363
+ messages << body.inspect
369
364
  elsif is_pdf?
370
- log("BODY is a PDF : not dumping")
365
+ messages << "BODY is a PDF : not dumping"
371
366
  else
372
367
  #multipart request for uploads arrive here in a Hash with UploadIO vals
373
368
  if body.is_a?(Hash)
374
369
  body.each do |k,v|
375
- log('BODY PART:')
370
+ messages << 'BODY PART:'
376
371
  val_content = v.inspect
377
- if v.is_a?(UploadIO)
372
+ if v.is_a?(Faraday::UploadIO)
378
373
  if v.content_type == 'application/xml'
379
374
  if v.io.is_a?(StringIO)
380
375
  val_content = log_xml(v.io.string)
381
376
  end
382
377
  end
383
378
  end
384
- log("#{k}: #{val_content}")
379
+ messages << "#{k}: #{val_content}"
385
380
  end
386
381
  else
387
- log(log_xml(body))
382
+ messages << log_xml(body)
388
383
  end
389
384
  end
385
+ messages
386
+ end
387
+
388
+ def log_response(response)
389
+ messages = []
390
+ messages << "------ QUICKBOOKS-RUBY RESPONSE ------"
391
+ messages << "RESPONSE CODE = #{response.code}"
392
+ messages.concat(response_body_messages(response))
393
+ messages << "RESPONSE HEADERS = #{response.headers}" if response.respond_to?(:headers)
394
+
395
+ log_multiple(messages)
396
+ end
397
+
398
+ def response_body_messages(response)
399
+ messages = []
400
+ messages << "RESPONSE BODY:"
401
+ if is_json?
402
+ messages << ">>>>#{response.plain_body.inspect}"
403
+ elsif is_pdf?
404
+ messages << "BODY is a PDF : not dumping"
405
+ else
406
+ messages << log_xml(response.plain_body)
407
+ end
408
+
409
+ messages
390
410
  end
391
411
 
392
412
  def parse_and_raise_exception(options = {})
393
413
  err = parse_intuit_error
394
- ex = Quickbooks::IntuitRequestException.new("#{err[:message]}:\n\t#{err[:detail]}")
414
+ element_msg = err[:element] ? "#{err[:element]}: " : ""
415
+ ex = Quickbooks::IntuitRequestException.new("#{element_msg}#{err[:message]}:\n\t#{err[:detail]}")
395
416
  ex.code = err[:code]
396
417
  ex.detail = err[:detail]
397
418
  ex.type = err[:type]
419
+ ex.element = err[:element] if err[:element]
398
420
  if is_json?
399
421
  ex.request_json = options[:request]
400
422
  else
401
423
  ex.request_xml = options[:request]
402
424
  end
425
+ ex.intuit_tid = err[:intuit_tid]
403
426
  raise ex
404
427
  end
405
428
 
@@ -414,7 +437,7 @@ module Quickbooks
414
437
  end
415
438
 
416
439
  def parse_intuit_error
417
- error = {:message => "", :detail => "", :type => nil, :code => 0}
440
+ error = {:message => "", :detail => "", :type => nil, :code => 0, :intuit_tid => @last_response_intuit_tid}
418
441
  fault = @last_response_xml.xpath("//xmlns:IntuitResponse/xmlns:Fault")[0]
419
442
  if fault
420
443
  error[:type] = fault.attributes['type'].value
@@ -426,8 +449,8 @@ module Quickbooks
426
449
  error[:code] = code_attr.value
427
450
  end
428
451
  element_attr = error_element.attributes['element']
429
- if code_attr
430
- error[:element] = code_attr.value
452
+ if element_attr
453
+ error[:element] = element_attr.try(:value)
431
454
  end
432
455
  error[:message] = error_element.xpath("//xmlns:Message").text
433
456
  error[:detail] = error_element.xpath("//xmlns:Detail").text
@@ -441,6 +464,13 @@ module Quickbooks
441
464
  error
442
465
  end
443
466
 
467
+ def with_around_request(request_info, &block)
468
+ if around_request
469
+ around_request.call(request_info, &block)
470
+ else
471
+ block.call
472
+ end
473
+ end
444
474
  end
445
475
  end
446
476
  end
@@ -6,6 +6,12 @@ module Quickbooks
6
6
  delete_by_query_string(credit_memo)
7
7
  end
8
8
 
9
+ def pdf(credit_memo)
10
+ url = "#{url_for_resource(model::REST_RESOURCE)}/#{credit_memo.id}/pdf"
11
+ response = do_http_raw_get(url, {}, {'Accept' => 'application/pdf'})
12
+ response.plain_body
13
+ end
14
+
9
15
  private
10
16
 
11
17
  def model
@@ -0,0 +1,20 @@
1
+ module Quickbooks
2
+ module Service
3
+ class CustomField < BaseService
4
+
5
+ def delete(customer_type)
6
+ raise Quickbooks::UnsupportedOperation.new('Deleting CustomerType is not supported by Intuit')
7
+ end
8
+
9
+ def create(customer_type)
10
+ raise Quickbooks::UnsupportedOperation.new('Creating/updating CustomerType is not supported by Intuit')
11
+ end
12
+
13
+ private
14
+
15
+ def model
16
+ Quickbooks::Model::CustomField
17
+ end
18
+ end
19
+ end
20
+ end
@@ -7,21 +7,11 @@ module Quickbooks
7
7
  update(customer, :sparse => true)
8
8
  end
9
9
 
10
- def url_for_resource(resource)
11
- url = super(resource)
12
- "#{url}?minorversion=#{Quickbooks::Model::Customer::MINORVERSION}"
13
- end
14
-
15
10
  def fetch_by_id(id, params = {})
16
- url = "#{url_for_base}/customer/#{id}?minorversion=#{Quickbooks::Model::Customer::MINORVERSION}"
11
+ url = "#{url_for_base}/customer/#{id}"
17
12
  fetch_object(model, url, params)
18
13
  end
19
14
 
20
- def url_for_query(query = nil, start_position = 1, max_results = 20, options = {})
21
- url = super(query, start_position, max_results, options)
22
- "#{url}&minorversion=#{Quickbooks::Model::Customer::MINORVERSION}"
23
- end
24
-
25
15
  private
26
16
 
27
17
  def model
@@ -0,0 +1,20 @@
1
+ module Quickbooks
2
+ module Service
3
+ class CustomerType < BaseService
4
+
5
+ def delete(customer_type)
6
+ raise Quickbooks::UnsupportedOperation.new('Deleting CustomerType is not supported by Intuit')
7
+ end
8
+
9
+ def create(customer_type)
10
+ raise Quickbooks::UnsupportedOperation.new('Creating/updating CustomerType is not supported by Intuit')
11
+ end
12
+
13
+ private
14
+
15
+ def model
16
+ Quickbooks::Model::CustomerType
17
+ end
18
+ end
19
+ end
20
+ end
@@ -6,20 +6,11 @@ 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
9
  def fetch_by_id(id, params = {})
14
- url = "#{url_for_base}/invoice/#{id}?minorversion=#{Quickbooks::Model::Invoice::MINORVERSION}"
10
+ url = "#{url_for_base}/invoice/#{id}"
15
11
  fetch_object(model, url, params)
16
12
  end
17
13
 
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
-
23
14
  def send(invoice, email_address=nil)
24
15
  query = email_address.present? ? "?sendTo=#{email_address}" : ""
25
16
  url = "#{url_for_resource(model::REST_RESOURCE)}/#{invoice.id}/send#{query}"
@@ -7,21 +7,11 @@ module Quickbooks
7
7
  update(item, :sparse => true)
8
8
  end
9
9
 
10
- def url_for_resource(resource)
11
- url = super(resource)
12
- "#{url}?minorversion=#{Quickbooks::Model::Item::MINORVERSION}"
13
- end
14
-
15
10
  def fetch_by_id(id, params = {})
16
- url = "#{url_for_base}/item/#{id}?minorversion=#{Quickbooks::Model::Item::MINORVERSION}"
11
+ url = "#{url_for_base}/item/#{id}"
17
12
  fetch_object(model, url, params)
18
13
  end
19
14
 
20
- def url_for_query(query = nil, start_position = 1, max_results = 20, options = {})
21
- url = super(query, start_position, max_results, options)
22
- "#{url}&minorversion=#{Quickbooks::Model::Item::MINORVERSION}"
23
- end
24
-
25
15
  private
26
16
 
27
17
  def model
@@ -19,6 +19,12 @@ module Quickbooks
19
19
  end
20
20
  end
21
21
 
22
+ def pdf(payment)
23
+ url = "#{url_for_resource(model::REST_RESOURCE)}/#{payment.id}/pdf"
24
+ response = do_http_raw_get(url, {}, {'Accept' => 'application/pdf'})
25
+ response.plain_body
26
+ end
27
+
22
28
  private
23
29
 
24
30
  def model
@@ -2,11 +2,6 @@ module Quickbooks
2
2
  module Service
3
3
  class Preferences < BaseService
4
4
 
5
- def url_for_query(query = nil, start_position = 1, max_results = 20, options = {})
6
- url = super(query, start_position, max_results, options)
7
- "#{url}&minorversion=#{Quickbooks::Model::Preferences::MINORVERSION}"
8
- end
9
-
10
5
  private
11
6
 
12
7
  def model
@@ -0,0 +1,16 @@
1
+ module Quickbooks
2
+ module Service
3
+ class PurchaseChange < ChangeService
4
+
5
+ private
6
+
7
+ def entity
8
+ "Purchase"
9
+ end
10
+
11
+ def model
12
+ Quickbooks::Model::PurchaseChange
13
+ end
14
+ end
15
+ end
16
+ end
@@ -6,6 +6,22 @@ module Quickbooks
6
6
  delete_by_query_string(purchase_order)
7
7
  end
8
8
 
9
+ def fetch_by_id(id, params = {})
10
+ url = "#{url_for_base}/purchaseorder/#{id}?minorversion=#{Quickbooks.minorversion}"
11
+ fetch_object(model, url, params)
12
+ end
13
+
14
+ def url_for_query(query = nil, start_position = 1, max_results = 20, options = {})
15
+ url = super(query, start_position, max_results, options)
16
+ "#{url}&minorversion=#{Quickbooks.minorversion}"
17
+ end
18
+
19
+ def pdf(purchase_order)
20
+ url = "#{url_for_resource(model::REST_RESOURCE)}/#{purchase_order.id}/pdf"
21
+ response = do_http_raw_get(url, {}, {'Accept' => 'application/pdf'})
22
+ response.plain_body
23
+ end
24
+
9
25
  private
10
26
 
11
27
  def model
@@ -6,6 +6,12 @@ module Quickbooks
6
6
  delete_by_query_string(refund_receipt)
7
7
  end
8
8
 
9
+ def pdf(refund_receipt)
10
+ url = "#{url_for_resource(model::REST_RESOURCE)}/#{refund_receipt.id}/pdf"
11
+ response = do_http_raw_get(url, {}, {'Accept' => 'application/pdf'})
12
+ response.plain_body
13
+ end
14
+
9
15
  private
10
16
 
11
17
  def model
@@ -7,11 +7,7 @@ module Quickbooks
7
7
  class OAuthHttpResponse
8
8
 
9
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
10
+ Quickbooks::Service::Responses::OAuth2HttpResponse.new(response)
15
11
  end
16
12
 
17
13
  end
@@ -15,7 +15,7 @@ module Quickbooks
15
15
  def send(sr, email_address=nil)
16
16
  query = email_address.present? ? "?sendTo=#{email_address}" : ""
17
17
  url = "#{url_for_resource(model::REST_RESOURCE)}/#{sr.id}/send#{query}"
18
- response = do_http_post(url,{})
18
+ response = do_http_post(url, "", {}, { 'Content-Type' => 'application/octet-stream' })
19
19
  if response.code.to_i == 200
20
20
  model.from_xml(parse_singular_entity_response(model, response.plain_body))
21
21
  else
@@ -33,7 +33,10 @@ module Quickbooks
33
33
  if field.class == Symbol
34
34
  field = field.to_s.camelcase
35
35
  end
36
- q = "select * from %s where %s = '%s'" % [model.resource_for_singular, field, selector]
36
+
37
+ clause = Quickbooks::Util::QueryBuilder.new.clause(field, '=', selector)
38
+ q = "select * from %s where %s" % [model.resource_for_singular, clause]
39
+
37
40
  self.query(q, options)
38
41
  end
39
42
 
@@ -8,7 +8,7 @@ module Quickbooks
8
8
 
9
9
  def create(entity, options = {})
10
10
  raise Quickbooks::InvalidModelException.new(entity.errors.full_messages.join(',')) unless entity.valid?
11
- response = do_http(:post, url_for_resource(model.resource_for_singular), entity.to_json, options)
11
+ response = do_http_post(url_for_resource(model.resource_for_singular), entity.to_json, options)
12
12
  if response.code.to_i == 200
13
13
  JSON.parse(response.plain_body)
14
14
  else
@@ -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 = class_for_io.new(path_to_file, mime_type)
12
+ uploadIO = Faraday::UploadIO.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,10 +19,6 @@ 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
-
26
22
  def download(uploadId)
27
23
  url = url_for_resource("download/#{uploadId}")
28
24
  do_http_get(url, {}, headers)
@@ -1,12 +1,26 @@
1
1
  module Quickbooks
2
2
  module Util
3
3
  module Logging
4
+ attr_writer :log
5
+
4
6
  def log(msg)
5
- ::Quickbooks.log(msg)
7
+ ::Quickbooks.log(msg) if log?
8
+ end
9
+
10
+ def log_multiple(messages)
11
+ if condense_logs?
12
+ log(messages.join("\n"))
13
+ else
14
+ messages.each(&method(:log))
15
+ end
6
16
  end
7
17
 
8
18
  def log?
9
- ::Quickbooks.log?
19
+ defined?(@log) ? @log : ::Quickbooks.log?
20
+ end
21
+
22
+ def condense_logs?
23
+ ::Quickbooks.condense_logs?
10
24
  end
11
25
 
12
26
  def log_xml(str)