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.
- checksums.yaml +5 -5
- data/lib/quickbooks-ruby.rb +65 -13
- data/lib/quickbooks/faraday/middleware/gzip.rb +74 -0
- data/lib/quickbooks/model/base_model.rb +13 -2
- data/lib/quickbooks/model/batch_request.rb +11 -6
- data/lib/quickbooks/model/batch_response.rb +11 -6
- data/lib/quickbooks/model/bill.rb +3 -0
- data/lib/quickbooks/model/change_data_capture.rb +50 -0
- data/lib/quickbooks/model/company_currency.rb +19 -0
- data/lib/quickbooks/model/company_info.rb +2 -1
- data/lib/quickbooks/model/custom_field.rb +18 -0
- data/lib/quickbooks/model/customer.rb +6 -1
- data/lib/quickbooks/model/customer_type.rb +15 -0
- data/lib/quickbooks/model/deposit_line_detail.rb +2 -2
- data/lib/quickbooks/model/description_line_detail.rb +7 -0
- data/lib/quickbooks/model/effective_tax_rate.rb +15 -0
- data/lib/quickbooks/model/exchange_rate.rb +23 -0
- data/lib/quickbooks/model/group_line_detail.rb +2 -1
- data/lib/quickbooks/model/invoice.rb +7 -1
- data/lib/quickbooks/model/invoice_change.rb +2 -1
- data/lib/quickbooks/model/invoice_group_line_detail.rb +14 -0
- data/lib/quickbooks/model/invoice_line_item.rb +34 -4
- data/lib/quickbooks/model/item.rb +11 -3
- data/lib/quickbooks/model/item_group_detail.rb +9 -0
- data/lib/quickbooks/model/item_group_line.rb +20 -0
- data/lib/quickbooks/model/line.rb +12 -0
- data/lib/quickbooks/model/line_ex.rb +9 -0
- data/lib/quickbooks/model/linked_transaction.rb +7 -0
- data/lib/quickbooks/model/physical_address.rb +2 -2
- data/lib/quickbooks/model/preferences.rb +28 -4
- data/lib/quickbooks/model/purchase_change.rb +7 -0
- data/lib/quickbooks/model/purchase_line_item.rb +1 -0
- data/lib/quickbooks/model/purchase_order.rb +3 -1
- data/lib/quickbooks/model/refund_receipt_change.rb +8 -0
- data/lib/quickbooks/model/report.rb +9 -7
- data/lib/quickbooks/model/sales_receipt.rb +4 -2
- data/lib/quickbooks/model/tax_rate.rb +1 -1
- data/lib/quickbooks/model/time_activity.rb +2 -1
- data/lib/quickbooks/model/transfer.rb +21 -0
- data/lib/quickbooks/model/vendor.rb +1 -0
- data/lib/quickbooks/service/access_token.rb +12 -11
- data/lib/quickbooks/service/base_service.rb +148 -24
- data/lib/quickbooks/service/batch.rb +1 -1
- data/lib/quickbooks/service/change_data_capture.rb +24 -0
- data/lib/quickbooks/service/company_currency.rb +18 -0
- data/lib/quickbooks/service/credit_memo.rb +6 -0
- data/lib/quickbooks/service/custom_field.rb +20 -0
- data/lib/quickbooks/service/customer.rb +5 -0
- data/lib/quickbooks/service/customer_type.rb +20 -0
- data/lib/quickbooks/service/estimate.rb +6 -0
- data/lib/quickbooks/service/exchange_rate.rb +25 -0
- data/lib/quickbooks/service/invoice.rb +24 -1
- data/lib/quickbooks/service/item.rb +5 -0
- data/lib/quickbooks/service/payment.rb +13 -0
- data/lib/quickbooks/service/preferences.rb +1 -1
- data/lib/quickbooks/service/purchase_change.rb +16 -0
- data/lib/quickbooks/service/purchase_order.rb +16 -0
- data/lib/quickbooks/service/refund_receipt_change.rb +16 -0
- data/lib/quickbooks/service/responses/methods.rb +17 -0
- data/lib/quickbooks/service/responses/oauth2_http_response.rb +43 -0
- data/lib/quickbooks/service/responses/oauth_http_response.rb +17 -0
- data/lib/quickbooks/service/sales_receipt.rb +30 -0
- data/lib/quickbooks/service/service_crud.rb +21 -0
- data/lib/quickbooks/service/service_crud_json.rb +1 -1
- data/lib/quickbooks/service/transfer.rb +16 -0
- data/lib/quickbooks/service/upload.rb +5 -1
- data/lib/quickbooks/util/logging.rb +4 -0
- data/lib/quickbooks/util/multipart.rb +2 -65
- data/lib/quickbooks/util/name_entity.rb +2 -1
- data/lib/quickbooks/util/query_builder.rb +6 -5
- data/lib/quickbooks/version.rb +1 -1
- metadata +73 -62
@@ -1,9 +1,16 @@
|
|
1
1
|
module Quickbooks
|
2
2
|
module Model
|
3
3
|
class LinkedTransaction < BaseModel
|
4
|
+
#== Constants
|
5
|
+
DEFAULT_TXN_TYPE = 'BillPaymentCheck'.freeze
|
6
|
+
|
4
7
|
xml_accessor :txn_id, :from => 'TxnId'
|
5
8
|
xml_accessor :txn_type, :from => 'TxnType'
|
6
9
|
xml_accessor :txn_line_id, :from => 'TxnLineId'
|
10
|
+
|
11
|
+
def bill_payment_check_type?
|
12
|
+
txn_type.to_s == DEFAULT_TXN_TYPE
|
13
|
+
end
|
7
14
|
end
|
8
15
|
end
|
9
16
|
end
|
@@ -19,16 +19,40 @@ module Quickbooks
|
|
19
19
|
PREFERENCE_SECTIONS = {
|
20
20
|
:accounting_info => %w(TrackDepartments DepartmentTerminology ClassTrackingPerTxnLine? ClassTrackingPerTxn? CustomerTerminology),
|
21
21
|
:product_and_services => %w(ForSales? ForPurchase? QuantityWithPriceAndRate? QuantityOnHand?),
|
22
|
-
:sales_forms => %w(CustomTxnNumbers? AllowDeposit? AllowDiscount? DefaultDiscountAccount? AllowEstimates? EstimateMessage?
|
23
|
-
ETransactionEnabledStatus? ETransactionAttachPDF? ETransactionPaymentEnabled? IPNSupportEnabled?
|
24
|
-
AllowServiceDate? AllowShipping? DefaultShippingAccount? DefaultTerms DefaultCustomerMessage),
|
25
22
|
:vendor_and_purchase => %w(TrackingByCustomer? BillableExpenseTracking? DefaultTerms? DefaultMarkup? POCustomField),
|
26
23
|
:time_tracking => %w(UseServices? BillCustomers? ShowBillRateToAll WorkWeekStartDate MarkTimeEntiresBillable?),
|
27
|
-
:tax => %w(UsingSalesTax?),
|
24
|
+
:tax => %w(UsingSalesTax? PartnerTaxEnabled?),
|
28
25
|
:currency => %w(MultiCurrencyEnabled? HomeCurrency),
|
29
26
|
:report => %w(ReportBasis)
|
30
27
|
}
|
31
28
|
|
29
|
+
xml_reader :sales_forms, :from => "SalesFormsPrefs", :as => create_preference_class(*%w(
|
30
|
+
AllowDeposit?
|
31
|
+
AllowDiscount?
|
32
|
+
AllowEstimates?
|
33
|
+
AllowServiceDate?
|
34
|
+
AllowShipping?
|
35
|
+
AutoApplyCredit?
|
36
|
+
CustomField?
|
37
|
+
CustomTxnNumbers?
|
38
|
+
DefaultCustomerMessage
|
39
|
+
DefaultDiscountAccount?
|
40
|
+
DefaultShippingAccount?
|
41
|
+
DefaultTerms
|
42
|
+
EmailCopyToCompany?
|
43
|
+
EstimateMessage
|
44
|
+
ETransactionAttachPDF?
|
45
|
+
ETransactionEnabledStatus
|
46
|
+
ETransactionPaymentEnabled?
|
47
|
+
IPNSupportEnabled?
|
48
|
+
SalesEmailBcc
|
49
|
+
SalesEmailCc
|
50
|
+
UsingPriceLevels?
|
51
|
+
UsingProgressInvoicing?
|
52
|
+
)) {
|
53
|
+
xml_reader :custom_fields, :as => [CustomField], :from => 'CustomField', in: 'CustomField'
|
54
|
+
}
|
55
|
+
|
32
56
|
PREFERENCE_SECTIONS.each do |section_name, fields|
|
33
57
|
xml_reader section_name, :from => "#{section_name}_prefs".camelize, :as => create_preference_class(*fields)
|
34
58
|
end
|
@@ -12,6 +12,7 @@ module Quickbooks
|
|
12
12
|
xml_accessor :description, :from => 'Description'
|
13
13
|
xml_accessor :amount, :from => 'Amount', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
|
14
14
|
xml_accessor :detail_type, :from => 'DetailType'
|
15
|
+
xml_accessor :received, :from => 'Received', :as => BigDecimal, :to_xml => to_xml_big_decimal
|
15
16
|
|
16
17
|
#== Various detail types
|
17
18
|
xml_accessor :account_based_expense_line_detail, :from => ACCOUNT_BASED_EXPENSE_LINE_DETAIL, :as => AccountBasedExpenseLineDetail
|
@@ -16,6 +16,7 @@ module Quickbooks
|
|
16
16
|
xml_accessor :txn_date, :from => 'TxnDate', :as => Date
|
17
17
|
xml_accessor :custom_fields, :from => 'CustomField', :as => [CustomField]
|
18
18
|
xml_accessor :private_note, :from => 'PrivateNote'
|
19
|
+
xml_accessor :memo, :from => 'Memo'
|
19
20
|
|
20
21
|
xml_accessor :linked_transactions, :from => 'LinkedTxn', :as => [LinkedTransaction]
|
21
22
|
xml_accessor :line_items, :from => 'Line', :as => [PurchaseLineItem]
|
@@ -23,10 +24,11 @@ module Quickbooks
|
|
23
24
|
xml_accessor :attachable_ref, :from => 'AttachableRef', :as => BaseReference
|
24
25
|
xml_accessor :vendor_ref, :from => 'VendorRef', :as => BaseReference
|
25
26
|
xml_accessor :ap_account_ref, :from => 'APAccountRef', :as => BaseReference
|
27
|
+
xml_accessor :po_email, from: "POEmail", as: EmailAddress
|
26
28
|
xml_accessor :class_ref, :from => 'ClassRef', :as => BaseReference
|
27
29
|
xml_accessor :sales_term_ref, :from => 'SalesTermRef', :as => BaseReference
|
28
30
|
|
29
|
-
xml_accessor :total, :from => 'TotalAmt', :as => BigDecimal, :to_xml =>
|
31
|
+
xml_accessor :total, :from => 'TotalAmt', :as => BigDecimal, :to_xml => to_xml_big_decimal
|
30
32
|
xml_accessor :due_date, :from => 'DueDate', :as => Date
|
31
33
|
xml_accessor :vendor_address, :from => 'VendorAddr', :as => PhysicalAddress
|
32
34
|
xml_accessor :ship_address, :from => 'ShipAddr', :as => PhysicalAddress
|
@@ -37,16 +37,18 @@ module Quickbooks
|
|
37
37
|
row_node.elements.map.with_index do |el, i|
|
38
38
|
value = el.attr('value')
|
39
39
|
|
40
|
-
if
|
41
|
-
|
42
|
-
|
43
|
-
nil
|
44
|
-
else
|
45
|
-
BigDecimal(value)
|
46
|
-
end
|
40
|
+
next nil if value.blank?
|
41
|
+
|
42
|
+
parse_row_value(value)
|
47
43
|
end
|
48
44
|
end
|
49
45
|
|
46
|
+
def parse_row_value(value)
|
47
|
+
BigDecimal(value)
|
48
|
+
rescue ArgumentError
|
49
|
+
value
|
50
|
+
end
|
51
|
+
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
@@ -20,6 +20,7 @@ module Quickbooks
|
|
20
20
|
xml_accessor :department_ref, :from => 'DepartmentRef', :as => BaseReference
|
21
21
|
xml_accessor :bill_email, :from => 'BillEmail', :as => EmailAddress
|
22
22
|
xml_accessor :bill_address, :from => 'BillAddr', :as => PhysicalAddress
|
23
|
+
xml_accessor :delivery_info, :from => 'DeliveryInfo', :as => DeliveryInfo
|
23
24
|
xml_accessor :ship_address, :from => 'ShipAddr', :as => PhysicalAddress
|
24
25
|
xml_accessor :po_number, :from => 'PONumber'
|
25
26
|
xml_accessor :ship_method_ref, :from => 'ShipMethodRef', :as => BaseReference
|
@@ -54,9 +55,10 @@ module Quickbooks
|
|
54
55
|
validate :line_item_size
|
55
56
|
validate :document_numbering
|
56
57
|
|
57
|
-
def
|
58
|
-
self.bill_email = EmailAddress.new(
|
58
|
+
def billing_email_address=(email_address_string)
|
59
|
+
self.bill_email = EmailAddress.new(email_address_string)
|
59
60
|
end
|
61
|
+
alias_method :email=, :billing_email_address= # backward backward compatibility to v0.4.6
|
60
62
|
|
61
63
|
end
|
62
64
|
end
|
@@ -16,7 +16,7 @@ module Quickbooks
|
|
16
16
|
xml_accessor :tax_return_line_ref, :from => "TaxReturnLineRef", :as => BaseReference
|
17
17
|
xml_accessor :special_tax_type, :from => "SpecialTaxType"
|
18
18
|
xml_accessor :display_type, :from => "DisplayType"
|
19
|
-
xml_accessor :effective_tax_rate, :from => "EffectiveTaxRate"
|
19
|
+
xml_accessor :effective_tax_rate, :from => "EffectiveTaxRate", :as => [EffectiveTaxRate]
|
20
20
|
|
21
21
|
validates_presence_of :name, :rate_value
|
22
22
|
|
@@ -43,10 +43,11 @@ 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)
|
49
|
-
errors.add(:employee_ref, "
|
50
|
+
errors.add(:employee_ref, "EmployeeRef is required and must be a non-zero value.")
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Quickbooks
|
2
|
+
module Model
|
3
|
+
class Transfer < BaseModel
|
4
|
+
XML_COLLECTION_NODE = "Transfer"
|
5
|
+
XML_NODE = "Transfer"
|
6
|
+
REST_RESOURCE = 'transfer'
|
7
|
+
|
8
|
+
xml_accessor :id, :from => 'Id'
|
9
|
+
xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
|
10
|
+
xml_accessor :meta_data, :from => 'MetaData', :as => MetaData
|
11
|
+
xml_accessor :txn_date, :from => 'TxnDate', :as => Date
|
12
|
+
xml_accessor :currency_ref, :from => 'CurrencyRef', :as => BaseReference
|
13
|
+
xml_accessor :private_note, :from => 'PrivateNote'
|
14
|
+
xml_accessor :from_account_ref, :from => 'FromAccountRef', :as => BaseReference
|
15
|
+
xml_accessor :to_account_ref, :from => 'ToAccountRef', :as => BaseReference
|
16
|
+
xml_accessor :amount, :from => 'Amount', :as => BigDecimal, :to_xml => to_xml_big_decimal
|
17
|
+
|
18
|
+
reference_setters :currency_ref, :to_account_ref, :from_account_ref
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -41,6 +41,7 @@ module Quickbooks
|
|
41
41
|
xml_accessor :account_number, :from => 'AcctNum'
|
42
42
|
xml_accessor :is_1099?, :from => 'Vendor1099'
|
43
43
|
xml_accessor :currency_ref, :from => 'CurrencyRef', :as => BaseReference
|
44
|
+
xml_accessor :bill_rate, from: "BillRate", as: BigDecimal, to_xml: to_xml_big_decimal
|
44
45
|
|
45
46
|
#== Validations
|
46
47
|
validate :names_cannot_contain_invalid_characters
|
@@ -3,7 +3,7 @@ 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://
|
6
|
+
DISCONNECT_URL = "https://developer.api.intuit.com/v2/oauth2/tokens/revoke"
|
7
7
|
|
8
8
|
# https://developer.intuit.com/docs/0025_quickbooksapi/0053_auth_auth/oauth_management_api#Reconnect
|
9
9
|
def renew
|
@@ -21,18 +21,19 @@ module Quickbooks
|
|
21
21
|
|
22
22
|
# https://developer.intuit.com/docs/0025_quickbooksapi/0053_auth_auth/oauth_management_api#Disconnect
|
23
23
|
def disconnect
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
if code == 200
|
29
|
-
result = Quickbooks::Model::AccessTokenResponse.from_xml(response.plain_body)
|
30
|
-
end
|
31
|
-
end
|
24
|
+
conn = Faraday.new
|
25
|
+
conn.basic_auth oauth.client.id, oauth.client.secret
|
26
|
+
url = "#{DISCONNECT_URL}?minorversion=#{Quickbooks.minorversion}"
|
27
|
+
response = conn.post(url, token: oauth.refresh_token || oauth.token)
|
32
28
|
|
33
|
-
|
29
|
+
if response.success?
|
30
|
+
Quickbooks::Model::AccessTokenResponse.new(error_code: "0")
|
31
|
+
else
|
32
|
+
Quickbooks::Model::AccessTokenResponse.new(
|
33
|
+
error_code: response.status.to_s, error_message: response.reason_phrase
|
34
|
+
)
|
35
|
+
end
|
34
36
|
end
|
35
|
-
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|
@@ -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"
|
@@ -25,6 +30,7 @@ module Quickbooks
|
|
25
30
|
|
26
31
|
def access_token=(token)
|
27
32
|
@oauth = token
|
33
|
+
rebuild_connection!
|
28
34
|
end
|
29
35
|
|
30
36
|
def company_id=(company_id)
|
@@ -36,6 +42,22 @@ module Quickbooks
|
|
36
42
|
@company_id = company_id
|
37
43
|
end
|
38
44
|
|
45
|
+
# def oauth_v2?
|
46
|
+
# @oauth.is_a? OAuth2::AccessToken
|
47
|
+
# end
|
48
|
+
|
49
|
+
# [OAuth2] The default Faraday connection does not have gzip or multipart support.
|
50
|
+
# We need to reset the existing connection and build a new one.
|
51
|
+
def rebuild_connection!
|
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
|
@@ -49,15 +71,19 @@ module Quickbooks
|
|
49
71
|
self.class::HTTP_CONTENT_TYPE == "application/json"
|
50
72
|
end
|
51
73
|
|
74
|
+
def is_pdf?
|
75
|
+
self.class::HTTP_CONTENT_TYPE == "application/pdf"
|
76
|
+
end
|
77
|
+
|
52
78
|
def default_model_query
|
53
79
|
"SELECT * FROM #{self.class.name.split("::").last}"
|
54
80
|
end
|
55
81
|
|
56
|
-
def url_for_query(query = nil, start_position = 1, max_results = 20)
|
82
|
+
def url_for_query(query = nil, start_position = 1, max_results = 20, options = {})
|
57
83
|
query ||= default_model_query
|
58
84
|
query = "#{query} STARTPOSITION #{start_position} MAXRESULTS #{max_results}"
|
59
85
|
|
60
|
-
"#{url_for_base}/query?query=#{
|
86
|
+
"#{url_for_base}/query?query=#{CGI.escape(query)}"
|
61
87
|
end
|
62
88
|
|
63
89
|
private
|
@@ -174,6 +200,21 @@ module Quickbooks
|
|
174
200
|
do_http(:get, url, {}, headers)
|
175
201
|
end
|
176
202
|
|
203
|
+
def do_http_raw_get(url, params = {}, headers = {})
|
204
|
+
url = add_query_string_to_url(url, params)
|
205
|
+
unless headers.has_key?('Content-Type')
|
206
|
+
headers['Content-Type'] = self.class::HTTP_CONTENT_TYPE
|
207
|
+
end
|
208
|
+
unless headers.has_key?('Accept')
|
209
|
+
headers['Accept'] = self.class::HTTP_ACCEPT
|
210
|
+
end
|
211
|
+
unless headers.has_key?('Accept-Encoding')
|
212
|
+
headers['Accept-Encoding'] = HTTP_ACCEPT_ENCODING
|
213
|
+
end
|
214
|
+
raw_response = oauth_get(url, headers)
|
215
|
+
Quickbooks::Service::Responses::OAuthHttpResponse.wrap(raw_response)
|
216
|
+
end
|
217
|
+
|
177
218
|
def do_http_file_upload(uploadIO, url, metadata = nil)
|
178
219
|
headers = {
|
179
220
|
'Content-Type' => 'multipart/form-data'
|
@@ -188,6 +229,8 @@ module Quickbooks
|
|
188
229
|
body['file_metadata_0'] = param_part
|
189
230
|
end
|
190
231
|
|
232
|
+
url = add_query_string_to_url(url, {})
|
233
|
+
|
191
234
|
do_http(:upload, url, body, headers)
|
192
235
|
end
|
193
236
|
|
@@ -211,31 +254,71 @@ module Quickbooks
|
|
211
254
|
log_request_body(body)
|
212
255
|
log "REQUEST HEADERS = #{headers.inspect}"
|
213
256
|
|
214
|
-
|
257
|
+
request_info = RequestInfo.new(url, headers, body, method)
|
258
|
+
before_request.call(request_info) if before_request
|
259
|
+
|
260
|
+
raw_response = with_around_request(request_info) do
|
261
|
+
case method
|
215
262
|
when :get
|
216
|
-
|
263
|
+
oauth_get(url, headers)
|
217
264
|
when :post
|
218
|
-
|
265
|
+
oauth_post(url, body, headers)
|
219
266
|
when :upload
|
220
|
-
|
267
|
+
oauth_post_with_multipart(url, body, headers)
|
221
268
|
else
|
222
269
|
raise "Do not know how to perform that HTTP operation"
|
223
270
|
end
|
224
|
-
|
271
|
+
end
|
272
|
+
|
273
|
+
after_request.call(request_info, raw_response.body) if after_request
|
274
|
+
|
275
|
+
response = Quickbooks::Service::Responses::OAuthHttpResponse.wrap(raw_response)
|
276
|
+
log "------ QUICKBOOKS-RUBY RESPONSE ------"
|
277
|
+
log "RESPONSE CODE = #{response.code}"
|
278
|
+
log_response_body(response)
|
279
|
+
if response.respond_to?(:headers)
|
280
|
+
log "RESPONSE HEADERS = #{response.headers}"
|
281
|
+
end
|
282
|
+
check_response(response, request: body)
|
283
|
+
end
|
284
|
+
|
285
|
+
def oauth_get(url, headers)
|
286
|
+
@oauth.get(url, headers: headers, raise_errors: false)
|
225
287
|
end
|
226
288
|
|
227
|
-
def
|
289
|
+
def oauth_post(url, body, headers)
|
290
|
+
@oauth.post(url, headers: headers, body: body, raise_errors: false)
|
291
|
+
end
|
292
|
+
|
293
|
+
def oauth_post_with_multipart(url, body, headers)
|
294
|
+
@oauth.post_with_multipart(url, headers: headers, body: body, raise_errors: false)
|
295
|
+
end
|
296
|
+
|
297
|
+
def add_query_string_to_url(url, params = {})
|
298
|
+
params ||= {}
|
299
|
+
params['minorversion'] = Quickbooks.minorversion
|
228
300
|
if params.is_a?(Hash) && !params.empty?
|
229
|
-
|
301
|
+
keyvalues = params.collect { |k| "#{k.first}=#{k.last}" }.join("&")
|
302
|
+
delim = url.index("?") != nil ? "&" : "?"
|
303
|
+
url + delim + keyvalues
|
230
304
|
else
|
231
305
|
url
|
232
306
|
end
|
233
307
|
end
|
234
308
|
|
235
309
|
def check_response(response, options = {})
|
236
|
-
|
237
|
-
|
238
|
-
|
310
|
+
if is_json?
|
311
|
+
parse_json(response.plain_body)
|
312
|
+
elsif !is_pdf?
|
313
|
+
parse_xml(response.plain_body)
|
314
|
+
end
|
315
|
+
|
316
|
+
@last_response_intuit_tid = if response.respond_to?(:headers) && response.headers
|
317
|
+
response.headers['intuit_tid']
|
318
|
+
else
|
319
|
+
nil
|
320
|
+
end
|
321
|
+
|
239
322
|
status = response.code.to_i
|
240
323
|
case status
|
241
324
|
when 200
|
@@ -248,12 +331,23 @@ module Quickbooks
|
|
248
331
|
when 302
|
249
332
|
raise "Unhandled HTTP Redirect"
|
250
333
|
when 401
|
251
|
-
raise Quickbooks::AuthorizationFailure
|
334
|
+
raise Quickbooks::AuthorizationFailure, parse_intuit_error
|
252
335
|
when 403
|
253
|
-
|
336
|
+
message = parse_intuit_error[:message]
|
337
|
+
if message.include?('ThrottleExceeded')
|
338
|
+
raise Quickbooks::ThrottleExceeded, message
|
339
|
+
end
|
340
|
+
raise Quickbooks::Forbidden, message
|
341
|
+
when 404
|
342
|
+
raise Quickbooks::NotFound
|
343
|
+
when 413
|
344
|
+
raise Quickbooks::RequestTooLarge
|
254
345
|
when 400, 500
|
255
346
|
parse_and_raise_exception(options)
|
256
|
-
when
|
347
|
+
when 429
|
348
|
+
message = parse_intuit_error[:message]
|
349
|
+
raise Quickbooks::TooManyRequests, message
|
350
|
+
when 502, 503, 504
|
257
351
|
raise Quickbooks::ServiceUnavailable
|
258
352
|
else
|
259
353
|
raise "HTTP Error Code: #{status}, Msg: #{response.plain_body}"
|
@@ -264,10 +358,10 @@ module Quickbooks
|
|
264
358
|
log "RESPONSE BODY:"
|
265
359
|
if is_json?
|
266
360
|
log ">>>>#{response.plain_body.inspect}"
|
267
|
-
|
361
|
+
elsif is_pdf?
|
362
|
+
log("BODY is a PDF : not dumping")
|
268
363
|
else
|
269
364
|
log(log_xml(response.plain_body))
|
270
|
-
parse_xml(response.plain_body)
|
271
365
|
end
|
272
366
|
end
|
273
367
|
|
@@ -275,8 +369,26 @@ module Quickbooks
|
|
275
369
|
log "REQUEST BODY:"
|
276
370
|
if is_json?
|
277
371
|
log(body.inspect)
|
372
|
+
elsif is_pdf?
|
373
|
+
log("BODY is a PDF : not dumping")
|
278
374
|
else
|
279
|
-
|
375
|
+
#multipart request for uploads arrive here in a Hash with UploadIO vals
|
376
|
+
if body.is_a?(Hash)
|
377
|
+
body.each do |k,v|
|
378
|
+
log('BODY PART:')
|
379
|
+
val_content = v.inspect
|
380
|
+
if v.is_a?(UploadIO)
|
381
|
+
if v.content_type == 'application/xml'
|
382
|
+
if v.io.is_a?(StringIO)
|
383
|
+
val_content = log_xml(v.io.string)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
log("#{k}: #{val_content}")
|
388
|
+
end
|
389
|
+
else
|
390
|
+
log(log_xml(body))
|
391
|
+
end
|
280
392
|
end
|
281
393
|
end
|
282
394
|
|
@@ -291,17 +403,22 @@ module Quickbooks
|
|
291
403
|
else
|
292
404
|
ex.request_xml = options[:request]
|
293
405
|
end
|
406
|
+
ex.intuit_tid = err[:intuit_tid]
|
294
407
|
raise ex
|
295
408
|
end
|
296
409
|
|
297
410
|
def response_is_error?
|
298
|
-
|
299
|
-
|
300
|
-
|
411
|
+
begin
|
412
|
+
@last_response_xml.xpath("//xmlns:IntuitResponse/xmlns:Fault")[0] != nil
|
413
|
+
rescue Nokogiri::XML::XPath::SyntaxError => exception
|
414
|
+
#puts @last_response_xml.to_xml.to_s
|
415
|
+
#puts "WTF: #{exception.inspect}:#{exception.backtrace.join("\n")}"
|
416
|
+
true
|
417
|
+
end
|
301
418
|
end
|
302
419
|
|
303
420
|
def parse_intuit_error
|
304
|
-
error = {:message => "", :detail => "", :type => nil, :code => 0}
|
421
|
+
error = {:message => "", :detail => "", :type => nil, :code => 0, :intuit_tid => @last_response_intuit_tid}
|
305
422
|
fault = @last_response_xml.xpath("//xmlns:IntuitResponse/xmlns:Fault")[0]
|
306
423
|
if fault
|
307
424
|
error[:type] = fault.attributes['type'].value
|
@@ -313,7 +430,7 @@ module Quickbooks
|
|
313
430
|
error[:code] = code_attr.value
|
314
431
|
end
|
315
432
|
element_attr = error_element.attributes['element']
|
316
|
-
if
|
433
|
+
if element_attr
|
317
434
|
error[:element] = code_attr.value
|
318
435
|
end
|
319
436
|
error[:message] = error_element.xpath("//xmlns:Message").text
|
@@ -328,6 +445,13 @@ module Quickbooks
|
|
328
445
|
error
|
329
446
|
end
|
330
447
|
|
448
|
+
def with_around_request(request_info, &block)
|
449
|
+
if around_request
|
450
|
+
around_request.call(request_info, &block)
|
451
|
+
else
|
452
|
+
block.call
|
453
|
+
end
|
454
|
+
end
|
331
455
|
end
|
332
456
|
end
|
333
457
|
end
|