xero_gateway-float 2.0.15

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.
Files changed (71) hide show
  1. data/Gemfile +12 -0
  2. data/LICENSE +14 -0
  3. data/README.textile +357 -0
  4. data/Rakefile +14 -0
  5. data/examples/oauth.rb +25 -0
  6. data/examples/partner_app.rb +36 -0
  7. data/init.rb +1 -0
  8. data/lib/oauth/oauth_consumer.rb +14 -0
  9. data/lib/xero_gateway.rb +39 -0
  10. data/lib/xero_gateway/account.rb +95 -0
  11. data/lib/xero_gateway/accounts_list.rb +87 -0
  12. data/lib/xero_gateway/address.rb +96 -0
  13. data/lib/xero_gateway/bank_transaction.rb +178 -0
  14. data/lib/xero_gateway/ca-certificates.crt +2560 -0
  15. data/lib/xero_gateway/contact.rb +206 -0
  16. data/lib/xero_gateway/credit_note.rb +222 -0
  17. data/lib/xero_gateway/currency.rb +56 -0
  18. data/lib/xero_gateway/dates.rb +30 -0
  19. data/lib/xero_gateway/error.rb +18 -0
  20. data/lib/xero_gateway/exceptions.rb +46 -0
  21. data/lib/xero_gateway/gateway.rb +622 -0
  22. data/lib/xero_gateway/http.rb +138 -0
  23. data/lib/xero_gateway/http_encoding_helper.rb +49 -0
  24. data/lib/xero_gateway/invoice.rb +236 -0
  25. data/lib/xero_gateway/line_item.rb +125 -0
  26. data/lib/xero_gateway/line_item_calculations.rb +55 -0
  27. data/lib/xero_gateway/money.rb +16 -0
  28. data/lib/xero_gateway/oauth.rb +87 -0
  29. data/lib/xero_gateway/organisation.rb +75 -0
  30. data/lib/xero_gateway/partner_app.rb +30 -0
  31. data/lib/xero_gateway/payment.rb +40 -0
  32. data/lib/xero_gateway/phone.rb +77 -0
  33. data/lib/xero_gateway/private_app.rb +17 -0
  34. data/lib/xero_gateway/response.rb +41 -0
  35. data/lib/xero_gateway/tax_rate.rb +63 -0
  36. data/lib/xero_gateway/tracking_category.rb +87 -0
  37. data/test/integration/accounts_list_test.rb +109 -0
  38. data/test/integration/create_bank_transaction_test.rb +38 -0
  39. data/test/integration/create_contact_test.rb +66 -0
  40. data/test/integration/create_credit_note_test.rb +49 -0
  41. data/test/integration/create_invoice_test.rb +49 -0
  42. data/test/integration/get_accounts_test.rb +23 -0
  43. data/test/integration/get_bank_transaction_test.rb +51 -0
  44. data/test/integration/get_bank_transactions_test.rb +88 -0
  45. data/test/integration/get_contact_test.rb +28 -0
  46. data/test/integration/get_contacts_test.rb +40 -0
  47. data/test/integration/get_credit_note_test.rb +48 -0
  48. data/test/integration/get_credit_notes_test.rb +90 -0
  49. data/test/integration/get_currencies_test.rb +25 -0
  50. data/test/integration/get_invoice_test.rb +48 -0
  51. data/test/integration/get_invoices_test.rb +92 -0
  52. data/test/integration/get_organisation_test.rb +24 -0
  53. data/test/integration/get_tax_rates_test.rb +25 -0
  54. data/test/integration/get_tracking_categories_test.rb +27 -0
  55. data/test/integration/update_bank_transaction_test.rb +31 -0
  56. data/test/integration/update_contact_test.rb +31 -0
  57. data/test/integration/update_invoice_test.rb +31 -0
  58. data/test/test_helper.rb +179 -0
  59. data/test/unit/account_test.rb +47 -0
  60. data/test/unit/bank_transaction_test.rb +126 -0
  61. data/test/unit/contact_test.rb +97 -0
  62. data/test/unit/credit_note_test.rb +284 -0
  63. data/test/unit/currency_test.rb +31 -0
  64. data/test/unit/gateway_test.rb +119 -0
  65. data/test/unit/invoice_test.rb +326 -0
  66. data/test/unit/oauth_test.rb +116 -0
  67. data/test/unit/organisation_test.rb +38 -0
  68. data/test/unit/tax_rate_test.rb +38 -0
  69. data/test/unit/tracking_category_test.rb +52 -0
  70. data/xero_gateway.gemspec +15 -0
  71. metadata +164 -0
@@ -0,0 +1,92 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class GetInvoicesTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ INVALID_INVOICE_ID = "99999999-9999-9999-9999-999999999999" unless defined?(INVALID_INVOICE_ID)
7
+
8
+ def setup
9
+ @gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
10
+
11
+ if STUB_XERO_CALLS
12
+ @gateway.xero_url = "DUMMY_URL"
13
+
14
+ @gateway.stubs(:http_get).with {|client, url, params| url =~ /Invoices/ }.returns(get_file_as_string("invoices.xml"))
15
+ @gateway.stubs(:http_put).with {|client, url, body, params| url =~ /Invoices$/ }.returns(get_file_as_string("create_invoice.xml"))
16
+
17
+ # Get an invoice with an invalid ID number.
18
+ @gateway.stubs(:http_get).with {|client, url, params| url =~ Regexp.new("Invoices/#{INVALID_INVOICE_ID}") }.returns(get_file_as_string("invoice_not_found_error.xml"))
19
+ end
20
+ end
21
+
22
+ def test_get_invoices
23
+ # Make sure there is an invoice in Xero to retrieve
24
+ invoice = @gateway.create_invoice(dummy_invoice).invoice
25
+
26
+ result = @gateway.get_invoices
27
+ assert result.success?
28
+ assert !result.request_params.nil?
29
+ assert !result.response_xml.nil?
30
+ assert result.invoices.collect {|i| i.invoice_number}.include?(invoice.invoice_number)
31
+ assert result.invoices[0].sent_to_contact == true
32
+ assert result.invoices[1].sent_to_contact == false
33
+ end
34
+
35
+ def test_get_invoices_with_modified_since_date
36
+ # Create a test invoice
37
+ invoice = dummy_invoice
38
+ @gateway.create_invoice(invoice)
39
+
40
+ # Check that it is returned
41
+ result = @gateway.get_invoices(:modified_since => Date.today - 1)
42
+ assert result.success?
43
+ assert !result.request_params.nil?
44
+ assert !result.response_xml.nil?
45
+ assert result.request_params.keys.include?(:ModifiedAfter) # make sure the flag was sent
46
+ assert result.invoices.collect {|response_invoice| response_invoice.invoice_number}.include?(invoice.invoice_number)
47
+ end
48
+
49
+ def test_line_items_downloaded_set_correctly
50
+ # No line items.
51
+ response = @gateway.get_invoices
52
+ assert_equal(true, response.success?)
53
+
54
+ invoice = response.invoices.first
55
+ assert_kind_of(XeroGateway::Invoice, invoice)
56
+ assert_equal(false, invoice.line_items_downloaded?)
57
+ end
58
+
59
+ # Make sure that a reference to gateway is passed when the get_invoices response is parsed.
60
+ def test_get_contacts_gateway_reference
61
+ result = @gateway.get_invoices
62
+ assert(result.success?)
63
+ assert_not_equal(0, result.invoices.size)
64
+
65
+ result.invoices.each do | invoice |
66
+ assert(invoice.gateway === @gateway)
67
+ end
68
+ end
69
+
70
+ # Test to make sure that we correctly error when an invoice doesn't have an ID.
71
+ # This should usually never be ecountered, but might if a draft invoice is deleted from Xero.
72
+ def test_to_ensure_that_an_invoice_with_invalid_id_errors
73
+ # Make sure there is an invoice to retrieve, even though we will mangle it later.
74
+ invoice = @gateway.create_invoice(dummy_invoice).invoice
75
+
76
+ result = @gateway.get_invoices
77
+ assert_equal(true, result.success?)
78
+
79
+ invoice = result.invoices.first
80
+ assert_equal(false, invoice.line_items_downloaded?)
81
+
82
+ # Mangle invoice_id to invalid one.
83
+ invoice.invoice_id = INVALID_INVOICE_ID
84
+
85
+ # Make sure we fail here.
86
+ line_items = nil
87
+ assert_raise(XeroGateway::InvoiceNotFoundError) { line_items = invoice.line_items }
88
+ assert_nil(line_items)
89
+
90
+ end
91
+
92
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class GetOrganisationTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
8
+
9
+ if STUB_XERO_CALLS
10
+ @gateway.xero_url = "DUMMY_URL"
11
+
12
+ @gateway.stubs(:http_get).with {|client, url, params| url =~ /Organisation$/ }.returns(get_file_as_string("organisation.xml"))
13
+ end
14
+ end
15
+
16
+ def test_get_organisation
17
+ result = @gateway.get_organisation
18
+ assert result.success?
19
+ assert !result.response_xml.nil?
20
+
21
+ assert_equal XeroGateway::Organisation, result.organisation.class
22
+ assert_equal "Demo Company (NZ)", result.organisation.name
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class GetTaxRatesTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
8
+
9
+ if STUB_XERO_CALLS
10
+ @gateway.xero_url = "DUMMY_URL"
11
+
12
+ @gateway.stubs(:http_get).with {|client, url, params| url =~ /TaxRates$/ }.returns(get_file_as_string("tax_rates.xml"))
13
+ end
14
+ end
15
+
16
+ def test_get_tax_rates
17
+ result = @gateway.get_tax_rates
18
+ assert result.success?
19
+ assert !result.response_xml.nil?
20
+
21
+ assert result.tax_rates.size > 0
22
+ assert_equal XeroGateway::TaxRate, result.tax_rates.first.class
23
+ assert_equal "GST on Expenses", result.tax_rates.first.name
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class GetTrackingCategoriesTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
8
+
9
+ if STUB_XERO_CALLS
10
+ @gateway.xero_url = "DUMMY_URL"
11
+
12
+ @gateway.stubs(:http_get).with {|client, url, params| url =~ /TrackingCategories$/ }.returns(get_file_as_string("tracking_categories.xml"))
13
+ end
14
+ end
15
+
16
+ def test_get_tracking_categories
17
+ result = @gateway.get_tracking_categories
18
+ assert result.success?
19
+ assert !result.response_xml.nil?
20
+ if STUB_XERO_CALLS
21
+ # When operating against the Xero test environment, there may not be any tracking categories present,
22
+ # so this assertion can only be done when operating against stub responses
23
+ assert_equal 1, result.tracking_categories.size
24
+ assert_equal 4, result.tracking_categories.first.options.size
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class UpdateBankTransactionTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
8
+
9
+ if STUB_XERO_CALLS
10
+ @gateway.xero_url = "DUMMY_URL"
11
+
12
+ @gateway.stubs(:http_put).with {|client, url, body, params| url =~ /BankTransactions$/ }.returns(get_file_as_string("create_bank_transaction.xml"))
13
+ @gateway.stubs(:http_post).with {|client, url, body, params| url =~ /BankTransactions$/ }.returns(get_file_as_string("bank_transaction.xml"))
14
+ end
15
+ end
16
+
17
+ def test_update_bank_transaction
18
+ bank_transaction = @gateway.create_bank_transaction(create_test_bank_transaction).bank_transaction
19
+
20
+ today = Date.today
21
+ bank_transaction.date = today
22
+
23
+ result = @gateway.update_bank_transaction(bank_transaction)
24
+
25
+ assert result.success?
26
+ assert !result.request_xml.nil?
27
+ assert !result.response_xml.nil?
28
+ assert_equal bank_transaction.bank_transaction_id, result.bank_transaction.bank_transaction_id
29
+ assert_equal today, result.bank_transaction.date if !STUB_XERO_CALLS
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class UpdateContactTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
8
+
9
+ if STUB_XERO_CALLS
10
+ @gateway.xero_url = "DUMMY_URL"
11
+
12
+ @gateway.stubs(:http_put).with {|client, url, body, params| url =~ /Contacts$/ }.returns(get_file_as_string("contact.xml"))
13
+ @gateway.stubs(:http_post).with {|client, url, body, params| url =~ /Contacts$/ }.returns(get_file_as_string("contact.xml"))
14
+ end
15
+ end
16
+
17
+ def test_update_contact
18
+ # Make sure there is a contact in Xero to retrieve
19
+ contact = @gateway.create_contact(dummy_contact).contact
20
+
21
+ contact.phone.number = "123 4567"
22
+
23
+ result = @gateway.update_contact(contact)
24
+
25
+ assert result.success?
26
+ assert !result.request_xml.nil?
27
+ assert !result.response_xml.nil?
28
+ assert_equal contact.contact_id, result.contact.contact_id
29
+ assert_equal "123 4567", result.contact.phone.number if !STUB_XERO_CALLS
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class UpdateInvoiceTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
8
+
9
+ if STUB_XERO_CALLS
10
+ @gateway.xero_url = "DUMMY_URL"
11
+
12
+ @gateway.stubs(:http_put).with {|client, url, body, params| url =~ /Invoices$/ }.returns(get_file_as_string("create_invoice.xml"))
13
+ @gateway.stubs(:http_post).with {|client, url, body, params| url =~ /Invoices$/ }.returns(get_file_as_string("invoice.xml"))
14
+ end
15
+ end
16
+
17
+ def test_update_invoice
18
+ invoice = @gateway.create_invoice(dummy_invoice).invoice
19
+
20
+ today = Date.today
21
+ invoice.due_date = today
22
+
23
+ result = @gateway.update_invoice(invoice)
24
+
25
+ assert result.success?
26
+ assert !result.request_xml.nil?
27
+ assert !result.response_xml.nil?
28
+ assert_equal invoice.invoice_id, result.invoice.invoice_id
29
+ assert_equal today, result.invoice.due_date if !STUB_XERO_CALLS
30
+ end
31
+ end
@@ -0,0 +1,179 @@
1
+ require "rubygems"
2
+
3
+ require 'test/unit'
4
+ require 'mocha'
5
+ require 'shoulda'
6
+
7
+ require 'libxml'
8
+
9
+ require File.dirname(__FILE__) + '/../lib/xero_gateway.rb'
10
+
11
+ module TestHelper
12
+ # The integration tests can be run against the Xero test environment. You mush have a company set up in the test
13
+ # environment, and you must have set up a customer key for that account.
14
+ #
15
+ # You can then run the tests against the test environment using the commands (linux or mac):
16
+ # export STUB_XERO_CALLS=false
17
+ # rake test
18
+ # (this probably won't work under OAuth?)
19
+ #
20
+
21
+ STUB_XERO_CALLS = ENV["STUB_XERO_CALLS"].nil? ? true : (ENV["STUB_XERO_CALLS"] == "true") unless defined? STUB_XERO_CALLS
22
+
23
+ CONSUMER_KEY = ENV["CONSUMER_KEY"] || "fake_key" unless defined?(CONSUMER_KEY)
24
+ CONSUMER_SECRET = ENV["CONSUMER_SECRET"] || "fake_secret" unless defined?(CONSUMER_SECRET)
25
+
26
+ # Helper constant for checking regex
27
+ GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ unless defined?(GUID_REGEX)
28
+
29
+
30
+ def dummy_invoice(with_line_items = true)
31
+ invoice = XeroGateway::Invoice.new({
32
+ :invoice_type => "ACCREC",
33
+ :date => Time.now,
34
+ :due_date => Date.today + 20,
35
+ :invoice_number => STUB_XERO_CALLS ? "INV-0001" : "#{Time.now.to_f}",
36
+ :reference => "YOUR REFERENCE (NOT NECESSARILY UNIQUE!)",
37
+ :line_items_downloaded => with_line_items
38
+ })
39
+ invoice.contact = dummy_contact
40
+ if with_line_items
41
+ invoice.line_items << XeroGateway::LineItem.new(
42
+ :description => "THE DESCRIPTION OF THE LINE ITEM",
43
+ :unit_amount => 1000,
44
+ :tax_amount => 125,
45
+ :tracking => [
46
+ XeroGateway::TrackingCategory.new(:name => "THE FIRST TRACKING CATEGORY FOR THE LINE ITEM", :options => ["a", "b"]),
47
+ XeroGateway::TrackingCategory.new(:name => "THE SECOND TRACKING CATEGORY FOR THE LINE ITEM", :options => "c")
48
+ ]
49
+ )
50
+ end
51
+ invoice
52
+ end
53
+
54
+ def dummy_credit_note(with_line_items = true)
55
+ credit_note = XeroGateway::CreditNote.new({
56
+ :type => "ACCRECCREDIT",
57
+ :date => Time.now,
58
+ :credit_note_number => STUB_XERO_CALLS ? "CN-0153" : "#{Time.now.to_f}",
59
+ :reference => "YOUR REFERENCE (NOT NECESSARILY UNIQUE!)",
60
+ :line_items_downloaded => with_line_items
61
+ })
62
+ credit_note.contact = dummy_contact
63
+ if with_line_items
64
+ credit_note.line_items << XeroGateway::LineItem.new(
65
+ :description => "THE DESCRIPTION OF THE LINE ITEM",
66
+ :unit_amount => 1000,
67
+ :tax_amount => 125,
68
+ :tracking => [
69
+ XeroGateway::TrackingCategory.new(:name => "THE FIRST TRACKING CATEGORY FOR THE LINE ITEM", :options => ["a", "b"]),
70
+ XeroGateway::TrackingCategory.new(:name => "THE SECOND TRACKING CATEGORY FOR THE LINE ITEM", :options => "c")
71
+ ]
72
+ )
73
+ end
74
+ credit_note
75
+ end
76
+
77
+ def dummy_contact
78
+ unique_id = Time.now.to_f
79
+ contact = XeroGateway::Contact.new(:name => STUB_XERO_CALLS ? "CONTACT NAME" : "THE NAME OF THE CONTACT #{unique_id}")
80
+ contact.email = "bob#{unique_id}@example.com"
81
+ contact.phone.number = "12345"
82
+ contact.address.line_1 = "LINE 1 OF THE ADDRESS"
83
+ contact.address.line_2 = "LINE 2 OF THE ADDRESS"
84
+ contact.address.line_3 = "LINE 3 OF THE ADDRESS"
85
+ contact.address.line_4 = "LINE 4 OF THE ADDRESS"
86
+ contact.address.city = "WELLINGTON"
87
+ contact.address.region = "WELLINGTON"
88
+ contact.address.country = "NEW ZEALAND"
89
+ contact.address.post_code = "6021"
90
+
91
+ contact
92
+ end
93
+
94
+ def get_file_as_string(filename)
95
+ data = ''
96
+ f = File.open(File.dirname(__FILE__) + "/stub_responses/" + filename, "r")
97
+ f.each_line do |line|
98
+ data += line
99
+ end
100
+ f.close
101
+ return data
102
+ end
103
+
104
+ def create_test_bank_transaction(params={}, contact_params={}, line_item_params={})
105
+ params = {
106
+ :type => 'RECEIVE',
107
+ :date => Date.today,
108
+ :reference => '12345',
109
+ :status => 'ACTIVE',
110
+ }.merge(params)
111
+ bank_transaction = XeroGateway::BankTransaction.new(params)
112
+
113
+ bank_transaction.contact = create_test_contact(contact_params)
114
+ add_test_line_items(bank_transaction, line_item_params)
115
+ bank_transaction.bank_account = create_test_account
116
+
117
+ bank_transaction
118
+ end
119
+
120
+ def add_test_line_items(bank_transaction, line_item_params={})
121
+ if line_item_params
122
+ line_item_params = [line_item_params].flatten # always use an array, even if only a single hash passed in
123
+
124
+ # At least one line item, make first have some defaults.
125
+ line_item_params << {} if line_item_params.size == 0
126
+ line_item_params[0] = {
127
+ :description => "A LINE ITEM",
128
+ :account_code => "200",
129
+ :unit_amount => BigDecimal.new("100"),
130
+ :tax_amount => BigDecimal.new("12.5"),
131
+ :tracking => XeroGateway::TrackingCategory.new(:name => "blah", :options => "hello")
132
+ }.merge(line_item_params[0])
133
+
134
+ # Create line_items from line_item_params
135
+ line_item_params.each do |line_item|
136
+ bank_transaction.add_line_item(line_item)
137
+ end
138
+ end
139
+ bank_transaction
140
+ end
141
+
142
+ def create_test_account
143
+ account = XeroGateway::Account.new(:account_id => "57cedda9")
144
+ account.code = "200"
145
+ account.name = "Sales"
146
+ account.type = "REVENUE"
147
+ account.tax_type = "OUTPUT"
148
+ account.description = "Income from any normal business activity"
149
+ account.enable_payments_to_account = false
150
+ account
151
+ end
152
+
153
+ def create_test_contact(contact_params={})
154
+ # Strip out :address key from contact_params to use as the default address.
155
+ stripped_address = {
156
+ :address_type => 'STREET',
157
+ :line_1 => 'LINE 1 OF THE ADDRESS'
158
+ }.merge(contact_params.delete(:address) || {})
159
+
160
+ # Strip out :phone key from contact_params to use at the default phone.
161
+ stripped_phone = {
162
+ :phone_type => 'DEFAULT',
163
+ :number => '12345678'
164
+ }.merge(contact_params.delete(:phone) || {})
165
+
166
+ contact_params = {
167
+ :contact_id => '00000000-0000-0000-0000-000000000000', # Just any valid GUID
168
+ :name => "CONTACT NAME",
169
+ :first_name => "Bob",
170
+ :last_name => "Builder"
171
+ }.merge(contact_params)
172
+
173
+ contact = XeroGateway::Contact.new(contact_params)
174
+ contact.address = XeroGateway::Address.new(stripped_address)
175
+ contact.phone = XeroGateway::Phone.new(stripped_phone)
176
+ contact
177
+ end
178
+
179
+ end