quickeebooks 0.0.8 → 0.0.9

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.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- quickeebooks (0.0.8)
4
+ quickeebooks (0.0.9)
5
5
  activemodel
6
6
  nokogiri
7
7
  oauth
data/README.md CHANGED
@@ -22,22 +22,69 @@ Gems:
22
22
  * `nokogiri` : XML parsing
23
23
  * `active_model` : For validations
24
24
 
25
- ## Getting Started
25
+ ## Getting Started & Initiating Authentication Flow with Intuit
26
26
 
27
- This library assumes you already have an OAuth token and secret. You can then initialize your `OAuth Consumer` and create a `OAuth Client` via:
27
+ What follows is an example using Rails but the principles can be adapted to any other framework / pure Ruby.
28
+
29
+ Create a Rails initializer with:
28
30
 
29
31
  ```ruby
30
- QB_KEY = "your-qb-key"
31
- QB_SECRET = "your-qb-secret"
32
+ QB_KEY = "your apps Intuit App Key"
33
+ QB_SECRET = "your apps Intuit Secret Key"
32
34
 
33
- qb_oauth_consumer = OAuth::Consumer.new(QB_KEY, QB_SECRET, {
35
+ $qb_oauth_consumer = OAuth::Consumer.new(QB_KEY, QB_SECRET, {
34
36
  :site => "https://oauth.intuit.com",
35
37
  :request_token_path => "/oauth/v1/get_request_token",
36
38
  :authorize_url => "https://appcenter.intuit.com/Connect/Begin",
37
39
  :access_token_path => "/oauth/v1/get_access_token"
38
40
  })
41
+ ```
42
+
43
+ To start the authentication flow with Intuit you include the Intuit Javascript and on a page of your choosing you present the "Connect to Quickbooks" button by including this XHTML:
44
+
45
+
46
+ ```HTML
47
+ <!-- somewhere in your document include the Javascript -->
48
+ <script type="text/javascript" src="https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere.js"></script>
49
+
50
+ <!-- configure the Intuit object: 'grantUrl' is a URL in your application which kicks off the flow, see below -->
51
+ <script>
52
+ intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '/path/to/your-flow-start'});
53
+ </script>
54
+
55
+ <!-- this will display a button that the user clicks to start the flow -->
56
+ <ipp:connectToIntuit></ipp:connectToIntuit>
57
+ ```
58
+
59
+ Your Controller action (the `grantUrl` above) should look like this:
60
+
61
+ ```ruby
62
+ def authenticate
63
+ callback = quickbooks_oauth_callback_url
64
+ token = $qb_oauth_consumer.get_request_token(:oauth_callback => callback)
65
+ session[:qb_request_token] = token
66
+ redirect_to("https://appcenter.intuit.com/Connect/Begin?oauth_token=#{token.token}") and return
67
+ end
68
+ ```
69
+
70
+ Where `quickbooks_oauth_callback_url` is the absolute URL of your application that Intuit should send the user when authentication succeeeds. That action should look like:
71
+
72
+ ```ruby
73
+ def oauth_callback
74
+ at = session[:qb_request_token].get_access_token(:oauth_verifier => params[:oauth_verifier])
75
+ token = at.token
76
+ secret = at.secret
77
+ realm_id = params['realmId']
78
+ # store the token, secret & RealmID somewhere for this user, you will need all 3 to work with Quickeebooks
79
+ end
80
+ ```
39
81
 
40
- oauth_client = OAuth::AccessToken.new(qb_oauth_consumer, access_token, access_secret)
82
+ ## Creating an OAuth Access Token
83
+
84
+ Once you have your users OAuth Token & Secret you can initialize your `OAuth Consumer` and create a `OAuth Client` using the `$qb_oauth_consumer` you created earlier in your Rails initializer:
85
+
86
+ ```ruby
87
+ oauth_client = OAuth::AccessToken.new($qb_oauth_consumer, access_token, access_secret)
41
88
  ```
42
89
 
43
90
  ## Quickbooks Online vs Windows
@@ -46,17 +93,21 @@ IDS provides 2 APIs, one for interacting with Quickbooks Online resources and on
46
93
 
47
94
  See: https://ipp.developer.intuit.com/0010_Intuit_Partner_Platform/0050_Data_Services
48
95
 
49
- As of this time Quickeebooks has a little more features for Online API vs Windows API. Ultimately the Quickeebooks API should be the same and its just a matter of instantiating the correct classes.
96
+ You will need to be aware of which flavor of the API you want to invoke.
50
97
 
51
98
  For example:
52
99
 
53
100
  ```ruby
54
101
  # Instantiate a Online API
55
- customer_service = Quickeebooks::Online::Service::Customer.new(oauth_client, realm_id)
102
+ customer_service = Quickeebooks::Online::Service::Customer.new
103
+ customer_service.access_token = oauth_client
104
+ customer_service.realm_id = realm_id
56
105
  customer_service.list
57
106
 
58
107
  # Instantiate a Windows API
59
108
  customer_service = Quickeebooks::Windows::Service::Customer.new(oauth_client, realm_id)
109
+ customer_service.access_token = oauth_client
110
+ customer_service.realm_id = realm_id
60
111
  customer_service.list
61
112
  ```
62
113
 
@@ -65,7 +116,10 @@ All of the documentation below is geared towards the Online flavor but unless no
65
116
  Now we can initialize any of the `Service` clients:
66
117
 
67
118
  ```ruby
68
- customer_service = Quickeebooks::Online::Service::Customer.new(oauth_client, realm_id)
119
+ customer_service = Quickeebooks::Online::Service::Customer.new
120
+ customer_service.access_token = oauth_client
121
+ customer_service.realm_id = realm_id
122
+ customer_service.list
69
123
  customer_service.list
70
124
 
71
125
  # returns a `Collection` object
@@ -99,7 +153,11 @@ Pass a `Sort` object for any desired sorting or just let Intuit use the default
99
153
  Specify none of these to get the defaults:
100
154
 
101
155
  ```ruby
102
- customer_service = Quickeebooks::Online::Service::Customer.new(oauth_client, realm_id,)
156
+ customer_service = Quickeebooks::Online::Service::Customer.new
157
+ customer_service.access_token = oauth_client
158
+ customer_service.realm_id = realm_id
159
+ customer_service.list
160
+
103
161
  # fetch all customers with default parameters (pagination, sorting, filtering)
104
162
  customers = customer_service.list
105
163
  ```
@@ -172,7 +230,11 @@ filters = []
172
230
  filters << Quickeebooks::Online::Service::Filter.new(:text, :field => 'FamilyName', :value => 'Richards')
173
231
  datetime = Time.mktime(2011, 2, 25)
174
232
  filters << Quickeebooks::Online::Service::Filter.new(:datetime, :field => 'CreateTime', :before => datetime)
175
- customer_service = Quickeebooks::Online::Service::Customer.new(oauth_client, realm_id)
233
+ customer_service = Quickeebooks::Online::Service::Customer.new
234
+ customer_service.access_token = oauth_client
235
+ customer_service.realm_id = realm_id
236
+ customer_service.list
237
+
176
238
  customers = customer_service.list(filters)
177
239
  ```
178
240
  ## Sorting (currently only supported in the Online API)
@@ -201,7 +263,11 @@ filters << Quickeebooks::Online::Service::Filter.new(:datetime, :field => 'Creat
201
263
 
202
264
  sorter = Quickeebooks::Online::Service::Sort.new('FamilyName', 'AtoZ')
203
265
 
204
- customer_service = Quickeebooks::Online::Service::Customer.new(oauth_client, realm_id)
266
+ customer_service = Quickeebooks::Online::Service::Customer.new
267
+ customer_service.access_token = oauth_client
268
+ customer_service.realm_id = realm_id
269
+ customer_service.list
270
+
205
271
  customers = customer_service.list(filters, 1, 30, sort)
206
272
 
207
273
  # returns
@@ -222,7 +288,11 @@ Use the `Service` instance to fetch an object by its id using the `fetch_by_id`
222
288
 
223
289
  ```ruby
224
290
  # fetch the Customer object with an id of 100
225
- customer_service = Quickeebooks::Online::Service::Customer.new(oauth_client, realm_id)
291
+ customer_service = Quickeebooks::Online::Service::Customer.new
292
+ customer_service.access_token = oauth_client
293
+ customer_service.realm_id = realm_id
294
+ customer_service.list
295
+
226
296
  customer = customer_service.fetch_by_id(100)
227
297
  customer.name
228
298
  => John Doe
@@ -239,7 +309,11 @@ You will need make sure you supply all required fields for that Intuit object, s
239
309
  Pass an instance of your object to the `create` method on its related Service:
240
310
 
241
311
  ```ruby
242
- customer_service = Quickeebooks::Online::Service::Customer.new(oauth_client, realm_id)
312
+ customer_service = Quickeebooks::Online::Service::Customer.new
313
+ customer_service.access_token = oauth_client
314
+ customer_service.realm_id = realm_id
315
+ customer_service.list
316
+
243
317
  customer = Quickeebooks::Online::Model::Customer.new
244
318
  customer.name = "Richard Parker"
245
319
  customer.email = "richard@example.org"
@@ -253,7 +327,11 @@ customer_service.create(customer)
253
327
  Pass an instance of your object to the `update` method on its related Service:
254
328
 
255
329
  ```ruby
256
- customer_service = Quickeebooks::Online::Service::Customer.new(oauth_client, realm_id)
330
+ customer_service = Quickeebooks::Online::Service::Customer.new
331
+ customer_service.access_token = oauth_client
332
+ customer_service.realm_id = realm_id
333
+ customer_service.list
334
+
257
335
  customer = customer_service.fetch_by_id(100)
258
336
  customer.name = "Richard Parker"
259
337
  customer.email = "richard@example.org"
@@ -17,6 +17,7 @@ module Quickeebooks
17
17
  xml_accessor :sales_tax_code_name, :from => 'SalesTaxCodeName'
18
18
  xml_accessor :sub_total_amount, :from => 'SubTotalAmt', :as => Float
19
19
  xml_accessor :tax_rate, :from => 'TaxRate', :as => Float
20
+ xml_accessor :tax_amount, :from => 'TaxAmt', :as => Float
20
21
  xml_accessor :balance, :from => 'Balance', :as => Float
21
22
  xml_accessor :total_amount, :from => 'TotalAmt', :as => Float
22
23
  xml_accessor :due_date, :from => 'DueDate', :as => Time
@@ -1,5 +1,5 @@
1
1
  module Quickeebooks
2
2
 
3
- VERSION = "0.0.8"
3
+ VERSION = "0.0.9"
4
4
 
5
5
  end
@@ -15,8 +15,8 @@ module Quickeebooks
15
15
  xml_accessor :country_sub_division_code, :from => 'CountrySubDivisionCode'
16
16
  xml_accessor :postal_code, :from => 'PostalCode'
17
17
  xml_accessor :postal_code_suffix, :from => 'PostalCodeSuffix'
18
- xml_accessor :tag, :from => 'Tag'
19
18
  xml_accessor :default, :from => 'Default'
19
+ xml_accessor :tag, :from => 'Tag'
20
20
 
21
21
  def zip
22
22
  postal_code
@@ -34,9 +34,9 @@ module Quickeebooks
34
34
  xml_accessor :type_of, :from => 'TypeOf'
35
35
  xml_accessor :name, :from => 'Name'
36
36
  xml_accessor :addresses, :from => 'Address', :as => [Quickeebooks::Windows::Model::Address]
37
- xml_accessor :email, :from => 'Email', :as => Quickeebooks::Windows::Model::Email
38
37
  xml_accessor :phones, :from => 'Phone', :as => [Quickeebooks::Windows::Model::Phone]
39
38
  xml_accessor :web_site, :from => 'WebSite', :as => Quickeebooks::Windows::Model::WebSite
39
+ xml_accessor :email, :from => 'Email', :as => Quickeebooks::Windows::Model::Email
40
40
  xml_accessor :title, :from => 'Title'
41
41
  xml_accessor :given_name, :from => 'GivenName'
42
42
  xml_accessor :middle_name, :from => 'MiddleName'
@@ -7,8 +7,8 @@ module Quickeebooks
7
7
  xml_accessor :id, :from => 'Id'
8
8
  xml_accessor :device_type, :from => 'DeviceType'
9
9
  xml_accessor :free_form_number, :from => 'FreeFormNumber'
10
- xml_accessor :tag, :from => 'Tag'
11
10
  xml_accessor :default, :from => 'Default'
11
+ xml_accessor :tag, :from => 'Tag'
12
12
 
13
13
  def default?
14
14
  default == "true"
@@ -32,7 +32,41 @@ module Quickeebooks
32
32
  </Add>
33
33
  XML
34
34
  perform_write(Quickeebooks::Windows::Model::Customer, xml)
35
+ end
36
+
37
+ def update(customer)
38
+ # XML is a wrapped 'object' where the type is specified as an attribute
39
+ # <Object xsi:type="Invoice">
40
+
41
+ # Intuit requires that some fields are unset / do not exist.
42
+ customer.meta_data = nil
43
+ customer.external_key = nil
44
+
45
+ # unset Id fields in addresses, phones, email
46
+ if customer.addresses
47
+ customer.addresses.each {|address| address.id = nil }
48
+ end
49
+ if customer.email
50
+ customer.email.id = nil
51
+ end
52
+
53
+ if customer.phones
54
+ customer.phones.each {|phone| phone.id = nil }
55
+ end
56
+
57
+ if customer.web_site
58
+ customer.web_site.id = nil
59
+ end
35
60
 
61
+ xml_node = customer.to_xml(:name => 'Object')
62
+ xml_node.set_attribute('xsi:type', 'Customer')
63
+ xml = <<-XML
64
+ <Mod xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" RequestId="#{guid}" xmlns="http://www.intuit.com/sb/cdm/v2">
65
+ <ExternalRealmId>#{self.realm_id}</ExternalRealmId>
66
+ #{xml_node}
67
+ </Mod>
68
+ XML
69
+ perform_write(Quickeebooks::Windows::Model::Customer, xml)
36
70
  end
37
71
 
38
72
  end
@@ -153,6 +153,26 @@ describe "Quickeebooks::Windows::Service::Customer" do
153
153
  create_response.success.party_role_ref.id.value.should == "6762304"
154
154
  create_response.success.request_name.should == "CustomerAdd"
155
155
  end
156
+
157
+ it "can update a customer name" do
158
+ customer_xml = File.read(File.dirname(__FILE__) + "/../../../xml/windows/customer.xml")
159
+ update_response_xml = File.read(File.dirname(__FILE__) + "/../../../xml/windows/customer_update_success.xml")
160
+ service = Quickeebooks::Windows::Service::Customer.new
161
+ model = Quickeebooks::Windows::Model::Customer
162
+ customer = model.from_xml(customer_xml)
163
+ customer.name.should == "Wine House"
164
+
165
+ service.access_token = @oauth
166
+ service.realm_id = @realm_id
167
+ FakeWeb.register_uri(:post, service.url_for_resource(model::REST_RESOURCE), :status => ["200", "OK"], :body => update_response_xml)
168
+
169
+ # change the name
170
+ customer.name = "Acme Cafe"
171
+ update_response = service.update(customer)
172
+ update_response.success?.should == true
173
+ update_response.success.party_role_ref.id.value.should == "6762304"
174
+ update_response.success.request_name.should == "CustomerMod"
175
+ end
156
176
 
157
177
 
158
178
  end
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0"?>
2
+ <RestResponse xmlns="http://www.intuit.com/sb/cdm/v2">
3
+ <Success RequestId="1b405391016149c593c005e45700dd01">
4
+ <PartyRoleRef>
5
+ <Id idDomain="NG">6762304</Id>
6
+ <SyncToken>7</SyncToken>
7
+ <LastUpdatedTime>2012-11-29T01:01:47Z</LastUpdatedTime>
8
+ <PartyReferenceId idDomain="NG">6170150</PartyReferenceId>
9
+ </PartyRoleRef>
10
+ <RequestName>CustomerMod</RequestName>
11
+ <ProcessedTime>2012-11-29T01:01:47Z</ProcessedTime>
12
+ </Success>
13
+ </RestResponse>
@@ -3,6 +3,7 @@ require 'oauth'
3
3
  $: << File.expand_path('./lib')
4
4
  require 'quickeebooks'
5
5
 
6
+ # attached to "Vinosmith.qbw" in Quickbooks Simple Start 2010
6
7
  consumer_key = 'qyprdL8NUDMYcCzwp8ea9KbIhaMSRk'
7
8
  consumer_secret = 'FcE5kihBYMVQGvX9UNYMxsrM8mP7bfuxc36PLhJB'
8
9
  qb_oauth_consumer = OAuth::Consumer.new(consumer_key, consumer_secret, {
@@ -22,6 +23,22 @@ service = Quickeebooks::Windows::Service::Customer.new
22
23
  service.access_token = oauth
23
24
  service.realm_id = realm_id
24
25
 
26
+ customer = service.fetch_by_id(1)
27
+ puts customer.name
28
+ if customer.notes
29
+ customer.notes.each { |note| puts note.content }
30
+ end
31
+ # UPDATE it
32
+ customer.name = "Cody 22 TEST"
33
+
34
+ customer.meta_data = nil
35
+ customer.external_key = nil
36
+
37
+ response = service.update(customer)
38
+ #puts response.inspect
39
+
40
+ #puts service.list
41
+ =begin
25
42
  customer = Quickeebooks::Windows::Model::Customer.new
26
43
  customer.type_of = "Person"
27
44
  customer.name = "Cody Test-#{Time.now.to_i}"
@@ -38,4 +55,5 @@ billing_address.postal_code = "94117"
38
55
  billing_address.country = "USA"
39
56
  customer.address = billing_address
40
57
  result = service.create(customer)
41
- puts result.inspect
58
+ puts result.inspect
59
+ =end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quickeebooks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-20 00:00:00.000000000 Z
12
+ date: 2012-11-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: roxml
@@ -325,6 +325,7 @@ files:
325
325
  - spec/xml/windows/company_meta_data.xml
326
326
  - spec/xml/windows/customer.xml
327
327
  - spec/xml/windows/customer_create_success.xml
328
+ - spec/xml/windows/customer_update_success.xml
328
329
  - spec/xml/windows/customers.xml
329
330
  - spec/xml/windows/fetch_customer_by_id.xml
330
331
  - spec/xml/windows/http_401.xml