quickeebooks 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +52 -0
  3. data/MIT-LICENSE +9 -0
  4. data/README.md +306 -0
  5. data/Rakefile +17 -0
  6. data/lib/quickeebooks.rb +89 -0
  7. data/lib/quickeebooks/online/model/account.rb +47 -0
  8. data/lib/quickeebooks/online/model/account_detail_type.rb +233 -0
  9. data/lib/quickeebooks/online/model/account_reference.rb +17 -0
  10. data/lib/quickeebooks/online/model/address.rb +42 -0
  11. data/lib/quickeebooks/online/model/customer.rb +66 -0
  12. data/lib/quickeebooks/online/model/customer_custom_field.rb +51 -0
  13. data/lib/quickeebooks/online/model/email.rb +24 -0
  14. data/lib/quickeebooks/online/model/intuit_type.rb +25 -0
  15. data/lib/quickeebooks/online/model/invoice.rb +50 -0
  16. data/lib/quickeebooks/online/model/invoice_header.rb +29 -0
  17. data/lib/quickeebooks/online/model/invoice_line_item.rb +22 -0
  18. data/lib/quickeebooks/online/model/item.rb +47 -0
  19. data/lib/quickeebooks/online/model/meta_data.rb +27 -0
  20. data/lib/quickeebooks/online/model/note.rb +11 -0
  21. data/lib/quickeebooks/online/model/open_balance.rb +11 -0
  22. data/lib/quickeebooks/online/model/phone.rb +12 -0
  23. data/lib/quickeebooks/online/model/price.rb +18 -0
  24. data/lib/quickeebooks/online/model/purchase_cost.rb +11 -0
  25. data/lib/quickeebooks/online/model/unit_price.rb +11 -0
  26. data/lib/quickeebooks/online/model/web_site.rb +16 -0
  27. data/lib/quickeebooks/online/service/account.rb +52 -0
  28. data/lib/quickeebooks/online/service/customer.rb +57 -0
  29. data/lib/quickeebooks/online/service/entitlement.rb +15 -0
  30. data/lib/quickeebooks/online/service/filter.rb +96 -0
  31. data/lib/quickeebooks/online/service/invoice.rb +50 -0
  32. data/lib/quickeebooks/online/service/item.rb +52 -0
  33. data/lib/quickeebooks/online/service/pagination.rb +19 -0
  34. data/lib/quickeebooks/online/service/service_base.rb +202 -0
  35. data/lib/quickeebooks/online/service/sort.rb +19 -0
  36. data/lib/quickeebooks/version.rb +5 -0
  37. data/lib/quickeebooks/windows/model/account.rb +67 -0
  38. data/lib/quickeebooks/windows/model/account_detail_type.rb +233 -0
  39. data/lib/quickeebooks/windows/model/account_reference.rb +19 -0
  40. data/lib/quickeebooks/windows/model/address.rb +36 -0
  41. data/lib/quickeebooks/windows/model/custom_field.rb +13 -0
  42. data/lib/quickeebooks/windows/model/customer.rb +109 -0
  43. data/lib/quickeebooks/windows/model/email.rb +44 -0
  44. data/lib/quickeebooks/windows/model/intuit_type.rb +17 -0
  45. data/lib/quickeebooks/windows/model/invoice.rb +44 -0
  46. data/lib/quickeebooks/windows/model/invoice_header.rb +65 -0
  47. data/lib/quickeebooks/windows/model/invoice_line_item.rb +38 -0
  48. data/lib/quickeebooks/windows/model/item.rb +84 -0
  49. data/lib/quickeebooks/windows/model/meta_data.rb +31 -0
  50. data/lib/quickeebooks/windows/model/note.rb +19 -0
  51. data/lib/quickeebooks/windows/model/open_balance.rb +11 -0
  52. data/lib/quickeebooks/windows/model/phone.rb +20 -0
  53. data/lib/quickeebooks/windows/model/price.rb +18 -0
  54. data/lib/quickeebooks/windows/model/purchase_cost.rb +12 -0
  55. data/lib/quickeebooks/windows/model/tax_line.rb +18 -0
  56. data/lib/quickeebooks/windows/model/unit_price.rb +12 -0
  57. data/lib/quickeebooks/windows/model/vendor_reference.rb +13 -0
  58. data/lib/quickeebooks/windows/model/web_site.rb +19 -0
  59. data/lib/quickeebooks/windows/service/account.rb +16 -0
  60. data/lib/quickeebooks/windows/service/customer.rb +16 -0
  61. data/lib/quickeebooks/windows/service/invoice.rb +27 -0
  62. data/lib/quickeebooks/windows/service/item.rb +18 -0
  63. data/lib/quickeebooks/windows/service/service_base.rb +176 -0
  64. data/quickeebooks.gemspec +27 -0
  65. data/spec/mocks/oauth_consumer_mock.rb +2 -0
  66. data/spec/quickeebooks/online/account_spec.rb +41 -0
  67. data/spec/quickeebooks/online/customer_spec.rb +46 -0
  68. data/spec/quickeebooks/online/invoice_spec.rb +15 -0
  69. data/spec/quickeebooks/online/services/account_spec.rb +84 -0
  70. data/spec/quickeebooks/online/services/customer_spec.rb +107 -0
  71. data/spec/quickeebooks/online/services/filter_spec.rb +43 -0
  72. data/spec/quickeebooks/online/services/service_base_spec.rb +30 -0
  73. data/spec/quickeebooks/online/services/sort_spec.rb +17 -0
  74. data/spec/quickeebooks/windows/customer_spec.rb +49 -0
  75. data/spec/quickeebooks_spec.rb +11 -0
  76. data/spec/spec_helper.rb +20 -0
  77. data/spec/xml/online/account.xml +13 -0
  78. data/spec/xml/online/accounts.xml +108 -0
  79. data/spec/xml/online/customer.xml +63 -0
  80. data/spec/xml/online/customer2.xml +63 -0
  81. data/spec/xml/online/customers.xml +125 -0
  82. data/spec/xml/online/invoice.xml +33 -0
  83. data/spec/xml/online/user.xml +11 -0
  84. data/spec/xml/windows/customer.xml +56 -0
  85. data/spec/xml/windows/customers.xml +137 -0
  86. data/spec/xml/windows/http_401.xml +8 -0
  87. metadata +229 -0
@@ -0,0 +1,13 @@
1
+ require "quickeebooks"
2
+
3
+ module Quickeebooks
4
+ module Windows
5
+ module Model
6
+ class VendorReference < IntuitType
7
+ xml_accessor :vendor_id, :from => 'VendorId'
8
+ xml_accessor :vendor_name, :from => 'VendorName'
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ require "quickeebooks"
2
+
3
+ module Quickeebooks
4
+ module Windows
5
+ module Model
6
+ class WebSite < Quickeebooks::Windows::Model::IntuitType
7
+ xml_accessor :id, :from => 'Id'
8
+ xml_accessor :uri, :from => 'URI'
9
+ xml_accessor :tag, :from => 'Tag'
10
+ xml_accessor :default, :from => 'Default'
11
+
12
+ def to_xml(options = {})
13
+ return "" if uri.to_s.empty?
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ require 'quickeebooks/windows/model/account'
2
+ require 'quickeebooks/windows/service/service_base'
3
+
4
+ module Quickeebooks
5
+ module Windows
6
+ module Service
7
+ class Account < Quickeebooks::Windows::Service::ServiceBase
8
+
9
+ def list(filters = [], page = 1, per_page = 20, sort = nil, options = {})
10
+ fetch_collection("accounts", "Account", Quickeebooks::Windows::Model::Account, nil, filters, page, per_page, sort, options)
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'quickeebooks/windows/service/service_base'
2
+ require 'nokogiri'
3
+
4
+ module Quickeebooks
5
+ module Windows
6
+ module Service
7
+ class Customer < Quickeebooks::Windows::Service::ServiceBase
8
+
9
+ def list(filters = [], page = 1, per_page = 20, sort = nil, options = {})
10
+ fetch_collection("customer", "Customer", Quickeebooks::Windows::Model::Customer, nil, filters, page, per_page, sort, options)
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ require 'quickeebooks/windows/service/service_base'
2
+ require 'quickeebooks/windows/model/invoice'
3
+ require 'quickeebooks/windows/model/invoice_header'
4
+ require 'quickeebooks/windows/model/invoice_line_item'
5
+ require 'tempfile'
6
+
7
+ module Quickeebooks
8
+ module Windows
9
+ module Service
10
+ class Invoice < Quickeebooks::Windows::Service::ServiceBase
11
+
12
+
13
+ # Fetch a +Collection+ of +Invoice+ objects
14
+ # Arguments:
15
+ # filters: Array of +Filter+ objects to apply
16
+ # page: +Fixnum+ Starting page
17
+ # per_page: +Fixnum+ How many results to fetch per page
18
+ # sort: +Sort+ object
19
+ # options: +Hash+ extra arguments
20
+ def list(filters = [], page = 1, per_page = 20, sort = nil, options = {})
21
+ fetch_collection("invoices", "Invoice", Quickeebooks::Windows::Model::Invoice, nil, filters, page, per_page, sort, options)
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ require 'quickeebooks/windows/model/item'
2
+ require 'quickeebooks/windows/service/service_base'
3
+
4
+ module Quickeebooks
5
+ module Windows
6
+ module Service
7
+ class Item < Quickeebooks::Windows::Service::ServiceBase
8
+
9
+ def list(filters = [], page = 1, per_page = 20, sort = nil, options = {})
10
+ custom_field_query = '<ItemQuery xmlns="http://www.intuit.com/sb/cdm/v2"><CustomFieldEnable>true</CustomFieldEnable></ItemQuery>'
11
+ fetch_collection("item", "Item", Quickeebooks::Windows::Model::Item, custom_field_query, filters, page, per_page, sort, options)
12
+ end
13
+
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,176 @@
1
+ require 'rexml/document'
2
+ require 'uri'
3
+ require 'cgi'
4
+
5
+ class IntuitRequestException < Exception
6
+ attr_accessor :code, :cause
7
+ def initialize(msg)
8
+ super(msg)
9
+ end
10
+ end
11
+ class AuthorizationFailure < Exception; end
12
+
13
+ module Quickeebooks
14
+ module Windows
15
+ module Service
16
+ class ServiceBase
17
+
18
+ attr_accessor :realm_id
19
+ attr_accessor :oauth
20
+ attr_reader :base_uri
21
+ attr_reader :last_response_body
22
+ attr_reader :last_response_xml
23
+
24
+ XML_NS = %{xmlns:ns2="http://www.intuit.com/sb/cdm/qbo" xmlns="http://www.intuit.com/sb/cdm/v2" xmlns:ns3="http://www.intuit.com/sb/cdm"}
25
+
26
+ def initialize(oauth_access_token, realm_id)
27
+ @base_uri = 'https://services.intuit.com/sb'
28
+ @oauth = oauth_access_token
29
+ @realm_id = realm_id
30
+ end
31
+
32
+ def url_for_resource(resource)
33
+ url_for_base(resource)
34
+ end
35
+
36
+ def url_for_base(raw)
37
+ "#{@base_uri}/#{raw}/v2/#{@realm_id}"
38
+ end
39
+
40
+ private
41
+
42
+ def parse_xml(xml)
43
+ @last_response_xml ||=
44
+ begin
45
+ x = Nokogiri::XML(xml)
46
+ #x.document.remove_namespaces!
47
+ x
48
+ end
49
+ end
50
+
51
+ def valid_xml_document(xml)
52
+ %Q{<?xml version="1.0" encoding="utf-8"?>\n#{xml.strip}}
53
+ end
54
+
55
+ def fetch_collection(resource, container, model, custom_field_query = nil, filters = [], page = 1, per_page = 20, sort = nil, options ={})
56
+ raise ArgumentError, "missing resource to fetch" if resource.nil?
57
+ raise ArgumentError, "missing result container" if container.nil?
58
+ raise ArgumentError, "missing model to instantiate" if model.nil?
59
+
60
+ if custom_field_query != nil
61
+ response = do_http_post(url_for_resource(resource), custom_field_query, {}, {'Content-Type' => 'text/xml'})
62
+ else
63
+ response = do_http_get(url_for_resource(resource), {}, {'Content-Type' => 'text/html'})
64
+ end
65
+ if response
66
+ collection = Quickeebooks::Collection.new
67
+ xml = parse_xml(response.body)
68
+ begin
69
+ results = []
70
+ path_to_nodes = "//xmlns:RestResponse/xmlns:#{model::XML_COLLECTION_NODE}/xmlns:#{model::XML_NODE}"
71
+ collection.count = xml.xpath(path_to_nodes).count
72
+ if collection.count > 0
73
+ xml.xpath(path_to_nodes).each do |xa|
74
+ entry = model.from_xml(xa)
75
+ results << entry
76
+ end
77
+ end
78
+ collection.entries = results
79
+ collection.current_page = 1 # TODO: fix this
80
+ rescue => ex
81
+ log("Error parsing XML: #{ex.message}")
82
+ raise IntuitRequestException.new("Error parsing XML: #{ex.message}")
83
+ end
84
+ collection
85
+ else
86
+ nil
87
+ end
88
+ end
89
+
90
+ def do_http_post(url, body = "", params = {}, headers = {}) # throws IntuitRequestException
91
+ url = add_query_string_to_url(url, params)
92
+ do_http(:post, url, body, headers)
93
+ end
94
+
95
+ def do_http_get(url, params = {}, headers = {}) # throws IntuitRequestException
96
+ url = add_query_string_to_url(url, params)
97
+ do_http(:get, url, "", headers)
98
+ end
99
+
100
+ def do_http(method, url, body, headers) # throws IntuitRequestException
101
+ unless headers.has_key?('Content-Type')
102
+ headers.merge!({'Content-Type' => 'application/xml'})
103
+ end
104
+ # puts "METHOD = #{method}"
105
+ # puts "URL = #{url}"
106
+ # puts "BODY = #{body == nil ? "<NIL>" : body}"
107
+ # puts "HEADERS = #{headers.inspect}"
108
+ response = @oauth.request(method, url, body, headers)
109
+ check_response(response)
110
+ end
111
+
112
+ def add_query_string_to_url(url, params)
113
+ if params.is_a?(Hash) && !params.empty?
114
+ url + "?" + params.collect { |k| "#{k.first}=#{k.last}" }.join("&")
115
+ else
116
+ url
117
+ end
118
+ end
119
+
120
+ def check_response(response)
121
+ #puts "HTTP Response: #{response.code}"
122
+ parse_xml(response.body)
123
+ status = response.code.to_i
124
+ case status
125
+ when 200
126
+ # even HTTP 200 can contain an error, so we always have to peek for an Error
127
+ if response_is_error?
128
+ parse_and_raise_exceptione
129
+ else
130
+ response
131
+ end
132
+ when 302
133
+ raise "Unhandled HTTP Redirect"
134
+ when 401
135
+ raise AuthorizationFailure
136
+ when 400, 500
137
+ parse_and_raise_exceptione
138
+ else
139
+ raise "HTTP Error Code: #{status}, Msg: #{response.body}"
140
+ end
141
+ end
142
+
143
+ def parse_and_raise_exceptione
144
+ err = parse_intuit_error
145
+ ex = IntuitRequestException.new(err[:message])
146
+ ex.code = err[:code]
147
+ ex.cause = err[:cause]
148
+ raise ex
149
+ end
150
+
151
+ def response_is_error?
152
+ @last_response_xml.xpath("//xmlns:RestResponse/xmlns:Error").first != nil
153
+ end
154
+
155
+ def parse_intuit_error
156
+ error = {:message => "", :code => 0, :cause => ""}
157
+ fault = @last_response_xml.xpath("//xmlns:RestResponse/xmlns:Error/xmlns:ErrorDesc")[0]
158
+ if fault
159
+ error[:message] = fault.text
160
+ end
161
+ error_code = @last_response_xml.xpath("//xmlns:RestResponse/xmlns:Error/xmlns:ErrorCode")[0]
162
+ if error_code
163
+ error[:code] = error_code.text
164
+ end
165
+ error
166
+ end
167
+
168
+ def log(msg)
169
+ Quickeebooks.logger.info(msg)
170
+ Quickeebooks.logger.flush if Quickeebooks.logger.respond_to?(:flush)
171
+ end
172
+
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,27 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+ require "quickeebooks/version"
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "quickeebooks"
6
+ gem.version = Quickeebooks::VERSION
7
+
8
+ gem.author = "Cody Caughlan"
9
+ gem.email = "toolbag@gmail.com"
10
+ gem.homepage = "http://github.com/ruckus/quickeebooks"
11
+ gem.summary = "REST integration with Quickbooks Online"
12
+
13
+ gem.description = gem.summary
14
+
15
+ gem.files = Dir["**/*"]#.select { |d| d =~ %r{^(README|bin/|data/|ext/|lib/|spec/|test/)} }
16
+
17
+ gem.add_dependency 'roxml'
18
+ gem.add_dependency 'oauth'
19
+ gem.add_dependency 'nokogiri'
20
+ gem.add_dependency 'activemodel'
21
+
22
+ gem.add_development_dependency 'rake'
23
+ gem.add_development_dependency 'rcov', '~> 0.9.8'
24
+ gem.add_development_dependency 'rr', '~> 1.0.2'
25
+ gem.add_development_dependency 'rspec', '~> 2.0.0'
26
+ gem.add_development_dependency 'fakeweb'
27
+ end
@@ -0,0 +1,2 @@
1
+ class OauthConsumerMock
2
+ end
@@ -0,0 +1,41 @@
1
+ require "spec_helper"
2
+ require "stringio"
3
+ require "quickeebooks/online/model/account"
4
+
5
+ describe "Quickeebooks::Online::Model::Account" do
6
+
7
+ it "should convert Ruby to XML" do
8
+ account = Quickeebooks::Online::Model::Account.new
9
+ account.sync_token = 1
10
+ account.name = "John Doe"
11
+ expected = "<Account><Name>John Doe</Name></Account>"
12
+ # we have to jump through some hoops to get a non-pretty version for easier comparison
13
+ s = StringIO.new
14
+ xml = account.to_xml(:fields => 'Name').write_to(s, :indent => 0, :indent_text => '')
15
+ xml.string.gsub(/\n/, '').should == expected
16
+ end
17
+
18
+ it "has a validation error on invalid subtype" do
19
+ account = Quickeebooks::Online::Model::Account.new
20
+ account.sub_type = "invalid"
21
+ account.valid?.should == false
22
+ end
23
+
24
+ it "has a validation error when required attributes are not given" do
25
+ account = Quickeebooks::Online::Model::Account.new
26
+ account.valid?.should == false
27
+ end
28
+
29
+ it "should pass validation when all required attributes are given" do
30
+ account = Quickeebooks::Online::Model::Account.new
31
+ account.name = "John Doe"
32
+ account.sub_type = "AccountsPayable"
33
+ account.valid?.should == true
34
+ end
35
+
36
+ it "cannot delete an Account without providing required fields" do
37
+ account = Quickeebooks::Online::Model::Account.new
38
+ account.valid_for_deletion?.should == false
39
+ end
40
+
41
+ end
@@ -0,0 +1,46 @@
1
+ require "spec_helper"
2
+
3
+ require "quickeebooks/online/model/customer"
4
+
5
+ describe "Quickeebooks::Online::Model::Customer" do
6
+
7
+ it "parse customer from XML" do
8
+ xml = File.read(File.dirname(__FILE__) + "/../../xml/online/customer.xml")
9
+ customer = Quickeebooks::Online::Model::Customer.from_xml(xml)
10
+ customer.sync_token.should == 1
11
+ customer.name.should == "John Doe"
12
+
13
+ create_time = Date.civil(2011, 9, 29)
14
+ customer.meta_data.create_time.year.should == create_time.year
15
+ customer.addresses.count.should == 2
16
+
17
+ customer.addresses.first.line1.should == "123 Main St."
18
+
19
+ customer.phones.size.should == 2
20
+ customer.phones.first.free_form_number.should == "(408) 555-1212"
21
+
22
+ customer.email.address.should == "johndoe@gmail.com"
23
+
24
+ customer.notes.count.should == 1
25
+ customer.notes.first.content.should == "Likes chocolate and horses"
26
+
27
+ customer.custom_fields.count.should == 3
28
+
29
+ customer.open_balance.amount.should == 6200.0
30
+ end
31
+
32
+ it "can assign an email address" do
33
+ customer = Quickeebooks::Online::Model::Customer.new
34
+ the_email = "foo@example.org"
35
+ customer.email_address = the_email
36
+ customer.email.is_a?(Quickeebooks::Online::Model::Email).should == true
37
+ customer.email.address.should == the_email
38
+ end
39
+
40
+ it "cannot update an invalid model" do
41
+ customer = Quickeebooks::Online::Model::Customer.new
42
+ customer.valid_for_update?.should == false
43
+ customer.errors.keys.include?(:sync_token).should == true
44
+ end
45
+
46
+ end
@@ -0,0 +1,15 @@
1
+ require "spec_helper"
2
+
3
+ require "quickeebooks/online/model/invoice"
4
+
5
+ describe "Quickeebooks::Online::Model::Invoice" do
6
+
7
+ describe "parse invoice from XML" do
8
+ xml = File.read(File.dirname(__FILE__) + "/../../xml/online/invoice.xml")
9
+ invoice = Quickeebooks::Online::Model::Invoice.from_xml(xml)
10
+ invoice.id.should == 28
11
+ invoice.line_items.count.should == 1
12
+ invoice.line_items.first.unit_price.should == 100
13
+ end
14
+
15
+ end
@@ -0,0 +1,84 @@
1
+ require "spec_helper"
2
+ require "fakeweb"
3
+ require "oauth"
4
+ require "quickeebooks/online/service/account"
5
+
6
+ describe "Quickeebooks::Online::Service::Account" do
7
+ before(:all) do
8
+ FakeWeb.allow_net_connect = false
9
+ qb_key = "key"
10
+ qb_secret = "secreet"
11
+
12
+ @realm_id = "9991111222"
13
+ @base_uri = "https://qbo.intuit.com/qbo36"
14
+ @oauth_consumer = OAuth::Consumer.new(qb_key, qb_key, {
15
+ :site => "https://oauth.intuit.com",
16
+ :request_token_path => "/oauth/v1/get_request_token",
17
+ :authorize_path => "/oauth/v1/get_access_token",
18
+ :access_token_path => "/oauth/v1/get_access_token"
19
+ })
20
+ @oauth = OAuth::AccessToken.new(@oauth_consumer, "blah", "blah")
21
+ end
22
+
23
+ it "receives 404 from invalid base URL" do
24
+ uri = "https://qbo.intuit.com/invalid"
25
+ service = Quickeebooks::Online::Service::Account.new(@oauth, @realm_id, uri)
26
+ FakeWeb.register_uri(:post, service.url_for_resource("accounts"), :status => ["200", "OK"], :body => "blah")
27
+ lambda { service.list }.should raise_error(IntuitRequestException)
28
+ end
29
+
30
+ it "can fetch a list of accounts" do
31
+ xml = File.read(File.dirname(__FILE__) + "/../../../xml/online/accounts.xml")
32
+ service = Quickeebooks::Online::Service::Account.new(@oauth, @realm_id, @base_uri)
33
+ FakeWeb.register_uri(:post, service.url_for_resource("accounts"), :status => ["200", "OK"], :body => xml)
34
+ accounts = service.list
35
+ accounts.current_page.should == 1
36
+ accounts.entries.count.should == 10
37
+ accounts.entries.first.current_balance.should == 6200
38
+ end
39
+
40
+ it "can create an account" do
41
+ xml = File.read(File.dirname(__FILE__) + "/../../../xml/online/account.xml")
42
+ service = Quickeebooks::Online::Service::Account.new(@oauth, @realm_id, @base_uri)
43
+ FakeWeb.register_uri(:post, service.url_for_resource("account"), :status => ["200", "OK"], :body => xml)
44
+ account = Quickeebooks::Online::Model::Account.new
45
+ account.name = "Billy Bob"
46
+ account.sub_type = "AccountsPayable"
47
+ account.valid?.should == true
48
+ result = service.create(account)
49
+ result.id.to_i.should > 0
50
+ end
51
+
52
+ it "can delete an account" do
53
+ service = Quickeebooks::Online::Service::Account.new(@oauth, @realm_id, @base_uri)
54
+ url = "#{service.url_for_resource("account")}/99?methodx=delete"
55
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"])
56
+ account = Quickeebooks::Online::Model::Account.new
57
+ account.id = 99
58
+ account.sync_token = 0
59
+ result = service.delete(account)
60
+ result.should == true
61
+ end
62
+
63
+ it "cannot delete an account with missing required fields for deletion" do
64
+ service = Quickeebooks::Online::Service::Account.new(@oauth, @realm_id, @base_uri)
65
+ account = Quickeebooks::Online::Model::Account.new
66
+ lambda { service.delete(account) }.should raise_error(InvalidModelException, "Missing required parameters for delete")
67
+ end
68
+
69
+ it "exception is raised when we try to create an invalid account" do
70
+ account = Quickeebooks::Online::Model::Account.new
71
+ service = Quickeebooks::Online::Service::Account.new(@oauth, @realm_id, @base_uri)
72
+ lambda { service.create(account) }.should raise_error(InvalidModelException)
73
+ end
74
+
75
+ it "can fetch an account by id" do
76
+ xml = File.read(File.dirname(__FILE__) + "/../../../xml/online/account.xml")
77
+ service = Quickeebooks::Online::Service::Account.new(@oauth, @realm_id, @base_uri)
78
+ url = "#{service.url_for_resource("account")}/99"
79
+ FakeWeb.register_uri(:get, url, :status => ["200", "OK"], :body => xml)
80
+ account = service.fetch_by_id(99)
81
+ account.name.should == "Billy Bob"
82
+ end
83
+
84
+ end