quickbooks-ruby 1.0.4 → 1.0.9

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: 40551acdb7045eb4d1116184111f110f4874eb9e7391881f0e28aa9ddc4678c9
4
- data.tar.gz: c8c0d88b58964da0cde75066a6bcb79fa771945dc2abf94ae1bde9564164a85d
3
+ metadata.gz: 375f9daba794fd0b93b4fde2b81e668f480a6957b44f17cdfb040ca184a1678b
4
+ data.tar.gz: aca82b6f6dbdd8efd18b649cfb37360588a7d08f5834cac395f0714f62454d9c
5
5
  SHA512:
6
- metadata.gz: fdf59bc8aecbadb40920a63b7a98b6fb38690ff8ce4a416fd38866d7841b3511934a2a384b12f3bbf3ed6ccb6e22af201674d0420819e4506ca358b03a921502
7
- data.tar.gz: e71a5e129f98a03016cfd43e8e180c7dc9af8e0104d39d9052c5fd438a49bc742f667b1e9ac2e23ed3acd495d2f4d3d531c03a1fc6d907466f765aa3faa877b1
6
+ metadata.gz: fd4e12e405534be10ff030540645495c396f5f0d9238e261880584cf13418ce6642a7e8a59a0b1d7d0f5be97fdf50aee9f0f7339fc14b2ef593d610545c1b92b
7
+ data.tar.gz: 9c424fa4c473994139630bc131a1c58905e09aa16fae6b6dec2df9a17b8efdef1a55046518b9d5d0a7ffe532c281dbb81fdf16ee04cde39893ced168467b56f4
@@ -75,6 +75,7 @@ require 'quickbooks/model/invoice_line_item'
75
75
  require 'quickbooks/model/invoice_group_line_detail'
76
76
  require 'quickbooks/model/company_info'
77
77
  require 'quickbooks/model/company_currency'
78
+ require 'quickbooks/model/customer_type'
78
79
  require 'quickbooks/model/customer'
79
80
  require 'quickbooks/model/delivery_info'
80
81
  require 'quickbooks/model/sales_receipt'
@@ -137,6 +138,8 @@ require 'quickbooks/service/class'
137
138
  require 'quickbooks/service/attachable'
138
139
  require 'quickbooks/service/company_info'
139
140
  require 'quickbooks/service/company_currency'
141
+ require 'quickbooks/service/customer_type'
142
+ require 'quickbooks/service/custom_field'
140
143
  require 'quickbooks/service/customer'
141
144
  require 'quickbooks/service/department'
142
145
  require 'quickbooks/service/invoice'
@@ -188,6 +191,7 @@ Faraday::Middleware.register_middleware :gzip => lambda { Gzip }
188
191
  module Quickbooks
189
192
  @@sandbox_mode = false
190
193
  @@logger = nil
194
+ @@minorversion = 47
191
195
 
192
196
  class << self
193
197
  def sandbox_mode
@@ -198,6 +202,14 @@ module Quickbooks
198
202
  @@sandbox_mode = sandbox_mode
199
203
  end
200
204
 
205
+ def minorversion=(v)
206
+ @@minorversion = v
207
+ end
208
+
209
+ def minorversion
210
+ @@minorversion
211
+ end
212
+
201
213
  def logger
202
214
  @@logger ||= ::Logger.new($stdout) # TODO: replace with a real log file
203
215
  end
@@ -246,6 +258,7 @@ module Quickbooks
246
258
  class TooManyRequests < Error; end
247
259
  class ServiceUnavailable < Error; end
248
260
  class MissingRealmError < Error; end
261
+ class UnsupportedOperation < Error; end
249
262
 
250
263
  class IntuitRequestException < Error
251
264
  attr_accessor :message, :code, :detail, :type, :intuit_tid, :request_xml, :request_json
@@ -23,6 +23,8 @@ class Gzip < Faraday::Middleware
23
23
  def call(env)
24
24
  env[:request_headers][ACCEPT_ENCODING] ||= SUPPORTED_ENCODINGS
25
25
  @app.call(env).on_complete do |response_env|
26
+ break if response_env[:response_headers].nil?
27
+
26
28
  case response_env[:response_headers][CONTENT_ENCODING]
27
29
  when 'gzip'
28
30
  reset_body(response_env, &method(:uncompress_gzip))
@@ -4,7 +4,6 @@ module Quickbooks
4
4
  XML_COLLECTION_NODE = "Account"
5
5
  XML_NODE = "Account"
6
6
  REST_RESOURCE = 'account'
7
- MINORVERSION = 13
8
7
 
9
8
  ASSET = 'Asset'
10
9
  EQUITY = 'Equity'
@@ -16,6 +16,7 @@ module Quickbooks
16
16
  xml_accessor :department_ref, :from => 'DepartmentRef', :as => BaseReference
17
17
 
18
18
  xml_accessor :line_items, :from => 'Line', :as => [BillLineItem]
19
+ xml_accessor :txn_tax_detail, :from => 'TxnTaxDetail', :as => TransactionTaxDetail
19
20
 
20
21
  xml_accessor :private_note, :from => 'PrivateNote'
21
22
 
@@ -16,8 +16,6 @@ module Quickbooks
16
16
  include NameEntity::Quality
17
17
  include NameEntity::PermitAlterations
18
18
 
19
- MINORVERSION = 33
20
-
21
19
  xml_name XML_NODE
22
20
  xml_accessor :id, :from => 'Id'
23
21
  xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
@@ -56,12 +54,15 @@ module Quickbooks
56
54
  xml_accessor :notes, :from => 'Notes'
57
55
  xml_accessor :currency_ref, :from => 'CurrencyRef', :as => BaseReference
58
56
  xml_accessor :tax_exemption_reason_id, :from => 'TaxExemptionReasonId'
57
+ xml_accessor :primary_tax_identifier, :from => 'PrimaryTaxIdentifier'
58
+ xml_accessor :customer_type_ref, :from => 'CustomerTypeRef', :as => BaseReference
59
59
 
60
60
  #== Validations
61
61
  validate :names_cannot_contain_invalid_characters
62
62
  validate :email_address_is_valid
63
63
 
64
- reference_setters :parent_ref, :sales_term_ref, :payment_method_ref, :default_tax_code_ref, :currency_ref
64
+ reference_setters :parent_ref, :sales_term_ref, :payment_method_ref, :default_tax_code_ref, :currency_ref,
65
+ :customer_type_ref
65
66
 
66
67
  def job?
67
68
  job.to_s == 'true'
@@ -0,0 +1,15 @@
1
+ module Quickbooks
2
+ module Model
3
+ class CustomerType < BaseModel
4
+ XML_COLLECTION_NODE = "CustomerType"
5
+ XML_NODE = "CustomerType"
6
+ REST_RESOURCE = 'customertype'
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 :name, :from => 'Name'
12
+ xml_accessor :active?, :from => 'Active'
13
+ end
14
+ end
15
+ end
@@ -17,7 +17,6 @@ module Quickbooks
17
17
  XML_COLLECTION_NODE = "Invoice"
18
18
  XML_NODE = "Invoice"
19
19
  EMAIL_STATUS_NEED_TO_SEND = 'NeedToSend'
20
- MINORVERSION = 37
21
20
 
22
21
  xml_accessor :id, :from => 'Id'
23
22
  xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
@@ -10,7 +10,6 @@ module Quickbooks
10
10
  XML_COLLECTION_NODE = "Item"
11
11
  XML_NODE = "Item"
12
12
  REST_RESOURCE = 'item'
13
- MINORVERSION = 33
14
13
 
15
14
  INVENTORY_TYPE = 'Inventory'
16
15
  NON_INVENTORY_TYPE = 'NonInventory'
@@ -31,6 +30,7 @@ module Quickbooks
31
30
  xml_accessor :level, :from => 'Level', :as => Integer
32
31
  xml_accessor :pref_vendor_ref, :from => 'PrefVendorRef', :as => BaseReference
33
32
  xml_accessor :tax_classification_ref, :from => 'TaxClassificationRef', :as => BaseReference
33
+ xml_accessor :class_ref, :from => 'ClassRef', :as => BaseReference
34
34
 
35
35
  # read-only
36
36
  xml_accessor :fully_qualified_name, :from => 'FullyQualifiedName'
@@ -52,13 +52,11 @@ module Quickbooks
52
52
  xml_accessor :inv_start_date, :from => 'InvStartDate', :as => Date
53
53
  xml_accessor :custom_fields, :from => "CustomField", as: [CustomField]
54
54
  xml_accessor :print_grouped_items?, :from => 'PrintGroupedItems'
55
-
56
-
57
55
  xml_accessor :item_group_details, :from => 'ItemGroupDetail', :as => ItemGroupDetail
58
56
 
59
57
  reference_setters :parent_ref, :income_account_ref, :expense_account_ref
60
58
  reference_setters :asset_account_ref, :sales_tax_code_ref, :purchase_tax_code_ref
61
- reference_setters :pref_vendor_ref, :tax_classification_ref
59
+ reference_setters :pref_vendor_ref, :tax_classification_ref, :class_ref
62
60
 
63
61
  #== Validations
64
62
  validates_length_of :name, :minimum => 1
@@ -4,7 +4,6 @@ module Quickbooks
4
4
  XML_COLLECTION_NODE = "Preferences"
5
5
  XML_NODE = "Preferences"
6
6
  REST_RESOURCE = 'preferences'
7
- MINORVERSION = 32
8
7
 
9
8
  xml_name XML_NODE
10
9
 
@@ -8,7 +8,6 @@ module Quickbooks
8
8
  REST_RESOURCE = 'purchaseorder'
9
9
  XML_COLLECTION_NODE = "PurchaseOrder"
10
10
  XML_NODE = "PurchaseOrder"
11
- MINORVERSION = 45
12
11
 
13
12
  xml_accessor :id, :from => 'Id'
14
13
  xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
@@ -38,7 +38,7 @@ module Quickbooks
38
38
  value = el.attr('value')
39
39
 
40
40
  next nil if value.blank?
41
- next value if value.to_s.match(/^\d+$|^\d+.\d+$|^-\d+|^-\d+.\d+$|^.\d+$/).nil?
41
+ next value if value.to_s.match(/^\d+$|^\d+\.\d+$|^-\d+|^-\d+\.\d+$|^\.\d+$/).nil?
42
42
  BigDecimal(value)
43
43
  end
44
44
  end
@@ -3,8 +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_OAUTH1 = "https://appcenter.intuit.com/api/v1/connection/disconnect"
7
- DISCONNECT_URL_OAUTH2 = "https://developer.api.intuit.com/v2/oauth2/tokens/revoke"
6
+ DISCONNECT_URL = "https://developer.api.intuit.com/v2/oauth2/tokens/revoke"
8
7
 
9
8
  # https://developer.intuit.com/docs/0025_quickbooksapi/0053_auth_auth/oauth_management_api#Reconnect
10
9
  def renew
@@ -22,26 +21,18 @@ module Quickbooks
22
21
 
23
22
  # https://developer.intuit.com/docs/0025_quickbooksapi/0053_auth_auth/oauth_management_api#Disconnect
24
23
  def disconnect
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)
29
- 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)
24
+ conn = Faraday.new
25
+ conn.basic_auth oauth.client.id, oauth.client.secret
26
+ response = conn.post(DISCONNECT_URL, token: oauth.refresh_token || oauth.token)
34
27
 
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
28
+ if response.success?
29
+ Quickbooks::Model::AccessTokenResponse.new(error_code: "0")
30
+ else
31
+ Quickbooks::Model::AccessTokenResponse.new(
32
+ error_code: response.status.to_s, error_message: response.reason_phrase
33
+ )
42
34
  end
43
35
  end
44
-
45
36
  end
46
37
  end
47
38
  end
@@ -7,11 +7,6 @@ module Quickbooks
7
7
  update(account, :sparse => true)
8
8
  end
9
9
 
10
- def url_for_query(query = nil, start_position = 1, max_results = 20, options = {})
11
- url = super(query, start_position, max_results, options)
12
- "#{url}&minorversion=#{Quickbooks::Model::Account::MINORVERSION}"
13
- end
14
-
15
10
  private
16
11
 
17
12
  def model
@@ -9,6 +9,9 @@ module Quickbooks
9
9
  attr_reader :base_uri
10
10
  attr_reader :last_response_xml
11
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"
@@ -78,7 +83,7 @@ module Quickbooks
78
83
  query ||= default_model_query
79
84
  query = "#{query} STARTPOSITION #{start_position} MAXRESULTS #{max_results}"
80
85
 
81
- "#{url_for_base}/query?query=#{CGI.escape(query)}"
86
+ "#{url_for_base}/query?query=#{CGI.escape(query)}&minorversion=#{Quickbooks.minorversion}"
82
87
  end
83
88
 
84
89
  private
@@ -247,17 +252,24 @@ module Quickbooks
247
252
  log_request_body(body)
248
253
  log "REQUEST HEADERS = #{headers.inspect}"
249
254
 
250
- raw_response = case method
251
- when :get
252
- oauth_get(url, headers)
253
- when :post
254
- oauth_post(url, body, headers)
255
- when :upload
256
- oauth_post_with_multipart(url, body, headers)
257
- else
258
- raise "Do not know how to perform that HTTP operation"
255
+ request_info = RequestInfo.new(url, headers, body, method)
256
+ before_request.call(request_info) if before_request
257
+
258
+ raw_response = with_around_request(request_info) do
259
+ case method
260
+ when :get
261
+ oauth_get(url, headers)
262
+ when :post
263
+ oauth_post(url, body, headers)
264
+ when :upload
265
+ oauth_post_with_multipart(url, body, headers)
266
+ else
267
+ raise "Do not know how to perform that HTTP operation"
268
+ end
259
269
  end
260
270
 
271
+ after_request.call(request_info, raw_response.body) if after_request
272
+
261
273
  response = Quickbooks::Service::Responses::OAuthHttpResponse.wrap(raw_response)
262
274
  log "------ QUICKBOOKS-RUBY RESPONSE ------"
263
275
  log "RESPONSE CODE = #{response.code}"
@@ -429,6 +441,13 @@ module Quickbooks
429
441
  error
430
442
  end
431
443
 
444
+ def with_around_request(request_info, &block)
445
+ if around_request
446
+ around_request.call(request_info, &block)
447
+ else
448
+ block.call
449
+ end
450
+ end
432
451
  end
433
452
  end
434
453
  end
@@ -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
@@ -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
@@ -7,7 +7,7 @@ module Quickbooks
7
7
  end
8
8
 
9
9
  def fetch_by_id(id, params = {})
10
- url = "#{url_for_base}/invoice/#{id}?minorversion=#{Quickbooks::Model::PurchaseOrder::MINORVERSION}"
10
+ url = "#{url_for_base}/purchaseorder/#{id}?minorversion=#{Quickbooks::Model::PurchaseOrder::MINORVERSION}"
11
11
  fetch_object(model, url, params)
12
12
  end
13
13
 
@@ -10,26 +10,27 @@ module Quickbooks
10
10
  end
11
11
 
12
12
  def clause(field, operator, value)
13
+ # replace with an escaped backslash
14
+ escape_single_quotes = -> field { field.to_s.gsub("'", "\\\\'") }
15
+
13
16
  value = case value
14
17
  when DateTime, Time
15
18
  value.iso8601
16
19
  when Date
17
20
  value.strftime('%Y-%m-%d')
18
21
  when Array
19
- value = value.map{|v| v.to_s.gsub("'", "\\\\'") }
22
+ value = value.map(&escape_single_quotes)
20
23
  else
21
- # escape single quotes with an escaped backslash
22
- value = value.gsub("'", "\\\\'")
24
+ value = escape_single_quotes.call(value)
23
25
  end
24
26
 
25
27
  if operator.downcase == 'in' && value.is_a?(Array)
26
- value = value.map{|v| "#{VALUE_QUOTE}#{v}#{VALUE_QUOTE}"}
28
+ value = value.map { |v| "#{VALUE_QUOTE}#{v}#{VALUE_QUOTE}" }
27
29
  "#{field} #{operator} (#{value.join(', ')})"
28
30
  else
29
31
  "#{field} #{operator} #{VALUE_QUOTE}#{value}#{VALUE_QUOTE}"
30
32
  end
31
33
  end
32
-
33
34
  end
34
35
  end
35
36
  end
@@ -1,5 +1,5 @@
1
1
  module Quickbooks
2
2
 
3
- VERSION = "1.0.4"
3
+ VERSION = "1.0.9"
4
4
 
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quickbooks-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Caughlan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-22 00:00:00.000000000 Z
11
+ date: 2020-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth2
@@ -202,6 +202,7 @@ files:
202
202
  - lib/quickbooks/model/custom_field.rb
203
203
  - lib/quickbooks/model/customer.rb
204
204
  - lib/quickbooks/model/customer_change.rb
205
+ - lib/quickbooks/model/customer_type.rb
205
206
  - lib/quickbooks/model/definition.rb
206
207
  - lib/quickbooks/model/delivery_info.rb
207
208
  - lib/quickbooks/model/department.rb
@@ -293,8 +294,10 @@ files:
293
294
  - lib/quickbooks/service/company_info.rb
294
295
  - lib/quickbooks/service/credit_memo.rb
295
296
  - lib/quickbooks/service/credit_memo_change.rb
297
+ - lib/quickbooks/service/custom_field.rb
296
298
  - lib/quickbooks/service/customer.rb
297
299
  - lib/quickbooks/service/customer_change.rb
300
+ - lib/quickbooks/service/customer_type.rb
298
301
  - lib/quickbooks/service/department.rb
299
302
  - lib/quickbooks/service/deposit.rb
300
303
  - lib/quickbooks/service/employee.rb