xero_gateway 2.1.0 → 2.3.0

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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -11
  3. data/README.md +212 -0
  4. data/Rakefile +0 -1
  5. data/lib/oauth/oauth_consumer.rb +25 -9
  6. data/lib/xero_gateway.rb +5 -1
  7. data/lib/xero_gateway/address.rb +29 -27
  8. data/lib/xero_gateway/bank_transaction.rb +11 -3
  9. data/lib/xero_gateway/base_record.rb +97 -0
  10. data/lib/xero_gateway/contact_group.rb +87 -0
  11. data/lib/xero_gateway/currency.rb +8 -54
  12. data/lib/xero_gateway/dates.rb +4 -0
  13. data/lib/xero_gateway/exceptions.rb +14 -13
  14. data/lib/xero_gateway/gateway.rb +90 -5
  15. data/lib/xero_gateway/http.rb +16 -8
  16. data/lib/xero_gateway/invoice.rb +9 -3
  17. data/lib/xero_gateway/item.rb +27 -0
  18. data/lib/xero_gateway/line_item_calculations.rb +3 -3
  19. data/lib/xero_gateway/manual_journal.rb +5 -2
  20. data/lib/xero_gateway/organisation.rb +22 -73
  21. data/lib/xero_gateway/payment.rb +22 -9
  22. data/lib/xero_gateway/phone.rb +2 -0
  23. data/lib/xero_gateway/report.rb +95 -0
  24. data/lib/xero_gateway/response.rb +12 -7
  25. data/lib/xero_gateway/tax_rate.rb +13 -61
  26. data/lib/xero_gateway/tracking_category.rb +39 -13
  27. data/lib/xero_gateway/version.rb +3 -0
  28. data/test/integration/get_items_test.rb +25 -0
  29. data/test/integration/get_payments_test.rb +54 -0
  30. data/test/test_helper.rb +51 -16
  31. data/test/unit/address_test.rb +34 -0
  32. data/test/unit/bank_transaction_test.rb +7 -0
  33. data/test/unit/contact_group_test.rb +47 -0
  34. data/test/unit/contact_test.rb +35 -16
  35. data/test/unit/credit_note_test.rb +2 -2
  36. data/test/unit/gateway_test.rb +170 -1
  37. data/test/unit/invoice_test.rb +27 -7
  38. data/test/unit/item_test.rb +51 -0
  39. data/test/unit/organisation_test.rb +1 -0
  40. data/test/unit/payment_test.rb +18 -11
  41. data/test/unit/report_test.rb +78 -0
  42. data/xero_gateway.gemspec +29 -13
  43. metadata +176 -89
  44. data/README.textile +0 -357
  45. data/init.rb +0 -1
@@ -1,63 +1,15 @@
1
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
- next if !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
-
2
+ class TaxRate < BaseRecord
3
+ attributes({
4
+ "Name" => :string,
5
+ "TaxType" => :string,
6
+ "CanApplyToAssets" => :boolean,
7
+ "CanApplyToEquity" => :boolean,
8
+ "CanApplyToExpenses" => :boolean,
9
+ "CanApplyToLiabilities" => :boolean,
10
+ "CanApplyToRevenue" => :boolean,
11
+ "DisplayTaxRate" => :float,
12
+ "EffectiveRate" => :float
13
+ })
62
14
  end
63
- end
15
+ end
@@ -18,19 +18,43 @@
18
18
  #
19
19
  module XeroGateway
20
20
  class TrackingCategory
21
- attr_accessor :tracking_category_id, :name, :options
22
-
21
+ attr_accessor :tracking_category_id, :name, :status, :options
22
+ attr_accessor :all_options
23
+
24
+ class Option
25
+ attr_accessor :tracking_option_id, :name, :status
26
+
27
+ def initialize(params = {})
28
+ params.each do |k,v|
29
+ self.send("#{k}=", v)
30
+ end
31
+ end
32
+
33
+ def self.from_xml(option_element)
34
+ option = Option.new
35
+ option_element.children.each do |element|
36
+ case(element.name)
37
+ when "TrackingOptionID" then option.tracking_option_id = element.text
38
+ when "Name" then option.name = element.text
39
+ when "Status" then option.status = element.text
40
+ end
41
+ end
42
+ option
43
+ end
44
+ end
45
+
23
46
  def initialize(params = {})
24
47
  @options = []
48
+ @all_options = []
25
49
  params.each do |k,v|
26
50
  self.send("#{k}=", v)
27
51
  end
28
52
  end
29
-
53
+
30
54
  def option
31
55
  options[0] if options.size == 1
32
56
  end
33
-
57
+
34
58
  def to_xml(b = Builder::XmlMarkup.new)
35
59
  b.TrackingCategory {
36
60
  b.TrackingCategoryID tracking_category_id unless tracking_category_id.nil?
@@ -45,43 +69,45 @@ module XeroGateway
45
69
  else
46
70
  b.Option {
47
71
  b.Name self.options.to_s
48
- }
72
+ }
49
73
  end
50
74
  }
51
75
  }
52
76
  end
53
-
77
+
54
78
  # When a tracking category is serialized as part of an invoice it may only have a single
55
79
  # option, and the Options tag is omitted
56
80
  def to_xml_for_invoice_messages(b = Builder::XmlMarkup.new)
57
81
  b.TrackingCategory {
58
82
  b.TrackingCategoryID self.tracking_category_id unless tracking_category_id.nil?
59
83
  b.Name self.name
60
- b.Option self.options.is_a?(Array) ? self.options.first : self.options.to_s
61
- }
84
+ b.Option self.options.is_a?(Array) ? self.options.first : self.options.to_s
85
+ }
62
86
  end
63
-
87
+
64
88
  def self.from_xml(tracking_category_element)
65
89
  tracking_category = TrackingCategory.new
66
90
  tracking_category_element.children.each do |element|
67
91
  case(element.name)
68
92
  when "TrackingCategoryID" then tracking_category.tracking_category_id = element.text
69
93
  when "Name" then tracking_category.name = element.text
94
+ when "Status" then tracking_category.status = element.text
70
95
  when "Options" then
71
96
  element.children.each do |option_child|
72
97
  tracking_category.options << option_child.children.detect {|c| c.name == "Name"}.text
98
+ tracking_category.all_options << Option.from_xml(option_child)
73
99
  end
74
100
  when "Option" then tracking_category.options << element.text
75
101
  end
76
102
  end
77
- tracking_category
78
- end
79
-
103
+ tracking_category
104
+ end
105
+
80
106
  def ==(other)
81
107
  [:tracking_category_id, :name, :options].each do |field|
82
108
  return false if send(field) != other.send(field)
83
109
  end
84
110
  return true
85
- end
111
+ end
86
112
  end
87
113
  end
@@ -0,0 +1,3 @@
1
+ module XeroGateway
2
+ VERSION = "2.3.0"
3
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class GetItemsTest < 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 =~ /Items$/ }.returns(get_file_as_string("items.xml"))
13
+ end
14
+ end
15
+
16
+ def test_get_items
17
+ result = @gateway.get_items
18
+ assert result.success?
19
+ assert !result.response_xml.nil?
20
+
21
+ assert result.items.size > 0
22
+ assert_equal XeroGateway::Item, result.items.first.class
23
+ assert_equal "An Untracked Item", result.items.first.name
24
+ end
25
+ end
@@ -0,0 +1,54 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class GetPaymentsTest < 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 =~ /Payments(\/[0-9a-z\-]+)?$/i }.returns(get_file_as_string("payments.xml"))
13
+ @gateway.stubs(:http_put).with {|client, url, body, params| url =~ /Payments$/ }.returns(get_file_as_string("create_payments.xml"))
14
+ end
15
+ end
16
+
17
+ def test_get_payments
18
+ # Make sure there is a bank transaction in Xero to retrieve
19
+ payment = @gateway.create_payment(create_test_payment).payments
20
+
21
+ result = @gateway.get_payments
22
+ assert result.success?
23
+ assert !result.request_params.nil?
24
+ assert !result.response_xml.nil?
25
+ assert result.payments.collect {|i| i.reference}.include?(payment.first.reference)
26
+ assert result.payments.collect {|i| i.payment_id}.include?(payment.first.payment_id)
27
+ assert_kind_of(XeroGateway::Payment, payment.first)
28
+ end
29
+
30
+ def test_get_payments_modified_since_date
31
+ # Create a test payment
32
+ @gateway.create_payment(create_test_payment)
33
+
34
+ # Check that it is returned
35
+ result = @gateway.get_payments(:modified_since => Date.today - 1)
36
+ assert result.success?
37
+ assert !result.request_params.nil?
38
+ assert !result.response_xml.nil?
39
+ assert result.request_params.keys.include?(:ModifiedAfter) # make sure the flag was sent
40
+ end
41
+
42
+ def test_get_payments_find_by_id
43
+ # Create a test payment
44
+ @gateway.create_payment(create_test_payment)
45
+
46
+ # Check that it is returned
47
+ result = @gateway.get_payments(:payment_id => create_test_payment.payment_id)
48
+ assert result.success?
49
+ assert !result.request_params.nil?
50
+ assert !result.response_xml.nil?
51
+ assert result.request_params.keys.include?(:PaymentID) # make sure the flag was sent
52
+ end
53
+
54
+ end
data/test/test_helper.rb CHANGED
@@ -1,32 +1,32 @@
1
- require "rubygems"
1
+ require 'bundler/setup'
2
2
 
3
3
  require 'test/unit'
4
- require 'mocha'
4
+ require 'mocha/setup'
5
5
  require 'shoulda'
6
6
 
7
7
  require 'libxml'
8
8
 
9
- require File.dirname(__FILE__) + '/../lib/xero_gateway.rb' unless defined?(XeroGateway)
9
+ require File.dirname(__FILE__) + '/../lib/xero_gateway.rb'
10
10
 
11
11
  module TestHelper
12
12
  # The integration tests can be run against the Xero test environment. You mush have a company set up in the test
13
13
  # environment, and you must have set up a customer key for that account.
14
14
  #
15
15
  # You can then run the tests against the test environment using the commands (linux or mac):
16
- # export STUB_XERO_CALLS=false
16
+ # export STUB_XERO_CALLS=false
17
17
  # rake test
18
18
  # (this probably won't work under OAuth?)
19
19
  #
20
-
20
+
21
21
  STUB_XERO_CALLS = ENV["STUB_XERO_CALLS"].nil? ? true : (ENV["STUB_XERO_CALLS"] == "true") unless defined? STUB_XERO_CALLS
22
-
22
+
23
23
  CONSUMER_KEY = ENV["CONSUMER_KEY"] || "fake_key" unless defined?(CONSUMER_KEY)
24
24
  CONSUMER_SECRET = ENV["CONSUMER_SECRET"] || "fake_secret" unless defined?(CONSUMER_SECRET)
25
-
25
+
26
26
  # Helper constant for checking regex
27
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
28
 
29
-
29
+
30
30
  def dummy_invoice(with_line_items = true)
31
31
  invoice = XeroGateway::Invoice.new({
32
32
  :invoice_type => "ACCREC",
@@ -50,7 +50,7 @@ module TestHelper
50
50
  end
51
51
  invoice
52
52
  end
53
-
53
+
54
54
  def dummy_credit_note(with_line_items = true)
55
55
  credit_note = XeroGateway::CreditNote.new({
56
56
  :type => "ACCRECCREDIT",
@@ -73,7 +73,7 @@ module TestHelper
73
73
  end
74
74
  credit_note
75
75
  end
76
-
76
+
77
77
  def dummy_contact
78
78
  unique_id = Time.now.to_f
79
79
  contact = XeroGateway::Contact.new(:name => STUB_XERO_CALLS ? "CONTACT NAME" : "THE NAME OF THE CONTACT #{unique_id}")
@@ -90,15 +90,19 @@ module TestHelper
90
90
 
91
91
  contact
92
92
  end
93
-
93
+
94
94
  def get_file_as_string(filename)
95
95
  data = ''
96
- f = File.open(File.dirname(__FILE__) + "/stub_responses/" + filename, "r")
96
+ f = File.open(File.dirname(__FILE__) + "/stub_responses/" + filename, "r")
97
97
  f.each_line do |line|
98
98
  data += line
99
99
  end
100
100
  f.close
101
- return data
101
+ data
102
+ end
103
+
104
+ def get_file(filename)
105
+ data = File.read( File.dirname(__FILE__) + "/stub_responses/" + filename)
102
106
  end
103
107
 
104
108
  def create_test_bank_transaction(params={}, contact_params={}, line_item_params={})
@@ -117,6 +121,37 @@ module TestHelper
117
121
  bank_transaction
118
122
  end
119
123
 
124
+ def create_test_payment(params={}, contact_params={})
125
+ params = {
126
+ :payment_id => 'a99a9aaa-9999-99a9-9aa9-aaaaaa9a9999',
127
+ :payment_type => 'ACCRECPAYMENT',
128
+ :updated_at => Time.now,
129
+ :reference => '12345',
130
+ :account_id => 'o99o9ooo-9999-99o9-9oo9-oooooo9o9999',
131
+ :amount => 1000.0,
132
+ :currency_rate => 1.0,
133
+ :date => Date.today.to_time,
134
+ :invoice_id => 'i99i9iii-9999-99i9-9ii9-iiiiii9i9999',
135
+ :invoice_number => 'INV-0001',
136
+ :reconciled => true,
137
+ }.merge(params)
138
+ XeroGateway::Payment.new(params)
139
+ end
140
+
141
+ def create_test_report_bank_statement(params={}, body_params={})
142
+ params = {
143
+ :report_id => 'BankStatement',
144
+ :report_name => 'BankStatement',
145
+ :report_type => 'BankStatement',
146
+ :report_titles => [],
147
+ :report_date => Date.today,
148
+ :updated_at => Time.now-3.days,
149
+ :column_names => [],
150
+ :body => []
151
+ }.merge(params)
152
+ XeroGateway::Report.new(params)
153
+ end
154
+
120
155
  def add_test_line_items(bank_transaction, line_item_params={})
121
156
  if line_item_params
122
157
  line_item_params = [line_item_params].flatten # always use an array, even if only a single hash passed in
@@ -177,7 +212,7 @@ module TestHelper
177
212
  end
178
213
 
179
214
  def create_test_manual_journal(params={}, journal_line_params={})
180
- params = {
215
+ params = {
181
216
  :date => Date.today,
182
217
  :narration => 'test narration',
183
218
  :status => 'POSTED'
@@ -202,9 +237,9 @@ module TestHelper
202
237
  journal_line_params[1] = {
203
238
  :description => "SECOND LINE",
204
239
  :account_code => "200",
205
- :line_amount => BigDecimal.new("-100"),
240
+ :line_amount => BigDecimal.new("-100"),
206
241
  :tracking => XeroGateway::TrackingCategory.new(:name => "blah2", :options => "hello2")
207
- }.merge(params_line_1)
242
+ }.merge(params_line_1)
208
243
 
209
244
  # Create line_items from line_item_params
210
245
  journal_line_params.each do |journal_line|
@@ -0,0 +1,34 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
+
3
+ class AddressTest < Test::Unit::TestCase
4
+
5
+ test "build and parse XML" do
6
+ address = create_test_address
7
+
8
+ # Generate the XML message
9
+ address_xml = address.to_xml
10
+
11
+ # Parse the XML message and retrieve the address element
12
+ address_element = REXML::XPath.first(REXML::Document.new(address_xml), "/Address")
13
+
14
+ # Build a new contact from the XML
15
+ result_address = XeroGateway::Address.from_xml(address_element)
16
+
17
+ # Check the contact details
18
+ assert_equal address, result_address
19
+ end
20
+
21
+ private
22
+
23
+ def create_test_address
24
+ XeroGateway::Address.new(
25
+ line_1: "25 Taranaki St",
26
+ line_2: "Te Aro",
27
+ city: "Wellington",
28
+ post_code: "6011",
29
+ country: "New Zealand",
30
+ attention_to: "Hashigo Zake"
31
+ )
32
+ end
33
+
34
+ end
@@ -97,8 +97,15 @@ class BankTransactionTest < Test::Unit::TestCase
97
97
 
98
98
  assert_xml_field bank_transaction_element, 'Url', :value => 'http://example.com\?with=params&amp;and=more'
99
99
 
100
+ # test total without downloading each line items
101
+ total_elem = REXML::Element.new('Total')
102
+ total_elem.text = '1000'
103
+ bank_transaction_element.add_element(total_elem)
104
+
105
+ XeroGateway::BankTransaction.any_instance.stubs(:line_items_downloaded?).returns(false)
100
106
  parsed_bank_transaction = XeroGateway::BankTransaction.from_xml(bank_transaction_element)
101
107
  assert_equal 'http://example.com?with=params&and=more', parsed_bank_transaction.url
108
+ assert_equal BigDecimal.new('1000'), parsed_bank_transaction.total
102
109
  end
103
110
 
104
111
  should "ignore missing contact" do