quickeebooks 0.1.0 → 0.1.1

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.9)
4
+ quickeebooks (0.1.1)
5
5
  activemodel
6
6
  nokogiri
7
7
  oauth
data/HISTORY.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.1.1 (2013-01-16)
2
+
3
+ * Quickeebooks can now re-authorize a token via `Quickeebooks::Shared::Service::AccessToken.reconnect`. In addition destroying an access token can now be done via `Quickeebooks::Shared::Service::AccessToken.disconnect`. Thank you to `FundingGates` for the contribution.
4
+
1
5
  ## 0.1.0 (2013-01-16)
2
6
 
3
7
  * Quickbooks Online now supports a single HTTP endpoint for API calls, no need to first determine the Base URL. `Quickeebooks::Online::ServiceBase` has been adjusted to use a single API endpoint.
data/lib/quickeebooks.rb CHANGED
@@ -55,6 +55,7 @@ end
55
55
 
56
56
  # Services
57
57
  require 'quickeebooks/shared/service/filter'
58
+ require 'quickeebooks/shared/service/access_token'
58
59
 
59
60
  #== Online
60
61
 
@@ -90,6 +91,7 @@ require 'quickeebooks/online/service/invoice'
90
91
  require 'quickeebooks/online/service/item'
91
92
  require 'quickeebooks/online/service/entitlement'
92
93
  require 'quickeebooks/online/service/payment'
94
+ require 'quickeebooks/online/service/access_token'
93
95
 
94
96
  #== Windows
95
97
 
@@ -125,6 +127,10 @@ require 'quickeebooks/windows/model/credit_card'
125
127
  require 'quickeebooks/windows/model/credit_charge_info'
126
128
  require 'quickeebooks/windows/model/credit_charge_response'
127
129
  require 'quickeebooks/windows/model/clazz'
130
+ require 'quickeebooks/windows/model/sales_receipt_header'
131
+ require 'quickeebooks/windows/model/sales_receipt_line_item'
132
+ require 'quickeebooks/windows/model/sales_receipt'
133
+
128
134
 
129
135
  # Services
130
136
  require 'quickeebooks/windows/service/filter'
@@ -134,9 +140,11 @@ require 'quickeebooks/windows/service/customer'
134
140
  require 'quickeebooks/windows/service/item'
135
141
  require 'quickeebooks/windows/service/invoice'
136
142
  require 'quickeebooks/windows/service/sales_rep'
143
+ require 'quickeebooks/windows/service/sales_receipt'
137
144
  require 'quickeebooks/windows/service/ship_method'
138
145
  require 'quickeebooks/windows/service/sales_tax'
139
146
  require 'quickeebooks/windows/service/customer_msg'
140
147
  require 'quickeebooks/windows/service/company_meta_data'
141
148
  require 'quickeebooks/windows/service/payment'
142
149
  require 'quickeebooks/windows/service/clazz'
150
+ require 'quickeebooks/windows/service/access_token'
@@ -8,6 +8,7 @@ module Quickeebooks
8
8
 
9
9
  def to_xml(options = {})
10
10
  return "" if uri.to_s.empty?
11
+ super(options)
11
12
  end
12
13
 
13
14
  end
@@ -0,0 +1,11 @@
1
+ require 'quickeebooks/shared/service/access_token'
2
+
3
+ module Quickeebooks
4
+ module Online
5
+ module Service
6
+ class AccessToken < ServiceBase
7
+ include Quickeebooks::Shared::Service::AccessToken
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,43 @@
1
+ require "quickeebooks"
2
+
3
+ # See https://ipp.developer.intuit.com/0010_Intuit_Partner_Platform/0025_Intuit_Anywhere/0020_Connect/0010_From_Within_Your_App/Implement_OAuth_in_Your_App/Token_Renewal_and_Expiration
4
+ module Quickeebooks
5
+ module Shared
6
+ module Service
7
+ class AccessTokenResponse
8
+ include ROXML
9
+
10
+ xml_convention :camelcase
11
+ xml_accessor :error_code
12
+ xml_accessor :error_message
13
+ xml_accessor :token, :from => 'OAuthToken'
14
+ xml_accessor :secret, :from => 'OAuthTokenSecret'
15
+
16
+ def error?
17
+ error_code.to_i != 0
18
+ end
19
+ end
20
+ module AccessToken
21
+ # see https://ipp.developer.intuit.com/0010_Intuit_Partner_Platform/0025_Intuit_Anywhere/0060_Reference/3002_Reconnect_API
22
+ def reconnect
23
+ response = do_http_get("https://appcenter.intuit.com/api/v1/Connection/Reconnect")
24
+ if response && response.code.to_i == 200
25
+ Quickeebooks::Shared::Service::AccessTokenResponse.from_xml(response.body)
26
+ else
27
+ nil
28
+ end
29
+ end
30
+
31
+ # see https://ipp.developer.intuit.com/0010_Intuit_Partner_Platform/0025_Intuit_Anywhere/0060_Reference/3001_Disconnect_API
32
+ def disconnect
33
+ response = do_http_get("https://appcenter.intuit.com/api/v1/Connection/Disconnect")
34
+ if response && response.code.to_i == 200
35
+ Quickeebooks::Shared::Service::AccessTokenResponse.from_xml(response.body)
36
+ else
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -44,13 +44,13 @@ module Quickeebooks
44
44
  def number_to_s
45
45
  clauses = []
46
46
  if @eq
47
- clauses << "#{@field} :EQUALS: #{@value}"
47
+ clauses << "#{@field} :EQUALS: #{@eq}"
48
48
  end
49
49
  if @gt
50
- clauses << "#{@field} :GreaterThan: #{@value}"
50
+ clauses << "#{@field} :GreaterThan: #{@gt}"
51
51
  end
52
52
  if @lt
53
- clauses << "#{@field} :LessThan: #{@value}"
53
+ clauses << "#{@field} :LessThan: #{@lt}"
54
54
  end
55
55
  clauses.join(" :AND: ")
56
56
  end
@@ -1,5 +1,5 @@
1
1
  module Quickeebooks
2
2
 
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
 
5
5
  end
@@ -8,10 +8,14 @@ module Quickeebooks
8
8
  xml_accessor :account_name, :from => 'AccountName'
9
9
  xml_accessor :account_type, :from => 'AccountType'
10
10
 
11
- def initialize(account_id = nil)
11
+ def initialize(account_id = nil, account_name = nil)
12
12
  unless account_id.nil?
13
13
  self.account_id = account_id
14
14
  end
15
+
16
+ unless account_name.nil?
17
+ self.account_name = account_name
18
+ end
15
19
  end
16
20
  end
17
21
  end
@@ -6,8 +6,8 @@ module Quickeebooks
6
6
  xml_accessor :number, :from => 'Number'
7
7
  xml_accessor :type, :from => 'Type'
8
8
  xml_accessor :name_on_acct, :from => 'NameOnAcct'
9
- xml_accessor :cc_expiration_month, :from => 'CcExpireMn', :as => Integer
10
- xml_accessor :cc_expiration_year, :from => 'CcExpireYr', :as => Integer
9
+ xml_accessor :cc_expiration_month, :from => 'CcExpirMn', :as => Integer
10
+ xml_accessor :cc_expiration_year, :from => 'CcExpirYr', :as => Integer
11
11
  xml_accessor :billing_address_street, :from => 'BillAddrStreet'
12
12
  xml_accessor :zip_code, :from => 'ZipCode'
13
13
  xml_accessor :cvv, :from => 'Ccv'
@@ -0,0 +1,33 @@
1
+ require 'quickeebooks'
2
+ require 'quickeebooks/windows/model/id'
3
+ require 'quickeebooks/windows/model/external_key'
4
+ require 'quickeebooks/windows/model/meta_data'
5
+
6
+ module Quickeebooks
7
+ module Windows
8
+ module Model
9
+ class SalesReceipt < Quickeebooks::Windows::Model::IntuitType
10
+
11
+ XML_COLLECTION_NODE = 'SalesReceipts'
12
+ XML_NODE = 'SalesReceipt'
13
+
14
+ # https://services.intuit.com/sb/salesreceipt/v2/<realmID>
15
+ REST_RESOURCE = "salesreceipt"
16
+
17
+ xml_convention :camelcase
18
+ xml_accessor :id, :as => Quickeebooks::Windows::Model::Id
19
+ xml_accessor :meta_data, :from => 'MetaData', :as => Quickeebooks::Windows::Model::MetaData
20
+ xml_accessor :external_key, :as => Quickeebooks::Windows::Model::ExternalKey
21
+ xml_accessor :synchronized
22
+ xml_accessor :header, :from => 'Header', :as => Quickeebooks::Windows::Model::SalesReceiptHeader
23
+ xml_accessor :line_items, :from => 'Line', :as => [Quickeebooks::Windows::Model::SalesReceiptLineItem]
24
+ xml_accessor :tax_line, :from => 'TaxLine', :as => Quickeebooks::Windows::Model::TaxLine
25
+
26
+ def valid_for_create?
27
+ true
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,57 @@
1
+ require 'time'
2
+
3
+ module Quickeebooks
4
+ module Windows
5
+ module Model
6
+ class SalesReceiptHeader < Quickeebooks::Windows::Model::IntuitType
7
+
8
+ xml_name 'Header'
9
+ xml_accessor :doc_number, :from => 'DocNumber'
10
+ xml_accessor :txn_date, :from => 'TxnDate', :as => Time
11
+ xml_accessor :currency, :from => 'Currency'
12
+ xml_accessor :msg, :from => 'Msg'
13
+ xml_accessor :note, :from => 'Note'
14
+ xml_accessor :status, :from => 'Status'
15
+ xml_accessor :customer_id, :from => 'CustomerId', :as => Quickeebooks::Windows::Model::Id
16
+ xml_accessor :customer_name, :from => 'CustomerName'
17
+ xml_accessor :job_id, :from => 'JobId', :as => Quickeebooks::Windows::Model::Id
18
+ xml_accessor :job_name, :from => 'JobName'
19
+ xml_accessor :remit_to_id, :from => 'RemitToId', :as => Quickeebooks::Windows::Model::Id
20
+ xml_accessor :remit_to_name, :from => 'RemitToName'
21
+ xml_accessor :class_id, :from => 'ClassId', :as => Quickeebooks::Windows::Model::Id
22
+ xml_accessor :class_name, :from => 'ClassName'
23
+ xml_accessor :sales_rep_id, :from => 'SalesRepId', :as => Quickeebooks::Windows::Model::Id
24
+ xml_accessor :sales_rep_name, :from => 'SalesRepName'
25
+ xml_accessor :sales_tax_code_id, :from => 'SalesTaxCodeId', :as => Quickeebooks::Windows::Model::Id
26
+ xml_accessor :sales_tax_code_name, :from => 'SalesTaxCodeName'
27
+ xml_accessor :po_number, :from => 'PONumber'
28
+ xml_accessor :fob
29
+ xml_accessor :ship_date, :from => 'ShipDate', :as => Time
30
+ xml_accessor :sub_total_amount, :from => 'SubTotalAmt', :as => Float
31
+ xml_accessor :tax_id, :from => 'TaxId' # FEIN
32
+ xml_accessor :tax_name, :from => 'TaxName' # Business Name related to the FEIN
33
+ xml_accessor :tax_group_id, :from => 'TaxGroupId', :as => Quickeebooks::Windows::Model::Id
34
+ xml_accessor :tax_group_name, :from => 'TaxGroupName'
35
+ xml_accessor :tax_rate, :from => 'TaxRate', :as => Float
36
+ xml_accessor :tax_amount, :from => 'TaxAmt', :as => Float
37
+ xml_accessor :total_amount, :from => 'TotalAmt', :as => Float
38
+ xml_accessor :to_be_printed, :from => 'ToBePrinted'
39
+ xml_accessor :to_be_emailed, :from => 'ToBeEmailed'
40
+ xml_accessor :custom, :from => 'Custom'
41
+ xml_accessor :shipping_address, :from => 'ShipAddr', :as => Quickeebooks::Windows::Model::Address
42
+ xml_accessor :ship_method_id, :from => 'ShipMethodId', :as => Quickeebooks::Windows::Model::Id
43
+ xml_accessor :ship_method_name, :from => 'ShipMethodName'
44
+ xml_accessor :deposit_to_account_id, :from => "DepositToAccountId"
45
+ xml_accessor :deposit_to_account_name, :from => "DepositToAccountName"
46
+ xml_accessor :payment_method_id, :from => "PaymentMethodId", :as => Quickeebooks::Windows::Model::Id
47
+ xml_accessor :payment_method_name, :from => "PaymentMethodName"
48
+ xml_accessor :detail, :from => 'Detail', :as => Quickeebooks::Online::Model::PaymentDetail
49
+ xml_accessor :discount_amount, :from => 'DiscountAmt', :as => Float
50
+ xml_accessor :discount_rate, :from => 'DiscountRate', :as => Float
51
+ xml_accessor :discount_account_id, :from => 'DiscountAccountId'
52
+ xml_accessor :discount_account_name, :from => 'DiscountAccountName'
53
+ xml_accessor :discount_taxable, :from => 'DiscountTaxable'
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,40 @@
1
+ module Quickeebooks
2
+ module Windows
3
+ module Model
4
+ class SalesReceiptLineItem < Quickeebooks::Windows::Model::IntuitType
5
+ xml_name 'Line'
6
+ xml_accessor :id, :from => 'Id', :as => Quickeebooks::Windows::Model::Id
7
+ xml_accessor :desc, :from => 'Desc'
8
+ xml_accessor :group_member, :from => 'GroupMember'
9
+ xml_accessor :custom_fields, :from => 'CustomField', :as => [Quickeebooks::Windows::Model::CustomField]
10
+ xml_accessor :amount, :from => 'Amount', :as => Float
11
+ xml_accessor :class_id, :from => 'ClassId', :as => Quickeebooks::Windows::Model::Id
12
+ xml_accessor :class_name, :from => 'ClassName'
13
+ xml_accessor :taxable, :from => 'Taxable'
14
+ xml_accessor :item_id, :from => 'ItemId', :as => Quickeebooks::Windows::Model::Id
15
+ xml_accessor :item_name, :from => 'ItemName'
16
+ xml_accessor :item_type, :from => 'ItemType'
17
+ xml_accessor :unit_price, :from => 'UnitPrice', :as => Float
18
+ xml_accessor :rate_percent, :from => 'RatePercent', :as => Float
19
+ xml_accessor :price_level_id, :from => 'PriceLevelId', :as => Quickeebooks::Windows::Model::Id
20
+ xml_accessor :price_level_name, :from => 'PriceLevelName'
21
+ xml_accessor :uom_id, :from => 'UOMId'
22
+ xml_accessor :uom_abbrev, :from => 'UOMAbbrv'
23
+ xml_accessor :override_item_account_id, :from => 'OverrideItemAccountId'
24
+ xml_accessor :override_item_account_name, :from => 'OverrideItemAccountName'
25
+ xml_accessor :discount_id, :from => 'DiscountId', :as => Quickeebooks::Windows::Model::Id
26
+ xml_accessor :discount_name, :from => 'DiscountName'
27
+ xml_accessor :quantity, :from => 'Qty', :as => Float
28
+
29
+ xml_accessor :discount_amount, :from => 'DiscountAmount', :as => Float
30
+ xml_accessor :discount_rate_percent, :from => 'DiscountRatePercent', :as => Float
31
+
32
+ xml_accessor :sales_tax_code_id, :from => 'SalesTaxCodeId', :as => Quickeebooks::Windows::Model::Id
33
+ xml_accessor :sales_tax_code_name, :from => 'SalesTaxCodeName'
34
+ xml_accessor :service_date, :from => 'ServiceDate', :as => Time
35
+ xml_accessor :custom1, :from => 'Custom1'
36
+ xml_accessor :custom2, :from => 'Custom2'
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,11 @@
1
+ require 'quickeebooks/shared/service/access_token'
2
+
3
+ module Quickeebooks
4
+ module Windows
5
+ module Service
6
+ class AccessToken < ServiceBase
7
+ include Quickeebooks::Shared::Service::AccessToken
8
+ end
9
+ end
10
+ end
11
+ end
@@ -7,7 +7,7 @@ module Quickeebooks
7
7
  class Account < Quickeebooks::Windows::Service::ServiceBase
8
8
 
9
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)
10
+ fetch_collection(Quickeebooks::Windows::Model::Account, nil, filters, page, per_page, sort, options)
11
11
  end
12
12
 
13
13
  end
@@ -14,6 +14,20 @@ module Quickeebooks
14
14
  fetch_collection(Quickeebooks::Windows::Model::Item, custom_field_query.strip, filters, page, per_page, sort, options)
15
15
  end
16
16
 
17
+ def create(item)
18
+ # XML is a wrapped 'object' where the type is specified as an attribute
19
+ # <Object xsi:type="Item">
20
+ xml_node = item.to_xml(:name => 'Object')
21
+ xml_node.set_attribute('xsi:type', 'Item')
22
+ xml = <<-XML
23
+ <Add 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">
24
+ <ExternalRealmId>#{self.realm_id}</ExternalRealmId>
25
+ #{xml_node}
26
+ </Add>
27
+ XML
28
+ perform_write(Quickeebooks::Windows::Model::Item, xml)
29
+ end
30
+
17
31
  end
18
32
  end
19
33
 
@@ -0,0 +1,39 @@
1
+ require 'quickeebooks/windows/model/sales_receipt'
2
+ require 'quickeebooks/windows/model/sales_receipt_header'
3
+ require 'quickeebooks/windows/model/sales_receipt_line_item'
4
+ require 'quickeebooks/windows/service/service_base'
5
+
6
+ module Quickeebooks
7
+ module Windows
8
+ module Service
9
+ class SalesReceipt < Quickeebooks::Windows::Service::ServiceBase
10
+
11
+ def list(filters = [], page = 1, per_page = 20, sort = nil, options = {})
12
+ custom_field_query = '<?xml version="1.0" encoding="utf-8"?>'
13
+ custom_field_query += '<SalesReceiptQuery xmlns="http://www.intuit.com/sb/cdm/v2">'
14
+ custom_field_query += "<StartPage>#{page}</StartPage><ChunkSize>#{per_page}</ChunkSize>"
15
+ custom_field_query += '<CustomFieldEnable>true</CustomFieldEnable></SalesReceiptQuery>'
16
+ fetch_collection(Quickeebooks::Windows::Model::SalesReceipt, custom_field_query.strip, filters, page, per_page, sort, options)
17
+ end
18
+
19
+ def create(sales_receipt)
20
+ raise InvalidModelException unless sales_receipt.valid_for_create?
21
+
22
+ # XML is a wrapped 'object' where the type is specified as an attribute
23
+ # <Object xsi:type="Invoice">
24
+ xml_node = sales_receipt.to_xml(:name => 'Object')
25
+ xml_node.set_attribute('xsi:type', 'SalesReceipt')
26
+ xml = <<-XML
27
+ <Add 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">
28
+ <ExternalRealmId>#{self.realm_id}</ExternalRealmId>
29
+ #{xml_node}
30
+ </Add>
31
+ XML
32
+ perform_write(Quickeebooks::Windows::Model::SalesReceipt, xml)
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -102,5 +102,14 @@ describe "Quickeebooks::Online::Service::Customer" do
102
102
  updated.name.should == "Billy Bob"
103
103
  end
104
104
 
105
+ it 'Can update a fetched customer' do
106
+ xml = File.read(File.dirname(__FILE__) + "/../../../xml/online/customer.xml")
107
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::Customer.resource_for_singular)}/99"
108
+ FakeWeb.register_uri(:get, url, :status => ["200", "OK"], :body => xml)
109
+ customer = @service.fetch_by_id(99)
110
+ url = "#{@service.url_for_resource(Quickeebooks::Online::Model::Customer.resource_for_singular)}/#{customer.id.value}"
111
+ FakeWeb.register_uri(:post, url, :status => ["200", "OK"], :body => xml)
112
+ updated = @service.update(customer)
113
+ end
105
114
 
106
115
  end
@@ -6,7 +6,7 @@ require "quickeebooks"
6
6
  describe "Quickeebooks::Online::Service::Filter" do
7
7
  before(:all) do
8
8
  end
9
-
9
+
10
10
  it "can generate a text filter" do
11
11
  filter = Quickeebooks::Online::Service::Filter.new(:text, :field => "Name", :value => "Smith")
12
12
  filter.to_s.should == "Name :EQUALS: Smith"
@@ -29,6 +29,21 @@ describe "Quickeebooks::Online::Service::Filter" do
29
29
  filter.to_s.should == "CreateTime :AFTER: #{time.strftime(Quickeebooks::Online::Service::Filter::DATE_TIME_FORMAT)}"
30
30
  end
31
31
 
32
+ it "can generate a number filter with equals" do
33
+ filter = Quickeebooks::Online::Service::Filter.new(:number, :field => "OpenBalance", :eq => 5)
34
+ filter.to_s.should == "OpenBalance :EQUALS: 5"
35
+ end
36
+
37
+ it "can generate a number filter with greater than" do
38
+ filter = Quickeebooks::Online::Service::Filter.new(:number, :field => "OpenBalance", :gt => 5)
39
+ filter.to_s.should == "OpenBalance :GreaterThan: 5"
40
+ end
41
+
42
+ it "can generate a number filter with less than" do
43
+ filter = Quickeebooks::Online::Service::Filter.new(:number, :field => "OpenBalance", :lt => 5)
44
+ filter.to_s.should == "OpenBalance :LessThan: 5"
45
+ end
46
+
32
47
  it "can generate a datetime filter with bounded dates" do
33
48
  time1 = Time.mktime(2012, 1, 2, 1)
34
49
  time2 = Time.mktime(2012, 1, 5, 8)
@@ -0,0 +1,134 @@
1
+ require "spec_helper"
2
+ require "fakeweb"
3
+ require "oauth"
4
+ require "quickeebooks"
5
+
6
+ describe "Quickeebooks::Shared::Service::AccessToken" do
7
+
8
+ shared_examples "access_token_operations" do
9
+ context "reconnect" do
10
+ let(:reconnect_url){ "https://appcenter.intuit.com/api/v1/Connection/Reconnect" }
11
+
12
+ it "can successfully reconnect" do
13
+ xml = File.read(File.dirname(__FILE__) + "/../../xml/shared/reconnect_success.xml")
14
+ FakeWeb.register_uri(:get, reconnect_url, :status => ["200", "OK"], :body => xml)
15
+
16
+ response = @service.reconnect
17
+
18
+ response.error?.should be_false
19
+ response.token.should == "qye2eIdQ5H5yMyrlJflUWh712xfFXjyNnW1MfbC0rz04TfCP"
20
+ response.secret.should == "cyDeUNQTkFzoR0KkDn7viN6uLQxWTobeEUKW7I79"
21
+ end
22
+
23
+ it "can handle expired tokens" do
24
+ xml = File.read(File.dirname(__FILE__) + "/../../xml/shared/reconnect_error_expired.xml")
25
+ FakeWeb.register_uri(:get, reconnect_url, :status => ["200", "OK"], :body => xml)
26
+
27
+ response = @service.reconnect
28
+
29
+ response.error?.should be_true
30
+ response.error_code.should == "270"
31
+ response.error_message.should == "OAuth Token Rejected"
32
+ end
33
+
34
+ it "can handle out-of-bounds refresh windows" do
35
+ xml = File.read(File.dirname(__FILE__) + "/../../xml/shared/reconnect_error_out_of_bounds.xml")
36
+ FakeWeb.register_uri(:get, reconnect_url, :status => ["200", "OK"], :body => xml)
37
+
38
+ response = @service.reconnect
39
+
40
+ response.error?.should be_true
41
+ response.error_code.should == "212"
42
+ response.error_message.should == "Token Refresh Window Out of Bounds"
43
+ end
44
+
45
+
46
+ it "can handle unapproved apps" do
47
+ xml = File.read(File.dirname(__FILE__) + "/../../xml/shared/reconnect_error_not_approved.xml")
48
+ FakeWeb.register_uri(:get, reconnect_url, :status => ["200", "OK"], :body => xml)
49
+
50
+ response = @service.reconnect
51
+
52
+ response.error?.should be_true
53
+ response.error_code.should == "24"
54
+ response.error_message.should == "Invalid App Token"
55
+ end
56
+ end
57
+
58
+ context "disconnect" do
59
+ let(:disconnect_url){ "https://appcenter.intuit.com/api/v1/Connection/Disconnect" }
60
+
61
+ it "can successfully disconnect" do
62
+ xml = File.read(File.dirname(__FILE__) + "/../../xml/shared/disconnect_success.xml")
63
+ FakeWeb.register_uri(:get, disconnect_url, :status => ["200", "OK"], :body => xml)
64
+
65
+ response = @service.disconnect
66
+
67
+ response.error?.should be_false
68
+ end
69
+
70
+ it "can handle invalid tokens" do
71
+ xml = File.read(File.dirname(__FILE__) + "/../../xml/shared/disconnect_invalid.xml")
72
+ FakeWeb.register_uri(:get, disconnect_url, :status => ["200", "OK"], :body => xml)
73
+
74
+ response = @service.disconnect
75
+
76
+ response.error?.should be_true
77
+ response.error_code.should == "270"
78
+ response.error_message.should == "OAuth Token rejected"
79
+ end
80
+ end
81
+ end
82
+
83
+ context "online" do
84
+ before(:all) do
85
+ FakeWeb.allow_net_connect = false
86
+ qb_key = "key"
87
+ qb_secret = "secreet"
88
+
89
+ @realm_id = "9991111222"
90
+ @oauth_consumer = OAuth::Consumer.new(qb_key, qb_key, {
91
+ :site => "https://oauth.intuit.com",
92
+ :request_token_path => "/oauth/v1/get_request_token",
93
+ :authorize_path => "/oauth/v1/get_access_token",
94
+ :access_token_path => "/oauth/v1/get_access_token"
95
+ })
96
+ @oauth = OAuth::AccessToken.new(@oauth_consumer, "blah", "blah")
97
+
98
+ @service = Quickeebooks::Online::Service::AccessToken.new
99
+ @service.access_token = @oauth
100
+ @service.instance_eval {
101
+ @realm_id = "9991111222"
102
+ }
103
+ end
104
+
105
+ it_behaves_like "access_token_operations"
106
+ end
107
+
108
+ context "windows" do
109
+ before(:all) do
110
+ FakeWeb.allow_net_connect = false
111
+ qb_key = "key"
112
+ qb_secret = "secreet"
113
+
114
+ @realm_id = "9991111222"
115
+ #@base_uri = "https://qbo.intuit.com/qbo36"
116
+ @oauth_consumer = OAuth::Consumer.new(qb_key, qb_key, {
117
+ :site => "https://oauth.intuit.com",
118
+ :request_token_path => "/oauth/v1/get_request_token",
119
+ :authorize_path => "/oauth/v1/get_access_token",
120
+ :access_token_path => "/oauth/v1/get_access_token"
121
+ })
122
+ @oauth = OAuth::AccessToken.new(@oauth_consumer, "blah", "blah")
123
+
124
+ @service = Quickeebooks::Windows::Service::AccessToken.new
125
+
126
+ @service.access_token = @oauth
127
+ @service.instance_eval {
128
+ @realm_id = "9991111222"
129
+ }
130
+ end
131
+
132
+ it_behaves_like "access_token_operations"
133
+ end
134
+ end
@@ -33,7 +33,9 @@
33
33
  <DeviceType>Mobile</DeviceType>
34
34
  <FreeFormNumber>(831) 334-0987</FreeFormNumber>
35
35
  </Phone>
36
- <WebSite/>
36
+ <WebSite>
37
+ <URI>http://blah.com</URI>
38
+ </WebSite>
37
39
  <Email>
38
40
  <Address>johndoe@gmail.com</Address>
39
41
  </Email>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <PlatformResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://platform.intuit.com/api/v1">
3
+ <ErrorMessage>OAuth Token rejected</ErrorMessage>
4
+ <ErrorCode>270</ErrorCode>
5
+ <ServerTime>2011-11-24T17:45:27.11097Z</ServerTime>
6
+ </PlatformResponse>
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <PlatformResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://platform.intuit.com/api/v1">
3
+ <ErrorCode>0</ErrorCode>
4
+ <ServerTime>2011-11-23T17:15:27.21097Z</ServerTime>
5
+ </PlatformResponse>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <ReconnectResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://platform.intuit.com/api/v1">
3
+ <ErrorMessage>OAuth Token Rejected</ErrorMessage>
4
+ <ErrorCode>270</ErrorCode>
5
+ <ServerTime>2012-01-04T19:21:21.0782072Z</ServerTime>
6
+ </ReconnectResponse>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <ReconnectResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://platform.intuit.com/api/v1">
3
+ <ErrorMessage>Invalid App Token</ErrorMessage>
4
+ <ErrorCode>24</ErrorCode>
5
+ <ServerTime>2012-01-04T19:21:21.0782072Z</ServerTime>
6
+ </ReconnectResponse>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <ReconnectResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://platform.intuit.com/api/v1">
3
+ <ErrorMessage>Token Refresh Window Out of Bounds</ErrorMessage>
4
+ <ErrorCode>212</ErrorCode>
5
+ <ServerTime>2012-01-04T19:21:21.0782072Z</ServerTime>
6
+ </ReconnectResponse>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <ReconnectResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://platform.intuit.com/api/v1">
3
+ <ErrorMessage />
4
+ <ErrorCode>0</ErrorCode>
5
+ <ServerTime>2012-01-04T19:21:21.0782072Z</ServerTime>
6
+ <OAuthToken>qye2eIdQ5H5yMyrlJflUWh712xfFXjyNnW1MfbC0rz04TfCP</OAuthToken>
7
+ <OAuthTokenSecret>cyDeUNQTkFzoR0KkDn7viN6uLQxWTobeEUKW7I79</OAuthTokenSecret>
8
+ </ReconnectResponse>
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.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -209,6 +209,7 @@ files:
209
209
  - lib/quickeebooks/online/model/purchase_cost.rb
210
210
  - lib/quickeebooks/online/model/unit_price.rb
211
211
  - lib/quickeebooks/online/model/web_site.rb
212
+ - lib/quickeebooks/online/service/access_token.rb
212
213
  - lib/quickeebooks/online/service/account.rb
213
214
  - lib/quickeebooks/online/service/company_meta_data.rb
214
215
  - lib/quickeebooks/online/service/customer.rb
@@ -220,6 +221,7 @@ files:
220
221
  - lib/quickeebooks/online/service/payment.rb
221
222
  - lib/quickeebooks/online/service/service_base.rb
222
223
  - lib/quickeebooks/online/service/sort.rb
224
+ - lib/quickeebooks/shared/service/access_token.rb
223
225
  - lib/quickeebooks/shared/service/filter.rb
224
226
  - lib/quickeebooks/version.rb
225
227
  - lib/quickeebooks/windows/model/account.rb
@@ -258,6 +260,9 @@ files:
258
260
  - lib/quickeebooks/windows/model/price.rb
259
261
  - lib/quickeebooks/windows/model/purchase_cost.rb
260
262
  - lib/quickeebooks/windows/model/rest_response.rb
263
+ - lib/quickeebooks/windows/model/sales_receipt.rb
264
+ - lib/quickeebooks/windows/model/sales_receipt_header.rb
265
+ - lib/quickeebooks/windows/model/sales_receipt_line_item.rb
261
266
  - lib/quickeebooks/windows/model/sales_rep.rb
262
267
  - lib/quickeebooks/windows/model/sales_tax.rb
263
268
  - lib/quickeebooks/windows/model/ship_method.rb
@@ -268,6 +273,7 @@ files:
268
273
  - lib/quickeebooks/windows/model/vendor_id.rb
269
274
  - lib/quickeebooks/windows/model/vendor_reference.rb
270
275
  - lib/quickeebooks/windows/model/web_site.rb
276
+ - lib/quickeebooks/windows/service/access_token.rb
271
277
  - lib/quickeebooks/windows/service/account.rb
272
278
  - lib/quickeebooks/windows/service/clazz.rb
273
279
  - lib/quickeebooks/windows/service/company_meta_data.rb
@@ -277,6 +283,7 @@ files:
277
283
  - lib/quickeebooks/windows/service/invoice.rb
278
284
  - lib/quickeebooks/windows/service/item.rb
279
285
  - lib/quickeebooks/windows/service/payment.rb
286
+ - lib/quickeebooks/windows/service/sales_receipt.rb
280
287
  - lib/quickeebooks/windows/service/sales_rep.rb
281
288
  - lib/quickeebooks/windows/service/sales_tax.rb
282
289
  - lib/quickeebooks/windows/service/service_base.rb
@@ -299,6 +306,7 @@ files:
299
306
  - spec/quickeebooks/online/services/invoice_spec.rb
300
307
  - spec/quickeebooks/online/services/service_base_spec.rb
301
308
  - spec/quickeebooks/online/services/sort_spec.rb
309
+ - spec/quickeebooks/shared/access_token_spec.rb
302
310
  - spec/quickeebooks/windows/customer_spec.rb
303
311
  - spec/quickeebooks/windows/services/class_spec.rb
304
312
  - spec/quickeebooks/windows/services/company_meta_data_spec.rb
@@ -322,6 +330,12 @@ files:
322
330
  - spec/xml/online/invoice.xml
323
331
  - spec/xml/online/payment.xml
324
332
  - spec/xml/online/user.xml
333
+ - spec/xml/shared/disconnect_invalid.xml
334
+ - spec/xml/shared/disconnect_success.xml
335
+ - spec/xml/shared/reconnect_error_expired.xml
336
+ - spec/xml/shared/reconnect_error_not_approved.xml
337
+ - spec/xml/shared/reconnect_error_out_of_bounds.xml
338
+ - spec/xml/shared/reconnect_success.xml
325
339
  - spec/xml/windows/classes.xml
326
340
  - spec/xml/windows/company_meta_data.xml
327
341
  - spec/xml/windows/customer.xml