quickbooks-ruby 0.4.0 → 1.0.16

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 (72) hide show
  1. checksums.yaml +5 -5
  2. data/lib/quickbooks-ruby.rb +65 -13
  3. data/lib/quickbooks/faraday/middleware/gzip.rb +74 -0
  4. data/lib/quickbooks/model/base_model.rb +13 -2
  5. data/lib/quickbooks/model/batch_request.rb +11 -6
  6. data/lib/quickbooks/model/batch_response.rb +11 -6
  7. data/lib/quickbooks/model/bill.rb +3 -0
  8. data/lib/quickbooks/model/change_data_capture.rb +50 -0
  9. data/lib/quickbooks/model/company_currency.rb +19 -0
  10. data/lib/quickbooks/model/company_info.rb +2 -1
  11. data/lib/quickbooks/model/custom_field.rb +18 -0
  12. data/lib/quickbooks/model/customer.rb +6 -1
  13. data/lib/quickbooks/model/customer_type.rb +15 -0
  14. data/lib/quickbooks/model/deposit_line_detail.rb +2 -2
  15. data/lib/quickbooks/model/description_line_detail.rb +7 -0
  16. data/lib/quickbooks/model/effective_tax_rate.rb +15 -0
  17. data/lib/quickbooks/model/exchange_rate.rb +23 -0
  18. data/lib/quickbooks/model/group_line_detail.rb +2 -1
  19. data/lib/quickbooks/model/invoice.rb +7 -1
  20. data/lib/quickbooks/model/invoice_change.rb +2 -1
  21. data/lib/quickbooks/model/invoice_group_line_detail.rb +14 -0
  22. data/lib/quickbooks/model/invoice_line_item.rb +34 -4
  23. data/lib/quickbooks/model/item.rb +11 -3
  24. data/lib/quickbooks/model/item_group_detail.rb +9 -0
  25. data/lib/quickbooks/model/item_group_line.rb +20 -0
  26. data/lib/quickbooks/model/line.rb +12 -0
  27. data/lib/quickbooks/model/line_ex.rb +9 -0
  28. data/lib/quickbooks/model/linked_transaction.rb +7 -0
  29. data/lib/quickbooks/model/physical_address.rb +2 -2
  30. data/lib/quickbooks/model/preferences.rb +28 -4
  31. data/lib/quickbooks/model/purchase_change.rb +7 -0
  32. data/lib/quickbooks/model/purchase_line_item.rb +1 -0
  33. data/lib/quickbooks/model/purchase_order.rb +3 -1
  34. data/lib/quickbooks/model/refund_receipt_change.rb +8 -0
  35. data/lib/quickbooks/model/report.rb +9 -7
  36. data/lib/quickbooks/model/sales_receipt.rb +4 -2
  37. data/lib/quickbooks/model/tax_rate.rb +1 -1
  38. data/lib/quickbooks/model/time_activity.rb +2 -1
  39. data/lib/quickbooks/model/transfer.rb +21 -0
  40. data/lib/quickbooks/model/vendor.rb +1 -0
  41. data/lib/quickbooks/service/access_token.rb +12 -11
  42. data/lib/quickbooks/service/base_service.rb +148 -24
  43. data/lib/quickbooks/service/batch.rb +1 -1
  44. data/lib/quickbooks/service/change_data_capture.rb +24 -0
  45. data/lib/quickbooks/service/company_currency.rb +18 -0
  46. data/lib/quickbooks/service/credit_memo.rb +6 -0
  47. data/lib/quickbooks/service/custom_field.rb +20 -0
  48. data/lib/quickbooks/service/customer.rb +5 -0
  49. data/lib/quickbooks/service/customer_type.rb +20 -0
  50. data/lib/quickbooks/service/estimate.rb +6 -0
  51. data/lib/quickbooks/service/exchange_rate.rb +25 -0
  52. data/lib/quickbooks/service/invoice.rb +24 -1
  53. data/lib/quickbooks/service/item.rb +5 -0
  54. data/lib/quickbooks/service/payment.rb +13 -0
  55. data/lib/quickbooks/service/preferences.rb +1 -1
  56. data/lib/quickbooks/service/purchase_change.rb +16 -0
  57. data/lib/quickbooks/service/purchase_order.rb +16 -0
  58. data/lib/quickbooks/service/refund_receipt_change.rb +16 -0
  59. data/lib/quickbooks/service/responses/methods.rb +17 -0
  60. data/lib/quickbooks/service/responses/oauth2_http_response.rb +43 -0
  61. data/lib/quickbooks/service/responses/oauth_http_response.rb +17 -0
  62. data/lib/quickbooks/service/sales_receipt.rb +30 -0
  63. data/lib/quickbooks/service/service_crud.rb +21 -0
  64. data/lib/quickbooks/service/service_crud_json.rb +1 -1
  65. data/lib/quickbooks/service/transfer.rb +16 -0
  66. data/lib/quickbooks/service/upload.rb +5 -1
  67. data/lib/quickbooks/util/logging.rb +4 -0
  68. data/lib/quickbooks/util/multipart.rb +2 -65
  69. data/lib/quickbooks/util/name_entity.rb +2 -1
  70. data/lib/quickbooks/util/query_builder.rb +6 -5
  71. data/lib/quickbooks/version.rb +1 -1
  72. metadata +73 -62
@@ -3,7 +3,7 @@ module Quickbooks
3
3
  class Batch < BaseService
4
4
 
5
5
  def make_request(entity, options = {})
6
- response = do_http_post(url_for_resource('batch'), valid_xml_document(entity.to_xml_ns))
6
+ response = do_http_post(url_for_resource('batch'), valid_xml_document(entity.to_xml_ns), options[:query])
7
7
  Quickbooks::Model::BatchResponse.from_xml(response.plain_body)
8
8
  end
9
9
  end
@@ -0,0 +1,24 @@
1
+ module Quickbooks
2
+ module Service
3
+ class ChangeDataCapture < BaseService
4
+
5
+ def url_for_query(entity_list, query=nil)
6
+ q = entity_list.join(",")
7
+ q = "#{q}&#{query}" if query.present?
8
+ return "#{url_for_base}/cdc?entities=#{q}"
9
+ end
10
+
11
+ def since(entity_list, timestamp)
12
+ do_http_get(url_for_query(entity_list, "changedSince=#{URI.encode_www_form_component(timestamp.iso8601)}"))
13
+ model.new(:xml => @last_response_xml)
14
+ end
15
+
16
+ private
17
+
18
+ def model
19
+ Quickbooks::Model::ChangeDataCapture
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ module Quickbooks
2
+ module Service
3
+ class CompanyCurrency < BaseService
4
+
5
+ def delete(company_currency)
6
+ company_currency.active = false
7
+ update(company_currency, :sparse => true)
8
+ end
9
+
10
+ private
11
+
12
+ def model
13
+ Quickbooks::Model::CompanyCurrency
14
+ end
15
+
16
+ end
17
+ end
18
+ 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,6 +7,11 @@ module Quickbooks
7
7
  update(customer, :sparse => true)
8
8
  end
9
9
 
10
+ def fetch_by_id(id, params = {})
11
+ url = "#{url_for_base}/customer/#{id}"
12
+ fetch_object(model, url, params)
13
+ end
14
+
10
15
  private
11
16
 
12
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
@@ -5,6 +5,12 @@ module Quickbooks
5
5
  def delete(estimate)
6
6
  delete_by_query_string(estimate)
7
7
  end
8
+
9
+ def pdf(estimate)
10
+ url = "#{url_for_resource(model::REST_RESOURCE)}/#{estimate.id}/pdf"
11
+ response = do_http_raw_get(url, {}, {'Accept' => 'application/pdf'})
12
+ response.plain_body
13
+ end
8
14
 
9
15
  private
10
16
 
@@ -0,0 +1,25 @@
1
+ module Quickbooks
2
+ module Service
3
+ class ExchangeRate < BaseService
4
+
5
+ def fetch_by_currency(source_currency_code, as_of_date = nil)
6
+ url = url_for_resource(model::REST_RESOURCE)
7
+ params = { sourcecurrencycode: source_currency_code }
8
+ params[:asofdate] = as_of_date unless as_of_date.nil?
9
+
10
+ response = do_http_get(url, params)
11
+ if response.code.to_i == 200
12
+ model.from_xml(parse_singular_entity_response(model, response.plain_body))
13
+ else
14
+ nil
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def model
21
+ Quickbooks::Model::ExchangeRate
22
+ end
23
+ end
24
+ end
25
+ end
@@ -6,10 +6,15 @@ module Quickbooks
6
6
  delete_by_query_string(invoice)
7
7
  end
8
8
 
9
+ def fetch_by_id(id, params = {})
10
+ url = "#{url_for_base}/invoice/#{id}"
11
+ fetch_object(model, url, params)
12
+ end
13
+
9
14
  def send(invoice, email_address=nil)
10
15
  query = email_address.present? ? "?sendTo=#{email_address}" : ""
11
16
  url = "#{url_for_resource(model::REST_RESOURCE)}/#{invoice.id}/send#{query}"
12
- response = do_http_post(url,{})
17
+ response = do_http_post(url, "", {}, { 'Content-Type' => 'application/octet-stream' })
13
18
  if response.code.to_i == 200
14
19
  model.from_xml(parse_singular_entity_response(model, response.plain_body))
15
20
  else
@@ -17,6 +22,24 @@ module Quickbooks
17
22
  end
18
23
  end
19
24
 
25
+ def pdf(invoice)
26
+ url = "#{url_for_resource(model::REST_RESOURCE)}/#{invoice.id}/pdf"
27
+ response = do_http_raw_get(url, {}, {'Accept' => 'application/pdf'})
28
+ response.plain_body
29
+ end
30
+
31
+ def void(invoice, options = {})
32
+ url = "#{url_for_resource(model::REST_RESOURCE)}?operation=void"
33
+
34
+ xml = invoice.to_xml_ns(options)
35
+ response = do_http_post(url, valid_xml_document(xml))
36
+ if response.code.to_i == 200
37
+ model.from_xml(parse_singular_entity_response(model, response.plain_body))
38
+ else
39
+ false
40
+ end
41
+ end
42
+
20
43
  private
21
44
 
22
45
  def model
@@ -7,6 +7,11 @@ module Quickbooks
7
7
  update(item, :sparse => true)
8
8
  end
9
9
 
10
+ def fetch_by_id(id, params = {})
11
+ url = "#{url_for_base}/item/#{id}"
12
+ fetch_object(model, url, params)
13
+ end
14
+
10
15
  private
11
16
 
12
17
  def model
@@ -6,6 +6,19 @@ module Quickbooks
6
6
  delete_by_query_string(payment)
7
7
  end
8
8
 
9
+ def void(entity, options = {})
10
+ raise Quickbooks::InvalidModelException.new(entity.errors.full_messages.join(',')) unless entity.valid?
11
+ xml = entity.to_xml_ns(options)
12
+ url = "#{url_for_resource(model::REST_RESOURCE)}?include=void"
13
+
14
+ response = do_http_post(url, valid_xml_document(xml), {})
15
+ if response.code.to_i == 200
16
+ model.from_xml(parse_singular_entity_response(model, response.plain_body))
17
+ else
18
+ false
19
+ end
20
+ end
21
+
9
22
  private
10
23
 
11
24
  def model
@@ -3,7 +3,7 @@ module Quickbooks
3
3
  class Preferences < BaseService
4
4
 
5
5
  private
6
-
6
+
7
7
  def model
8
8
  Quickbooks::Model::Preferences
9
9
  end
@@ -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
@@ -0,0 +1,16 @@
1
+ module Quickbooks
2
+ module Service
3
+ class RefundReceiptChange < ChangeService
4
+
5
+ private
6
+
7
+ def entity
8
+ "RefundReceipt"
9
+ end
10
+
11
+ def model
12
+ Quickbooks::Model::RefundReceiptChange
13
+ end
14
+ end
15
+ end
16
+ end
@@ -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,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,17 @@
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
+ Quickbooks::Service::Responses::OAuth2HttpResponse.new(response)
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -6,6 +6,36 @@ module Quickbooks
6
6
  delete_by_query_string(sales_receipt)
7
7
  end
8
8
 
9
+ def pdf(sales_receipt)
10
+ url = "#{url_for_resource(model::REST_RESOURCE)}/#{sales_receipt.id}/pdf"
11
+ response = do_http_raw_get(url, {}, {'Accept' => 'application/pdf'})
12
+ response.plain_body
13
+ end
14
+
15
+ def send(sr, email_address=nil)
16
+ query = email_address.present? ? "?sendTo=#{email_address}" : ""
17
+ url = "#{url_for_resource(model::REST_RESOURCE)}/#{sr.id}/send#{query}"
18
+ response = do_http_post(url, "", {}, { 'Content-Type' => 'application/octet-stream' })
19
+ if response.code.to_i == 200
20
+ model.from_xml(parse_singular_entity_response(model, response.plain_body))
21
+ else
22
+ nil
23
+ end
24
+ end
25
+
26
+ def void(sales_receipt, options = {})
27
+ raise Quickbooks::InvalidModelException.new(sales_receipt.errors.full_messages.join(',')) unless sales_receipt.valid?
28
+ xml = sales_receipt.to_xml_ns(options)
29
+ url = "#{url_for_resource(model::REST_RESOURCE)}?include=void"
30
+
31
+ response = do_http_post(url, valid_xml_document(xml), {})
32
+ if response.code.to_i == 200
33
+ model.from_xml(parse_singular_entity_response(model, response.plain_body))
34
+ else
35
+ false
36
+ end
37
+ end
38
+
9
39
  private
10
40
 
11
41
  def model
@@ -6,6 +6,15 @@ module Quickbooks
6
6
  fetch_collection(object_query, model, options)
7
7
  end
8
8
 
9
+ # fetch all records, returns an array of models
10
+ def all(object_query=nil, options={})
11
+ collection = []
12
+ self.query_in_batches(object_query, options) do |batch|
13
+ collection << batch.entries
14
+ end
15
+ collection.flatten
16
+ end
17
+
9
18
  def query_in_batches(object_query=nil, options={})
10
19
  page = 0
11
20
  per_page = options.delete(:per_page) || 1_000
@@ -16,6 +25,18 @@ module Quickbooks
16
25
  end until results.count < per_page
17
26
  end
18
27
 
28
+ def exists?(field, selector, options={})
29
+ find_by(field, selector, options).count > 0
30
+ end
31
+
32
+ def find_by(field, selector, options={})
33
+ if field.class == Symbol
34
+ field = field.to_s.camelcase
35
+ end
36
+ q = "select * from %s where %s = '%s'" % [model.resource_for_singular, field, selector]
37
+ self.query(q, options)
38
+ end
39
+
19
40
  def fetch_by_id(id, params = {})
20
41
  url = "#{url_for_resource(model.resource_for_singular)}/#{id}"
21
42
  fetch_object(model, url, params)