xero_gateway 2.0.4 → 2.0.5
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/README.textile +57 -5
- data/lib/xero_gateway/account.rb +8 -2
- data/lib/xero_gateway/credit_note.rb +275 -0
- data/lib/xero_gateway/exceptions.rb +3 -1
- data/lib/xero_gateway/gateway.rb +119 -3
- data/lib/xero_gateway/http.rb +10 -6
- data/lib/xero_gateway/oauth.rb +3 -1
- data/lib/xero_gateway/response.rb +2 -0
- data/lib/xero_gateway/tracking_category.rb +5 -2
- data/lib/xero_gateway.rb +1 -0
- data/test/integration/create_credit_note_test.rb +49 -0
- data/test/integration/get_credit_note_test.rb +48 -0
- data/test/integration/get_credit_notes_test.rb +90 -0
- data/test/integration/get_tracking_categories_test.rb +3 -2
- data/test/test_helper.rb +24 -1
- data/test/unit/account_test.rb +3 -2
- data/test/unit/credit_note_test.rb +284 -0
- data/test/unit/gateway_test.rb +17 -1
- data/xero_gateway.gemspec +3 -76
- metadata +13 -29
- data/CHANGELOG.textile +0 -57
- data/test/stub_responses/accounts.xml +0 -1
- data/test/stub_responses/api_exception.xml +0 -153
- data/test/stub_responses/contact.xml +0 -1
- data/test/stub_responses/contacts.xml +0 -2189
- data/test/stub_responses/create_invoice.xml +0 -64
- data/test/stub_responses/currencies.xml +0 -16
- data/test/stub_responses/invalid_api_key_error.xml +0 -1
- data/test/stub_responses/invalid_consumer_key +0 -1
- data/test/stub_responses/invalid_request_token +0 -1
- data/test/stub_responses/invoice.xml +0 -1
- data/test/stub_responses/invoice_not_found_error.xml +0 -1
- data/test/stub_responses/invoices.xml +0 -1
- data/test/stub_responses/organisation.xml +0 -14
- data/test/stub_responses/tax_rates.xml +0 -52
- data/test/stub_responses/token_expired +0 -1
- data/test/stub_responses/tracking_categories.xml +0 -1
- data/test/stub_responses/unknown_error.xml +0 -1
- data/test/xsd/README +0 -2
- data/test/xsd/create_contact.xsd +0 -61
- data/test/xsd/create_invoice.xsd +0 -107
@@ -18,7 +18,7 @@
|
|
18
18
|
#
|
19
19
|
module XeroGateway
|
20
20
|
class TrackingCategory
|
21
|
-
attr_accessor :name, :options
|
21
|
+
attr_accessor :tracking_category_id, :name, :options
|
22
22
|
|
23
23
|
def initialize(params = {})
|
24
24
|
@options = []
|
@@ -33,6 +33,7 @@ module XeroGateway
|
|
33
33
|
|
34
34
|
def to_xml(b = Builder::XmlMarkup.new)
|
35
35
|
b.TrackingCategory {
|
36
|
+
b.TrackingCategoryID self.tracking_category_id
|
36
37
|
b.Name self.name
|
37
38
|
b.Options {
|
38
39
|
if self.options.is_a?(Array)
|
@@ -54,6 +55,7 @@ module XeroGateway
|
|
54
55
|
# option, and the Options tag is omitted
|
55
56
|
def to_xml_for_invoice_messages(b = Builder::XmlMarkup.new)
|
56
57
|
b.TrackingCategory {
|
58
|
+
b.TrackingCategoryID self.tracking_category_id
|
57
59
|
b.Name self.name
|
58
60
|
b.Option self.options.is_a?(Array) ? self.options.first : self.options.to_s
|
59
61
|
}
|
@@ -63,6 +65,7 @@ module XeroGateway
|
|
63
65
|
tracking_category = TrackingCategory.new
|
64
66
|
tracking_category_element.children.each do |element|
|
65
67
|
case(element.name)
|
68
|
+
when "TrackingCategoryID" then tracking_category.tracking_category_id = element.text
|
66
69
|
when "Name" then tracking_category.name = element.text
|
67
70
|
when "Options" then
|
68
71
|
element.children.each do |option_child|
|
@@ -74,7 +77,7 @@ module XeroGateway
|
|
74
77
|
end
|
75
78
|
|
76
79
|
def ==(other)
|
77
|
-
[:name, :options].each do |field|
|
80
|
+
[:tracking_category_id, :name, :options].each do |field|
|
78
81
|
return false if send(field) != other.send(field)
|
79
82
|
end
|
80
83
|
return true
|
data/lib/xero_gateway.rb
CHANGED
@@ -21,6 +21,7 @@ require File.join(File.dirname(__FILE__), 'xero_gateway', 'contact')
|
|
21
21
|
require File.join(File.dirname(__FILE__), 'xero_gateway', 'line_item')
|
22
22
|
require File.join(File.dirname(__FILE__), 'xero_gateway', 'payment')
|
23
23
|
require File.join(File.dirname(__FILE__), 'xero_gateway', 'invoice')
|
24
|
+
require File.join(File.dirname(__FILE__), 'xero_gateway', 'credit_note')
|
24
25
|
require File.join(File.dirname(__FILE__), 'xero_gateway', 'address')
|
25
26
|
require File.join(File.dirname(__FILE__), 'xero_gateway', 'phone')
|
26
27
|
require File.join(File.dirname(__FILE__), 'xero_gateway', 'organisation')
|
@@ -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,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class GetCreditNoteTest < 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 =~ /CreditNotes(\/[0-9a-z\-]+)?$/i }.returns(get_file_as_string("credit_note.xml"))
|
13
|
+
@gateway.stubs(:http_put).with {|client, url, body, params| url =~ /CreditNotes$/ }.returns(get_file_as_string("create_credit_note.xml"))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_get_credit_note
|
18
|
+
# Make sure there is an credit_note in Xero to retrieve
|
19
|
+
credit_note = @gateway.create_credit_note(dummy_credit_note).credit_note
|
20
|
+
|
21
|
+
result = @gateway.get_credit_note(credit_note.credit_note_id)
|
22
|
+
assert result.success?
|
23
|
+
assert !result.request_params.nil?
|
24
|
+
assert !result.response_xml.nil?
|
25
|
+
assert_equal result.credit_note.credit_note_number, credit_note.credit_note_number
|
26
|
+
|
27
|
+
result = @gateway.get_credit_note(credit_note.credit_note_number)
|
28
|
+
assert result.success?
|
29
|
+
assert !result.request_params.nil?
|
30
|
+
assert !result.response_xml.nil?
|
31
|
+
assert_equal result.credit_note.credit_note_id, credit_note.credit_note_id
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_line_items_downloaded_set_correctly
|
35
|
+
# Make sure there is an credit_note in Xero to retrieve.
|
36
|
+
example_credit_note = @gateway.create_credit_note(dummy_credit_note).credit_note
|
37
|
+
|
38
|
+
# No line items.
|
39
|
+
response = @gateway.get_credit_note(example_credit_note.credit_note_id)
|
40
|
+
assert_equal(true, response.success?)
|
41
|
+
|
42
|
+
credit_note = response.credit_note
|
43
|
+
assert_kind_of(XeroGateway::LineItem, credit_note.line_items.first)
|
44
|
+
assert_kind_of(XeroGateway::CreditNote, credit_note)
|
45
|
+
assert_equal(true, credit_note.line_items_downloaded?)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class GetCreditNotesTest < Test::Unit::TestCase
|
4
|
+
include TestHelper
|
5
|
+
|
6
|
+
INVALID_CREDIT_NOTE_ID = "99999999-9999-9999-9999-999999999999" unless defined?(INVALID_CREDIT_NOTE_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 =~ /CreditNotes/ }.returns(get_file_as_string("credit_notes.xml"))
|
15
|
+
@gateway.stubs(:http_put).with {|client, url, body, params| url =~ /CreditNotes$/ }.returns(get_file_as_string("create_credit_note.xml"))
|
16
|
+
|
17
|
+
# Get an credit_note with an invalid ID number.
|
18
|
+
@gateway.stubs(:http_get).with {|client, url, params| url =~ Regexp.new("CreditNotes/#{INVALID_CREDIT_NOTE_ID}") }.returns(get_file_as_string("credit_note_not_found_error.xml"))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_get_credit_notes
|
23
|
+
# Make sure there is an credit_note in Xero to retrieve
|
24
|
+
credit_note = @gateway.create_credit_note(dummy_credit_note).credit_note
|
25
|
+
|
26
|
+
result = @gateway.get_credit_notes
|
27
|
+
assert result.success?
|
28
|
+
assert !result.request_params.nil?
|
29
|
+
assert !result.response_xml.nil?
|
30
|
+
assert result.credit_notes.collect {|i| i.credit_note_number}.include?(credit_note.credit_note_number)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_get_credit_notes_with_modified_since_date
|
34
|
+
# Create a test credit_note
|
35
|
+
credit_note = dummy_credit_note
|
36
|
+
@gateway.create_credit_note(credit_note)
|
37
|
+
|
38
|
+
# Check that it is returned
|
39
|
+
result = @gateway.get_credit_notes(:modified_since => Date.today - 1)
|
40
|
+
assert result.success?
|
41
|
+
assert !result.request_params.nil?
|
42
|
+
assert !result.response_xml.nil?
|
43
|
+
assert result.request_params.keys.include?(:ModifiedAfter) # make sure the flag was sent
|
44
|
+
assert result.credit_notes.collect {|response_credit_note| response_credit_note.credit_note_number}.include?(credit_note.credit_note_number)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_line_items_downloaded_set_correctly
|
48
|
+
# No line items.
|
49
|
+
response = @gateway.get_credit_notes
|
50
|
+
assert_equal(true, response.success?)
|
51
|
+
|
52
|
+
credit_note = response.credit_notes.first
|
53
|
+
assert_kind_of(XeroGateway::CreditNote, credit_note)
|
54
|
+
assert_equal(false, credit_note.line_items_downloaded?)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Make sure that a reference to gateway is passed when the get_credit_notes response is parsed.
|
58
|
+
def test_get_contacts_gateway_reference
|
59
|
+
result = @gateway.get_credit_notes
|
60
|
+
assert(result.success?)
|
61
|
+
assert_not_equal(0, result.credit_notes.size)
|
62
|
+
|
63
|
+
result.credit_notes.each do | credit_note |
|
64
|
+
assert(credit_note.gateway === @gateway)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Test to make sure that we correctly error when an credit_note doesn't have an ID.
|
69
|
+
# This should usually never be ecountered, but might if a draft credit_note is deleted from Xero.
|
70
|
+
def test_to_ensure_that_an_credit_note_with_invalid_id_errors
|
71
|
+
# Make sure there is an credit_note to retrieve, even though we will mangle it later.
|
72
|
+
credit_note = @gateway.create_credit_note(dummy_credit_note).credit_note
|
73
|
+
|
74
|
+
result = @gateway.get_credit_notes
|
75
|
+
assert_equal(true, result.success?)
|
76
|
+
|
77
|
+
credit_note = result.credit_notes.first
|
78
|
+
assert_equal(false, credit_note.line_items_downloaded?)
|
79
|
+
|
80
|
+
# Mangle credit_note_id to invalid one.
|
81
|
+
credit_note.credit_note_id = INVALID_CREDIT_NOTE_ID
|
82
|
+
|
83
|
+
# Make sure we fail here.
|
84
|
+
line_items = nil
|
85
|
+
assert_raise(XeroGateway::CreditNoteNotFoundError) { line_items = credit_note.line_items }
|
86
|
+
assert_nil(line_items)
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -20,7 +20,8 @@ class GetTrackingCategoriesTest < Test::Unit::TestCase
|
|
20
20
|
if STUB_XERO_CALLS
|
21
21
|
# When operating against the Xero test environment, there may not be any tracking categories present,
|
22
22
|
# so this assertion can only be done when operating against stub responses
|
23
|
-
|
23
|
+
assert_equal 1, result.tracking_categories.size
|
24
|
+
assert_equal 4, result.tracking_categories.first.options.size
|
24
25
|
end
|
25
26
|
end
|
26
|
-
end
|
27
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -51,6 +51,29 @@ module TestHelper
|
|
51
51
|
invoice
|
52
52
|
end
|
53
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
|
+
|
54
77
|
def dummy_contact
|
55
78
|
unique_id = Time.now.to_f
|
56
79
|
contact = XeroGateway::Contact.new(:name => STUB_XERO_CALLS ? "CONTACT NAME" : "THE NAME OF THE CONTACT #{unique_id}")
|
@@ -78,4 +101,4 @@ module TestHelper
|
|
78
101
|
return data
|
79
102
|
end
|
80
103
|
|
81
|
-
end
|
104
|
+
end
|
data/test/unit/account_test.rb
CHANGED
@@ -22,13 +22,14 @@ class AccountTest < Test::Unit::TestCase
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def create_test_account
|
25
|
-
account = XeroGateway::Account.new
|
25
|
+
account = XeroGateway::Account.new(:account_id => "57cedda9")
|
26
26
|
account.code = "200"
|
27
27
|
account.name = "Sales"
|
28
28
|
account.type = "REVENUE"
|
29
29
|
account.tax_type = "OUTPUT"
|
30
30
|
account.description = "Income from any normal business activity"
|
31
|
+
account.enable_payments_to_account = false
|
31
32
|
|
32
33
|
account
|
33
34
|
end
|
34
|
-
end
|
35
|
+
end
|
@@ -0,0 +1,284 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper.rb')
|
2
|
+
|
3
|
+
class CreditNoteTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# Tests that a credit note can be converted into XML that Xero can understand, and then converted back to a credit note
|
6
|
+
def test_build_and_parse_xml
|
7
|
+
credit_note = create_test_credit_note
|
8
|
+
|
9
|
+
# Generate the XML message
|
10
|
+
credit_note_as_xml = credit_note.to_xml
|
11
|
+
|
12
|
+
# Parse the XML message and retrieve the credit_note element
|
13
|
+
credit_note_element = REXML::XPath.first(REXML::Document.new(credit_note_as_xml), "/CreditNote")
|
14
|
+
|
15
|
+
# Build a new credit_note from the XML
|
16
|
+
result_credit_note = XeroGateway::CreditNote.from_xml(credit_note_element)
|
17
|
+
|
18
|
+
assert_equal(credit_note, result_credit_note)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Tests the sub_total calculation and that setting it manually doesn't modify the data.
|
22
|
+
def test_credit_note_sub_total_calculation
|
23
|
+
credit_note = create_test_credit_note
|
24
|
+
line_item = credit_note.line_items.first
|
25
|
+
|
26
|
+
# Make sure that everything adds up to begin with.
|
27
|
+
expected_sub_total = credit_note.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount }
|
28
|
+
assert_equal(expected_sub_total, credit_note.sub_total)
|
29
|
+
|
30
|
+
# Change the sub_total and check that it doesn't modify anything.
|
31
|
+
credit_note.sub_total = expected_sub_total * 10
|
32
|
+
assert_equal(expected_sub_total, credit_note.sub_total)
|
33
|
+
|
34
|
+
# Change the amount of the first line item and make sure that
|
35
|
+
# everything still continues to add up.
|
36
|
+
line_item.unit_amount = line_item.unit_amount + 10
|
37
|
+
assert_not_equal(expected_sub_total, credit_note.sub_total)
|
38
|
+
expected_sub_total = credit_note.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount }
|
39
|
+
assert_equal(expected_sub_total, credit_note.sub_total)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Tests the total_tax calculation and that setting it manually doesn't modify the data.
|
43
|
+
def test_credit_note_sub_total_calculation
|
44
|
+
credit_note = create_test_credit_note
|
45
|
+
line_item = credit_note.line_items.first
|
46
|
+
|
47
|
+
# Make sure that everything adds up to begin with.
|
48
|
+
expected_total_tax = credit_note.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount }
|
49
|
+
assert_equal(expected_total_tax, credit_note.total_tax)
|
50
|
+
|
51
|
+
# Change the total_tax and check that it doesn't modify anything.
|
52
|
+
credit_note.total_tax = expected_total_tax * 10
|
53
|
+
assert_equal(expected_total_tax, credit_note.total_tax)
|
54
|
+
|
55
|
+
# Change the tax_amount of the first line item and make sure that
|
56
|
+
# everything still continues to add up.
|
57
|
+
line_item.tax_amount = line_item.tax_amount + 10
|
58
|
+
assert_not_equal(expected_total_tax, credit_note.total_tax)
|
59
|
+
expected_total_tax = credit_note.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount }
|
60
|
+
assert_equal(expected_total_tax, credit_note.total_tax)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Tests the total calculation and that setting it manually doesn't modify the data.
|
64
|
+
def test_credit_note_sub_total_calculation
|
65
|
+
credit_note = create_test_credit_note
|
66
|
+
line_item = credit_note.line_items.first
|
67
|
+
|
68
|
+
# Make sure that everything adds up to begin with.
|
69
|
+
expected_total = credit_note.sub_total + credit_note.total_tax
|
70
|
+
assert_equal(expected_total, credit_note.total)
|
71
|
+
|
72
|
+
# Change the total and check that it doesn't modify anything.
|
73
|
+
credit_note.total = expected_total * 10
|
74
|
+
assert_equal(expected_total, credit_note.total)
|
75
|
+
|
76
|
+
# Change the quantity of the first line item and make sure that
|
77
|
+
# everything still continues to add up.
|
78
|
+
line_item.quantity = line_item.quantity + 5
|
79
|
+
assert_not_equal(expected_total, credit_note.total)
|
80
|
+
expected_total = credit_note.sub_total + credit_note.total_tax
|
81
|
+
assert_equal(expected_total, credit_note.total)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Tests that the LineItem#line_amount calculation is working correctly.
|
85
|
+
def test_line_amount_calculation
|
86
|
+
credit_note = create_test_credit_note
|
87
|
+
line_item = credit_note.line_items.first
|
88
|
+
|
89
|
+
# Make sure that everything adds up to begin with.
|
90
|
+
expected_amount = line_item.quantity * line_item.unit_amount
|
91
|
+
assert_equal(expected_amount, line_item.line_amount)
|
92
|
+
|
93
|
+
# Change the line_amount and check that it doesn't modify anything.
|
94
|
+
line_item.line_amount = expected_amount * 10
|
95
|
+
assert_equal(expected_amount, line_item.line_amount)
|
96
|
+
|
97
|
+
# Change the quantity and check that the line_amount has been updated.
|
98
|
+
quantity = line_item.quantity + 2
|
99
|
+
line_item.quantity = quantity
|
100
|
+
assert_not_equal(expected_amount, line_item.line_amount)
|
101
|
+
assert_equal(quantity * line_item.unit_amount, line_item.line_amount)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Ensure that the totalling methods don't raise exceptions, even when
|
105
|
+
# credit_note.line_items is empty.
|
106
|
+
def test_totalling_methods_when_line_items_empty
|
107
|
+
credit_note = create_test_credit_note
|
108
|
+
credit_note.line_items = []
|
109
|
+
|
110
|
+
assert_nothing_raised(Exception) {
|
111
|
+
assert_equal(BigDecimal.new('0'), credit_note.sub_total)
|
112
|
+
assert_equal(BigDecimal.new('0'), credit_note.total_tax)
|
113
|
+
assert_equal(BigDecimal.new('0'), credit_note.total)
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_type_helper_methods
|
118
|
+
# Test accounts receivable credit_notes.
|
119
|
+
credit_note = create_test_credit_note({:type => 'ACCRECCREDIT'})
|
120
|
+
assert_equal(true, credit_note.accounts_receivable?, "Accounts RECEIVABLE credit_note doesn't think it is.")
|
121
|
+
assert_equal(false, credit_note.accounts_payable?, "Accounts RECEIVABLE credit_note thinks it's payable.")
|
122
|
+
|
123
|
+
# Test accounts payable credit_notes.
|
124
|
+
credit_note = create_test_credit_note({:type => 'ACCPAYCREDIT'})
|
125
|
+
assert_equal(false, credit_note.accounts_receivable?, "Accounts PAYABLE credit_note doesn't think it is.")
|
126
|
+
assert_equal(true, credit_note.accounts_payable?, "Accounts PAYABLE credit_note thinks it's receivable.")
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# Make sure that the create_test_credit_note method is working correctly
|
131
|
+
# with all the defaults and overrides.
|
132
|
+
def test_create_test_credit_note_defaults_working
|
133
|
+
credit_note = create_test_credit_note
|
134
|
+
|
135
|
+
# Test credit_note defaults.
|
136
|
+
assert_equal('ACCRECCREDIT', credit_note.type)
|
137
|
+
assert_kind_of(Date, credit_note.date)
|
138
|
+
assert_equal('12345', credit_note.credit_note_number)
|
139
|
+
assert_equal('MY REFERENCE FOR THIS CREDIT NOTE', credit_note.reference)
|
140
|
+
assert_equal("Exclusive", credit_note.line_amount_types)
|
141
|
+
|
142
|
+
# Test the contact defaults.
|
143
|
+
assert_equal('00000000-0000-0000-0000-000000000000', credit_note.contact.contact_id)
|
144
|
+
assert_equal('CONTACT NAME', credit_note.contact.name)
|
145
|
+
|
146
|
+
# Test address defaults.
|
147
|
+
assert_equal('DEFAULT', credit_note.contact.address.address_type)
|
148
|
+
assert_equal('LINE 1 OF THE ADDRESS', credit_note.contact.address.line_1)
|
149
|
+
|
150
|
+
# Test phone defaults.
|
151
|
+
assert_equal('DEFAULT', credit_note.contact.phone.phone_type)
|
152
|
+
assert_equal('12345678', credit_note.contact.phone.number)
|
153
|
+
|
154
|
+
# Test the line_item defaults.
|
155
|
+
assert_equal('A LINE ITEM', credit_note.line_items.first.description)
|
156
|
+
assert_equal('200', credit_note.line_items.first.account_code)
|
157
|
+
assert_equal(BigDecimal.new('100'), credit_note.line_items.first.unit_amount)
|
158
|
+
assert_equal(BigDecimal.new('12.5'), credit_note.line_items.first.tax_amount)
|
159
|
+
|
160
|
+
# Test overriding an credit_note parameter (assume works for all).
|
161
|
+
credit_note = create_test_credit_note({:type => 'ACCPAYCREDIT'})
|
162
|
+
assert_equal('ACCPAYCREDIT', credit_note.type)
|
163
|
+
|
164
|
+
# Test overriding a contact/address/phone parameter (assume works for all).
|
165
|
+
credit_note = create_test_credit_note({}, {:name => 'OVERRIDDEN NAME', :address => {:line_1 => 'OVERRIDDEN LINE 1'}, :phone => {:number => '999'}})
|
166
|
+
assert_equal('OVERRIDDEN NAME', credit_note.contact.name)
|
167
|
+
assert_equal('OVERRIDDEN LINE 1', credit_note.contact.address.line_1)
|
168
|
+
assert_equal('999', credit_note.contact.phone.number)
|
169
|
+
|
170
|
+
# Test overriding line_items with hash.
|
171
|
+
credit_note = create_test_credit_note({}, {}, {:description => 'OVERRIDDEN LINE ITEM'})
|
172
|
+
assert_equal(1, credit_note.line_items.size)
|
173
|
+
assert_equal('OVERRIDDEN LINE ITEM', credit_note.line_items.first.description)
|
174
|
+
assert_equal(BigDecimal.new('100'), credit_note.line_items.first.unit_amount)
|
175
|
+
|
176
|
+
# Test overriding line_items with array of 2 line_items.
|
177
|
+
credit_note = create_test_credit_note({}, {}, [
|
178
|
+
{:description => 'OVERRIDDEN ITEM 1'},
|
179
|
+
{:description => 'OVERRIDDEN ITEM 2', :account_code => '200', :unit_amount => BigDecimal.new('200'), :tax_amount => '25.0'}
|
180
|
+
])
|
181
|
+
assert_equal(2, credit_note.line_items.size)
|
182
|
+
assert_equal('OVERRIDDEN ITEM 1', credit_note.line_items[0].description)
|
183
|
+
assert_equal(BigDecimal.new('100'), credit_note.line_items[0].unit_amount)
|
184
|
+
assert_equal('OVERRIDDEN ITEM 2', credit_note.line_items[1].description)
|
185
|
+
assert_equal(BigDecimal.new('200'), credit_note.line_items[1].unit_amount)
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_auto_creation_of_associated_contact
|
189
|
+
credit_note = create_test_credit_note({}, nil) # no contact
|
190
|
+
assert_nil(credit_note.instance_variable_get("@contact"))
|
191
|
+
|
192
|
+
new_contact = credit_note.contact
|
193
|
+
assert_kind_of(XeroGateway::Contact, new_contact)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_add_line_item
|
197
|
+
credit_note = create_test_credit_note({}, {}, nil) # no line_items
|
198
|
+
assert_equal(0, credit_note.line_items.size)
|
199
|
+
|
200
|
+
line_item_params = {:description => "Test Item 1", :unit_amount => 100}
|
201
|
+
|
202
|
+
# Test adding line item by hash
|
203
|
+
line_item = credit_note.add_line_item(line_item_params)
|
204
|
+
assert_kind_of(XeroGateway::LineItem, line_item)
|
205
|
+
assert_equal(line_item_params[:description], line_item.description)
|
206
|
+
assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
|
207
|
+
assert_equal(1, credit_note.line_items.size)
|
208
|
+
|
209
|
+
# Test adding line item by XeroGateway::LineItem
|
210
|
+
line_item = credit_note.add_line_item(line_item_params)
|
211
|
+
assert_kind_of(XeroGateway::LineItem, line_item)
|
212
|
+
assert_equal(line_item_params[:description], line_item.description)
|
213
|
+
assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
|
214
|
+
assert_equal(2, credit_note.line_items.size)
|
215
|
+
|
216
|
+
# Test that pushing anything else into add_line_item fails.
|
217
|
+
["invalid", 100, nil, []].each do | invalid_object |
|
218
|
+
assert_raise(XeroGateway::CreditNote::InvalidLineItemError) { credit_note.add_line_item(invalid_object) }
|
219
|
+
assert_equal(2, credit_note.line_items.size)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
def create_test_credit_note(credit_note_params = {}, contact_params = {}, line_item_params = [])
|
226
|
+
unless credit_note_params.nil?
|
227
|
+
credit_note_params = {
|
228
|
+
:type => 'ACCRECCREDIT',
|
229
|
+
:date => Date.today,
|
230
|
+
:credit_note_number => '12345',
|
231
|
+
:reference => "MY REFERENCE FOR THIS CREDIT NOTE",
|
232
|
+
:line_amount_types => "Exclusive"
|
233
|
+
}.merge(credit_note_params)
|
234
|
+
end
|
235
|
+
credit_note = XeroGateway::CreditNote.new(credit_note_params || {})
|
236
|
+
|
237
|
+
unless contact_params.nil?
|
238
|
+
# Strip out :address key from contact_params to use as the default address.
|
239
|
+
stripped_address = {
|
240
|
+
:address_type => 'DEFAULT',
|
241
|
+
:line_1 => 'LINE 1 OF THE ADDRESS'
|
242
|
+
}.merge(contact_params.delete(:address) || {})
|
243
|
+
|
244
|
+
# Strip out :phone key from contact_params to use at the default phone.
|
245
|
+
stripped_phone = {
|
246
|
+
:phone_type => 'DEFAULT',
|
247
|
+
:number => '12345678'
|
248
|
+
}.merge(contact_params.delete(:phone) || {})
|
249
|
+
|
250
|
+
contact_params = {
|
251
|
+
:contact_id => '00000000-0000-0000-0000-000000000000', # Just any valid GUID
|
252
|
+
:name => "CONTACT NAME",
|
253
|
+
:first_name => "Bob",
|
254
|
+
:last_name => "Builder"
|
255
|
+
}.merge(contact_params)
|
256
|
+
|
257
|
+
# Create credit_note.contact from contact_params.
|
258
|
+
credit_note.contact = XeroGateway::Contact.new(contact_params)
|
259
|
+
credit_note.contact.address = XeroGateway::Address.new(stripped_address)
|
260
|
+
credit_note.contact.phone = XeroGateway::Phone.new(stripped_phone)
|
261
|
+
end
|
262
|
+
|
263
|
+
unless line_item_params.nil?
|
264
|
+
line_item_params = [line_item_params].flatten # always use an array, even if only a single hash passed in
|
265
|
+
|
266
|
+
# At least one line item, make first have some defaults.
|
267
|
+
line_item_params << {} if line_item_params.size == 0
|
268
|
+
line_item_params[0] = {
|
269
|
+
:description => "A LINE ITEM",
|
270
|
+
:account_code => "200",
|
271
|
+
:unit_amount => BigDecimal.new("100"),
|
272
|
+
:tax_amount => BigDecimal.new("12.5"),
|
273
|
+
:tracking => XeroGateway::TrackingCategory.new(:name => "blah", :options => "hello")
|
274
|
+
}.merge(line_item_params[0])
|
275
|
+
|
276
|
+
# Create credit_note.line_items from line_item_params
|
277
|
+
line_item_params.each do | line_item |
|
278
|
+
credit_note.add_line_item(line_item)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
credit_note
|
283
|
+
end
|
284
|
+
end
|
data/test/unit/gateway_test.rb
CHANGED
@@ -32,6 +32,22 @@ class GatewayTest < Test::Unit::TestCase
|
|
32
32
|
@gateway.get_accounts
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
should "handle rate limit exceeded" do
|
37
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("rate_limit_exceeded"), :code => "401"))
|
38
|
+
|
39
|
+
assert_raises XeroGateway::OAuth::RateLimitExceeded do
|
40
|
+
@gateway.get_accounts
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
should "handle unknown errors" do
|
45
|
+
XeroGateway::OAuth.any_instance.stubs(:get).returns(stub(:plain_body => get_file_as_string("bogus_oauth_error"), :code => "401"))
|
46
|
+
|
47
|
+
assert_raises XeroGateway::OAuth::UnknownError do
|
48
|
+
@gateway.get_accounts
|
49
|
+
end
|
50
|
+
end
|
35
51
|
|
36
52
|
should "handle ApiExceptions" do
|
37
53
|
XeroGateway::OAuth.any_instance.stubs(:put).returns(stub(:plain_body => get_file_as_string("api_exception.xml"), :code => "400"))
|
@@ -76,4 +92,4 @@ class GatewayTest < Test::Unit::TestCase
|
|
76
92
|
assert_equal "Xero.API.Library.Exceptions.ObjectDoesNotExistException", result.errors.first.type
|
77
93
|
assert !result.errors.first.description.nil?
|
78
94
|
end
|
79
|
-
end
|
95
|
+
end
|