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,47 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
+
3
+ class AccountTest < Test::Unit::TestCase
4
+ # Tests that an account can be converted into XML that Xero can understand, and then converted back to an account
5
+ def test_build_and_parse_xml
6
+ account = create_test_account
7
+
8
+ # Generate the XML message
9
+ account_as_xml = account.to_xml
10
+
11
+ # Parse the XML message and retrieve the account element
12
+ account_element = REXML::XPath.first(REXML::Document.new(account_as_xml), "/Account")
13
+
14
+ # Build a new account from the XML
15
+ result_account = XeroGateway::Account.from_xml(account_element)
16
+
17
+ # Check the account details
18
+ assert_equal account, result_account
19
+ end
20
+
21
+ def test_build_and_parse_xml_for_bank_accounts
22
+ account = create_test_account(:type => 'BANK', :currency_code => 'NZD')
23
+ account_as_xml = account.to_xml
24
+ assert_match 'CurrencyCode', account_as_xml.to_s
25
+
26
+ account_element = REXML::XPath.first(REXML::Document.new(account_as_xml), "/Account")
27
+ result_account = XeroGateway::Account.from_xml(account_element)
28
+ assert_equal 'BANK', result_account.type
29
+ assert_equal 'NZD', result_account.currency_code
30
+ assert_equal account, result_account
31
+ end
32
+
33
+ private
34
+
35
+ def create_test_account(options={})
36
+ account = XeroGateway::Account.new(:account_id => "57cedda9")
37
+ account.code = "200"
38
+ account.name = "Sales"
39
+ account.type = options[:type] || "REVENUE"
40
+ account.tax_type = "OUTPUT"
41
+ account.description = "Income from any normal business activity"
42
+ account.enable_payments_to_account = false
43
+ account.currency_code = options[:currency_code] if options[:currency_code]
44
+
45
+ account
46
+ end
47
+ end
@@ -0,0 +1,126 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
+
3
+ class BankTransactionTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ context "creating test bank transactions" do
7
+ should "work" do
8
+ bank_transaction = create_test_bank_transaction
9
+
10
+ # test transaction defaults
11
+ assert_equal 'RECEIVE', bank_transaction.type
12
+ assert_kind_of Date, bank_transaction.date
13
+ assert_equal '12345', bank_transaction.reference
14
+ assert_equal 'ACTIVE', bank_transaction.status
15
+
16
+ # Test the contact defaults.
17
+ contact = bank_transaction.contact
18
+ assert_equal '00000000-0000-0000-0000-000000000000', contact.contact_id
19
+ assert_equal 'CONTACT NAME', contact.name
20
+
21
+ # Test address defaults.
22
+ assert_equal 'STREET', contact.address.address_type
23
+ assert_equal 'LINE 1 OF THE ADDRESS', contact.address.line_1
24
+
25
+ # Test phone defaults.
26
+ assert_equal('DEFAULT', contact.phone.phone_type)
27
+ assert_equal('12345678', contact.phone.number)
28
+
29
+ # Test the line_item defaults.
30
+ line_item = bank_transaction.line_items.first
31
+ assert_equal('A LINE ITEM', line_item.description)
32
+ assert_equal('200', line_item.account_code)
33
+ assert_equal(BigDecimal.new('100'), line_item.unit_amount)
34
+ assert_equal(BigDecimal.new('12.5'), line_item.tax_amount)
35
+ end
36
+
37
+ should "allow overriding transaction defaults" do
38
+ assert_equal 'SPEND', create_test_bank_transaction(:type => 'SPEND').type
39
+ end
40
+ end
41
+
42
+ context "adding line items" do
43
+ setup do
44
+ @bank_transaction = create_test_bank_transaction({}, {}, nil) # no line_items
45
+ end
46
+
47
+ should "work" do
48
+ assert_equal(0, @bank_transaction.line_items.size)
49
+
50
+ line_item_params = {:description => "Test Item 1", :unit_amount => 100}
51
+
52
+ # Test adding line item by hash
53
+ line_item = @bank_transaction.add_line_item(line_item_params)
54
+ assert_kind_of(XeroGateway::LineItem, line_item)
55
+ assert_equal(line_item_params[:description], line_item.description)
56
+ assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
57
+ assert_equal(1, @bank_transaction.line_items.size)
58
+
59
+ # Test adding line item by XeroGateway::LineItem
60
+ line_item = @bank_transaction.add_line_item(line_item_params)
61
+ assert_kind_of(XeroGateway::LineItem, line_item)
62
+ assert_equal(line_item_params[:description], line_item.description)
63
+ assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
64
+ assert_equal(2, @bank_transaction.line_items.size)
65
+
66
+ # Test that pushing anything else into add_line_item fails.
67
+ ["invalid", 100, nil, []].each do | invalid_object |
68
+ assert_raise(XeroGateway::Invoice::InvalidLineItemError) { @bank_transaction.add_line_item(invalid_object) }
69
+ assert_equal(2, @bank_transaction.line_items.size)
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+ context "building and parsing XML" do
76
+ should "work vice versa" do
77
+ bank_transaction = create_test_bank_transaction
78
+ bank_transaction_as_xml = bank_transaction.to_xml
79
+ bank_transaction_element = REXML::XPath.first(REXML::Document.new(bank_transaction_as_xml), "/BankTransaction")
80
+
81
+ # checking for mandatory fields
82
+ assert_xml_field bank_transaction_element, 'Type', :value => 'RECEIVE'
83
+ assert_xml_field bank_transaction_element, 'Date'
84
+ assert_xml_field bank_transaction_element, 'Reference', :value => '12345'
85
+ assert_xml_field bank_transaction_element, 'Status', :value => 'ACTIVE'
86
+ assert_xml_field bank_transaction_element, 'Contact', :value => 'CONTACT NAME'
87
+ assert_xml_field bank_transaction_element, 'LineItems', :value => 'A LINE ITEM'
88
+ assert_xml_field bank_transaction_element, 'BankAccount'
89
+
90
+ parsed_bank_transaction = XeroGateway::BankTransaction.from_xml(bank_transaction_element)
91
+ assert_equal(bank_transaction, parsed_bank_transaction)
92
+ end
93
+
94
+ should "work for optional params" do
95
+ bank_transaction = create_test_bank_transaction(:url => 'http://example.com?with=params&and=more')
96
+ bank_transaction_element = REXML::XPath.first(REXML::Document.new(bank_transaction.to_xml), "/BankTransaction")
97
+
98
+ assert_xml_field bank_transaction_element, 'Url', :value => 'http://example.com\?with=params&amp;and=more'
99
+
100
+ parsed_bank_transaction = XeroGateway::BankTransaction.from_xml(bank_transaction_element)
101
+ assert_equal 'http://example.com?with=params&and=more', parsed_bank_transaction.url
102
+ end
103
+
104
+ should "ignore missing contact" do
105
+ bank_transaction = create_test_bank_transaction
106
+ bank_transaction.contact = nil
107
+ bank_transaction.to_xml
108
+ end
109
+
110
+ should "ignore missing bank account" do
111
+ bank_transaction = create_test_bank_transaction
112
+ bank_transaction.bank_account = nil
113
+ bank_transaction.to_xml
114
+ end
115
+ end
116
+
117
+ private
118
+
119
+ def assert_xml_field(xml, field_name, options={})
120
+ assert_match /#{field_name}/, xml.to_s, "Didn't find the field #{field_name} in the XML document!"
121
+ if options[:value]
122
+ assert_match /#{field_name}.*#{options[:value]}.*#{field_name}/, xml.to_s, "The field #{field_name} was expected to be '#{options[:value]}'!"
123
+ end
124
+ end
125
+
126
+ end
@@ -0,0 +1,97 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
+
3
+ class ContactTest < Test::Unit::TestCase
4
+ def setup
5
+ @schema = LibXML::XML::Schema.document(LibXML::XML::Document.file(File.join(File.dirname(__FILE__), '../xsd/create_contact.xsd')))
6
+ end
7
+
8
+ # Tests that the XML generated from a contact object validates against the Xero XSD
9
+ def test_build_xml
10
+ contact = create_test_contact
11
+
12
+ message = contact.to_xml
13
+
14
+ # Check that the document matches the XSD
15
+ assert LibXML::XML::Parser.string(message).parse.validate_schema(@schema), "The XML document generated did not validate against the XSD"
16
+ end
17
+
18
+ # Tests that a contact can be converted into XML that Xero can understand, and then converted back to a contact
19
+ def test_build_and_parse_xml
20
+ contact = create_test_contact
21
+
22
+ # Generate the XML message
23
+ contact_as_xml = contact.to_xml
24
+
25
+ # Parse the XML message and retrieve the contact element
26
+ contact_element = REXML::XPath.first(REXML::Document.new(contact_as_xml), "/Contact")
27
+
28
+ # Build a new contact from the XML
29
+ result_contact = XeroGateway::Contact.from_xml(contact_element)
30
+
31
+ # Check the contact details
32
+ assert_equal contact, result_contact
33
+ end
34
+
35
+ # Test Contact#add_address helper creates a valid XeroGateway::Contact object with the passed in values
36
+ # and appends it to the Contact#addresses attribute.
37
+ def test_add_address_helper
38
+ contact = create_test_contact
39
+ assert_equal(1, contact.addresses.size)
40
+
41
+ new_values = {
42
+ :address_type => 'POBOX',
43
+ :line_1 => 'NEW LINE 1',
44
+ :line_2 => 'NEW LINE 2',
45
+ :line_3 => 'NEW LINE 3',
46
+ :line_4 => 'NEW LINE 4',
47
+ :city => 'NEW CITY',
48
+ :region => 'NEW REGION',
49
+ :post_code => '5555',
50
+ :country => 'Australia'
51
+ }
52
+ contact.add_address(new_values)
53
+
54
+ assert_equal(2, contact.addresses.size)
55
+ assert_kind_of(XeroGateway::Address, contact.addresses.last)
56
+ new_values.each { |k,v| assert_equal(v, contact.addresses.last.send("#{k}")) }
57
+ end
58
+
59
+ # Test Contact#add_phone helper creates a valid XeroGateway::Phone object with the passed in values
60
+ # and appends it to the Contact#phones attribute.
61
+ def test_add_address_helper
62
+ contact = create_test_contact
63
+ assert_equal(1, contact.phones.size)
64
+
65
+ new_values = {
66
+ :phone_type => 'MOBILE',
67
+ :country_code => '61',
68
+ :area_code => '406',
69
+ :number => '123456'
70
+ }
71
+ contact.add_phone(new_values)
72
+
73
+ assert_equal(2, contact.phones.size)
74
+ assert_kind_of(XeroGateway::Phone, contact.phones.last)
75
+ new_values.each { |k,v| assert_equal(v, contact.phones.last.send("#{k}")) }
76
+ end
77
+
78
+
79
+ private
80
+
81
+ def create_test_contact
82
+ contact = XeroGateway::Contact.new(:contact_id => "55555")
83
+ contact.contact_number = "aaa111"
84
+ contact.name = "CONTACT NAME"
85
+ contact.email = "someone@somewhere.com"
86
+ contact.address.address_type = "THE ADDRESS TYPE FOR THE CONTACT"
87
+ contact.address.line_1 = "LINE 1 OF THE ADDRESS"
88
+ contact.address.line_2 = "LINE 2 OF THE ADDRESS"
89
+ contact.address.line_3 = "LINE 3 OF THE ADDRESS"
90
+ contact.address.line_4 = "LINE 4 OF THE ADDRESS"
91
+ contact.phone.number = "12345"
92
+ contact.is_customer = true
93
+ contact.is_supplier = true
94
+
95
+ contact
96
+ end
97
+ 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