xero_gateway-float 2.0.15

Sign up to get free protection for your applications and to get access to all the features.
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,63 @@
1
+ module XeroGateway
2
+ class TaxRate
3
+
4
+ unless defined? ATTRS
5
+ ATTRS = {
6
+ "Name" => :string,
7
+ "TaxType" => :string,
8
+ "CanApplyToAssets" => :boolean,
9
+ "CanApplyToEquity" => :boolean,
10
+ "CanApplyToExpenses" => :boolean,
11
+ "CanApplyToLiabilities" => :boolean,
12
+ "CanApplyToRevenue" => :boolean,
13
+ "DisplayTaxRate" => :float,
14
+ "EffectiveRate" => :float
15
+ }
16
+ end
17
+
18
+ attr_accessor *ATTRS.keys.map(&:underscore)
19
+
20
+ def initialize(params = {})
21
+ params.each do |k,v|
22
+ self.send("#{k}=", v)
23
+ end
24
+ end
25
+
26
+ def ==(other)
27
+ ATTRS.keys.map(&:underscore).each do |field|
28
+ return false if send(field) != other.send(field)
29
+ end
30
+ return true
31
+ end
32
+
33
+ def to_xml
34
+ b = Builder::XmlMarkup.new
35
+
36
+ b.TaxRate do
37
+ ATTRS.keys.each do |attr|
38
+ eval("b.#{attr} '#{self.send(attr.underscore.to_sym)}'")
39
+ end
40
+ end
41
+ end
42
+
43
+ def self.from_xml(tax_rate_element)
44
+ TaxRate.new.tap do |tax_rate|
45
+ tax_rate_element.children.each do |element|
46
+
47
+ attribute = element.name
48
+ underscored_attribute = element.name.underscore
49
+
50
+ raise "Unknown attribute: #{attribute}" unless ATTRS.keys.include?(attribute)
51
+
52
+ case (ATTRS[attribute])
53
+ when :boolean then tax_rate.send("#{underscored_attribute}=", (element.text == "true"))
54
+ when :float then tax_rate.send("#{underscored_attribute}=", element.text.to_f)
55
+ else tax_rate.send("#{underscored_attribute}=", element.text)
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,87 @@
1
+ # Tacking categories look like:
2
+ #
3
+ # <TrackingCategory>
4
+ # <Name>Region</Name>
5
+ # <Status>ACTIVE</Status>
6
+ # <TrackingCategoryID>e4a95e64-ebaa-401e-81cf-b625c7532d01</TrackingCategoryID>
7
+ # <Options>
8
+ # <Option>
9
+ # <TrackingOptionID>ea7f7b6a-0d22-4d5c-9317-54542a10215e</TrackingOptionID>
10
+ # <Name>North</Name>
11
+ # </Option>
12
+ # <Option>
13
+ # <TrackingOptionID>8e8b8d7b-fa75-4b24-b429-8cbc1a21af23</TrackingOptionID>
14
+ # <Name>South</Name>
15
+ # </Option>
16
+ # </Options>
17
+ # </TrackingCategory>
18
+ #
19
+ module XeroGateway
20
+ class TrackingCategory
21
+ attr_accessor :tracking_category_id, :name, :options
22
+
23
+ def initialize(params = {})
24
+ @options = []
25
+ params.each do |k,v|
26
+ self.send("#{k}=", v)
27
+ end
28
+ end
29
+
30
+ def option
31
+ options[0] if options.size == 1
32
+ end
33
+
34
+ def to_xml(b = Builder::XmlMarkup.new)
35
+ b.TrackingCategory {
36
+ b.TrackingCategoryID tracking_category_id unless tracking_category_id.nil?
37
+ b.Name self.name
38
+ b.Options {
39
+ if self.options.is_a?(Array)
40
+ self.options.each do |option|
41
+ b.Option {
42
+ b.Name option
43
+ }
44
+ end
45
+ else
46
+ b.Option {
47
+ b.Name self.options.to_s
48
+ }
49
+ end
50
+ }
51
+ }
52
+ end
53
+
54
+ # When a tracking category is serialized as part of an invoice it may only have a single
55
+ # option, and the Options tag is omitted
56
+ def to_xml_for_invoice_messages(b = Builder::XmlMarkup.new)
57
+ b.TrackingCategory {
58
+ b.TrackingCategoryID self.tracking_category_id unless tracking_category_id.nil?
59
+ b.Name self.name
60
+ b.Option self.options.is_a?(Array) ? self.options.first : self.options.to_s
61
+ }
62
+ end
63
+
64
+ def self.from_xml(tracking_category_element)
65
+ tracking_category = TrackingCategory.new
66
+ tracking_category_element.children.each do |element|
67
+ case(element.name)
68
+ when "TrackingCategoryID" then tracking_category.tracking_category_id = element.text
69
+ when "Name" then tracking_category.name = element.text
70
+ when "Options" then
71
+ element.children.each do |option_child|
72
+ tracking_category.options << option_child.children.detect {|c| c.name == "Name"}.text
73
+ end
74
+ when "Option" then tracking_category.options << element.text
75
+ end
76
+ end
77
+ tracking_category
78
+ end
79
+
80
+ def ==(other)
81
+ [:tracking_category_id, :name, :options].each do |field|
82
+ return false if send(field) != other.send(field)
83
+ end
84
+ return true
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,109 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class AccountsListTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
8
+
9
+ # Always stub out calls for this integration test as we need to be able to control the data.
10
+ @gateway.xero_url = "DUMMY_URL"
11
+
12
+ @gateway.stubs(:http_get).with {|client, url, params| url =~ /Accounts$/ }.returns(get_file_as_string("accounts.xml"))
13
+ end
14
+
15
+ def test_get_accounts_list
16
+ accounts_list = @gateway.get_accounts_list
17
+ assert_not_equal(0, accounts_list.accounts.size)
18
+ end
19
+
20
+ # Make sure that the list is loaded when finding things.
21
+ def test_raise_error_on_not_loaded
22
+ accounts_list = @gateway.get_accounts_list(false)
23
+ assert_equal(false, accounts_list.loaded?)
24
+ assert_raise(XeroGateway::AccountsList::AccountsListNotLoadedError) { accounts_list[200] }
25
+ assert_raise(XeroGateway::AccountsList::AccountsListNotLoadedError) { accounts_list.find_by_code(200) }
26
+ assert_raise(XeroGateway::AccountsList::AccountsListNotLoadedError) { accounts_list.find_all_by_type('EXPENSE') }
27
+ assert_raise(XeroGateway::AccountsList::AccountsListNotLoadedError) { accounts_list.find_all_by_tax_type('OUTPUT') }
28
+ end
29
+
30
+ # Test simple lookup by account code (from cache).
31
+ def test_simple_lookup_by_account_code
32
+ accounts_list = @gateway.get_accounts_list
33
+ assert_equal(true, accounts_list.loaded?)
34
+
35
+ # Load data in the stubbed response.
36
+ expected_accounts = accounts_as_array
37
+
38
+ # Make sure that every single expected account exists in the cached lookup hash.
39
+ expected_accounts.each do | expected_account |
40
+ found_account = accounts_list.find_by_code(expected_account.code)
41
+ assert_kind_of(XeroGateway::Account, found_account)
42
+ assert(expected_account == found_account, "Found account does not match expected account.")
43
+
44
+ found_account_shortcut = accounts_list[expected_account.code]
45
+ assert_kind_of(XeroGateway::Account, found_account_shortcut)
46
+ assert(expected_account == found_account_shortcut, "Found account does not match expected account (shortcut).")
47
+ end
48
+ end
49
+
50
+ # Test finding accounts by their account type (from cache).
51
+ def test_lookup_by_account_type
52
+ accounts_list = @gateway.get_accounts_list
53
+ assert_equal(true, accounts_list.loaded?)
54
+
55
+ # Load data in the stubbed response.
56
+ expected_accounts = accounts_as_array
57
+
58
+ # Get all the unique account types present in the expected accounts data along with their counts.
59
+ unique_types = expected_accounts.inject({}) do | list, account |
60
+ list[account.type] = 0 if list[account.type].nil?
61
+ list[account.type] += 1
62
+ list
63
+ end
64
+
65
+ assert_not_equal(0, unique_types)
66
+ unique_types.each do | account_type, count |
67
+ found_accounts = accounts_list.find_all_by_type(account_type)
68
+ assert_equal(count, found_accounts.size)
69
+ found_accounts.each do | found_account |
70
+ assert_kind_of(XeroGateway::Account, found_account)
71
+ assert_equal(account_type, found_account.type)
72
+ end
73
+ end
74
+ end
75
+
76
+ # Test finding accounts by their tax type (from cache).
77
+ def test_lookup_by_tax_type
78
+ accounts_list = @gateway.get_accounts_list
79
+ assert_equal(true, accounts_list.loaded?)
80
+
81
+ # Load data in the stubbed response.
82
+ expected_accounts = accounts_as_array
83
+
84
+ # Get all the unique tax types present in the expected accounts data along with their counts.
85
+ unique_types = expected_accounts.inject({}) do | list, account |
86
+ list[account.tax_type] = 0 if list[account.tax_type].nil?
87
+ list[account.tax_type] += 1
88
+ list
89
+ end
90
+
91
+ assert_not_equal(0, unique_types)
92
+ unique_types.each do | tax_type, count |
93
+ found_accounts = accounts_list.find_all_by_tax_type(tax_type)
94
+ assert_equal(count, found_accounts.size)
95
+ found_accounts.each do | found_account |
96
+ assert_kind_of(XeroGateway::Account, found_account)
97
+ assert_equal(tax_type, found_account.tax_type)
98
+ end
99
+ end
100
+ end
101
+
102
+ private
103
+
104
+ def accounts_as_array
105
+ response = @gateway.__send__(:parse_response, get_file_as_string("accounts.xml"))
106
+ response.accounts
107
+ end
108
+
109
+ end
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class CreateBankTransactionTest < 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_create_bank_transaction
18
+ example_bank_transaction = create_test_bank_transaction.dup
19
+
20
+ result = @gateway.create_bank_transaction(example_bank_transaction)
21
+ assert_kind_of XeroGateway::Response, result
22
+ assert result.success?
23
+ assert !result.request_xml.nil?
24
+ assert !result.response_xml.nil?
25
+ assert !result.bank_transaction.bank_transaction_id.nil?
26
+ assert example_bank_transaction.bank_transaction_id =~ GUID_REGEX
27
+ end
28
+
29
+ def test_create_bank_transaction_valid
30
+ example_bank_transaction = create_test_bank_transaction.dup
31
+ assert_equal true, example_bank_transaction.valid?,
32
+ "bank_transaction is invalid - errors:\n\t#{example_bank_transaction.errors.map { | error | "#{error[0]} #{error[1]}"}.join("\n\t")}"
33
+ end
34
+
35
+ private
36
+
37
+
38
+ end
@@ -0,0 +1,66 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class CreateContactTest < 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_create_contact
18
+ example_contact = dummy_contact.dup
19
+
20
+ result = @gateway.create_contact(example_contact)
21
+ assert_valid_contact_save_response(result, example_contact)
22
+ end
23
+
24
+ def test_create_from_contact
25
+ example_contact = dummy_contact.dup
26
+
27
+ contact = @gateway.build_contact(example_contact)
28
+ result = contact.create
29
+ assert_valid_contact_save_response(result, example_contact)
30
+ end
31
+
32
+ def test_update_from_contact
33
+ example_contact = dummy_contact.dup
34
+
35
+ contact = @gateway.build_contact(example_contact)
36
+ contact.create # need to create first so we have a ContactID
37
+
38
+ result = contact.update
39
+ assert_valid_contact_save_response(result, example_contact)
40
+ end
41
+
42
+ def test_save_from_contact
43
+ example_contact = dummy_contact.dup
44
+
45
+ contact = @gateway.build_contact(example_contact)
46
+ result = contact.save
47
+ assert_valid_contact_save_response(result, example_contact)
48
+ end
49
+
50
+ def test_create_contact_valid
51
+ example_contact = dummy_contact.dup
52
+ assert_equal true, example_contact.valid?, "contact is invalid - errors:\n\t#{example_contact.errors.map { | error | "#{error[0]} #{error[1]}"}.join("\n\t")}"
53
+ end
54
+
55
+ private
56
+
57
+ def assert_valid_contact_save_response(result, example_contact)
58
+ assert_kind_of XeroGateway::Response, result
59
+ assert result.success?
60
+ assert !result.contact.contact_id.nil?
61
+ assert !result.request_xml.nil?
62
+ assert !result.response_xml.nil?
63
+ assert_equal result.contact.name, example_contact.name
64
+ assert example_contact.contact_id =~ GUID_REGEX
65
+ end
66
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class CreateCreditNoteTest < 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 =~ /CreditNotes$/ }.returns(get_file_as_string("create_credit_note.xml"))
13
+ @gateway.stubs(:http_post).with {|client, url, body, params| url =~ /CreditNotes$/ }.returns(get_file_as_string("credit_note.xml"))
14
+ end
15
+ end
16
+
17
+ def test_create_credit_note
18
+ example_credit_note = dummy_credit_note.dup
19
+
20
+ result = @gateway.create_credit_note(example_credit_note)
21
+ assert_valid_credit_note_save_response(result, example_credit_note)
22
+ end
23
+
24
+ def test_create_from_credit_note
25
+ example_credit_note = dummy_credit_note.dup
26
+
27
+ credit_note = @gateway.build_credit_note(example_credit_note)
28
+ result = credit_note.create
29
+ assert_valid_credit_note_save_response(result, example_credit_note)
30
+ end
31
+
32
+ def test_create_credit_note_valid
33
+ example_credit_note = dummy_credit_note.dup
34
+ assert_equal true, example_credit_note.valid?, "credit_note is invalid - errors:\n\t#{example_credit_note.errors.map { | error | "#{error[0]} #{error[1]}"}.join("\n\t")}"
35
+ end
36
+
37
+ private
38
+
39
+ def assert_valid_credit_note_save_response(result, example_credit_note)
40
+ assert_kind_of XeroGateway::Response, result
41
+ assert result.success?
42
+ assert !result.request_xml.nil?
43
+ assert !result.response_xml.nil?
44
+ assert !result.credit_note.credit_note_id.nil?
45
+ assert result.credit_note.credit_note_number == example_credit_note.credit_note_number
46
+ assert result.credit_note.credit_note_id =~ GUID_REGEX
47
+ end
48
+
49
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class CreateInvoiceTest < 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_create_invoice
18
+ example_invoice = dummy_invoice.dup
19
+
20
+ result = @gateway.create_invoice(example_invoice)
21
+ assert_valid_invoice_save_response(result, example_invoice)
22
+ end
23
+
24
+ def test_create_from_invoice
25
+ example_invoice = dummy_invoice.dup
26
+
27
+ invoice = @gateway.build_invoice(example_invoice)
28
+ result = invoice.create
29
+ assert_valid_invoice_save_response(result, example_invoice)
30
+ end
31
+
32
+ def test_create_invoice_valid
33
+ example_invoice = dummy_invoice.dup
34
+ assert_equal true, example_invoice.valid?, "invoice is invalid - errors:\n\t#{example_invoice.errors.map { | error | "#{error[0]} #{error[1]}"}.join("\n\t")}"
35
+ end
36
+
37
+ private
38
+
39
+ def assert_valid_invoice_save_response(result, example_invoice)
40
+ assert_kind_of XeroGateway::Response, result
41
+ assert result.success?
42
+ assert !result.request_xml.nil?
43
+ assert !result.response_xml.nil?
44
+ assert !result.invoice.invoice_id.nil?
45
+ assert result.invoice.invoice_number == example_invoice.invoice_number
46
+ assert example_invoice.invoice_id =~ GUID_REGEX
47
+ end
48
+
49
+ end